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 2729 - (hide annotations) (download) (as text)
Sun Nov 14 15:53:21 2004 UTC (19 years, 5 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 114026 byte(s)
This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches.

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