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 2796 - (hide annotations) (download) (as text)
Tue Mar 8 14:24:11 2005 UTC (19 years, 1 month ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 139728 byte(s)
SSH2 log dump機構の追加。
とりあえず、DH_GEXにおけるkey verifyまでにトレース採取を組み込んだ。

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     // for calculate SSH2 hash
1196     // �T�[�o�o�[�W�����������i���s���������������j
1197     if (ID_len >= sizeof(pvar->server_version_string))
1198     return FALSE;
1199     strncpy(pvar->server_version_string, ID, ID_len);
1200    
1201    
1202     if (ID[ID_len - 1] != '\n') {
1203     pvar->ssh_state.status_flags |= STATUS_IN_PARTIAL_ID_STRING;
1204     return FALSE;
1205     } else
1206     if ((pvar->ssh_state.
1207     status_flags & STATUS_IN_PARTIAL_ID_STRING) != 0) {
1208     pvar->ssh_state.status_flags &= ~STATUS_IN_PARTIAL_ID_STRING;
1209     return FALSE;
1210     } else if (strncmp(ID, "SSH-", 4) != 0) {
1211     return FALSE;
1212     } else {
1213     ID[ID_len - 1] = 0;
1214    
1215     if (ID_len > 1 && ID[ID_len - 2] == '\r') {
1216     ID[ID_len - 2] = 0;
1217     }
1218    
1219     pvar->ssh_state.server_ID = _strdup(ID);
1220    
1221     if (!parse_protocol_ID(pvar, ID) || !negotiate_protocol(pvar)) {
1222     notify_fatal_error(pvar,
1223     "This program does not understand the server's version of the protocol.");
1224     } else {
1225     char TTSSH_ID[1024];
1226     int TTSSH_ID_len;
1227 yutakakn 2793 int a, b, c, d;
1228 yutakakn 2728
1229 yutakakn 2793 // �������g���o�[�W�������������� (2005.3.3 yutaka)
1230     get_file_version("ttxssh.dll", &a, &b, &c, &d);
1231    
1232 yutakakn 2728 _snprintf(TTSSH_ID, sizeof(TTSSH_ID),
1233 yutakakn 2793 "SSH-%d.%d-TTSSH/%d.%d Win32\n",
1234     pvar->protocol_major, pvar->protocol_minor, a, b);
1235 yutakakn 2728 TTSSH_ID_len = strlen(TTSSH_ID);
1236    
1237     // for SSH2(yutaka)
1238     // �N���C�A���g�o�[�W�����������i���s���������������j
1239     strncpy(pvar->client_version_string, TTSSH_ID, TTSSH_ID_len);
1240    
1241     if ((pvar->Psend) (pvar->socket, TTSSH_ID, TTSSH_ID_len,
1242     0) != TTSSH_ID_len) {
1243     notify_fatal_error(pvar,
1244     "An error occurred while sending the SSH ID string.\n"
1245     "The connection will close.");
1246     } else {
1247     // ���s�R�[�h������ (2004.8.4 yutaka)
1248     pvar->server_version_string[--ID_len] = 0;
1249     pvar->client_version_string[--TTSSH_ID_len] = 0;
1250    
1251 yutakakn 2796 push_memdump("server ID", NULL, pvar->server_version_string, strlen(pvar->server_version_string));
1252     push_memdump("client ID", NULL, pvar->client_version_string, strlen(pvar->client_version_string));
1253    
1254 yutakakn 2728 // SSH�n���h�����o�^���s��
1255     init_protocol(pvar);
1256    
1257     SSH2_dispatch_init(1);
1258     SSH2_dispatch_add_message(SSH2_MSG_KEXINIT);
1259 yutakakn 2796 SSH2_dispatch_add_message(SSH2_MSG_IGNORE); // XXX: Tru64 UNIX workaround (2005.3.3 yutaka)
1260 yutakakn 2728 }
1261     }
1262    
1263     return TRUE;
1264     }
1265     }
1266     }
1267    
1268     static BOOL handle_exit(PTInstVar pvar)
1269     {
1270     if (grab_payload(pvar, 4)) {
1271     begin_send_packet(pvar, SSH_CMSG_EXIT_CONFIRMATION, 0);
1272     finish_send_packet(pvar);
1273     notify_closed_connection(pvar);
1274     }
1275     return TRUE;
1276     }
1277    
1278     static BOOL handle_data(PTInstVar pvar)
1279     {
1280     if (grab_payload_limited(pvar, 4)) {
1281     pvar->ssh_state.payload_datalen = get_payload_uint32(pvar, 0);
1282     pvar->ssh_state.payload_datastart = 4;
1283     }
1284     return TRUE;
1285     }
1286    
1287     static BOOL handle_channel_open(PTInstVar pvar)
1288     {
1289     int host_len;
1290     int originator_len;
1291    
1292     if ((pvar->ssh_state.
1293     server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
1294     if (grab_payload(pvar, 8)
1295     && grab_payload(pvar,
1296     8 + (host_len = get_payload_uint32(pvar, 4)))
1297     && grab_payload(pvar, originator_len =
1298     get_payload_uint32(pvar, host_len + 12))) {
1299     int local_port = get_payload_uint32(pvar, 8 + host_len);
1300    
1301     pvar->ssh_state.payload[8 + host_len] = 0;
1302     FWD_open(pvar, get_payload_uint32(pvar, 0),
1303     pvar->ssh_state.payload + 8, local_port,
1304     pvar->ssh_state.payload + 16 + host_len,
1305     originator_len);
1306     }
1307     } else {
1308     if (grab_payload(pvar, 8)
1309     && grab_payload(pvar,
1310     4 + (host_len =
1311     get_payload_uint32(pvar, 4)))) {
1312     int local_port = get_payload_uint32(pvar, 8 + host_len);
1313    
1314     pvar->ssh_state.payload[8 + host_len] = 0;
1315     FWD_open(pvar, get_payload_uint32(pvar, 0),
1316     pvar->ssh_state.payload + 8, local_port, NULL, 0);
1317     }
1318     }
1319    
1320     return TRUE;
1321     }
1322    
1323     static BOOL handle_X11_channel_open(PTInstVar pvar)
1324     {
1325     int originator_len;
1326    
1327     if ((pvar->ssh_state.
1328     server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
1329     if (grab_payload(pvar, 8)
1330     && grab_payload(pvar, originator_len =
1331     get_payload_uint32(pvar, 4))) {
1332     FWD_X11_open(pvar, get_payload_uint32(pvar, 0),
1333     pvar->ssh_state.payload + 8, originator_len);
1334     }
1335     } else {
1336     if (grab_payload(pvar, 4)) {
1337     FWD_X11_open(pvar, get_payload_uint32(pvar, 0), NULL, 0);
1338     }
1339     }
1340    
1341     return TRUE;
1342     }
1343    
1344     static BOOL handle_channel_open_confirmation(PTInstVar pvar)
1345     {
1346     if (grab_payload(pvar, 8)) {
1347     FWD_confirmed_open(pvar, get_payload_uint32(pvar, 0),
1348     get_payload_uint32(pvar, 4));
1349     }
1350     return FALSE;
1351     }
1352    
1353     static BOOL handle_channel_open_failure(PTInstVar pvar)
1354     {
1355     if (grab_payload(pvar, 4)) {
1356     FWD_failed_open(pvar, get_payload_uint32(pvar, 0));
1357     }
1358     return FALSE;
1359     }
1360    
1361     static BOOL handle_channel_data(PTInstVar pvar)
1362     {
1363     int len;
1364    
1365     if (grab_payload(pvar, 8)
1366     && grab_payload(pvar, len = get_payload_uint32(pvar, 4))) {
1367     FWD_received_data(pvar, get_payload_uint32(pvar, 0),
1368     pvar->ssh_state.payload + 8, len);
1369     }
1370     return TRUE;
1371     }
1372    
1373     static BOOL handle_channel_input_eof(PTInstVar pvar)
1374     {
1375     if (grab_payload(pvar, 4)) {
1376     FWD_channel_input_eof(pvar, get_payload_uint32(pvar, 0));
1377     }
1378     return TRUE;
1379     }
1380    
1381     static BOOL handle_channel_output_eof(PTInstVar pvar)
1382     {
1383     if (grab_payload(pvar, 4)) {
1384     FWD_channel_output_eof(pvar, get_payload_uint32(pvar, 0));
1385     }
1386     return TRUE;
1387     }
1388    
1389    
1390    
1391     // �n���h�����O�������b�Z�[�W����������
1392    
1393     #define HANDLE_MESSAGE_MAX 30
1394     static unsigned char handle_messages[HANDLE_MESSAGE_MAX];
1395     static int handle_message_count = 0;
1396     static int handle_message_stage = 0;
1397    
1398     void SSH2_dispatch_init(int stage)
1399     {
1400     handle_message_count = 0;
1401     handle_message_stage = stage;
1402     }
1403    
1404     int SSH2_dispatch_enabled_check(unsigned char message)
1405     {
1406     int i;
1407    
1408     for (i = 0 ; i < handle_message_count ; i++) {
1409     if (handle_messages[i] == message)
1410     return 1;
1411     }
1412     return 0;
1413     }
1414    
1415     void SSH2_dispatch_add_message(unsigned char message)
1416     {
1417    
1418     if (handle_message_count >= HANDLE_MESSAGE_MAX) {
1419     // TODO: error check
1420     return;
1421     }
1422    
1423     handle_messages[handle_message_count++] = message;
1424     }
1425    
1426     void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end)
1427     {
1428     unsigned char c;
1429    
1430     for (c = begin ; c <= end ; c++) {
1431     SSH2_dispatch_add_message(c);
1432     }
1433     }
1434    
1435    
1436     /* default window/packet sizes for tcp/x11-fwd-channel */
1437     #define CHAN_SES_PACKET_DEFAULT (32*1024)
1438     #define CHAN_SES_WINDOW_DEFAULT (2*CHAN_SES_PACKET_DEFAULT) // READAMOUNT @ pkt.c����������������
1439    
1440     //#define CHAN_TCP_PACKET_DEFAULT (32*1024)
1441     //#define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT)
1442     //#define CHAN_X11_PACKET_DEFAULT (16*1024)
1443     //#define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT)
1444    
1445     // �N���C�A���g��window size���T�[�o���m������
1446     static void do_SSH2_adjust_window_size(PTInstVar pvar)
1447     {
1448     const unsigned int window_size = CHAN_SES_PACKET_DEFAULT;
1449     buffer_t *msg;
1450     unsigned char *outmsg;
1451     int len;
1452    
1453     // ���[�J����window size�������]�T�����������A�����������B
1454     if (pvar->local_window > window_size)
1455     return;
1456    
1457     {
1458     // pty open
1459     msg = buffer_init();
1460     if (msg == NULL) {
1461     // TODO: error check
1462     return;
1463     }
1464     buffer_put_int(msg, pvar->remote_id);
1465     buffer_put_int(msg, window_size - pvar->local_window);
1466    
1467     len = buffer_len(msg);
1468     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_WINDOW_ADJUST, len);
1469     memcpy(outmsg, buffer_ptr(msg), len);
1470     finish_send_packet(pvar);
1471     buffer_free(msg);
1472    
1473     // �N���C�A���g��window size��������
1474     pvar->local_window = window_size;
1475     }
1476    
1477     }
1478    
1479    
1480     static void SSH2_consume_packet_size(PTInstVar pvar, unsigned char message)
1481     {
1482     int len;
1483     char *data;
1484    
1485     if (!(message >= SSH2_MSG_CHANNEL_OPEN_CONFIRMATION && message <= SSH2_MSG_CHANNEL_FAILURE)) {
1486     return;
1487     }
1488    
1489     // 6byte�i�T�C�Y�{�p�f�B���O�{�^�C�v�j���������������~���y�C���[�h
1490     data = pvar->ssh_state.payload;
1491     // �p�P�b�g�T�C�Y - (�p�f�B���O�T�C�Y+1)�G�^���p�P�b�g�T�C�Y
1492     len = pvar->ssh_state.payloadlen;
1493    
1494     pvar->local_window -= (len + 1);
1495    
1496     do_SSH2_adjust_window_size(pvar);
1497    
1498     }
1499    
1500    
1501     void SSH_handle_packet(PTInstVar pvar, char FAR * data, int len,
1502     int padding)
1503     {
1504     unsigned char message = prep_packet(pvar, data, len, padding);
1505    
1506    
1507     #ifdef SSH2_DEBUG
1508     // for SSH2(yutaka)
1509     if (SSHv2(pvar)) {
1510     if (pvar->key_done) {
1511     message = message;
1512     }
1513    
1514     if (pvar->userauth_success) {
1515     message = message;
1516     }
1517    
1518     if (pvar->rekeying) {
1519     message = message;
1520     }
1521     }
1522     #endif
1523    
1524     // SSH�����b�Z�[�W�^�C�v���`�F�b�N
1525     if (message != SSH_MSG_NONE) {
1526     // ���b�Z�[�W�^�C�v���������n���h�����N��
1527     SSHPacketHandler handler = get_handler(pvar, message);
1528    
1529     // for SSH2(yutaka)
1530     if (SSHv2(pvar)) {
1531     // �z���O�����b�Z�[�W�^�C�v�������������A�{�[�g�������B
1532     if (!SSH2_dispatch_enabled_check(message) || handler == NULL) {
1533     char buf[1024];
1534    
1535     _snprintf(buf, sizeof(buf),
1536     "Unexpected SSH2 message(%d) on current stage(%d)", message, handle_message_stage);
1537     notify_fatal_error(pvar, buf);
1538     // abort
1539     }
1540     }
1541    
1542     if (handler == NULL) {
1543     if (SSHv1(pvar)) {
1544     char buf[1024];
1545    
1546     _snprintf(buf, sizeof(buf),
1547     "Unexpected packet type received: %d", message);
1548     buf[sizeof(buf) - 1] = 0;
1549     notify_fatal_error(pvar, buf);
1550     } else {
1551     unsigned char FAR *outmsg =
1552     begin_send_packet(pvar, SSH2_MSG_UNIMPLEMENTED, 4);
1553    
1554     set_uint32(outmsg,
1555     pvar->ssh_state.receiver_sequence_number - 1);
1556     finish_send_packet(pvar);
1557     /* XXX need to decompress incoming packet, but how? */
1558     }
1559     } else {
1560     if (!handler(pvar)) {
1561     deque_handlers(pvar, message);
1562     }
1563     }
1564     }
1565     }
1566    
1567     static BOOL handle_pty_success(PTInstVar pvar)
1568     {
1569     FWD_enter_interactive_mode(pvar);
1570     enque_handler(pvar, SSH_SMSG_EXITSTATUS, handle_exit);
1571     enque_handler(pvar, SSH_SMSG_STDOUT_DATA, handle_data);
1572     enque_handler(pvar, SSH_SMSG_STDERR_DATA, handle_data);
1573     enque_handler(pvar, SSH_MSG_CHANNEL_DATA, handle_channel_data);
1574     enque_handler(pvar, SSH_MSG_CHANNEL_INPUT_EOF,
1575     handle_channel_input_eof);
1576     enque_handler(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED,
1577     handle_channel_output_eof);
1578     enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open);
1579     enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open);
1580     return FALSE;
1581     }
1582    
1583     static BOOL handle_pty_failure(PTInstVar pvar)
1584     {
1585     notify_nonfatal_error(pvar,
1586     "The server cannot allocate a pseudo-terminal. "
1587     "You may encounter some problems with the terminal.");
1588     return handle_pty_success(pvar);
1589     }
1590    
1591     static void prep_pty(PTInstVar pvar)
1592     {
1593     int len = strlen(pvar->ts->TermType);
1594     unsigned char FAR *outmsg =
1595     begin_send_packet(pvar, SSH_CMSG_REQUEST_PTY,
1596     4 + len + 16 + sizeof(ssh_ttymodes));
1597     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1598     static const SSHPacketHandler handlers[]
1599     = { handle_pty_success, handle_pty_failure };
1600    
1601     set_uint32(outmsg, len);
1602     memcpy(outmsg + 4, pvar->ts->TermType, len);
1603     set_uint32(outmsg + 4 + len, pvar->ssh_state.win_rows);
1604     set_uint32(outmsg + 4 + len + 4, pvar->ssh_state.win_cols);
1605     set_uint32(outmsg + 4 + len + 8, 0);
1606     set_uint32(outmsg + 4 + len + 12, 0);
1607     memcpy(outmsg + 4 + len + 16, ssh_ttymodes, sizeof(ssh_ttymodes));
1608     finish_send_packet(pvar);
1609    
1610     enque_handlers(pvar, 2, msgs, handlers);
1611    
1612     begin_send_packet(pvar, SSH_CMSG_EXEC_SHELL, 0);
1613     finish_send_packet(pvar);
1614     }
1615    
1616     static void prep_forwarding(PTInstVar pvar)
1617     {
1618     FWD_prep_forwarding(pvar);
1619     prep_pty(pvar);
1620     }
1621    
1622     static void enable_compression(PTInstVar pvar)
1623     {
1624     pvar->ssh_state.compress_stream.zalloc = NULL;
1625     pvar->ssh_state.compress_stream.zfree = NULL;
1626     pvar->ssh_state.compress_stream.opaque = NULL;
1627     if (deflateInit
1628     (&pvar->ssh_state.compress_stream,
1629     pvar->ssh_state.compression_level) != Z_OK) {
1630     notify_fatal_error(pvar,
1631     "An error occurred while setting up compression.\n"
1632     "The connection will close.");
1633     return;
1634     } else {
1635     pvar->ssh_state.compressing = TRUE;
1636     }
1637    
1638     pvar->ssh_state.decompress_stream.zalloc = NULL;
1639     pvar->ssh_state.decompress_stream.zfree = NULL;
1640     pvar->ssh_state.decompress_stream.opaque = NULL;
1641     if (inflateInit(&pvar->ssh_state.decompress_stream) != Z_OK) {
1642     deflateEnd(&pvar->ssh_state.compress_stream);
1643     notify_fatal_error(pvar,
1644     "An error occurred while setting up compression.\n"
1645     "The connection will close.");
1646     return;
1647     } else {
1648     pvar->ssh_state.decompressing = TRUE;
1649     buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf,
1650     &pvar->ssh_state.postdecompress_inbuflen, 1000);
1651     }
1652     }
1653    
1654     static BOOL handle_enable_compression(PTInstVar pvar)
1655     {
1656     enable_compression(pvar);
1657     prep_forwarding(pvar);
1658     return FALSE;
1659     }
1660    
1661     static BOOL handle_disable_compression(PTInstVar pvar)
1662     {
1663     prep_forwarding(pvar);
1664     return FALSE;
1665     }
1666    
1667     static void prep_compression(PTInstVar pvar)
1668     {
1669     if (pvar->session_settings.CompressionLevel > 0) {
1670     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1671     static const SSHPacketHandler handlers[]
1672     = { handle_enable_compression, handle_disable_compression };
1673    
1674     unsigned char FAR *outmsg =
1675     begin_send_packet(pvar, SSH_CMSG_REQUEST_COMPRESSION, 4);
1676    
1677     set_uint32(outmsg, pvar->session_settings.CompressionLevel);
1678     finish_send_packet(pvar);
1679    
1680     pvar->ssh_state.compression_level =
1681     pvar->session_settings.CompressionLevel;
1682    
1683     enque_handlers(pvar, 2, msgs, handlers);
1684     } else {
1685     prep_forwarding(pvar);
1686     }
1687     }
1688    
1689     static void enque_simple_auth_handlers(PTInstVar pvar)
1690     {
1691     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1692     static const SSHPacketHandler handlers[]
1693     = { handle_auth_success, handle_auth_failure };
1694    
1695     enque_handlers(pvar, 2, msgs, handlers);
1696     }
1697    
1698     static BOOL handle_rsa_challenge(PTInstVar pvar)
1699     {
1700     int challenge_bytes;
1701    
1702     if (!grab_payload(pvar, 2)) {
1703     return FALSE;
1704     }
1705    
1706     challenge_bytes = get_mpint_len(pvar, 0);
1707    
1708     if (grab_payload(pvar, challenge_bytes)) {
1709     unsigned char FAR *outmsg =
1710     begin_send_packet(pvar, SSH_CMSG_AUTH_RSA_RESPONSE, 16);
1711    
1712     if (CRYPT_generate_RSA_challenge_response
1713     (pvar, pvar->ssh_state.payload + 2, challenge_bytes, outmsg)) {
1714     AUTH_destroy_cur_cred(pvar);
1715     finish_send_packet(pvar);
1716    
1717     enque_simple_auth_handlers(pvar);
1718     } else {
1719     notify_fatal_error(pvar,
1720     "An error occurred while decrypting the RSA challenge.\n"
1721     "Perhaps the key file is corrupted.");
1722     }
1723     }
1724    
1725     return FALSE;
1726     }
1727    
1728     #define OBFUSCATING_ROUND_TO 32
1729    
1730     static int obfuscating_round_up(PTInstVar pvar, int size)
1731     {
1732     return (size + OBFUSCATING_ROUND_TO - 1) & ~(OBFUSCATING_ROUND_TO - 1);
1733     }
1734    
1735     static void try_send_credentials(PTInstVar pvar)
1736     {
1737     if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_CREDENTIALS) == 0) {
1738     AUTHCred FAR *cred = AUTH_get_cur_cred(pvar);
1739     static const int RSA_msgs[] =
1740     { SSH_SMSG_AUTH_RSA_CHALLENGE, SSH_SMSG_FAILURE };
1741     static const SSHPacketHandler RSA_handlers[]
1742     = { handle_rsa_challenge, handle_rsa_auth_refused };
1743     static const int TIS_msgs[] =
1744     { SSH_SMSG_AUTH_TIS_CHALLENGE, SSH_SMSG_FAILURE };
1745     static const SSHPacketHandler TIS_handlers[]
1746     = { handle_TIS_challenge, handle_auth_failure };
1747    
1748     switch (cred->method) {
1749     case SSH_AUTH_NONE:
1750     return;
1751     case SSH_AUTH_PASSWORD:{
1752     int len = strlen(cred->password);
1753     // Round up password length to discourage traffic analysis
1754     int obfuscated_len = obfuscating_round_up(pvar, len);
1755     unsigned char FAR *outmsg =
1756     begin_send_packet(pvar, SSH_CMSG_AUTH_PASSWORD,
1757     4 + obfuscated_len);
1758    
1759     notify_verbose_message(pvar,
1760     "Trying PASSWORD authentication...",
1761     LOG_LEVEL_VERBOSE);
1762    
1763     set_uint32(outmsg, obfuscated_len);
1764     memcpy(outmsg + 4, cred->password, len);
1765     memset(outmsg + 4 + len, 0, obfuscated_len - len);
1766     AUTH_destroy_cur_cred(pvar);
1767     enque_simple_auth_handlers(pvar);
1768     break;
1769     }
1770     case SSH_AUTH_RHOSTS:{
1771     int len = strlen(cred->rhosts_client_user);
1772     unsigned char FAR *outmsg =
1773     begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS, 4 + len);
1774    
1775     notify_verbose_message(pvar,
1776     "Trying RHOSTS authentication...",
1777     LOG_LEVEL_VERBOSE);
1778    
1779     set_uint32(outmsg, len);
1780     memcpy(outmsg + 4, cred->rhosts_client_user, len);
1781     AUTH_destroy_cur_cred(pvar);
1782     enque_simple_auth_handlers(pvar);
1783     break;
1784     }
1785     case SSH_AUTH_RSA:{
1786     int len = BN_num_bytes(cred->key_pair->RSA_key->n);
1787     unsigned char FAR *outmsg =
1788     begin_send_packet(pvar, SSH_CMSG_AUTH_RSA, 2 + len);
1789    
1790     notify_verbose_message(pvar,
1791     "Trying RSA authentication...",
1792     LOG_LEVEL_VERBOSE);
1793    
1794     set_ushort16_MSBfirst(outmsg, len * 8);
1795     BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + 2);
1796     /* don't destroy the current credentials yet */
1797     enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
1798     break;
1799     }
1800     case SSH_AUTH_RHOSTS_RSA:{
1801     int mod_len = BN_num_bytes(cred->key_pair->RSA_key->n);
1802     int name_len = strlen(cred->rhosts_client_user);
1803     int exp_len = BN_num_bytes(cred->key_pair->RSA_key->e);
1804     int index;
1805     unsigned char FAR *outmsg =
1806     begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS_RSA,
1807     12 + mod_len + name_len + exp_len);
1808    
1809     notify_verbose_message(pvar,
1810     "Trying RHOSTS+RSA authentication...",
1811     LOG_LEVEL_VERBOSE);
1812    
1813     set_uint32(outmsg, name_len);
1814     memcpy(outmsg + 4, cred->rhosts_client_user, name_len);
1815     index = 4 + name_len;
1816    
1817     set_uint32(outmsg + index, 8 * mod_len);
1818     set_ushort16_MSBfirst(outmsg + index + 4, 8 * exp_len);
1819     BN_bn2bin(cred->key_pair->RSA_key->e, outmsg + index + 6);
1820     index += 6 + exp_len;
1821    
1822     set_ushort16_MSBfirst(outmsg + index, 8 * mod_len);
1823     BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + index + 2);
1824     /* don't destroy the current credentials yet */
1825     enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
1826     break;
1827     }
1828     case SSH_AUTH_TIS:{
1829     if (cred->password == NULL) {
1830     unsigned char FAR *outmsg =
1831     begin_send_packet(pvar, SSH_CMSG_AUTH_TIS, 0);
1832    
1833     notify_verbose_message(pvar,
1834     "Trying TIS authentication...",
1835     LOG_LEVEL_VERBOSE);
1836     enque_handlers(pvar, 2, TIS_msgs, TIS_handlers);
1837     } else {
1838     int len = strlen(cred->password);
1839     int obfuscated_len = obfuscating_round_up(pvar, len);
1840     unsigned char FAR *outmsg =
1841     begin_send_packet(pvar, SSH_CMSG_AUTH_TIS_RESPONSE,
1842     4 + obfuscated_len);
1843    
1844     notify_verbose_message(pvar, "Sending TIS response",
1845     LOG_LEVEL_VERBOSE);
1846    
1847     set_uint32(outmsg, obfuscated_len);
1848     memcpy(outmsg + 4, cred->password, len);
1849     memset(outmsg + 4 + len, 0, obfuscated_len - len);
1850     enque_simple_auth_handlers(pvar);
1851     }
1852     AUTH_destroy_cur_cred(pvar);
1853     break;
1854     }
1855     default:
1856     notify_fatal_error(pvar,
1857     "Internal error: unsupported authentication method");
1858     return;
1859     }
1860    
1861     finish_send_packet(pvar);
1862     destroy_packet_buf(pvar);
1863    
1864     pvar->ssh_state.status_flags |= STATUS_DONT_SEND_CREDENTIALS;
1865     }
1866     }
1867    
1868     static void try_send_user_name(PTInstVar pvar)
1869     {
1870     if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_USER_NAME) == 0) {
1871     char FAR *username = AUTH_get_user_name(pvar);
1872    
1873     if (username != NULL) {
1874     int len = strlen(username);
1875     int obfuscated_len = obfuscating_round_up(pvar, len);
1876     unsigned char FAR *outmsg =
1877     begin_send_packet(pvar, SSH_CMSG_USER, 4 + obfuscated_len);
1878     char buf[1024] = "Sending user name: ";
1879     static const int msgs[] =
1880     { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1881     static const SSHPacketHandler handlers[]
1882     = { handle_noauth_success, handle_auth_required };
1883    
1884     set_uint32(outmsg, obfuscated_len);
1885     memcpy(outmsg + 4, username, len);
1886     memset(outmsg + 4 + len, 0, obfuscated_len - len);
1887     finish_send_packet(pvar);
1888    
1889     pvar->ssh_state.status_flags |= STATUS_DONT_SEND_USER_NAME;
1890    
1891     strncpy(buf + strlen(buf), username,
1892     sizeof(buf) - strlen(buf) - 2);
1893     buf[sizeof(buf) - 1] = 0;
1894     notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
1895    
1896     enque_handlers(pvar, 2, msgs, handlers);
1897     }
1898     }
1899     }
1900    
1901     static void send_session_key(PTInstVar pvar)
1902     {
1903     int encrypted_session_key_len;
1904     unsigned char FAR *outmsg;
1905    
1906     if (SSHv1(pvar)) {
1907     encrypted_session_key_len =
1908     CRYPT_get_encrypted_session_key_len(pvar);
1909     }
1910    
1911     if (!CRYPT_choose_ciphers(pvar))
1912     return;
1913    
1914     if (SSHv1(pvar)) {
1915     outmsg =
1916     begin_send_packet(pvar, SSH_CMSG_SESSION_KEY,
1917     15 + encrypted_session_key_len);
1918     outmsg[0] = (unsigned char) CRYPT_get_sender_cipher(pvar);
1919     memcpy(outmsg + 1, CRYPT_get_server_cookie(pvar), 8); /* antispoofing cookie */
1920     outmsg[9] = (unsigned char) (encrypted_session_key_len >> 5);
1921     outmsg[10] = (unsigned char) (encrypted_session_key_len << 3);
1922     if (!CRYPT_choose_session_key(pvar, outmsg + 11))
1923     return;
1924     set_uint32(outmsg + 11 + encrypted_session_key_len,
1925     SSH_PROTOFLAG_SCREEN_NUMBER |
1926     SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
1927     finish_send_packet(pvar);
1928     }
1929    
1930     if (!CRYPT_start_encryption(pvar, 1, 1))
1931     return;
1932     notify_established_secure_connection(pvar);
1933    
1934     if (SSHv1(pvar)) {
1935     enque_handler(pvar, SSH_SMSG_SUCCESS, handle_crypt_success);
1936     }
1937    
1938     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_USER_NAME;
1939    
1940     if (SSHv1(pvar)) {
1941     try_send_user_name(pvar);
1942     }
1943     }
1944    
1945     /*************************
1946     END of message handlers
1947     ************************/
1948    
1949     void SSH_init(PTInstVar pvar)
1950     {
1951     int i;
1952    
1953     buf_create(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
1954     buf_create(&pvar->ssh_state.precompress_outbuf,
1955     &pvar->ssh_state.precompress_outbuflen);
1956     buf_create(&pvar->ssh_state.postdecompress_inbuf,
1957     &pvar->ssh_state.postdecompress_inbuflen);
1958     pvar->ssh_state.payload = NULL;
1959     pvar->ssh_state.compressing = FALSE;
1960     pvar->ssh_state.decompressing = FALSE;
1961     pvar->ssh_state.status_flags =
1962     STATUS_DONT_SEND_USER_NAME | STATUS_DONT_SEND_CREDENTIALS;
1963     pvar->ssh_state.payload_datalen = 0;
1964     pvar->ssh_state.hostname = NULL;
1965     pvar->ssh_state.server_ID = NULL;
1966     pvar->ssh_state.receiver_sequence_number = 0;
1967     pvar->ssh_state.sender_sequence_number = 0;
1968     for (i = 0; i < NUM_ELEM(pvar->ssh_state.packet_handlers); i++) {
1969     pvar->ssh_state.packet_handlers[i] = NULL;
1970     }
1971    
1972     // for SSH2(yutaka)
1973     memset(pvar->ssh2_keys, 0, sizeof(pvar->ssh2_keys));
1974     pvar->userauth_success = 0;
1975     pvar->session_nego_status = 0;
1976 yutakakn 2738 pvar->settings.ssh_protocol_version = 2; // SSH2(default)
1977 yutakakn 2728 pvar->rekeying = 0;
1978     pvar->key_done = 0;
1979 yutakakn 2739 pvar->ssh2_autologin = 0; // autologin disabled(default)
1980 yutakakn 2728
1981     }
1982    
1983     void SSH_open(PTInstVar pvar)
1984     {
1985     pvar->ssh_state.hostname = _strdup(pvar->ts->HostName);
1986     pvar->ssh_state.win_cols = pvar->ts->TerminalWidth;
1987     pvar->ssh_state.win_rows = pvar->ts->TerminalHeight;
1988     }
1989    
1990     void SSH_notify_disconnecting(PTInstVar pvar, char FAR * reason)
1991     {
1992     if (SSHv1(pvar)) {
1993     int len = reason == NULL ? 0 : strlen(reason);
1994     unsigned char FAR *outmsg =
1995     begin_send_packet(pvar, SSH_MSG_DISCONNECT, len + 4);
1996    
1997     set_uint32(outmsg, len);
1998     if (reason != NULL) {
1999     memcpy(outmsg + 4, reason, len);
2000     }
2001     finish_send_packet(pvar);
2002    
2003     } else { // for SSH2(yutaka)
2004     buffer_t *msg;
2005     unsigned char *outmsg;
2006     int len;
2007    
2008     // SSH2 server��channel close���`����
2009     msg = buffer_init();
2010     if (msg == NULL) {
2011     // TODO: error check
2012     return;
2013     }
2014     buffer_put_int(msg, pvar->remote_id);
2015    
2016     len = buffer_len(msg);
2017     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_CLOSE, len);
2018     memcpy(outmsg, buffer_ptr(msg), len);
2019     finish_send_packet(pvar);
2020     buffer_free(msg);
2021    
2022     }
2023    
2024     }
2025    
2026     void SSH_notify_host_OK(PTInstVar pvar)
2027     {
2028     if ((pvar->ssh_state.status_flags & STATUS_HOST_OK) == 0) {
2029     pvar->ssh_state.status_flags |= STATUS_HOST_OK;
2030     send_session_key(pvar);
2031     }
2032     }
2033    
2034     void SSH_notify_win_size(PTInstVar pvar, int cols, int rows)
2035     {
2036     pvar->ssh_state.win_cols = cols;
2037     pvar->ssh_state.win_rows = rows;
2038    
2039 yutakakn 2771 if (SSHv1(pvar)) {
2040     if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) == handle_data) {
2041     unsigned char FAR *outmsg =
2042     begin_send_packet(pvar, SSH_CMSG_WINDOW_SIZE, 16);
2043 yutakakn 2728
2044 yutakakn 2771 set_uint32(outmsg, rows);
2045     set_uint32(outmsg + 4, cols);
2046     set_uint32(outmsg + 8, 0);
2047     set_uint32(outmsg + 12, 0);
2048     finish_send_packet(pvar);
2049     }
2050    
2051 yutakakn 2777 } else if (SSHv2(pvar)) { // �^�[�~�i���T�C�Y���X���m������ (2005.1.4 yutaka)
2052     // SSH2�����������`�F�b�N���s���B(2005.1.5 yutaka)
2053 yutakakn 2771 buffer_t *msg;
2054     char *s;
2055     unsigned char *outmsg;
2056     int len;
2057    
2058     msg = buffer_init();
2059     if (msg == NULL) {
2060     // TODO: error check
2061     return;
2062     }
2063     buffer_put_int(msg, pvar->remote_id);
2064     s = "window-change";
2065     buffer_put_string(msg, s, strlen(s));
2066     buffer_put_char(msg, 0); // wantconfirm
2067     buffer_put_int(msg, pvar->ssh_state.win_cols); // columns
2068     buffer_put_int(msg, pvar->ssh_state.win_rows); // lines
2069     buffer_put_int(msg, 480); // XXX:
2070     buffer_put_int(msg, 640); // XXX:
2071     len = buffer_len(msg);
2072     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
2073     memcpy(outmsg, buffer_ptr(msg), len);
2074 yutakakn 2728 finish_send_packet(pvar);
2075 yutakakn 2771 buffer_free(msg);
2076    
2077 yutakakn 2777 } else {
2078     // SSH�����������������������B
2079    
2080 yutakakn 2728 }
2081 yutakakn 2777
2082 yutakakn 2728 }
2083    
2084     int SSH_get_min_packet_size(PTInstVar pvar)
2085     {
2086     if (SSHv1(pvar)) {
2087     return 12;
2088     } else {
2089     int block_size = CRYPT_get_decryption_block_size(pvar);
2090    
2091     return max(16, block_size);
2092     }
2093     }
2094    
2095     /* data is guaranteed to be at least SSH_get_min_packet_size bytes long
2096     at least 5 bytes must be decrypted */
2097     void SSH_predecrpyt_packet(PTInstVar pvar, char FAR * data)
2098     {
2099     if (SSHv2(pvar)) {
2100     CRYPT_decrypt(pvar, data, get_predecryption_amount(pvar));
2101     }
2102     }
2103    
2104     int SSH_get_clear_MAC_size(PTInstVar pvar)
2105     {
2106     if (SSHv1(pvar)) {
2107     return 0;
2108     } else {
2109     return CRYPT_get_receiver_MAC_size(pvar);
2110     }
2111     }
2112    
2113     void SSH_notify_user_name(PTInstVar pvar)
2114     {
2115     try_send_user_name(pvar);
2116     }
2117    
2118     void SSH_notify_cred(PTInstVar pvar)
2119     {
2120     try_send_credentials(pvar);
2121     }
2122    
2123     void SSH_send(PTInstVar pvar, unsigned char const FAR * buf, int buflen)
2124     {
2125     if (SSHv1(pvar)) {
2126     if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) != handle_data) {
2127     return;
2128     }
2129    
2130     while (buflen > 0) {
2131     int len =
2132     buflen >
2133     SSH_MAX_SEND_PACKET_SIZE ? SSH_MAX_SEND_PACKET_SIZE : buflen;
2134     unsigned char FAR *outmsg =
2135     begin_send_packet(pvar, SSH_CMSG_STDIN_DATA, 4 + len);
2136    
2137     set_uint32(outmsg, len);
2138    
2139     if (pvar->ssh_state.compressing) {
2140     buf_ensure_size(&pvar->ssh_state.outbuf,
2141     &pvar->ssh_state.outbuflen,
2142     len + (len >> 6) + 50);
2143     pvar->ssh_state.compress_stream.next_in =
2144     pvar->ssh_state.precompress_outbuf;
2145     pvar->ssh_state.compress_stream.avail_in = 5;
2146     pvar->ssh_state.compress_stream.next_out =
2147     pvar->ssh_state.outbuf + 12;
2148     pvar->ssh_state.compress_stream.avail_out =
2149     pvar->ssh_state.outbuflen - 12;
2150    
2151     if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) !=
2152     Z_OK) {
2153     notify_fatal_error(pvar, "Error compressing packet data");
2154     return;
2155     }
2156    
2157     pvar->ssh_state.compress_stream.next_in =
2158     (unsigned char FAR *) buf;
2159     pvar->ssh_state.compress_stream.avail_in = len;
2160    
2161     if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2162     Z_OK) {
2163     notify_fatal_error(pvar, "Error compressing packet data");
2164     return;
2165     }
2166     } else {
2167     memcpy(outmsg + 4, buf, len);
2168     }
2169    
2170     finish_send_packet_special(pvar, 1);
2171    
2172     buflen -= len;
2173     buf += len;
2174     }
2175    
2176     } else { // for SSH2(yutaka)
2177     buffer_t *msg;
2178     unsigned char *outmsg;
2179     int len;
2180    
2181     msg = buffer_init();
2182     if (msg == NULL) {
2183     // TODO: error check
2184     return;
2185     }
2186     buffer_put_int(msg, pvar->remote_id);
2187     buffer_put_string(msg, (char *)buf, buflen);
2188    
2189     len = buffer_len(msg);
2190     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len);
2191     memcpy(outmsg, buffer_ptr(msg), len);
2192     finish_send_packet(pvar);
2193     buffer_free(msg);
2194    
2195     // remote window size������
2196     pvar->remote_window -= len;
2197    
2198     }
2199    
2200     }
2201    
2202     int SSH_extract_payload(PTInstVar pvar, unsigned char FAR * dest, int len)
2203     {
2204     int num_bytes = pvar->ssh_state.payload_datalen;
2205    
2206     if (num_bytes > len) {
2207     num_bytes = len;
2208     }
2209    
2210     if (!pvar->ssh_state.decompressing) {
2211     memcpy(dest,
2212     pvar->ssh_state.payload + pvar->ssh_state.payload_datastart,
2213     num_bytes);
2214     pvar->ssh_state.payload_datastart += num_bytes;
2215     } else if (num_bytes > 0) {
2216     pvar->ssh_state.decompress_stream.next_out = dest;
2217     pvar->ssh_state.decompress_stream.avail_out = num_bytes;
2218    
2219     if (inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH) !=
2220     Z_OK) {
2221     notify_fatal_error(pvar,
2222     "Invalid compressed data in received packet");
2223     return 0;
2224     }
2225     }
2226    
2227     pvar->ssh_state.payload_datalen -= num_bytes;
2228    
2229     return num_bytes;
2230     }
2231    
2232     void SSH_get_compression_info(PTInstVar pvar, char FAR * dest, int len)
2233     {
2234     char buf[1024];
2235     char buf2[1024];
2236    
2237     if (pvar->ssh_state.compressing) {
2238     unsigned long total_in = pvar->ssh_state.compress_stream.total_in;
2239     unsigned long total_out =
2240     pvar->ssh_state.compress_stream.total_out;
2241    
2242     if (total_out > 0) {
2243     _snprintf(buf, sizeof(buf), "level %d; ratio %.1f (%ld:%ld)",
2244     pvar->ssh_state.compression_level,
2245     ((double) total_in) / total_out, total_in,
2246     total_out);
2247     } else {
2248     _snprintf(buf, sizeof(buf), "level %d",
2249     pvar->ssh_state.compression_level);
2250     }
2251     } else {
2252     strcpy(buf, "none");
2253     }
2254     buf[sizeof(buf) - 1] = 0;
2255    
2256     if (pvar->ssh_state.decompressing) {
2257     unsigned long total_in =
2258     pvar->ssh_state.decompress_stream.total_in;
2259     unsigned long total_out =
2260     pvar->ssh_state.decompress_stream.total_out;
2261    
2262     if (total_in > 0) {
2263     _snprintf(buf2, sizeof(buf2), "level %d; ratio %.1f (%ld:%ld)",
2264     pvar->ssh_state.compression_level,
2265     ((double) total_out) / total_in, total_out,
2266     total_in);
2267     } else {
2268     _snprintf(buf2, sizeof(buf2), "level %d",
2269     pvar->ssh_state.compression_level);
2270     }
2271     } else {
2272     strcpy(buf2, "none");
2273     }
2274     buf2[sizeof(buf2) - 1] = 0;
2275    
2276     _snprintf(dest, len, "Upstream %s; Downstream %s", buf, buf2);
2277     dest[len - 1] = 0;
2278     }
2279    
2280     void SSH_get_server_ID_info(PTInstVar pvar, char FAR * dest, int len)
2281     {
2282     strncpy(dest, pvar->ssh_state.server_ID == NULL ? "Unknown"
2283     : pvar->ssh_state.server_ID, len);
2284     dest[len - 1] = 0;
2285     }
2286    
2287     void SSH_get_protocol_version_info(PTInstVar pvar, char FAR * dest,
2288     int len)
2289     {
2290     if (pvar->protocol_major == 0) {
2291     strncpy(dest, "Unknown", len);
2292     } else {
2293     _snprintf(dest, len, "%d.%d", pvar->protocol_major,
2294     pvar->protocol_minor);
2295     }
2296     dest[len - 1] = 0;
2297     }
2298    
2299     void SSH_end(PTInstVar pvar)
2300     {
2301     int i;
2302    
2303     for (i = 0; i < 256; i++) {
2304     SSHPacketHandlerItem FAR *first_item =
2305     pvar->ssh_state.packet_handlers[i];
2306    
2307     if (first_item != NULL) {
2308     SSHPacketHandlerItem FAR *item = first_item;
2309    
2310     do {
2311     SSHPacketHandlerItem FAR *cur_item = item;
2312    
2313     item = item->next_for_message;
2314     free(cur_item);
2315     } while (item != first_item);
2316     }
2317     pvar->ssh_state.packet_handlers[i] = NULL;
2318     }
2319    
2320     free(pvar->ssh_state.hostname);
2321     pvar->ssh_state.hostname = NULL;
2322     free(pvar->ssh_state.server_ID);
2323     pvar->ssh_state.server_ID = NULL;
2324     buf_destroy(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2325     buf_destroy(&pvar->ssh_state.precompress_outbuf,
2326     &pvar->ssh_state.precompress_outbuflen);
2327     buf_destroy(&pvar->ssh_state.postdecompress_inbuf,
2328     &pvar->ssh_state.postdecompress_inbuflen);
2329    
2330     if (pvar->ssh_state.compressing) {
2331     deflateEnd(&pvar->ssh_state.compress_stream);
2332     pvar->ssh_state.compressing = FALSE;
2333     }
2334     if (pvar->ssh_state.decompressing) {
2335     inflateEnd(&pvar->ssh_state.decompress_stream);
2336     pvar->ssh_state.decompressing = FALSE;
2337     }
2338 yutakakn 2766
2339     #if 1
2340     // SSH2���f�[�^���������� (2004.12.27 yutaka)
2341     if (SSHv2(pvar)) {
2342     if (pvar->kexdh) {
2343     DH_free(pvar->kexdh);
2344     pvar->kexdh = NULL;
2345     }
2346     memset(pvar->server_version_string, 0, sizeof(pvar->server_version_string));
2347     memset(pvar->client_version_string, 0, sizeof(pvar->client_version_string));
2348    
2349     if (pvar->my_kex != NULL) {
2350     buffer_free(pvar->my_kex);
2351     pvar->my_kex = NULL;
2352     }
2353     if (pvar->peer_kex != NULL) {
2354     buffer_free(pvar->peer_kex);
2355     pvar->peer_kex = NULL;
2356     }
2357    
2358     pvar->we_need = 0;
2359     pvar->key_done = 0;
2360     pvar->rekeying = 0;
2361    
2362     if (pvar->session_id != NULL) {
2363     free(pvar->session_id);
2364     pvar->session_id = NULL;
2365     }
2366     pvar->session_id_len = 0;
2367    
2368     pvar->userauth_success = 0;
2369     pvar->remote_id = 0;
2370     pvar->session_nego_status = 0;
2371    
2372     pvar->ssh_heartbeat_tick = 0;
2373     }
2374     #endif
2375    
2376 yutakakn 2728 }
2377    
2378     /* support for port forwarding */
2379     void SSH_channel_send(PTInstVar pvar, uint32 remote_channel_num,
2380     unsigned char FAR * buf, int len)
2381     {
2382     unsigned char FAR *outmsg =
2383     begin_send_packet(pvar, SSH_MSG_CHANNEL_DATA, 8 + len);
2384    
2385     set_uint32(outmsg, remote_channel_num);
2386     set_uint32(outmsg + 4, len);
2387    
2388     if (pvar->ssh_state.compressing) {
2389     buf_ensure_size(&pvar->ssh_state.outbuf,
2390     &pvar->ssh_state.outbuflen, len + (len >> 6) + 50);
2391     pvar->ssh_state.compress_stream.next_in =
2392     pvar->ssh_state.precompress_outbuf;
2393     pvar->ssh_state.compress_stream.avail_in = 9;
2394     pvar->ssh_state.compress_stream.next_out =
2395     pvar->ssh_state.outbuf + 12;
2396     pvar->ssh_state.compress_stream.avail_out =
2397     pvar->ssh_state.outbuflen - 12;
2398    
2399     if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) != Z_OK) {
2400     notify_fatal_error(pvar, "Error compressing packet data");
2401     return;
2402     }
2403    
2404     pvar->ssh_state.compress_stream.next_in =
2405     (unsigned char FAR *) buf;
2406     pvar->ssh_state.compress_stream.avail_in = len;
2407    
2408     if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2409     Z_OK) {
2410     notify_fatal_error(pvar, "Error compressing packet data");
2411     return;
2412     }
2413     } else {
2414     memcpy(outmsg + 8, buf, len);
2415     }
2416    
2417     finish_send_packet_special(pvar, 1);
2418     }
2419    
2420     void SSH_fail_channel_open(PTInstVar pvar, uint32 remote_channel_num)
2421     {
2422     unsigned char FAR *outmsg =
2423     begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_FAILURE, 4);
2424    
2425     set_uint32(outmsg, remote_channel_num);
2426     finish_send_packet(pvar);
2427     }
2428    
2429     void SSH_confirm_channel_open(PTInstVar pvar, uint32 remote_channel_num,
2430     uint32 local_channel_num)
2431     {
2432     unsigned char FAR *outmsg =
2433     begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 8);
2434    
2435     set_uint32(outmsg, remote_channel_num);
2436     set_uint32(outmsg + 4, local_channel_num);
2437     finish_send_packet(pvar);
2438     }
2439    
2440     void SSH_channel_output_eof(PTInstVar pvar, uint32 remote_channel_num)
2441     {
2442     unsigned char FAR *outmsg =
2443     begin_send_packet(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4);
2444    
2445     set_uint32(outmsg, remote_channel_num);
2446     finish_send_packet(pvar);
2447     }
2448    
2449     void SSH_channel_input_eof(PTInstVar pvar, uint32 remote_channel_num)
2450     {
2451     unsigned char FAR *outmsg =
2452     begin_send_packet(pvar, SSH_MSG_CHANNEL_INPUT_EOF, 4);
2453    
2454     set_uint32(outmsg, remote_channel_num);
2455     finish_send_packet(pvar);
2456     }
2457    
2458     void SSH_request_forwarding(PTInstVar pvar, int from_server_port,
2459     char FAR * to_local_host, int to_local_port)
2460     {
2461     int host_len = strlen(to_local_host);
2462     unsigned char FAR *outmsg =
2463     begin_send_packet(pvar, SSH_CMSG_PORT_FORWARD_REQUEST,
2464     12 + host_len);
2465    
2466     set_uint32(outmsg, from_server_port);
2467     set_uint32(outmsg + 4, host_len);
2468     memcpy(outmsg + 8, to_local_host, host_len);
2469     set_uint32(outmsg + 8 + host_len, to_local_port);
2470     finish_send_packet(pvar);
2471    
2472     enque_forwarding_request_handlers(pvar);
2473     }
2474    
2475     void SSH_request_X11_forwarding(PTInstVar pvar,
2476     char FAR * auth_protocol,
2477     unsigned char FAR * auth_data,
2478     int auth_data_len, int screen_num)
2479     {
2480     int protocol_len = strlen(auth_protocol);
2481     int data_len = auth_data_len * 2;
2482     unsigned char FAR *outmsg =
2483     begin_send_packet(pvar, SSH_CMSG_X11_REQUEST_FORWARDING,
2484     12 + protocol_len + data_len);
2485     int i;
2486     char FAR *auth_data_ptr;
2487    
2488     set_uint32(outmsg, protocol_len);
2489     memcpy(outmsg + 4, auth_protocol, protocol_len);
2490     set_uint32(outmsg + 4 + protocol_len, data_len);
2491     auth_data_ptr = outmsg + 8 + protocol_len;
2492     for (i = 0; i < auth_data_len; i++) {
2493     sprintf(auth_data_ptr + i * 2, "%.2x", auth_data[i]);
2494     }
2495     set_uint32(outmsg + 8 + protocol_len + data_len, screen_num);
2496    
2497     finish_send_packet(pvar);
2498    
2499     enque_forwarding_request_handlers(pvar);
2500     }
2501    
2502     void SSH_open_channel(PTInstVar pvar, uint32 local_channel_num,
2503     char FAR * to_remote_host, int to_remote_port,
2504     char FAR * originator)
2505     {
2506     static const int msgs[]
2507     = { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, SSH_MSG_CHANNEL_OPEN_FAILURE };
2508     static const SSHPacketHandler handlers[]
2509     = { handle_channel_open_confirmation, handle_channel_open_failure };
2510    
2511     int host_len = strlen(to_remote_host);
2512    
2513     if ((pvar->ssh_state.
2514     server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
2515     int originator_len = strlen(originator);
2516     unsigned char FAR *outmsg =
2517     begin_send_packet(pvar, SSH_MSG_PORT_OPEN,
2518     16 + host_len + originator_len);
2519    
2520     set_uint32(outmsg, local_channel_num);
2521     set_uint32(outmsg + 4, host_len);
2522     memcpy(outmsg + 8, to_remote_host, host_len);
2523     set_uint32(outmsg + 8 + host_len, to_remote_port);
2524     set_uint32(outmsg + 12 + host_len, originator_len);
2525     memcpy(outmsg + 16