Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2777 - (show annotations) (download) (as text)
Thu Jan 6 12:29:07 2005 UTC (19 years, 3 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 129771 byte(s)
telnet接続時にターミナルサイズ変更を行うと、アプリケーションエラーとなるバグを修正。

1 /*
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 <openssl/rsa.h>
37 #include <openssl/dsa.h>
38 #include <limits.h>
39 #include <malloc.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <process.h>
43 #include "buffer.h"
44 #include "ssh.h"
45 #include "crypt.h"
46
47 #ifdef _DEBUG
48 #define SSH2_DEBUG
49 #endif
50
51 #define INTBLOB_LEN 20
52 #define SIGBLOB_LEN (2*INTBLOB_LEN)
53
54 static char ssh_ttymodes[] = "\x01\x03\x02\x1c\x03\x08\x04\x15\x05\x04";
55
56 static void try_send_credentials(PTInstVar pvar);
57 static void prep_compression(PTInstVar pvar);
58
59 // �����v���g�^�C�v����
60 void SSH2_send_kexinit(PTInstVar pvar);
61 static BOOL handle_SSH2_kexinit(PTInstVar pvar);
62 static void SSH2_dh_kex_init(PTInstVar pvar);
63 static void SSH2_dh_gex_kex_init(PTInstVar pvar);
64 static BOOL handle_SSH2_dh_common_reply(PTInstVar pvar);
65 static BOOL handle_SSH2_dh_gex_reply(PTInstVar pvar);
66 static BOOL handle_SSH2_newkeys(PTInstVar pvar);
67 static BOOL handle_SSH2_authrequest(PTInstVar pvar);
68 static BOOL handle_SSH2_userauth_success(PTInstVar pvar);
69 static BOOL handle_SSH2_userauth_failure(PTInstVar pvar);
70 static BOOL handle_SSH2_userauth_banner(PTInstVar pvar);
71 static BOOL handle_SSH2_open_confirm(PTInstVar pvar);
72 static BOOL handle_SSH2_request_success(PTInstVar pvar);
73 static BOOL handle_SSH2_channel_success(PTInstVar pvar);
74 static BOOL handle_SSH2_channel_data(PTInstVar pvar);
75 static BOOL handle_SSH2_channel_extended_data(PTInstVar pvar);
76 static BOOL handle_SSH2_channel_eof(PTInstVar pvar);
77 static BOOL handle_SSH2_channel_close(PTInstVar pvar);
78 static BOOL handle_SSH2_window_adjust(PTInstVar pvar);
79 static BOOL handle_SSH2_channel_request(PTInstVar pvar);
80 void SSH2_dispatch_init(int stage);
81 int SSH2_dispatch_enabled_check(unsigned char message);
82 void SSH2_dispatch_add_message(unsigned char message);
83 void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end);
84 int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
85 static void start_ssh_heartbeat_thread(PTInstVar pvar);
86
87
88 //
89 // SSH heartbeat mutex
90 //
91 static CRITICAL_SECTION g_ssh_heartbeat_lock; /* ���b�N�p���� */
92
93 void ssh_heartbeat_lock_initialize(void)
94 {
95 InitializeCriticalSection(&g_ssh_heartbeat_lock);
96 }
97
98 void ssh_heartbeat_lock_finalize(void)
99 {
100 DeleteCriticalSection(&g_ssh_heartbeat_lock);
101 }
102
103 void ssh_heartbeat_lock(void)
104 {
105 EnterCriticalSection(&g_ssh_heartbeat_lock);
106 }
107
108 void ssh_heartbeat_unlock(void)
109 {
110 LeaveCriticalSection(&g_ssh_heartbeat_lock);
111 }
112
113
114 static int get_predecryption_amount(PTInstVar pvar)
115 {
116 static int small_block_decryption_sizes[] = { 5, 5, 6, 6, 8 };
117
118 if (SSHv1(pvar)) {
119 return 0;
120 } else {
121 int block_size = CRYPT_get_decryption_block_size(pvar);
122
123 if (block_size < 5) {
124 return small_block_decryption_sizes[block_size];
125 } else {
126 return block_size;
127 }
128 }
129 }
130
131 /* Get up to 'limit' bytes into the payload buffer.
132 'limit' is counted from the start of the payload data.
133 Returns the amount of data in the payload buffer, or
134 -1 if there is an error.
135 We can return more than limit in some cases. */
136 static int buffer_packet_data(PTInstVar pvar, int limit)
137 {
138 if (pvar->ssh_state.payloadlen >= 0) {
139 return pvar->ssh_state.payloadlen;
140 } else {
141 int cur_decompressed_bytes =
142 pvar->ssh_state.decompress_stream.next_out -
143 pvar->ssh_state.postdecompress_inbuf;
144
145 while (limit > cur_decompressed_bytes) {
146 int result;
147
148 pvar->ssh_state.payload =
149 pvar->ssh_state.postdecompress_inbuf + 1;
150 if (pvar->ssh_state.postdecompress_inbuflen ==
151 cur_decompressed_bytes) {
152 buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf,
153 &pvar->ssh_state.postdecompress_inbuflen,
154 min(limit, cur_decompressed_bytes * 2));
155 }
156
157 pvar->ssh_state.decompress_stream.next_out
158 =
159 pvar->ssh_state.postdecompress_inbuf +
160 cur_decompressed_bytes;
161 pvar->ssh_state.decompress_stream.avail_out =
162 min(limit, pvar->ssh_state.postdecompress_inbuflen)
163 - cur_decompressed_bytes;
164
165 result =
166 inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH);
167 cur_decompressed_bytes =
168 pvar->ssh_state.decompress_stream.next_out -
169 pvar->ssh_state.postdecompress_inbuf;
170
171 switch (result) {
172 case Z_OK:
173 break;
174 case Z_BUF_ERROR:
175 pvar->ssh_state.payloadlen = cur_decompressed_bytes;
176 return cur_decompressed_bytes;
177 default:
178 notify_fatal_error(pvar,
179 "Invalid compressed data in received packet");
180 return -1;
181 }
182 }
183
184 return cur_decompressed_bytes;
185 }
186 }
187
188 /* For use by the protocol processing code.
189 Gets N bytes of uncompressed payload. Returns FALSE if data not available
190 and a fatal error has been signaled.
191 The data is available in the payload buffer. This buffer address
192 can change during a call to grab_payload, so take care!
193 The payload pointer is set to point to the first byte of the actual data
194 (after the packet type byte).
195 */
196 static BOOL grab_payload(PTInstVar pvar, int num_bytes)
197 {
198 /* Accept maximum of 4MB of payload data */
199 int in_buffer = buffer_packet_data(pvar, 4 * 1024 * 1024);
200
201 if (in_buffer < 0) {
202 return FALSE;
203 } else {
204 pvar->ssh_state.payload_grabbed += num_bytes;
205 if (pvar->ssh_state.payload_grabbed > in_buffer) {
206 notify_fatal_error(pvar, "Received truncated packet");
207 return FALSE;
208 } else {
209 return TRUE;
210 }
211 }
212 }
213
214 static BOOL grab_payload_limited(PTInstVar pvar, int num_bytes)
215 {
216 int in_buffer;
217
218 pvar->ssh_state.payload_grabbed += num_bytes;
219 in_buffer = buffer_packet_data(pvar, pvar->ssh_state.payload_grabbed);
220
221 if (in_buffer < 0) {
222 return FALSE;
223 } else {
224 if (pvar->ssh_state.payload_grabbed > in_buffer) {
225 notify_fatal_error(pvar, "Received truncated packet");
226 return FALSE;
227 } else {
228 return TRUE;
229 }
230 }
231 }
232
233 #define get_payload_uint32(pvar, offset) get_uint32_MSBfirst((pvar)->ssh_state.payload + (offset))
234 #define get_uint32(buf) get_uint32_MSBfirst((buf))
235 #define set_uint32(buf, v) set_uint32_MSBfirst((buf), (v))
236 #define get_mpint_len(pvar, offset) ((get_ushort16_MSBfirst((pvar)->ssh_state.payload + (offset)) + 7) >> 3)
237 #define get_ushort16(buf) get_ushort16_MSBfirst((buf))
238
239 #define do_crc(buf, len) (~(uint32)crc32(0xFFFFFFFF, (buf), (len)))
240
241 /* Decrypt the payload, checksum it, eat the padding, get the packet type
242 and return it.
243 'data' points to the start of the packet --- its length field.
244 'len' is the length of the
245 payload + padding (+ length of CRC for SSHv1). 'padding' is the length
246 of the padding alone. */
247 static int prep_packet(PTInstVar pvar, char FAR * data, int len,
248 int padding)
249 {
250 pvar->ssh_state.payload = data + 4;
251 pvar->ssh_state.payloadlen = len;
252
253 if (SSHv1(pvar)) {
254 if (CRYPT_detect_attack(pvar, pvar->ssh_state.payload, len)) {
255 notify_fatal_error(pvar,
256 "'CORE insertion attack' detected. Aborting connection.");
257 return SSH_MSG_NONE;
258 }
259
260 CRYPT_decrypt(pvar, pvar->ssh_state.payload, len);
261 /* PKT guarantees that the data is always 4-byte aligned */
262 if (do_crc(pvar->ssh_state.payload, len - 4) !=
263 get_uint32_MSBfirst(pvar->ssh_state.payload + len - 4)) {
264 notify_fatal_error(pvar,
265 "Detected corrupted data; connection terminating.");
266 return SSH_MSG_NONE;
267 }
268
269 pvar->ssh_state.payload += padding;
270 pvar->ssh_state.payloadlen -= padding + 4;
271 } else {
272 int already_decrypted = get_predecryption_amount(pvar);
273
274 #if 0
275 CRYPT_decrypt(pvar, data + already_decrypted,
276 len - already_decrypted);
277 #else
278 CRYPT_decrypt(pvar, data + already_decrypted,
279 (4 + len) - already_decrypted);
280 #endif
281
282 if (!CRYPT_verify_receiver_MAC
283 (pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4,
284 data + len + 4)) {
285 notify_fatal_error(pvar,
286 "Detected corrupted data; connection terminating.");
287 return SSH_MSG_NONE;
288 }
289
290 pvar->ssh_state.payload++;
291 pvar->ssh_state.payloadlen -= padding + 1;
292 }
293
294 pvar->ssh_state.payload_grabbed = 0;
295
296 if (pvar->ssh_state.decompressing) {
297 if (pvar->ssh_state.decompress_stream.avail_in != 0) {
298 notify_nonfatal_error(pvar,
299 "Internal error: a packet was not fully decompressed.\n"
300 "This is a bug, please report it.");
301 }
302
303 pvar->ssh_state.decompress_stream.next_in =
304 pvar->ssh_state.payload;
305 pvar->ssh_state.decompress_stream.avail_in =
306 pvar->ssh_state.payloadlen;
307 pvar->ssh_state.decompress_stream.next_out =
308 pvar->ssh_state.postdecompress_inbuf;
309 pvar->ssh_state.payloadlen = -1;
310 } else {
311 pvar->ssh_state.payload++;
312 }
313
314 if (!grab_payload_limited(pvar, 1)) {
315 return SSH_MSG_NONE;
316 }
317
318 pvar->ssh_state.receiver_sequence_number++;
319
320 return pvar->ssh_state.payload[-1];
321 }
322
323 /* Create a packet to be sent. The SSH protocol packet type is in 'type';
324 'len' contains the length of the packet payload, in bytes (this
325 does not include the space for any of the packet headers or padding,
326 or for the packet type byte).
327 Returns a pointer to the payload data area, a region of length 'len',
328 to be filled by the caller. */
329 static unsigned char FAR *begin_send_packet(PTInstVar pvar, int type,
330 int len)
331 {
332 unsigned char FAR *buf;
333
334 pvar->ssh_state.outgoing_packet_len = len + 1;
335
336 if (pvar->ssh_state.compressing) {
337 buf_ensure_size(&pvar->ssh_state.precompress_outbuf,
338 &pvar->ssh_state.precompress_outbuflen, 1 + len);
339 buf = pvar->ssh_state.precompress_outbuf;
340 } else {
341 /* For SSHv2,
342 Encrypted_length is 4(packetlength) + 1(paddinglength) + 1(packettype)
343 + len(payload) + 4(minpadding), rounded up to nearest block_size
344 We only need a reasonable upper bound for the buffer size */
345 buf_ensure_size(&pvar->ssh_state.outbuf,
346 &pvar->ssh_state.outbuflen,
347 len + 30 + CRYPT_get_sender_MAC_size(pvar) +
348 CRYPT_get_encryption_block_size(pvar));
349 buf = pvar->ssh_state.outbuf + 12;
350 }
351
352 buf[0] = (unsigned char) type;
353 return buf + 1;
354 }
355
356 #define finish_send_packet(pvar) finish_send_packet_special((pvar), 0)
357
358 static BOOL send_packet_blocking(PTInstVar pvar, char FAR * data, int len)
359 {
360 u_long do_block = 0;
361
362 if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
363 0, 0) == SOCKET_ERROR
364 || ioctlsocket(pvar->socket, FIONBIO, &do_block) == SOCKET_ERROR
365 || (pvar->Psend) (pvar->socket, data, len, 0) != len
366 || (pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
367 pvar->notification_msg,
368 pvar->notification_events) ==
369 SOCKET_ERROR) {
370 notify_fatal_error(pvar,
371 "A communications error occurred while sending an SSH packet.\n"
372 "The connection will close.");
373 return FALSE;
374 } else {
375 return TRUE;
376 }
377 }
378
379 /* if skip_compress is true, then the data has already been compressed
380 into outbuf + 12 */
381 static void finish_send_packet_special(PTInstVar pvar, int skip_compress)
382 {
383 int len = pvar->ssh_state.outgoing_packet_len;
384 char FAR *data;
385 int data_length;
386
387 if (pvar->ssh_state.compressing) {
388 if (!skip_compress) {
389 buf_ensure_size(&pvar->ssh_state.outbuf,
390 &pvar->ssh_state.outbuflen,
391 len + (len >> 6) + 50 +
392 CRYPT_get_sender_MAC_size(pvar));
393 pvar->ssh_state.compress_stream.next_in =
394 pvar->ssh_state.precompress_outbuf;
395 pvar->ssh_state.compress_stream.avail_in = len;
396 pvar->ssh_state.compress_stream.next_out =
397 pvar->ssh_state.outbuf + 12;
398 pvar->ssh_state.compress_stream.avail_out =
399 pvar->ssh_state.outbuflen - 12;
400
401 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
402 Z_OK) {
403 notify_fatal_error(pvar,
404 "An error occurred while compressing packet data.\n"
405 "The connection will close.");
406 return;
407 }
408 }
409
410 len =
411 pvar->ssh_state.outbuflen - 12 -
412 pvar->ssh_state.compress_stream.avail_out;
413 }
414
415 if (SSHv1(pvar)) {
416 int padding = 8 - ((len + 4) % 8);
417
418 data = pvar->ssh_state.outbuf + 8 - padding;
419 data_length = padding + len + 8;
420
421 set_uint32(data, len + 4);
422 if (CRYPT_get_receiver_cipher(pvar) != SSH_CIPHER_NONE) {
423 CRYPT_set_random_data(pvar, data + 4, padding);
424 } else {
425 memset(data + 4, 0, padding);
426 }
427 set_uint32(data + data_length - 4,
428 do_crc(data + 4, data_length - 8));
429 CRYPT_encrypt(pvar, data + 4, data_length - 4);
430 } else { //for SSH2(yutaka)
431 int block_size = CRYPT_get_encryption_block_size(pvar);
432 int encryption_size;
433 int padding;
434 BOOL ret;
435
436 if (block_size < 8) {
437 block_size = 8;
438 }
439 encryption_size = ((len + 8) / block_size + 1) * block_size;
440 data = pvar->ssh_state.outbuf + 7;
441 data_length = encryption_size + CRYPT_get_sender_MAC_size(pvar);
442
443 set_uint32(data, encryption_size - 4);
444 padding = encryption_size - len - 5;
445 data[4] = (unsigned char) padding;
446 CRYPT_set_random_data(pvar, data + 5 + len, padding);
447 ret = CRYPT_build_sender_MAC(pvar,
448 pvar->ssh_state.sender_sequence_number,
449 data, encryption_size,
450 data + encryption_size);
451 if (ret == FALSE) { // HMAC��������������������������
452 data_length = encryption_size;
453 }
454
455 // �p�P�b�g�������������BHMAC���~�������������O�B
456 CRYPT_encrypt(pvar, data, encryption_size);
457 }
458
459 send_packet_blocking(pvar, data, data_length);
460
461 pvar->ssh_state.sender_sequence_number++;
462
463 // ���M�������L�^
464 pvar->ssh_heartbeat_tick = time(NULL);
465 }
466
467 static void destroy_packet_buf(PTInstVar pvar)
468 {
469 memset(pvar->ssh_state.outbuf, 0, pvar->ssh_state.outbuflen);
470 if (pvar->ssh_state.compressing) {
471 memset(pvar->ssh_state.precompress_outbuf, 0,
472 pvar->ssh_state.precompress_outbuflen);
473 }
474 }
475
476 /* The handlers are added to the queue for each message. When one of the
477 handlers fires, if it returns FALSE, then all handlers in the set are
478 removed from their queues. */
479 static void enque_handlers(PTInstVar pvar, int num_msgs,
480 const int FAR * messages,
481 const SSHPacketHandler FAR * handlers)
482 {
483 SSHPacketHandlerItem FAR *first_item;
484 SSHPacketHandlerItem FAR *last_item = NULL;
485 int i;
486
487 for (i = 0; i < num_msgs; i++) {
488 SSHPacketHandlerItem FAR *item =
489 (SSHPacketHandlerItem FAR *)
490 malloc(sizeof(SSHPacketHandlerItem));
491 SSHPacketHandlerItem FAR *cur_item =
492 pvar->ssh_state.packet_handlers[messages[i]];
493
494 item->handler = handlers[i];
495
496 if (cur_item == NULL) {
497 pvar->ssh_state.packet_handlers[messages[i]] = item;
498 item->next_for_message = item;
499 item->last_for_message = item;
500 item->active_for_message = messages[i];
501 } else {
502 item->next_for_message = cur_item;
503 item->last_for_message = cur_item->last_for_message;
504 cur_item->last_for_message->next_for_message = item;
505 cur_item->last_for_message = item;
506 item->active_for_message = -1;
507 }
508
509 if (last_item != NULL) {
510 last_item->next_in_set = item;
511 } else {
512 first_item = item;
513 }
514 last_item = item;
515 }
516
517 if (last_item != NULL) {
518 last_item->next_in_set = first_item;
519 }
520 }
521
522 static SSHPacketHandler get_handler(PTInstVar pvar, int message)
523 {
524 SSHPacketHandlerItem FAR *cur_item =
525 pvar->ssh_state.packet_handlers[message];
526
527 if (cur_item == NULL) {
528 return NULL;
529 } else {
530 return cur_item->handler;
531 }
532 }
533
534 /* Called only by SSH_handle_packet */
535 static void deque_handlers(PTInstVar pvar, int message)
536 {
537 SSHPacketHandlerItem FAR *cur_item =
538 pvar->ssh_state.packet_handlers[message];
539 SSHPacketHandlerItem FAR *first_item_in_set = cur_item;
540
541 do {
542 SSHPacketHandlerItem FAR *next_in_set = cur_item->next_in_set;
543
544 if (cur_item->active_for_message >= 0) {
545 SSHPacketHandlerItem FAR *replacement =
546 cur_item->next_for_message;
547
548 if (replacement == cur_item) {
549 replacement = NULL;
550 } else {
551 replacement->active_for_message =
552 cur_item->active_for_message;
553 }
554 pvar->ssh_state.packet_handlers[cur_item->active_for_message] =
555 replacement;
556 }
557 cur_item->next_for_message->last_for_message =
558 cur_item->last_for_message;
559 cur_item->last_for_message->next_for_message =
560 cur_item->next_for_message;
561
562 free(cur_item);
563 cur_item = next_in_set;
564 } while (cur_item != first_item_in_set);
565 }
566
567 static void enque_handler(PTInstVar pvar, int message,
568 SSHPacketHandler handler)
569 {
570 enque_handlers(pvar, 1, &message, &handler);
571 }
572
573 static void chop_newlines(char FAR * buf)
574 {
575 int len = strlen(buf);
576
577 while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) {
578 buf[len - 1] = 0;
579 len--;
580 }
581 }
582
583 /********************/
584 /* Message handlers */
585 /********************/
586
587 static BOOL handle_forwarding_success(PTInstVar pvar)
588 {
589 return FALSE;
590 }
591
592 static BOOL handle_forwarding_failure(PTInstVar pvar)
593 {
594 return FALSE;
595 }
596
597 static void enque_forwarding_request_handlers(PTInstVar pvar)
598 {
599 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
600 static const SSHPacketHandler handlers[]
601 = { handle_forwarding_success, handle_forwarding_failure };
602
603 enque_handlers(pvar, 2, msgs, handlers);
604 }
605
606 static BOOL handle_auth_failure(PTInstVar pvar)
607 {
608 notify_verbose_message(pvar, "Authentication failed",
609 LOG_LEVEL_VERBOSE);
610
611 AUTH_set_generic_mode(pvar);
612 AUTH_advance_to_next_cred(pvar);
613 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
614 try_send_credentials(pvar);
615 return FALSE;
616 }
617
618 static BOOL handle_rsa_auth_refused(PTInstVar pvar)
619 {
620 AUTH_destroy_cur_cred(pvar);
621 return handle_auth_failure(pvar);
622 }
623
624 static BOOL handle_TIS_challenge(PTInstVar pvar)
625 {
626 if (grab_payload(pvar, 4)) {
627 int len = get_payload_uint32(pvar, 0);
628
629 if (grab_payload(pvar, len)) {
630 notify_verbose_message(pvar, "Received TIS challenge",
631 LOG_LEVEL_VERBOSE);
632
633 AUTH_set_TIS_mode(pvar, pvar->ssh_state.payload + 4, len);
634 AUTH_advance_to_next_cred(pvar);
635 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
636 try_send_credentials(pvar);
637 }
638 }
639 return FALSE;
640 }
641
642 static BOOL handle_auth_required(PTInstVar pvar)
643 {
644 notify_verbose_message(pvar, "Server requires authentication",
645 LOG_LEVEL_VERBOSE);
646
647 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
648 try_send_credentials(pvar);
649 /* the first AUTH_advance_to_next_cred is issued early by ttxssh.c */
650
651 return FALSE;
652 }
653
654 static BOOL handle_ignore(PTInstVar pvar)
655 {
656 if (grab_payload(pvar, 4)
657 && grab_payload(pvar, get_payload_uint32(pvar, 0))) {
658 /* ignore it! but it must be decompressed */
659 }
660 return TRUE;
661 }
662
663 static BOOL handle_debug(PTInstVar pvar)
664 {
665 BOOL always_display;
666 char FAR *description;
667 int description_len;
668 char buf[2048];
669
670 if (SSHv1(pvar)) {
671 if (grab_payload(pvar, 4)
672 && grab_payload(pvar, description_len =
673 get_payload_uint32(pvar, 0))) {
674 always_display = FALSE;
675 description = pvar->ssh_state.payload + 4;
676 description[description_len] = 0;
677 } else {
678 return TRUE;
679 }
680 } else {
681 if (grab_payload(pvar, 5)
682 && grab_payload(pvar,
683 (description_len =
684 get_payload_uint32(pvar, 1)) + 4)
685 && grab_payload(pvar,
686 get_payload_uint32(pvar,
687 5 + description_len))) {
688 always_display = pvar->ssh_state.payload[0] != 0;
689 description = pvar->ssh_state.payload + 5;
690 description[description_len] = 0;
691 } else {
692 return TRUE;
693 }
694 }
695
696 chop_newlines(description);
697 _snprintf(buf, sizeof(buf), "DEBUG message from server: %s",
698 description);
699 buf[sizeof(buf) - 1] = 0;
700 if (always_display) {
701 notify_nonfatal_error(pvar, buf);
702 } else {
703 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
704 }
705 return TRUE;
706 }
707
708 static BOOL handle_disconnect(PTInstVar pvar)
709 {
710 int reason_code;
711 char FAR *description;
712 int description_len;
713 char buf[2048];
714 char FAR *explanation = "";
715
716 if (SSHv1(pvar)) {
717 if (grab_payload(pvar, 4)
718 && grab_payload(pvar, description_len =
719 get_payload_uint32(pvar, 0))) {
720 reason_code = -1;
721 description = pvar->ssh_state.payload + 4;
722 description[description_len] = 0;
723 } else {
724 return TRUE;
725 }
726 } else {
727 if (grab_payload(pvar, 8)
728 && grab_payload(pvar,
729 (description_len =
730 get_payload_uint32(pvar, 4)) + 4)
731 && grab_payload(pvar,
732 get_payload_uint32(pvar,
733 8 + description_len))) {
734 reason_code = get_payload_uint32(pvar, 0);
735 description = pvar->ssh_state.payload + 8;
736 description[description_len] = 0;
737 } else {
738 return TRUE;
739 }
740 }
741
742 chop_newlines(description);
743 if (description[0] == 0) {
744 description = NULL;
745 }
746
747 if (get_handler(pvar, SSH_SMSG_FAILURE) == handle_forwarding_failure) {
748 explanation =
749 "\nIt may have disconnected because it was unable to forward a port you requested to be forwarded from the server.\n"
750 "This often happens when someone is already forwarding that port from the server.";
751 }
752
753 if (description != NULL) {
754 _snprintf(buf, sizeof(buf),
755 "Server disconnected with message '%s'.%s", description,
756 explanation);
757 } else {
758 _snprintf(buf, sizeof(buf),
759 "Server disconnected (no reason given).%s", explanation);
760 }
761 buf[sizeof(buf) - 1] = 0;
762 notify_fatal_error(pvar, buf);
763
764 return TRUE;
765 }
766
767 static BOOL handle_unimplemented(PTInstVar pvar)
768 {
769 /* Should never receive this since we only send base 2.0 protocol messages */
770 grab_payload(pvar, 4);
771 return TRUE;
772 }
773
774 static BOOL handle_crypt_success(PTInstVar pvar)
775 {
776 notify_verbose_message(pvar, "Secure mode successfully achieved",
777 LOG_LEVEL_VERBOSE);
778 return FALSE;
779 }
780
781 static BOOL handle_noauth_success(PTInstVar pvar)
782 {
783 notify_verbose_message(pvar, "Server does not require authentication",
784 LOG_LEVEL_VERBOSE);
785 prep_compression(pvar);
786 return FALSE;
787 }
788
789 static BOOL handle_auth_success(PTInstVar pvar)
790 {
791 notify_verbose_message(pvar, "Authentication accepted",
792 LOG_LEVEL_VERBOSE);
793 prep_compression(pvar);
794
795 // �n�[�g�r�[�g�E�X���b�h���J�n (2004.12.11 yutaka)
796 start_ssh_heartbeat_thread(pvar);
797
798 return FALSE;
799 }
800
801 static BOOL handle_server_public_key(PTInstVar pvar)
802 {
803 int server_key_public_exponent_len;
804 int server_key_public_modulus_pos;
805 int server_key_public_modulus_len;
806 int host_key_bits_pos;
807 int host_key_public_exponent_len;
808 int host_key_public_modulus_pos;
809 int host_key_public_modulus_len;
810 int protocol_flags_pos;
811 int supported_ciphers;
812 char FAR *inmsg;
813
814 if (!grab_payload(pvar, 14))
815 return FALSE;
816 server_key_public_exponent_len = get_mpint_len(pvar, 12);
817
818 if (!grab_payload(pvar, server_key_public_exponent_len + 2))
819 return FALSE;
820 server_key_public_modulus_pos = 14 + server_key_public_exponent_len;
821 server_key_public_modulus_len =
822 get_mpint_len(pvar, server_key_public_modulus_pos);
823
824 if (!grab_payload(pvar, server_key_public_modulus_len + 6))
825 return FALSE;
826 host_key_bits_pos =
827 server_key_public_modulus_pos + 2 + server_key_public_modulus_len;
828 host_key_public_exponent_len =
829 get_mpint_len(pvar, host_key_bits_pos + 4);
830
831 if (!grab_payload(pvar, host_key_public_exponent_len + 2))
832 return FALSE;
833 host_key_public_modulus_pos =
834 host_key_bits_pos + 6 + host_key_public_exponent_len;
835 host_key_public_modulus_len =
836 get_mpint_len(pvar, host_key_public_modulus_pos);
837
838 if (!grab_payload(pvar, host_key_public_modulus_len + 12))
839 return FALSE;
840 protocol_flags_pos =
841 host_key_public_modulus_pos + 2 + host_key_public_modulus_len;
842
843 inmsg = pvar->ssh_state.payload;
844
845 CRYPT_set_server_cookie(pvar, inmsg);
846 if (!CRYPT_set_server_RSA_key
847 (pvar, get_uint32(inmsg + 8), pvar->ssh_state.payload + 12,
848 inmsg + server_key_public_modulus_pos))
849 return FALSE;
850 if (!CRYPT_set_host_RSA_key
851 (pvar, get_uint32(inmsg + host_key_bits_pos),
852 inmsg + host_key_bits_pos + 4,
853 inmsg + host_key_public_modulus_pos))
854 return FALSE;
855 pvar->ssh_state.server_protocol_flags =
856 get_uint32(inmsg + protocol_flags_pos);
857
858 supported_ciphers = get_uint32(inmsg + protocol_flags_pos + 4);
859 if (!CRYPT_set_supported_ciphers
860 (pvar, supported_ciphers, supported_ciphers))
861 return FALSE;
862 if (!AUTH_set_supported_auth_types
863 (pvar, get_uint32(inmsg + protocol_flags_pos + 8)))
864 return FALSE;
865
866 /* this must be the LAST THING in this function, since it can cause
867 host_is_OK to be called. */
868 HOSTS_check_host_key(pvar, pvar->ssh_state.hostname,
869 get_uint32(inmsg + host_key_bits_pos),
870 inmsg + host_key_bits_pos + 4,
871 inmsg + host_key_public_modulus_pos);
872
873 return FALSE;
874 }
875
876 /*
877 The ID must have already been found to start with "SSH-". It must
878 be null-terminated.
879 */
880 static BOOL parse_protocol_ID(PTInstVar pvar, char FAR * ID)
881 {
882 char FAR *str;
883
884 for (str = ID + 4; *str >= '0' && *str <= '9'; str++) {
885 }
886
887 if (*str != '.') {
888 return FALSE;
889 }
890
891 pvar->protocol_major = atoi(ID + 4);
892 pvar->protocol_minor = atoi(str + 1);
893
894 // for SSH2(yutaka)
895 // 1.99����SSH2�����������s��
896 if (pvar->protocol_major == 1 && pvar->protocol_minor == 99) {
897 // ���[�U�� SSH2 ���I������������������
898 if (pvar->settings.ssh_protocol_version == 2) {
899 pvar->protocol_major = 2;
900 pvar->protocol_minor = 0;
901 }
902
903 }
904
905 for (str = str + 1; *str >= '0' && *str <= '9'; str++) {
906 }
907
908 return *str == '-';
909 }
910
911 /*
912 On entry, the pvar->protocol_xxx fields hold the server's advertised
913 protocol number. We replace the fields with the protocol number we will
914 actually use, or return FALSE if there is no usable protocol version.
915 */
916 static BOOL negotiate_protocol(PTInstVar pvar)
917 {
918 switch (pvar->protocol_major) {
919 case 1:
920 if (pvar->protocol_minor > 5) {
921 pvar->protocol_minor = 5;
922 }
923
924 return TRUE;
925
926 // for SSH2(yutaka)
927 case 2:
928 return TRUE; // SSH2 support
929
930 default:
931 return FALSE;
932 }
933 }
934
935 static void init_protocol(PTInstVar pvar)
936 {
937 CRYPT_initialize_random_numbers(pvar);
938 HOSTS_prefetch_host_key(pvar, pvar->ssh_state.hostname);
939 /* while we wait for a response from the server... */
940
941 if (SSHv1(pvar)) {
942 enque_handler(pvar, SSH_MSG_DISCONNECT, handle_disconnect);
943 enque_handler(pvar, SSH_MSG_IGNORE, handle_ignore);
944 enque_handler(pvar, SSH_MSG_DEBUG, handle_debug);
945 enque_handler(pvar, SSH_SMSG_PUBLIC_KEY, handle_server_public_key);
946
947 } else { // for SSH2(yutaka)
948 enque_handler(pvar, SSH2_MSG_DISCONNECT, handle_disconnect);
949 enque_handler(pvar, SSH2_MSG_IGNORE, handle_ignore);
950 enque_handler(pvar, SSH2_MSG_DEBUG, handle_debug);
951 enque_handler(pvar, SSH2_MSG_KEXINIT, handle_SSH2_kexinit);
952 enque_handler(pvar, SSH2_MSG_KEXDH_INIT, handle_unimplemented);
953 enque_handler(pvar, SSH2_MSG_KEXDH_REPLY, handle_SSH2_dh_common_reply);
954 enque_handler(pvar, SSH2_MSG_KEX_DH_GEX_REPLY, handle_SSH2_dh_gex_reply);
955 enque_handler(pvar, SSH2_MSG_NEWKEYS, handle_SSH2_newkeys);
956 enque_handler(pvar, SSH2_MSG_SERVICE_ACCEPT, handle_SSH2_authrequest);
957 enque_handler(pvar, SSH2_MSG_USERAUTH_SUCCESS, handle_SSH2_userauth_success);
958 enque_handler(pvar, SSH2_MSG_USERAUTH_FAILURE, handle_SSH2_userauth_failure);
959 enque_handler(pvar, SSH2_MSG_USERAUTH_BANNER, handle_SSH2_userauth_banner);
960
961 enque_handler(pvar, SSH2_MSG_UNIMPLEMENTED, handle_unimplemented);
962
963 // ���[�U�F�������f�B�X�p�b�`���[�`��
964 enque_handler(pvar, SSH2_MSG_CHANNEL_CLOSE, handle_SSH2_channel_close);
965 enque_handler(pvar, SSH2_MSG_CHANNEL_DATA, handle_SSH2_channel_data);
966 enque_handler(pvar, SSH2_MSG_CHANNEL_EOF, handle_SSH2_channel_eof);
967 // enque_handler(pvar, SSH2_MSG_CHANNEL_EXTENDED_DATA, handle_SSH2_channel_extended_data);
968 // enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN, handle_unimplemented);
969 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, handle_SSH2_open_confirm);
970 // enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_FAILURE, handle_unimplemented);
971 enque_handler(pvar, SSH2_MSG_CHANNEL_REQUEST, handle_SSH2_channel_request);
972 enque_handler(pvar, SSH2_MSG_CHANNEL_WINDOW_ADJUST, handle_SSH2_window_adjust);
973 enque_handler(pvar, SSH2_MSG_CHANNEL_SUCCESS, handle_SSH2_channel_success);
974 // enque_handler(pvar, SSH2_MSG_GLOBAL_REQUEST, handle_unimplemented);
975 // enque_handler(pvar, SSH2_MSG_REQUEST_FAILURE, handle_unimplemented);
976 enque_handler(pvar, SSH2_MSG_REQUEST_SUCCESS, handle_SSH2_request_success);
977
978 }
979 }
980
981 BOOL SSH_handle_server_ID(PTInstVar pvar, char FAR * ID, int ID_len)
982 {
983 static const char prefix[] = "Received server prologue string: ";
984
985 if (ID_len <= 0) {
986 return FALSE;
987 } else {
988 char FAR *buf = (char FAR *) malloc(ID_len + NUM_ELEM(prefix));
989
990 strcpy(buf, prefix);
991 strncpy(buf + NUM_ELEM(prefix) - 1, ID, ID_len);
992 buf[NUM_ELEM(prefix) + ID_len - 1] = 0;
993 chop_newlines(buf);
994
995 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
996
997 free(buf);
998
999
1000 // for calculate SSH2 hash
1001 // �T�[�o�o�[�W�����������i���s���������������j
1002 if (ID_len >= sizeof(pvar->server_version_string))
1003 return FALSE;
1004 strncpy(pvar->server_version_string, ID, ID_len);
1005
1006
1007 if (ID[ID_len - 1] != '\n') {
1008 pvar->ssh_state.status_flags |= STATUS_IN_PARTIAL_ID_STRING;
1009 return FALSE;
1010 } else
1011 if ((pvar->ssh_state.
1012 status_flags & STATUS_IN_PARTIAL_ID_STRING) != 0) {
1013 pvar->ssh_state.status_flags &= ~STATUS_IN_PARTIAL_ID_STRING;
1014 return FALSE;
1015 } else if (strncmp(ID, "SSH-", 4) != 0) {
1016 return FALSE;
1017 } else {
1018 ID[ID_len - 1] = 0;
1019
1020 if (ID_len > 1 && ID[ID_len - 2] == '\r') {
1021 ID[ID_len - 2] = 0;
1022 }
1023
1024 pvar->ssh_state.server_ID = _strdup(ID);
1025
1026 if (!parse_protocol_ID(pvar, ID) || !negotiate_protocol(pvar)) {
1027 notify_fatal_error(pvar,
1028 "This program does not understand the server's version of the protocol.");
1029 } else {
1030 char TTSSH_ID[1024];
1031 int TTSSH_ID_len;
1032
1033 _snprintf(TTSSH_ID, sizeof(TTSSH_ID),
1034 "SSH-%d.%d-TTSSH/1.5.4 Win32\n",
1035 pvar->protocol_major, pvar->protocol_minor);
1036 TTSSH_ID_len = strlen(TTSSH_ID);
1037
1038 // for SSH2(yutaka)
1039 // �N���C�A���g�o�[�W�����������i���s���������������j
1040 strncpy(pvar->client_version_string, TTSSH_ID, TTSSH_ID_len);
1041
1042 if ((pvar->Psend) (pvar->socket, TTSSH_ID, TTSSH_ID_len,
1043 0) != TTSSH_ID_len) {
1044 notify_fatal_error(pvar,
1045 "An error occurred while sending the SSH ID string.\n"
1046 "The connection will close.");
1047 } else {
1048 // ���s�R�[�h������ (2004.8.4 yutaka)
1049 pvar->server_version_string[--ID_len] = 0;
1050 pvar->client_version_string[--TTSSH_ID_len] = 0;
1051
1052 // SSH�n���h�����o�^���s��
1053 init_protocol(pvar);
1054
1055 SSH2_dispatch_init(1);
1056 SSH2_dispatch_add_message(SSH2_MSG_KEXINIT);
1057 }
1058 }
1059
1060 return TRUE;
1061 }
1062 }
1063 }
1064
1065 static BOOL handle_exit(PTInstVar pvar)
1066 {
1067 if (grab_payload(pvar, 4)) {
1068 begin_send_packet(pvar, SSH_CMSG_EXIT_CONFIRMATION, 0);
1069 finish_send_packet(pvar);
1070 notify_closed_connection(pvar);
1071 }
1072 return TRUE;
1073 }
1074
1075 static BOOL handle_data(PTInstVar pvar)
1076 {
1077 if (grab_payload_limited(pvar, 4)) {
1078 pvar->ssh_state.payload_datalen = get_payload_uint32(pvar, 0);
1079 pvar->ssh_state.payload_datastart = 4;
1080 }
1081 return TRUE;
1082 }
1083
1084 static BOOL handle_channel_open(PTInstVar pvar)
1085 {
1086 int host_len;
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,
1093 8 + (host_len = get_payload_uint32(pvar, 4)))
1094 && grab_payload(pvar, originator_len =
1095 get_payload_uint32(pvar, host_len + 12))) {
1096 int local_port = get_payload_uint32(pvar, 8 + host_len);
1097
1098 pvar->ssh_state.payload[8 + host_len] = 0;
1099 FWD_open(pvar, get_payload_uint32(pvar, 0),
1100 pvar->ssh_state.payload + 8, local_port,
1101 pvar->ssh_state.payload + 16 + host_len,
1102 originator_len);
1103 }
1104 } else {
1105 if (grab_payload(pvar, 8)
1106 && grab_payload(pvar,
1107 4 + (host_len =
1108 get_payload_uint32(pvar, 4)))) {
1109 int local_port = get_payload_uint32(pvar, 8 + host_len);
1110
1111 pvar->ssh_state.payload[8 + host_len] = 0;
1112 FWD_open(pvar, get_payload_uint32(pvar, 0),
1113 pvar->ssh_state.payload + 8, local_port, NULL, 0);
1114 }
1115 }
1116
1117 return TRUE;
1118 }
1119
1120 static BOOL handle_X11_channel_open(PTInstVar pvar)
1121 {
1122 int originator_len;
1123
1124 if ((pvar->ssh_state.
1125 server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
1126 if (grab_payload(pvar, 8)
1127 && grab_payload(pvar, originator_len =
1128 get_payload_uint32(pvar, 4))) {
1129 FWD_X11_open(pvar, get_payload_uint32(pvar, 0),
1130 pvar->ssh_state.payload + 8, originator_len);
1131 }
1132 } else {
1133 if (grab_payload(pvar, 4)) {
1134 FWD_X11_open(pvar, get_payload_uint32(pvar, 0), NULL, 0);
1135 }
1136 }
1137
1138 return TRUE;
1139 }
1140
1141 static BOOL handle_channel_open_confirmation(PTInstVar pvar)
1142 {
1143 if (grab_payload(pvar, 8)) {
1144 FWD_confirmed_open(pvar, get_payload_uint32(pvar, 0),
1145 get_payload_uint32(pvar, 4));
1146 }
1147 return FALSE;
1148 }
1149
1150 static BOOL handle_channel_open_failure(PTInstVar pvar)
1151 {
1152 if (grab_payload(pvar, 4)) {
1153 FWD_failed_open(pvar, get_payload_uint32(pvar, 0));
1154 }
1155 return FALSE;
1156 }
1157
1158 static BOOL handle_channel_data(PTInstVar pvar)
1159 {
1160 int len;
1161
1162 if (grab_payload(pvar, 8)
1163 && grab_payload(pvar, len = get_payload_uint32(pvar, 4))) {
1164 FWD_received_data(pvar, get_payload_uint32(pvar, 0),
1165 pvar->ssh_state.payload + 8, len);
1166 }
1167 return TRUE;
1168 }
1169
1170 static BOOL handle_channel_input_eof(PTInstVar pvar)
1171 {
1172 if (grab_payload(pvar, 4)) {
1173 FWD_channel_input_eof(pvar, get_payload_uint32(pvar, 0));
1174 }
1175 return TRUE;
1176 }
1177
1178 static BOOL handle_channel_output_eof(PTInstVar pvar)
1179 {
1180 if (grab_payload(pvar, 4)) {
1181 FWD_channel_output_eof(pvar, get_payload_uint32(pvar, 0));
1182 }
1183 return TRUE;
1184 }
1185
1186
1187
1188 // �n���h�����O�������b�Z�[�W����������
1189
1190 #define HANDLE_MESSAGE_MAX 30
1191 static unsigned char handle_messages[HANDLE_MESSAGE_MAX];
1192 static int handle_message_count = 0;
1193 static int handle_message_stage = 0;
1194
1195 void SSH2_dispatch_init(int stage)
1196 {
1197 handle_message_count = 0;
1198 handle_message_stage = stage;
1199 }
1200
1201 int SSH2_dispatch_enabled_check(unsigned char message)
1202 {
1203 int i;
1204
1205 for (i = 0 ; i < handle_message_count ; i++) {
1206 if (handle_messages[i] == message)
1207 return 1;
1208 }
1209 return 0;
1210 }
1211
1212 void SSH2_dispatch_add_message(unsigned char message)
1213 {
1214
1215 if (handle_message_count >= HANDLE_MESSAGE_MAX) {
1216 // TODO: error check
1217 return;
1218 }
1219
1220 handle_messages[handle_message_count++] = message;
1221 }
1222
1223 void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end)
1224 {
1225 unsigned char c;
1226
1227 for (c = begin ; c <= end ; c++) {
1228 SSH2_dispatch_add_message(c);
1229 }
1230 }
1231
1232
1233 /* default window/packet sizes for tcp/x11-fwd-channel */
1234 #define CHAN_SES_PACKET_DEFAULT (32*1024)
1235 #define CHAN_SES_WINDOW_DEFAULT (2*CHAN_SES_PACKET_DEFAULT) // READAMOUNT @ pkt.c����������������
1236
1237 //#define CHAN_TCP_PACKET_DEFAULT (32*1024)
1238 //#define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT)
1239 //#define CHAN_X11_PACKET_DEFAULT (16*1024)
1240 //#define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT)
1241
1242 // �N���C�A���g��window size���T�[�o���m������
1243 static void do_SSH2_adjust_window_size(PTInstVar pvar)
1244 {
1245 const unsigned int window_size = CHAN_SES_PACKET_DEFAULT;
1246 buffer_t *msg;
1247 unsigned char *outmsg;
1248 int len;
1249
1250 // ���[�J����window size�������]�T�����������A�����������B
1251 if (pvar->local_window > window_size)
1252 return;
1253
1254 {
1255 // pty open
1256 msg = buffer_init();
1257 if (msg == NULL) {
1258 // TODO: error check
1259 return;
1260 }
1261 buffer_put_int(msg, pvar->remote_id);
1262 buffer_put_int(msg, window_size - pvar->local_window);
1263
1264 len = buffer_len(msg);
1265 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_WINDOW_ADJUST, len);
1266 memcpy(outmsg, buffer_ptr(msg), len);
1267 finish_send_packet(pvar);
1268 buffer_free(msg);
1269
1270 // �N���C�A���g��window size��������
1271 pvar->local_window = window_size;
1272 }
1273
1274 }
1275
1276
1277 static void SSH2_consume_packet_size(PTInstVar pvar, unsigned char message)
1278 {
1279 int len;
1280 char *data;
1281
1282 if (!(message >= SSH2_MSG_CHANNEL_OPEN_CONFIRMATION && message <= SSH2_MSG_CHANNEL_FAILURE)) {
1283 return;
1284 }
1285
1286 // 6byte�i�T�C�Y�{�p�f�B���O�{�^�C�v�j���������������~���y�C���[�h
1287 data = pvar->ssh_state.payload;
1288 // �p�P�b�g�T�C�Y - (�p�f�B���O�T�C�Y+1)�G�^���p�P�b�g�T�C�Y
1289 len = pvar->ssh_state.payloadlen;
1290
1291 pvar->local_window -= (len + 1);
1292
1293 do_SSH2_adjust_window_size(pvar);
1294
1295 }
1296
1297
1298 void SSH_handle_packet(PTInstVar pvar, char FAR * data, int len,
1299 int padding)
1300 {
1301 unsigned char message = prep_packet(pvar, data, len, padding);
1302
1303
1304 #ifdef SSH2_DEBUG
1305 // for SSH2(yutaka)
1306 if (SSHv2(pvar)) {
1307 if (pvar->key_done) {
1308 message = message;
1309 }
1310
1311 if (pvar->userauth_success) {
1312 message = message;
1313 }
1314
1315 if (pvar->rekeying) {
1316 message = message;
1317 }
1318 }
1319 #endif
1320
1321 // SSH�����b�Z�[�W�^�C�v���`�F�b�N
1322 if (message != SSH_MSG_NONE) {
1323 // ���b�Z�[�W�^�C�v���������n���h�����N��
1324 SSHPacketHandler handler = get_handler(pvar, message);
1325
1326 // for SSH2(yutaka)
1327 if (SSHv2(pvar)) {
1328 // �z���O�����b�Z�[�W�^�C�v�������������A�{�[�g�������B
1329 if (!SSH2_dispatch_enabled_check(message) || handler == NULL) {
1330 char buf[1024];
1331
1332 _snprintf(buf, sizeof(buf),
1333 "Unexpected SSH2 message(%d) on current stage(%d)", message, handle_message_stage);
1334 notify_fatal_error(pvar, buf);
1335 // abort
1336 }
1337 }
1338
1339 if (handler == NULL) {
1340 if (SSHv1(pvar)) {
1341 char buf[1024];
1342
1343 _snprintf(buf, sizeof(buf),
1344 "Unexpected packet type received: %d", message);
1345 buf[sizeof(buf) - 1] = 0;
1346 notify_fatal_error(pvar, buf);
1347 } else {
1348 unsigned char FAR *outmsg =
1349 begin_send_packet(pvar, SSH2_MSG_UNIMPLEMENTED, 4);
1350
1351 set_uint32(outmsg,
1352 pvar->ssh_state.receiver_sequence_number - 1);
1353 finish_send_packet(pvar);
1354 /* XXX need to decompress incoming packet, but how? */
1355 }
1356 } else {
1357 if (!handler(pvar)) {
1358 deque_handlers(pvar, message);
1359 }
1360 }
1361 }
1362 }
1363
1364 static BOOL handle_pty_success(PTInstVar pvar)
1365 {
1366 FWD_enter_interactive_mode(pvar);
1367 enque_handler(pvar, SSH_SMSG_EXITSTATUS, handle_exit);
1368 enque_handler(pvar, SSH_SMSG_STDOUT_DATA, handle_data);
1369 enque_handler(pvar, SSH_SMSG_STDERR_DATA, handle_data);
1370 enque_handler(pvar, SSH_MSG_CHANNEL_DATA, handle_channel_data);
1371 enque_handler(pvar, SSH_MSG_CHANNEL_INPUT_EOF,
1372 handle_channel_input_eof);
1373 enque_handler(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED,
1374 handle_channel_output_eof);
1375 enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open);
1376 enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open);
1377 return FALSE;
1378 }
1379
1380 static BOOL handle_pty_failure(PTInstVar pvar)
1381 {
1382 notify_nonfatal_error(pvar,
1383 "The server cannot allocate a pseudo-terminal. "
1384 "You may encounter some problems with the terminal.");
1385 return handle_pty_success(pvar);
1386 }
1387
1388 static void prep_pty(PTInstVar pvar)
1389 {
1390 int len = strlen(pvar->ts->TermType);
1391 unsigned char FAR *outmsg =
1392 begin_send_packet(pvar, SSH_CMSG_REQUEST_PTY,
1393 4 + len + 16 + sizeof(ssh_ttymodes));
1394 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1395 static const SSHPacketHandler handlers[]
1396 = { handle_pty_success, handle_pty_failure };
1397
1398 set_uint32(outmsg, len);
1399 memcpy(outmsg + 4, pvar->ts->TermType, len);
1400 set_uint32(outmsg + 4 + len, pvar->ssh_state.win_rows);
1401 set_uint32(outmsg + 4 + len + 4, pvar->ssh_state.win_cols);
1402 set_uint32(outmsg + 4 + len + 8, 0);
1403 set_uint32(outmsg + 4 + len + 12, 0);
1404 memcpy(outmsg + 4 + len + 16, ssh_ttymodes, sizeof(ssh_ttymodes));
1405 finish_send_packet(pvar);
1406
1407 enque_handlers(pvar, 2, msgs, handlers);
1408
1409 begin_send_packet(pvar, SSH_CMSG_EXEC_SHELL, 0);
1410 finish_send_packet(pvar);
1411 }
1412
1413 static void prep_forwarding(PTInstVar pvar)
1414 {
1415 FWD_prep_forwarding(pvar);
1416 prep_pty(pvar);
1417 }
1418
1419 static void enable_compression(PTInstVar pvar)
1420 {
1421 pvar->ssh_state.compress_stream.zalloc = NULL;
1422 pvar->ssh_state.compress_stream.zfree = NULL;
1423 pvar->ssh_state.compress_stream.opaque = NULL;
1424 if (deflateInit
1425 (&pvar->ssh_state.compress_stream,
1426 pvar->ssh_state.compression_level) != Z_OK) {
1427 notify_fatal_error(pvar,
1428 "An error occurred while setting up compression.\n"
1429 "The connection will close.");
1430 return;
1431 } else {
1432 pvar->ssh_state.compressing = TRUE;
1433 }
1434
1435 pvar->ssh_state.decompress_stream.zalloc = NULL;
1436 pvar->ssh_state.decompress_stream.zfree = NULL;
1437 pvar->ssh_state.decompress_stream.opaque = NULL;
1438 if (inflateInit(&pvar->ssh_state.decompress_stream) != Z_OK) {
1439 deflateEnd(&pvar->ssh_state.compress_stream);
1440 notify_fatal_error(pvar,
1441 "An error occurred while setting up compression.\n"
1442 "The connection will close.");
1443 return;
1444 } else {
1445 pvar->ssh_state.decompressing = TRUE;
1446 buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf,
1447 &pvar->ssh_state.postdecompress_inbuflen, 1000);
1448 }
1449 }
1450
1451 static BOOL handle_enable_compression(PTInstVar pvar)
1452 {
1453 enable_compression(pvar);
1454 prep_forwarding(pvar);
1455 return FALSE;
1456 }
1457
1458 static BOOL handle_disable_compression(PTInstVar pvar)
1459 {
1460 prep_forwarding(pvar);
1461 return FALSE;
1462 }
1463
1464 static void prep_compression(PTInstVar pvar)
1465 {
1466 if (pvar->session_settings.CompressionLevel > 0) {
1467 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1468 static const SSHPacketHandler handlers[]
1469 = { handle_enable_compression, handle_disable_compression };
1470
1471 unsigned char FAR *outmsg =
1472 begin_send_packet(pvar, SSH_CMSG_REQUEST_COMPRESSION, 4);
1473
1474 set_uint32(outmsg, pvar->session_settings.CompressionLevel);
1475 finish_send_packet(pvar);
1476
1477 pvar->ssh_state.compression_level =
1478 pvar->session_settings.CompressionLevel;
1479
1480 enque_handlers(pvar, 2, msgs, handlers);
1481 } else {
1482 prep_forwarding(pvar);
1483 }
1484 }
1485
1486 static void enque_simple_auth_handlers(PTInstVar pvar)
1487 {
1488 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1489 static const SSHPacketHandler handlers[]
1490 = { handle_auth_success, handle_auth_failure };
1491
1492 enque_handlers(pvar, 2, msgs, handlers);
1493 }
1494
1495 static BOOL handle_rsa_challenge(PTInstVar pvar)
1496 {
1497 int challenge_bytes;
1498
1499 if (!grab_payload(pvar, 2)) {
1500 return FALSE;
1501 }
1502
1503 challenge_bytes = get_mpint_len(pvar, 0);
1504
1505 if (grab_payload(pvar, challenge_bytes)) {
1506 unsigned char FAR *outmsg =
1507 begin_send_packet(pvar, SSH_CMSG_AUTH_RSA_RESPONSE, 16);
1508
1509 if (CRYPT_generate_RSA_challenge_response
1510 (pvar, pvar->ssh_state.payload + 2, challenge_bytes, outmsg)) {
1511 AUTH_destroy_cur_cred(pvar);
1512 finish_send_packet(pvar);
1513
1514 enque_simple_auth_handlers(pvar);
1515 } else {
1516 notify_fatal_error(pvar,
1517 "An error occurred while decrypting the RSA challenge.\n"
1518 "Perhaps the key file is corrupted.");
1519 }
1520 }
1521
1522 return FALSE;
1523 }
1524
1525 #define OBFUSCATING_ROUND_TO 32
1526
1527 static int obfuscating_round_up(PTInstVar pvar, int size)
1528 {
1529 return (size + OBFUSCATING_ROUND_TO - 1) & ~(OBFUSCATING_ROUND_TO - 1);
1530 }
1531
1532 static void try_send_credentials(PTInstVar pvar)
1533 {
1534 if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_CREDENTIALS) == 0) {
1535 AUTHCred FAR *cred = AUTH_get_cur_cred(pvar);
1536 static const int RSA_msgs[] =
1537 { SSH_SMSG_AUTH_RSA_CHALLENGE, SSH_SMSG_FAILURE };
1538 static const SSHPacketHandler RSA_handlers[]
1539 = { handle_rsa_challenge, handle_rsa_auth_refused };
1540 static const int TIS_msgs[] =
1541 { SSH_SMSG_AUTH_TIS_CHALLENGE, SSH_SMSG_FAILURE };
1542 static const SSHPacketHandler TIS_handlers[]
1543 = { handle_TIS_challenge, handle_auth_failure };
1544
1545 switch (cred->method) {
1546 case SSH_AUTH_NONE:
1547 return;
1548 case SSH_AUTH_PASSWORD:{
1549 int len = strlen(cred->password);
1550 // Round up password length to discourage traffic analysis
1551 int obfuscated_len = obfuscating_round_up(pvar, len);
1552 unsigned char FAR *outmsg =
1553 begin_send_packet(pvar, SSH_CMSG_AUTH_PASSWORD,
1554 4 + obfuscated_len);
1555
1556 notify_verbose_message(pvar,
1557 "Trying PASSWORD authentication...",
1558 LOG_LEVEL_VERBOSE);
1559
1560 set_uint32(outmsg, obfuscated_len);
1561 memcpy(outmsg + 4, cred->password, len);
1562 memset(outmsg + 4 + len, 0, obfuscated_len - len);
1563 AUTH_destroy_cur_cred(pvar);
1564 enque_simple_auth_handlers(pvar);
1565 break;
1566 }
1567 case SSH_AUTH_RHOSTS:{
1568 int len = strlen(cred->rhosts_client_user);
1569 unsigned char FAR *outmsg =
1570 begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS, 4 + len);
1571
1572 notify_verbose_message(pvar,
1573 "Trying RHOSTS authentication...",
1574 LOG_LEVEL_VERBOSE);
1575
1576 set_uint32(outmsg, len);
1577 memcpy(outmsg + 4, cred->rhosts_client_user, len);
1578 AUTH_destroy_cur_cred(pvar);
1579 enque_simple_auth_handlers(pvar);
1580 break;
1581 }
1582 case SSH_AUTH_RSA:{
1583 int len = BN_num_bytes(cred->key_pair->RSA_key->n);
1584 unsigned char FAR *outmsg =
1585 begin_send_packet(pvar, SSH_CMSG_AUTH_RSA, 2 + len);
1586
1587 notify_verbose_message(pvar,
1588 "Trying RSA authentication...",
1589 LOG_LEVEL_VERBOSE);
1590
1591 set_ushort16_MSBfirst(outmsg, len * 8);
1592 BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + 2);
1593 /* don't destroy the current credentials yet */
1594 enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
1595 break;
1596 }
1597 case SSH_AUTH_RHOSTS_RSA:{
1598 int mod_len = BN_num_bytes(cred->key_pair->RSA_key->n);
1599 int name_len = strlen(cred->rhosts_client_user);
1600 int exp_len = BN_num_bytes(cred->key_pair->RSA_key->e);
1601 int index;
1602 unsigned char FAR *outmsg =
1603 begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS_RSA,
1604 12 + mod_len + name_len + exp_len);
1605
1606 notify_verbose_message(pvar,
1607 "Trying RHOSTS+RSA authentication...",
1608 LOG_LEVEL_VERBOSE);
1609
1610 set_uint32(outmsg, name_len);
1611 memcpy(outmsg + 4, cred->rhosts_client_user, name_len);
1612 index = 4 + name_len;
1613
1614 set_uint32(outmsg + index, 8 * mod_len);
1615 set_ushort16_MSBfirst(outmsg + index + 4, 8 * exp_len);
1616 BN_bn2bin(cred->key_pair->RSA_key->e, outmsg + index + 6);
1617 index += 6 + exp_len;
1618
1619 set_ushort16_MSBfirst(outmsg + index, 8 * mod_len);
1620 BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + index + 2);
1621 /* don't destroy the current credentials yet */
1622 enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
1623 break;
1624 }
1625 case SSH_AUTH_TIS:{
1626 if (cred->password == NULL) {
1627 unsigned char FAR *outmsg =
1628 begin_send_packet(pvar, SSH_CMSG_AUTH_TIS, 0);
1629
1630 notify_verbose_message(pvar,
1631 "Trying TIS authentication...",
1632 LOG_LEVEL_VERBOSE);
1633 enque_handlers(pvar, 2, TIS_msgs, TIS_handlers);
1634 } else {
1635 int len = strlen(cred->password);
1636 int obfuscated_len = obfuscating_round_up(pvar, len);
1637 unsigned char FAR *outmsg =
1638 begin_send_packet(pvar, SSH_CMSG_AUTH_TIS_RESPONSE,
1639 4 + obfuscated_len);
1640
1641 notify_verbose_message(pvar, "Sending TIS response",
1642 LOG_LEVEL_VERBOSE);
1643
1644 set_uint32(outmsg, obfuscated_len);
1645 memcpy(outmsg + 4, cred->password, len);
1646 memset(outmsg + 4 + len, 0, obfuscated_len - len);
1647 enque_simple_auth_handlers(pvar);
1648 }
1649 AUTH_destroy_cur_cred(pvar);
1650 break;
1651 }
1652 default:
1653 notify_fatal_error(pvar,
1654 "Internal error: unsupported authentication method");
1655 return;
1656 }
1657
1658 finish_send_packet(pvar);
1659 destroy_packet_buf(pvar);
1660
1661 pvar->ssh_state.status_flags |= STATUS_DONT_SEND_CREDENTIALS;
1662 }
1663 }
1664
1665 static void try_send_user_name(PTInstVar pvar)
1666 {
1667 if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_USER_NAME) == 0) {
1668 char FAR *username = AUTH_get_user_name(pvar);
1669
1670 if (username != NULL) {
1671 int len = strlen(username);
1672 int obfuscated_len = obfuscating_round_up(pvar, len);
1673 unsigned char FAR *outmsg =
1674 begin_send_packet(pvar, SSH_CMSG_USER, 4 + obfuscated_len);
1675 char buf[1024] = "Sending user name: ";
1676 static const int msgs[] =
1677 { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1678 static const SSHPacketHandler handlers[]
1679 = { handle_noauth_success, handle_auth_required };
1680
1681 set_uint32(outmsg, obfuscated_len);
1682 memcpy(outmsg + 4, username, len);
1683 memset(outmsg + 4 + len, 0, obfuscated_len - len);
1684 finish_send_packet(pvar);
1685
1686 pvar->ssh_state.status_flags |= STATUS_DONT_SEND_USER_NAME;
1687
1688 strncpy(buf + strlen(buf), username,
1689 sizeof(buf) - strlen(buf) - 2);
1690 buf[sizeof(buf) - 1] = 0;
1691 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
1692
1693 enque_handlers(pvar, 2, msgs, handlers);
1694 }
1695 }
1696 }
1697
1698 static void send_session_key(PTInstVar pvar)
1699 {
1700 int encrypted_session_key_len;
1701 unsigned char FAR *outmsg;
1702
1703 if (SSHv1(pvar)) {
1704 encrypted_session_key_len =
1705 CRYPT_get_encrypted_session_key_len(pvar);
1706 }
1707
1708 if (!CRYPT_choose_ciphers(pvar))
1709 return;
1710
1711 if (SSHv1(pvar)) {
1712 outmsg =
1713 begin_send_packet(pvar, SSH_CMSG_SESSION_KEY,
1714 15 + encrypted_session_key_len);
1715 outmsg[0] = (unsigned char) CRYPT_get_sender_cipher(pvar);
1716 memcpy(outmsg + 1, CRYPT_get_server_cookie(pvar), 8); /* antispoofing cookie */
1717 outmsg[9] = (unsigned char) (encrypted_session_key_len >> 5);
1718 outmsg[10] = (unsigned char) (encrypted_session_key_len << 3);
1719 if (!CRYPT_choose_session_key(pvar, outmsg + 11))
1720 return;
1721 set_uint32(outmsg + 11 + encrypted_session_key_len,
1722 SSH_PROTOFLAG_SCREEN_NUMBER |
1723 SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
1724 finish_send_packet(pvar);
1725 }
1726
1727 if (!CRYPT_start_encryption(pvar, 1, 1))
1728 return;
1729 notify_established_secure_connection(pvar);
1730
1731 if (SSHv1(pvar)) {
1732 enque_handler(pvar, SSH_SMSG_SUCCESS, handle_crypt_success);
1733 }
1734
1735 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_USER_NAME;
1736
1737 if (SSHv1(pvar)) {
1738 try_send_user_name(pvar);
1739 }
1740 }
1741
1742 /*************************
1743 END of message handlers
1744 ************************/
1745
1746 void SSH_init(PTInstVar pvar)
1747 {
1748 int i;
1749
1750 buf_create(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
1751 buf_create(&pvar->ssh_state.precompress_outbuf,
1752 &pvar->ssh_state.precompress_outbuflen);
1753 buf_create(&pvar->ssh_state.postdecompress_inbuf,
1754 &pvar->ssh_state.postdecompress_inbuflen);
1755 pvar->ssh_state.payload = NULL;
1756 pvar->ssh_state.compressing = FALSE;
1757 pvar->ssh_state.decompressing = FALSE;
1758 pvar->ssh_state.status_flags =
1759 STATUS_DONT_SEND_USER_NAME | STATUS_DONT_SEND_CREDENTIALS;
1760 pvar->ssh_state.payload_datalen = 0;
1761 pvar->ssh_state.hostname = NULL;
1762 pvar->ssh_state.server_ID = NULL;
1763 pvar->ssh_state.receiver_sequence_number = 0;
1764 pvar->ssh_state.sender_sequence_number = 0;
1765 for (i = 0; i < NUM_ELEM(pvar->ssh_state.packet_handlers); i++) {
1766 pvar->ssh_state.packet_handlers[i] = NULL;
1767 }
1768
1769 // for SSH2(yutaka)
1770 memset(pvar->ssh2_keys, 0, sizeof(pvar->ssh2_keys));
1771 pvar->userauth_success = 0;
1772 pvar->session_nego_status = 0;
1773 pvar->settings.ssh_protocol_version = 2; // SSH2(default)
1774 pvar->rekeying = 0;
1775 pvar->key_done = 0;
1776 pvar->ssh2_autologin = 0; // autologin disabled(default)
1777
1778 }
1779
1780 void SSH_open(PTInstVar pvar)
1781 {
1782 pvar->ssh_state.hostname = _strdup(pvar->ts->HostName);
1783 pvar->ssh_state.win_cols = pvar->ts->TerminalWidth;
1784 pvar->ssh_state.win_rows = pvar->ts->TerminalHeight;
1785 }
1786
1787 void SSH_notify_disconnecting(PTInstVar pvar, char FAR * reason)
1788 {
1789 if (SSHv1(pvar)) {
1790 int len = reason == NULL ? 0 : strlen(reason);
1791 unsigned char FAR *outmsg =
1792 begin_send_packet(pvar, SSH_MSG_DISCONNECT, len + 4);
1793
1794 set_uint32(outmsg, len);
1795 if (reason != NULL) {
1796 memcpy(outmsg + 4, reason, len);
1797 }
1798 finish_send_packet(pvar);
1799
1800 } else { // for SSH2(yutaka)
1801 buffer_t *msg;
1802 unsigned char *outmsg;
1803 int len;
1804
1805 // SSH2 server��channel close���`����
1806 msg = buffer_init();
1807 if (msg == NULL) {
1808 // TODO: error check
1809 return;
1810 }
1811 buffer_put_int(msg, pvar->remote_id);
1812
1813 len = buffer_len(msg);
1814 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_CLOSE, len);
1815 memcpy(outmsg, buffer_ptr(msg), len);
1816 finish_send_packet(pvar);
1817 buffer_free(msg);
1818
1819 }
1820
1821 }
1822
1823 void SSH_notify_host_OK(PTInstVar pvar)
1824 {
1825 if ((pvar->ssh_state.status_flags & STATUS_HOST_OK) == 0) {
1826 pvar->ssh_state.status_flags |= STATUS_HOST_OK;
1827 send_session_key(pvar);
1828 }
1829 }
1830
1831 void SSH_notify_win_size(PTInstVar pvar, int cols, int rows)
1832 {
1833 pvar->ssh_state.win_cols = cols;
1834 pvar->ssh_state.win_rows = rows;
1835
1836 if (SSHv1(pvar)) {
1837 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) == handle_data) {
1838 unsigned char FAR *outmsg =
1839 begin_send_packet(pvar, SSH_CMSG_WINDOW_SIZE, 16);
1840
1841 set_uint32(outmsg, rows);
1842 set_uint32(outmsg + 4, cols);
1843 set_uint32(outmsg + 8, 0);
1844 set_uint32(outmsg + 12, 0);
1845 finish_send_packet(pvar);
1846 }
1847
1848 } else if (SSHv2(pvar)) { // �^�[�~�i���T�C�Y���X���m������ (2005.1.4 yutaka)
1849 // SSH2�����������`�F�b�N���s���B(2005.1.5 yutaka)
1850 buffer_t *msg;
1851 char *s;
1852 unsigned char *outmsg;
1853 int len;
1854
1855 msg = buffer_init();
1856 if (msg == NULL) {
1857 // TODO: error check
1858 return;
1859 }
1860 buffer_put_int(msg, pvar->remote_id);
1861 s = "window-change";
1862 buffer_put_string(msg, s, strlen(s));
1863 buffer_put_char(msg, 0); // wantconfirm
1864 buffer_put_int(msg, pvar->ssh_state.win_cols); // columns
1865 buffer_put_int(msg, pvar->ssh_state.win_rows); // lines
1866 buffer_put_int(msg, 480); // XXX:
1867 buffer_put_int(msg, 640); // XXX:
1868 len = buffer_len(msg);
1869 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
1870 memcpy(outmsg, buffer_ptr(msg), len);
1871 finish_send_packet(pvar);
1872 buffer_free(msg);
1873
1874 } else {
1875 // SSH�����������������������B
1876
1877 }
1878
1879 }
1880
1881 int SSH_get_min_packet_size(PTInstVar pvar)
1882 {
1883 if (SSHv1(pvar)) {
1884 return 12;
1885 } else {
1886 int block_size = CRYPT_get_decryption_block_size(pvar);
1887
1888 return max(16, block_size);
1889 }
1890 }
1891
1892 /* data is guaranteed to be at least SSH_get_min_packet_size bytes long
1893 at least 5 bytes must be decrypted */
1894 void SSH_predecrpyt_packet(PTInstVar pvar, char FAR * data)
1895 {
1896 if (SSHv2(pvar)) {
1897 CRYPT_decrypt(pvar, data, get_predecryption_amount(pvar));
1898 }
1899 }
1900
1901 int SSH_get_clear_MAC_size(PTInstVar pvar)
1902 {
1903 if (SSHv1(pvar)) {
1904 return 0;
1905 } else {
1906 return CRYPT_get_receiver_MAC_size(pvar);
1907 }
1908 }
1909
1910 void SSH_notify_user_name(PTInstVar pvar)
1911 {
1912 try_send_user_name(pvar);
1913 }
1914
1915 void SSH_notify_cred(PTInstVar pvar)
1916 {
1917 try_send_credentials(pvar);
1918 }
1919
1920 void SSH_send(PTInstVar pvar, unsigned char const FAR * buf, int buflen)
1921 {
1922 if (SSHv1(pvar)) {
1923 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) != handle_data) {
1924 return;
1925 }
1926
1927 while (buflen > 0) {
1928 int len =
1929 buflen >
1930 SSH_MAX_SEND_PACKET_SIZE ? SSH_MAX_SEND_PACKET_SIZE : buflen;
1931 unsigned char FAR *outmsg =
1932 begin_send_packet(pvar, SSH_CMSG_STDIN_DATA, 4 + len);
1933
1934 set_uint32(outmsg, len);
1935
1936 if (pvar->ssh_state.compressing) {
1937 buf_ensure_size(&pvar->ssh_state.outbuf,
1938 &pvar->ssh_state.outbuflen,
1939 len + (len >> 6) + 50);
1940 pvar->ssh_state.compress_stream.next_in =
1941 pvar->ssh_state.precompress_outbuf;
1942 pvar->ssh_state.compress_stream.avail_in = 5;
1943 pvar->ssh_state.compress_stream.next_out =
1944 pvar->ssh_state.outbuf + 12;
1945 pvar->ssh_state.compress_stream.avail_out =
1946 pvar->ssh_state.outbuflen - 12;
1947
1948 if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) !=
1949 Z_OK) {
1950 notify_fatal_error(pvar, "Error compressing packet data");
1951 return;
1952 }
1953
1954 pvar->ssh_state.compress_stream.next_in =
1955 (unsigned char FAR *) buf;
1956 pvar->ssh_state.compress_stream.avail_in = len;
1957
1958 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
1959 Z_OK) {
1960 notify_fatal_error(pvar, "Error compressing packet data");
1961 return;
1962 }
1963 } else {
1964 memcpy(outmsg + 4, buf, len);
1965 }
1966
1967 finish_send_packet_special(pvar, 1);
1968
1969 buflen -= len;
1970 buf += len;
1971 }
1972
1973 } else { // for SSH2(yutaka)
1974 buffer_t *msg;
1975 unsigned char *outmsg;
1976 int len;
1977
1978 msg = buffer_init();
1979 if (msg == NULL) {
1980 // TODO: error check
1981 return;
1982 }
1983 buffer_put_int(msg, pvar->remote_id);
1984 buffer_put_string(msg, (char *)buf, buflen);
1985
1986 len = buffer_len(msg);
1987 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len);
1988 memcpy(outmsg, buffer_ptr(msg), len);
1989 finish_send_packet(pvar);
1990 buffer_free(msg);
1991
1992 // remote window size������
1993 pvar->remote_window -= len;
1994
1995 }
1996
1997 }
1998
1999 int SSH_extract_payload(PTInstVar pvar, unsigned char FAR * dest, int len)
2000 {
2001 int num_bytes = pvar->ssh_state.payload_datalen;
2002
2003 if (num_bytes > len) {
2004 num_bytes = len;
2005 }
2006
2007 if (!pvar->ssh_state.decompressing) {
2008 memcpy(dest,
2009 pvar->ssh_state.payload + pvar->ssh_state.payload_datastart,
2010 num_bytes);
2011 pvar->ssh_state.payload_datastart += num_bytes;
2012 } else if (num_bytes > 0) {
2013 pvar->ssh_state.decompress_stream.next_out = dest;
2014 pvar->ssh_state.decompress_stream.avail_out = num_bytes;
2015
2016 if (inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH) !=
2017 Z_OK) {
2018 notify_fatal_error(pvar,
2019 "Invalid compressed data in received packet");
2020 return 0;
2021 }
2022 }
2023
2024 pvar->ssh_state.payload_datalen -= num_bytes;
2025
2026 return num_bytes;
2027 }
2028
2029 void SSH_get_compression_info(PTInstVar pvar, char FAR * dest, int len)
2030 {
2031 char buf[1024];
2032 char buf2[1024];
2033
2034 if (pvar->ssh_state.compressing) {
2035 unsigned long total_in = pvar->ssh_state.compress_stream.total_in;
2036 unsigned long total_out =
2037 pvar->ssh_state.compress_stream.total_out;
2038
2039 if (total_out > 0) {
2040 _snprintf(buf, sizeof(buf), "level %d; ratio %.1f (%ld:%ld)",
2041 pvar->ssh_state.compression_level,
2042 ((double) total_in) / total_out, total_in,
2043 total_out);
2044 } else {
2045 _snprintf(buf, sizeof(buf), "level %d",
2046 pvar->ssh_state.compression_level);
2047 }
2048 } else {
2049 strcpy(buf, "none");
2050 }
2051 buf[sizeof(buf) - 1] = 0;
2052
2053 if (pvar->ssh_state.decompressing) {
2054 unsigned long total_in =
2055 pvar->ssh_state.decompress_stream.total_in;
2056 unsigned long total_out =
2057 pvar->ssh_state.decompress_stream.total_out;
2058
2059 if (total_in > 0) {
2060 _snprintf(buf2, sizeof(buf2), "level %d; ratio %.1f (%ld:%ld)",
2061 pvar->ssh_state.compression_level,
2062 ((double) total_out) / total_in, total_out,
2063 total_in);
2064 } else {
2065 _snprintf(buf2, sizeof(buf2), "level %d",
2066 pvar->ssh_state.compression_level);
2067 }
2068 } else {
2069 strcpy(buf2, "none");
2070 }
2071 buf2[sizeof(buf2) - 1] = 0;
2072
2073 _snprintf(dest, len, "Upstream %s; Downstream %s", buf, buf2);
2074 dest[len - 1] = 0;
2075 }
2076
2077 void SSH_get_server_ID_info(PTInstVar pvar, char FAR * dest, int len)
2078 {
2079 strncpy(dest, pvar->ssh_state.server_ID == NULL ? "Unknown"
2080 : pvar->ssh_state.server_ID, len);
2081 dest[len - 1] = 0;
2082 }
2083
2084 void SSH_get_protocol_version_info(PTInstVar pvar, char FAR * dest,
2085 int len)
2086 {
2087 if (pvar->protocol_major == 0) {
2088 strncpy(dest, "Unknown", len);
2089 } else {
2090 _snprintf(dest, len, "%d.%d", pvar->protocol_major,
2091 pvar->protocol_minor);
2092 }
2093 dest[len - 1] = 0;
2094 }
2095
2096 void SSH_end(PTInstVar pvar)
2097 {
2098 int i;
2099
2100 for (i = 0; i < 256; i++) {
2101 SSHPacketHandlerItem FAR *first_item =
2102 pvar->ssh_state.packet_handlers[i];
2103
2104 if (first_item != NULL) {
2105 SSHPacketHandlerItem FAR *item = first_item;
2106
2107 do {
2108 SSHPacketHandlerItem FAR *cur_item = item;
2109
2110 item = item->next_for_message;
2111 free(cur_item);
2112 } while (item != first_item);
2113 }
2114 pvar->ssh_state.packet_handlers[i] = NULL;
2115 }
2116
2117 free(pvar->ssh_state.hostname);
2118 pvar->ssh_state.hostname = NULL;
2119 free(pvar->ssh_state.server_ID);
2120 pvar->ssh_state.server_ID = NULL;
2121 buf_destroy(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2122 buf_destroy(&pvar->ssh_state.precompress_outbuf,
2123 &pvar->ssh_state.precompress_outbuflen);
2124 buf_destroy(&pvar->ssh_state.postdecompress_inbuf,
2125 &pvar->ssh_state.postdecompress_inbuflen);
2126
2127 if (pvar->ssh_state.compressing) {
2128 deflateEnd(&pvar->ssh_state.compress_stream);
2129 pvar->ssh_state.compressing = FALSE;
2130 }
2131 if (pvar->ssh_state.decompressing) {
2132 inflateEnd(&pvar->ssh_state.decompress_stream);
2133 pvar->ssh_state.decompressing = FALSE;
2134 }
2135
2136 #if 1
2137 // SSH2���f�[�^���������� (2004.12.27 yutaka)
2138 if (SSHv2(pvar)) {
2139 if (pvar->kexdh) {
2140 DH_free(pvar->kexdh);
2141 pvar->kexdh = NULL;
2142 }
2143 memset(pvar->server_version_string, 0, sizeof(pvar->server_version_string));
2144 memset(pvar->client_version_string, 0, sizeof(pvar->client_version_string));
2145
2146 if (pvar->my_kex != NULL) {
2147 buffer_free(pvar->my_kex);
2148 pvar->my_kex = NULL;
2149 }
2150 if (pvar->peer_kex != NULL) {
2151 buffer_free(pvar->peer_kex);
2152 pvar->peer_kex = NULL;
2153 }
2154
2155 pvar->we_need = 0;
2156 pvar->key_done = 0;
2157 pvar->rekeying = 0;
2158
2159 if (pvar->session_id != NULL) {
2160 free(pvar->session_id);
2161 pvar->session_id = NULL;
2162 }
2163 pvar->session_id_len = 0;
2164
2165 pvar->userauth_success = 0;
2166 pvar->remote_id = 0;
2167 pvar->session_nego_status = 0;
2168
2169 pvar->ssh_heartbeat_tick = 0;
2170 }
2171 #endif
2172
2173 }
2174
2175 /* support for port forwarding */
2176 void SSH_channel_send(PTInstVar pvar, uint32 remote_channel_num,
2177 unsigned char FAR * buf, int len)
2178 {
2179 unsigned char FAR *outmsg =
2180 begin_send_packet(pvar, SSH_MSG_CHANNEL_DATA, 8 + len);
2181
2182 set_uint32(outmsg, remote_channel_num);
2183 set_uint32(outmsg + 4, len);
2184
2185 if (pvar->ssh_state.compressing) {
2186 buf_ensure_size(&pvar->ssh_state.outbuf,
2187 &pvar->ssh_state.outbuflen, len + (len >> 6) + 50);
2188 pvar->ssh_state.compress_stream.next_in =
2189 pvar->ssh_state.precompress_outbuf;
2190 pvar->ssh_state.compress_stream.avail_in = 9;
2191 pvar->ssh_state.compress_stream.next_out =
2192 pvar->ssh_state.outbuf + 12;
2193 pvar->ssh_state.compress_stream.avail_out =
2194 pvar->ssh_state.outbuflen - 12;
2195
2196 if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) != Z_OK) {
2197 notify_fatal_error(pvar, "Error compressing packet data");
2198 return;
2199 }
2200
2201 pvar->ssh_state.compress_stream.next_in =
2202 (unsigned char FAR *) buf;
2203 pvar->ssh_state.compress_stream.avail_in = len;
2204
2205 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2206 Z_OK) {
2207 notify_fatal_error(pvar, "Error compressing packet data");
2208 return;
2209 }
2210 } else {
2211 memcpy(outmsg + 8, buf, len);
2212 }
2213
2214 finish_send_packet_special(pvar, 1);
2215 }
2216
2217 void SSH_fail_channel_open(PTInstVar pvar, uint32 remote_channel_num)
2218 {
2219 unsigned char FAR *outmsg =
2220 begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_FAILURE, 4);
2221
2222 set_uint32(outmsg, remote_channel_num);
2223 finish_send_packet(pvar);
2224 }
2225
2226 void SSH_confirm_channel_open(PTInstVar pvar, uint32 remote_channel_num,
2227 uint32 local_channel_num)
2228 {
2229 unsigned char FAR *outmsg =
2230 begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 8);
2231
2232 set_uint32(outmsg, remote_channel_num);
2233 set_uint32(outmsg + 4, local_channel_num);
2234 finish_send_packet(pvar);
2235 }
2236
2237 void SSH_channel_output_eof(PTInstVar pvar, uint32 remote_channel_num)
2238 {
2239 unsigned char FAR *outmsg =
2240 begin_send_packet(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4);
2241
2242 set_uint32(outmsg, remote_channel_num);
2243 finish_send_packet(pvar);
2244 }
2245
2246 void SSH_channel_input_eof(PTInstVar pvar, uint32 remote_channel_num)
2247 {
2248 unsigned char FAR *outmsg =
2249 begin_send_packet(pvar, SSH_MSG_CHANNEL_INPUT_EOF, 4);
2250
2251 set_uint32(outmsg, remote_channel_num);
2252 finish_send_packet(pvar);
2253 }
2254
2255 void SSH_request_forwarding(PTInstVar pvar, int from_server_port,
2256 char FAR * to_local_host, int to_local_port)
2257 {
2258 int host_len = strlen(to_local_host);
2259 unsigned char FAR *outmsg =
2260 begin_send_packet(pvar, SSH_CMSG_PORT_FORWARD_REQUEST,
2261 12 + host_len);
2262
2263 set_uint32(outmsg, from_server_port);
2264 set_uint32(outmsg + 4, host_len);
2265 memcpy(outmsg + 8, to_local_host, host_len);
2266 set_uint32(outmsg + 8 + host_len, to_local_port);
2267 finish_send_packet(pvar);
2268
2269 enque_forwarding_request_handlers(pvar);
2270 }
2271
2272 void SSH_request_X11_forwarding(PTInstVar pvar,
2273 char FAR * auth_protocol,
2274 unsigned char FAR * auth_data,
2275 int auth_data_len, int screen_num)
2276 {
2277 int protocol_len = strlen(auth_protocol);
2278 int data_len = auth_data_len * 2;
2279 unsigned char FAR *outmsg =
2280 begin_send_packet(pvar, SSH_CMSG_X11_REQUEST_FORWARDING,
2281 12 + protocol_len + data_len);
2282 int i;
2283 char FAR *auth_data_ptr;
2284
2285 set_uint32(outmsg, protocol_len);
2286 memcpy(outmsg + 4, auth_protocol, protocol_len);
2287 set_uint32(outmsg + 4 + protocol_len, data_len);
2288 auth_data_ptr = outmsg + 8 + protocol_len;
2289 for (i = 0; i < auth_data_len; i++) {
2290 sprintf(auth_data_ptr + i * 2, "%.2x", auth_data[i]);
2291 }
2292 set_uint32(outmsg + 8 + protocol_len + data_len, screen_num);
2293
2294 finish_send_packet(pvar);
2295
2296 enque_forwarding_request_handlers(pvar);
2297 }
2298
2299 void SSH_open_channel(PTInstVar pvar, uint32 local_channel_num,
2300 char FAR * to_remote_host, int to_remote_port,
2301 char FAR * originator)
2302 {
2303 static const int msgs[]
2304 = { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, SSH_MSG_CHANNEL_OPEN_FAILURE };
2305 static const SSHPacketHandler handlers[]
2306 = { handle_channel_open_confirmation, handle_channel_open_failure };
2307
2308 int host_len = strlen(to_remote_host);
2309
2310 if ((pvar->ssh_state.
2311 server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
2312 int originator_len = strlen(originator);
2313 unsigned char FAR *outmsg =
2314 begin_send_packet(pvar, SSH_MSG_PORT_OPEN,
2315 16 + host_len + originator_len);
2316
2317 set_uint32(outmsg, local_channel_num);
2318 set_uint32(outmsg + 4, host_len);
2319 memcpy(outmsg + 8, to_remote_host, host_len);
2320 set_uint32(outmsg + 8 + host_len, to_remote_port);
2321 set_uint32(outmsg + 12 + host_len, originator_len);
2322 memcpy(outmsg + 16 + host_len, originator, originator_len);
2323 } else {
2324 unsigned char FAR *outmsg =
2325 begin_send_packet(pvar, SSH_MSG_PORT_OPEN,
2326 12 + host_len);
2327
2328 set_uint32(outmsg, local_channel_num);
2329 set_uint32(outmsg + 4, host_len);
2330 memcpy(outmsg + 8, to_remote_host, host_len);
2331 set_uint32(outmsg + 8 + host_len, to_remote_port);
2332 }
2333
2334 finish_send_packet(pvar);
2335
2336 enque_handlers(pvar, 2, msgs, handlers);
2337 }
2338
2339
2340 /////////////////////////////////////////////////////////////////////////////
2341 //
2342 // SSH2 protocol procedure in the following code:
2343 //
2344 /////////////////////////////////////////////////////////////////////////////
2345
2346 void debug_print(int no, char *msg, int len)
2347 {
2348 #ifdef _DEBUG
2349 FILE *fp;
2350 char file[128];
2351
2352 sprintf(file, "dump%d.bin", no);
2353
2354 fp = fopen(file, "wb");
2355 if (fp == NULL)
2356 return;
2357
2358 fwrite(msg, 1, len, fp);
2359
2360 fclose(fp);
2361 #endif
2362 }
2363
2364 // �N���C�A���g�����T�[�o������������
2365 #ifdef SSH2_DEBUG
2366 static char *myproposal[PROPOSAL_MAX] = {
2367 "diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1",
2368 // "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1,diffie-hellman-group-exchange-sha1",
2369 // "ssh-rsa,ssh-dss",
2370 "ssh-dss,ssh-rsa",
2371 "3des-cbc,aes128-cbc",
2372 "3des-cbc,aes128-cbc",
2373 "hmac-md5,hmac-sha1",
2374 "hmac-md5,hmac-sha1",
2375 // "hmac-sha1,hmac-md5",
2376 // "hmac-sha1,hmac-md5",
2377 // "hmac-sha1",
2378 // "hmac-sha1",
2379 "none",
2380 "none",
2381 "",
2382 "",
2383 };
2384 #else
2385 static char *myproposal[PROPOSAL_MAX] = {
2386 "diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1",
2387 "ssh-rsa,ssh-dss",
2388 "3des-cbc,aes128-cbc",
2389 "3des-cbc,aes128-cbc",
2390 "hmac-sha1,hmac-md5",
2391 "hmac-sha1,hmac-md5",
2392 "none",
2393 "none",
2394 "",
2395 "",
2396 };
2397 #endif
2398
2399
2400 typedef struct ssh2_cipher {
2401 SSHCipher cipher;
2402 char *name;
2403 int block_size;
2404 int key_len;
2405 const EVP_CIPHER *(*func)(void);
2406 } ssh2_cipher_t;
2407
2408 ssh2_cipher_t ssh2_ciphers[] = {
2409 {SSH_CIPHER_3DES_CBC, "3des-cbc", 8, 24, EVP_des_ede3_cbc},
2410 {SSH_CIPHER_AES128, "aes128-cbc", 16, 16, EVP_aes_128_cbc},
2411 {SSH_CIPHER_NONE, NULL, 0, 0, NULL},
2412 };
2413
2414
2415 typedef struct ssh2_mac {
2416 char *name;
2417 const EVP_MD *(*func)(void);
2418 int truncatebits;
2419 } ssh2_mac_t;
2420
2421 ssh2_mac_t ssh2_macs[] = {
2422 {"hmac-sha1", EVP_sha1, 0},
2423 {"hmac-md5", EVP_md5, 0},
2424 {NULL, NULL, 0},
2425 };
2426
2427 static Newkeys current_keys[MODE_MAX];
2428
2429
2430 #define write_buffer_file(buf,len) do_write_buffer_file(buf,len,__FILE__,__LINE__)
2431
2432
2433 static int get_cipher_block_size(SSHCipher cipher)
2434 {
2435 ssh2_cipher_t *ptr = ssh2_ciphers;
2436 int val = 0;
2437
2438 while (ptr->name != NULL) {
2439 if (cipher == ptr->cipher) {
2440 val = ptr->block_size;
2441 break;
2442 }
2443 ptr++;
2444 }
2445 return (val);
2446 }
2447
2448 static int get_cipher_key_len(SSHCipher cipher)
2449 {
2450 ssh2_cipher_t *ptr = ssh2_ciphers;
2451 int val = 0;
2452
2453 while (ptr->name != NULL) {
2454 if (cipher == ptr->cipher) {
2455 val = ptr->key_len;
2456 break;
2457 }
2458 ptr++;
2459 }
2460 return (val);
2461 }
2462
2463
2464 #if 0
2465 static int get_mac_index(char *name)
2466 {
2467 ssh2_mac_t *ptr = ssh2_macs;
2468 int val = -1;
2469
2470 while (ptr->name != NULL) {
2471 if (strcmp(ptr->name, name) == 0) {
2472 val = ptr - ssh2_macs;
2473 break;
2474 }
2475 ptr++;
2476 }
2477 return (val);
2478 }
2479 #endif
2480
2481
2482 static void do_write_buffer_file(void *buf, int len, char *file, int lineno)
2483 {
2484 FILE *fp;
2485 char filename[256];
2486
2487 _snprintf(filename, sizeof(filename), "data%d.bin", lineno);
2488
2489 fp = fopen(filename, "wb");
2490 if (fp == NULL)
2491 return;
2492
2493 fwrite(buf, 1, len, fp);
2494
2495 fclose(fp);
2496 }
2497
2498
2499 void SSH2_packet_start(buffer_t *msg, unsigned char type)
2500 {
2501 unsigned char buf[9];
2502 int len = 6;
2503
2504 memset(buf, 0, sizeof(buf));
2505 buf[len - 1] = type;
2506 buffer_clear(msg);
2507 buffer_append(msg, buf, len);
2508 }
2509
2510
2511 // the caller is normalize_cipher_order()
2512 void SSH2_update_cipher_myproposal(PTInstVar pvar)
2513 {
2514 static char buf[128]; // TODO: malloc()��������
2515 int cipher;
2516 int len, i;
2517
2518 // �����A���S���Y���D���������������Amyproposal[]�������������B(2004.11.6 yutaka)
2519 buf[0] = '\0';
2520 for (i = 0 ; pvar->ts_SSH->CipherOrder[i] != 0 ; i++) {
2521 cipher = pvar->ts_SSH->CipherOrder[i] - '0';
2522 if (cipher == 0) // disabled line
2523 break;
2524 if (cipher == SSH_CIPHER_AES128) {
2525 strcat(buf, "aes128-cbc,");
2526 }
2527 if (cipher == SSH_CIPHER_3DES_CBC) {
2528 strcat(buf, "3des-cbc,");
2529 }
2530 }
2531 if (buf[0] != '\0') {
2532 len = strlen(buf);
2533 buf[len - 1] = '\0'; // get rid of comma
2534 myproposal[PROPOSAL_ENC_ALGS_CTOS] = buf; // Client To Server
2535 myproposal[PROPOSAL_ENC_ALGS_STOC] = buf; // Server To Client
2536 }
2537 }
2538
2539
2540 // �N���C�A���g�����T�[�o�����L�[�����J�n�v��
2541 void SSH2_send_kexinit(PTInstVar pvar)
2542 {
2543 char cookie[SSH2_COOKIE_LENGTH];
2544 buffer_t *msg;
2545 unsigned char *outmsg;
2546 int len, i;
2547
2548 msg = buffer_init();
2549 if (msg == NULL) {
2550 // TODO: error check
2551 return;
2552 }
2553 if (pvar->my_kex != NULL)
2554 buffer_free(pvar->my_kex);
2555 pvar->my_kex = msg;
2556
2557 // ���b�Z�[�W�^�C�v
2558 //SSH2_packet_start(msg, SSH2_MSG_KEXINIT);
2559
2560 // cookie���Z�b�g
2561 CRYPT_set_random_data(pvar, cookie, sizeof(cookie));
2562 CRYPT_set_server_cookie(pvar, cookie);
2563 buffer_append(msg, cookie, sizeof(cookie));
2564
2565 // �N���C�A���g���L�[����
2566 for (i = 0 ; i < PROPOSAL_MAX ; i++) {
2567 buffer_put_string(msg, myproposal[i], strlen(myproposal[i]));
2568 }
2569 buffer_put_char(msg, 0);
2570 buffer_put_int(msg, 0);
2571
2572 len = buffer_len(msg);
2573 outmsg = begin_send_packet(pvar, SSH2_MSG_KEXINIT, len);
2574 memcpy(outmsg, buffer_ptr(msg), len);
2575 finish_send_packet(pvar);
2576
2577 //buffer_free(msg);
2578 }
2579
2580
2581 static SSHCipher choose_SSH2_cipher_algorithm(char *server_proposal, char *my_proposal)
2582 {
2583 char tmp[1024], *ptr;
2584 SSHCipher cipher = SSH_CIPHER_NONE;
2585
2586 _snprintf(tmp, sizeof(tmp), my_proposal);
2587 ptr = strtok(tmp, ","); // not thread-safe
2588 while (ptr != NULL) {
2589 // server_proposal�����T�[�o��proposal���J���}���������i�[����������
2590 if (strstr(server_proposal, ptr)) { // match
2591 break;
2592 }
2593 ptr = strtok(NULL, ",");
2594 }
2595 if (strstr(ptr, "3des-cbc")) {
2596 cipher = SSH_CIPHER_3DES_CBC;
2597
2598 } else if (strstr(ptr, "aes128-cbc")) {
2599 cipher = SSH_CIPHER_AES128;
2600 }
2601
2602 return (cipher);
2603 }
2604
2605
2606 static enum hmac_type choose_SSH2_hmac_algorithm(char *server_proposal, char *my_proposal)
2607 {
2608 char tmp[1024], *ptr;
2609 enum hmac_type type = HMAC_UNKNOWN;
2610
2611 _snprintf(tmp, sizeof(tmp), my_proposal);
2612 ptr = strtok(tmp, ","); // not thread-safe
2613 while (ptr != NULL) {
2614 // server_proposal�����T�[�o��proposal���J���}���������i�[����������
2615 if (strstr(server_proposal, ptr)) { // match
2616 break;
2617 }
2618 ptr = strtok(NULL, ",");
2619 }
2620 if (strstr(ptr, "hmac-sha1")) {
2621 type = HMAC_SHA1;
2622 } else if (strstr(ptr, "hmac-md5")) {
2623 type = HMAC_MD5;
2624 }
2625
2626 return (type);
2627 }
2628
2629
2630 // �����A���S���Y�����L�[�T�C�Y�A�u���b�N�T�C�Y�AMAC�T�C�Y�����������l(we_need)�����������B
2631 static void choose_SSH2_key_maxlength(PTInstVar pvar)
2632 {
2633 int mode, need, val, ctos;
2634 const EVP_MD *md;
2635
2636 for (mode = 0; mode < MODE_MAX; mode++) {
2637 if (mode == MODE_OUT)
2638 ctos = 1;
2639 else
2640 ctos = 0;
2641
2642 if (ctos == 1) {
2643 val = pvar->ctos_hmac;
2644 } else {
2645 val = pvar->stoc_hmac;
2646 }
2647
2648 // current_keys[]�����������������A������ pvar->ssh2_keys[] ���R�s�[�����B
2649 md = ssh2_macs[val].func();
2650 current_keys[mode].mac.md = md;
2651 current_keys[mode].mac.key_len = current_keys[mode].mac.mac_len = EVP_MD_size(md);
2652 if (ssh2_macs[val].truncatebits != 0) {
2653 current_keys[mode].mac.mac_len = ssh2_macs[val].truncatebits / 8;
2654 }
2655
2656 // �L�[�T�C�Y���u���b�N�T�C�Y�������������������� (2004.11.7 yutaka)
2657 if (ctos == 1) {
2658 current_keys[mode].enc.key_len = get_cipher_key_len(pvar->ctos_cipher);
2659 current_keys[mode].enc.block_size = get_cipher_block_size(pvar->ctos_cipher);
2660 } else {
2661 current_keys[mode].enc.key_len = get_cipher_key_len(pvar->stoc_cipher);
2662 current_keys[mode].enc.block_size = get_cipher_block_size(pvar->stoc_cipher);
2663 }
2664 current_keys[mode].mac.enabled = 0;
2665
2666 // �����_����MAC��disable
2667 pvar->ssh2_keys[mode].mac.enabled = 0;
2668 }
2669 need = 0;
2670 for (mode = 0; mode < MODE_MAX; mode++) {
2671 if (mode == MODE_OUT)
2672 ctos = 1;
2673 else
2674 ctos = 0;
2675
2676 val = current_keys[mode].enc.key_len;
2677 if (need < val)
2678 need = val;
2679
2680 val = current_keys[mode].enc.block_size;
2681 if (need < val)
2682 need = val;
2683
2684 val = current_keys[mode].mac.key_len;
2685 if (need < val)
2686 need = val;
2687 }
2688 pvar->we_need = need;
2689
2690 }
2691
2692
2693 // �L�[�����J�n�O���`�F�b�N (SSH2_MSG_KEXINIT)
2694 // �����Y�������f�[�^���M���������������������\������
2695 static BOOL handle_SSH2_kexinit(PTInstVar pvar)
2696 {
2697 char buf[1024];
2698 char *data;
2699 int len, i, size;
2700 int offset = 0;
2701 char *msg = NULL;
2702 char tmp[1024+512];
2703 char *ptr;
2704
2705 // �������L�[�������I�����������������������A�T�[�o���� SSH2_MSG_KEXINIT ��
2706 // �������������������A�L�[���������s���B(2004.10.24 yutaka)
2707 if (pvar->key_done == 1) {
2708 pvar->rekeying = 1;
2709 pvar->key_done = 0;
2710
2711 // �T�[�o��SSH2_MSG_KEXINIT ������
2712 SSH2_send_kexinit(pvar);
2713 }
2714
2715 if (pvar->peer_kex != NULL) { // already allocated
2716 buffer_free(pvar->peer_kex);
2717 }
2718 pvar->peer_kex = buffer_init();
2719 if (pvar->peer_kex == NULL) {
2720 msg = "Out of memory @ handle_SSH2_kexinit()";
2721 goto error;
2722 }
2723 // [-2]:padding size
2724 // len = pvar->ssh_state.payloadlen + pvar->ssh_state.payload[-2] + 1;
2725 len = pvar->ssh_state.payloadlen - 1;
2726 // buffer_append(pvar->peer_kex, &pvar->ssh_state.payload[-6], len);
2727 buffer_append(pvar->peer_kex, pvar->ssh_state.payload, len);
2728 //write_buffer_file(&pvar->ssh_state.payload[-6], len);
2729
2730 // TODO: buffer overrun check
2731
2732 // 6byte�i�T�C�Y�{�p�f�B���O�{�^�C�v�j���������������~���y�C���[�h
2733 data = pvar->ssh_state.payload;
2734 // �p�P�b�g�T�C�Y - (�p�f�B���O+1)�G�^���p�P�b�g�T�C�Y
2735 len = pvar->ssh_state.payloadlen;
2736
2737 //write_buffer_file(data, len);
2738
2739 if (offset + 20 >= len) {
2740 msg = "payload size too small @ handle_SSH2_kexinit()";
2741 goto error;
2742 }
2743
2744 #if 0
2745 for (i = 0; i < SSH2_COOKIE_LENGTH; i++) {
2746 cookie[i] = data[i];
2747 }
2748 #endif
2749 // get rid of Cookie length
2750 offset += SSH2_COOKIE_LENGTH;
2751
2752 // �L�[�����A���S���Y���`�F�b�N
2753 size = get_payload_uint32(pvar, offset);
2754 offset += 4;
2755 for (i = 0; i < size; i++) {
2756 buf[i] = data[offset + i];
2757 }
2758 buf[i] = '\0'; // null-terminate
2759 offset += size;
2760
2761 // KEX�������B��������myproposal[PROPOSAL_KEX_ALGS]���������������������B
2762 // �T�[�o���A�N���C�A���g���������������� myproposal[PROPOSAL_KEX_ALGS] ���J���}�������������A
2763 // �������������� myproposal[] �����r���s���A�������}�b�`����������KEX�A���S���Y��������
2764 // �I���������B(2004.10.30 yutaka)
2765 pvar->kex_type = -1;
2766 _snprintf(tmp, sizeof(tmp), myproposal[PROPOSAL_KEX_ALGS]);
2767 ptr = strtok(tmp, ","); // not thread-safe
2768 while (ptr != NULL) {
2769 // buf[]�����T�[�o��proposal���J���}���������i�[����������
2770 if (strstr(buf, ptr)) { // match
2771 break;
2772 }
2773 ptr = strtok(NULL, ",");
2774 }
2775 if (ptr == NULL) { // not match
2776 strcpy(tmp, "unknown KEX algorithm: ");
2777 strcat(tmp, buf);
2778 msg = tmp;
2779 goto error;
2780 }
2781 if (strstr(ptr, KEX_DH14)) {
2782 pvar->kex_type = KEX_DH_GRP14_SHA1;
2783 } else if (strstr(ptr, KEX_DH1)) {
2784 pvar->kex_type = KEX_DH_GRP1_SHA1;
2785 } else if (strstr(ptr, KEX_DHGEX)) {
2786 pvar->kex_type = KEX_DH_GEX_SHA1;
2787 }
2788
2789
2790 // �z�X�g�L�[�A���S���Y���`�F�b�N
2791 size = get_payload_uint32(pvar, offset);
2792 offset += 4;
2793 for (i = 0; i < size; i++) {
2794 buf[i] = data[offset + i];
2795 }
2796 buf[i] = 0;
2797 offset += size;
2798 pvar->hostkey_type = -1;
2799 _snprintf(tmp, sizeof(tmp), myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]);
2800 ptr = strtok(tmp, ","); // not thread-safe
2801 while (ptr != NULL) {
2802 // buf[]�����T�[�o��proposal���J���}���������i�[����������
2803 if (strstr(buf, ptr)) { // match
2804 break;
2805 }
2806 ptr = strtok(NULL, ",");
2807 }
2808 if (ptr == NULL) { // not match
2809 strcpy(tmp, "unknown host KEY type: ");
2810 strcat(tmp, buf);
2811 msg = tmp;
2812 goto error;
2813 }
2814 if (strstr(ptr, "ssh-rsa")) {
2815 pvar->hostkey_type = KEY_RSA;
2816 } else if (strstr(ptr, "ssh-dss")) {
2817 pvar->hostkey_type = KEY_DSA;
2818 } else if (strstr(ptr, "rsa1")) {
2819 pvar->hostkey_type = KEY_RSA1;
2820 } else if (strstr(ptr, "rsa")) {
2821 pvar->hostkey_type = KEY_RSA;
2822 } else if (strstr(ptr, "dsa")) {
2823 pvar->hostkey_type = KEY_DSA;
2824 }
2825 #if 0
2826 // TODO: ������ KEY_RSA �����T�|�[�g���������� (2004.10.24 yutaka)
2827 if (pvar->hostkey_type != KEY_RSA) {
2828 strcpy(tmp, "unknown KEY type: ");
2829 strcat(tmp, buf);
2830 msg = tmp;
2831 goto error;
2832 }
2833 #endif
2834
2835 // �N���C�A���g -> �T�[�o�����A���S���Y���`�F�b�N
2836 size = get_payload_uint32(pvar, offset);
2837 offset += 4;
2838 for (i = 0; i < size; i++) {
2839 buf[i] = data[offset + i];
2840 }
2841 buf[i] = 0;
2842 offset += size;
2843 pvar->ctos_cipher = choose_SSH2_cipher_algorithm(buf, myproposal[PROPOSAL_ENC_ALGS_CTOS]);
2844 if (pvar->ctos_cipher == SSH_CIPHER_NONE) {
2845 strcpy(tmp, "unknown Encrypt algorithm(ctos): ");
2846 strcat(tmp, buf);
2847 msg = tmp;
2848 goto error;
2849 }
2850
2851 // �T�[�o -> �N���C�A���g�����A���S���Y���`�F�b�N
2852 size = get_payload_uint32(pvar, offset);
2853 offset += 4;
2854 for (i = 0; i < size; i++) {
2855 buf[i] = data[offset + i];
2856 }
2857 buf[i] = 0;
2858 offset += size;
2859 pvar->stoc_cipher = choose_SSH2_cipher_algorithm(buf, myproposal[PROPOSAL_ENC_ALGS_STOC]);
2860 if (pvar->stoc_cipher == SSH_CIPHER_NONE) {
2861 strcpy(tmp, "unknown Encrypt algorithm(stoc): ");
2862 strcat(tmp, buf);
2863 msg = tmp;
2864 goto error;
2865 }
2866
2867
2868 // HMAC(Hash Message Authentication Code)�A���S���Y�������� (2004.12.17 yutaka)
2869 size = get_payload_uint32(pvar, offset);
2870 offset += 4;
2871 for (i = 0; i < size; i++) {
2872 buf[i] = data[offset + i];
2873 }
2874 buf[i] = 0;
2875 offset += size;
2876 pvar->ctos_hmac = choose_SSH2_hmac_algorithm(buf, myproposal[PROPOSAL_MAC_ALGS_CTOS]);
2877 if (pvar->ctos_hmac == HMAC_UNKNOWN) { // not match
2878 strcpy(tmp, "unknown HMAC algorithm: ");
2879 strcat(tmp, buf);
2880 msg = tmp;
2881 goto error;
2882 }
2883
2884 size = get_payload_uint32(pvar, offset);
2885 offset += 4;
2886 for (i = 0; i < size; i++) {
2887 buf[i] = data[offset + i];
2888 }
2889 buf[i] = 0;
2890 offset += size;
2891 pvar->stoc_hmac = choose_SSH2_hmac_algorithm(buf, myproposal[PROPOSAL_MAC_ALGS_STOC]);
2892 if (pvar->ctos_hmac == HMAC_UNKNOWN) { // not match
2893 strcpy(tmp, "unknown HMAC algorithm: ");
2894 strcat(tmp, buf);
2895 msg = tmp;
2896 goto error;
2897 }
2898
2899
2900 // we_need������ (2004.11.6 yutaka)
2901 // �L�[���������������X�L�b�v�����B
2902 if (pvar->rekeying == 0) {
2903 choose_SSH2_key_maxlength(pvar);
2904 }
2905
2906 // send DH kex init
2907 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
2908 SSH2_dh_kex_init(pvar);
2909
2910 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
2911 SSH2_dh_kex_init(pvar);
2912
2913 } else if (pvar->kex_type == KEX_DH_GEX_SHA1) {
2914 SSH2_dh_gex_kex_init(pvar);
2915
2916 }
2917
2918 return TRUE;
2919
2920 error:;
2921 buffer_free(pvar->peer_kex);
2922
2923 notify_fatal_error(pvar, msg);
2924
2925 return FALSE;
2926 }
2927
2928
2929
2930 static DH *dh_new_group_asc(const char *gen, const char *modulus)
2931 {
2932 DH *dh = NULL;
2933
2934 if ((dh = DH_new()) == NULL) {
2935 printf("dh_new_group_asc: DH_new");
2936 goto error;
2937 }
2938
2939 // P��G�����J�����������f�����g��������
2940 if (BN_hex2bn(&dh->p, modulus) == 0) {
2941 printf("BN_hex2bn p");
2942 goto error;
2943 }
2944
2945 if (BN_hex2bn(&dh->g, gen) == 0) {
2946 printf("BN_hex2bn g");
2947 goto error;
2948 }
2949
2950 return (dh);
2951
2952 error:
2953 DH_free(dh);
2954 return (NULL);
2955 }
2956
2957
2958 static DH *dh_new_group1(void)
2959 {
2960 static char *gen = "2", *group1 =
2961 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
2962 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
2963 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
2964 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
2965 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
2966 "FFFFFFFF" "FFFFFFFF";
2967
2968 return (dh_new_group_asc(gen, group1));
2969 }
2970
2971
2972 static DH *dh_new_group14(void)
2973 {
2974 static char *gen = "2", *group14 =
2975 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
2976 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
2977 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
2978 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
2979 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
2980 "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
2981 "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
2982 "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
2983 "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
2984 "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
2985 "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
2986
2987 return (dh_new_group_asc(gen, group14));
2988 }
2989
2990
2991 // DH������������
2992 static void dh_gen_key(PTInstVar pvar, DH *dh, int we_need /* bytes */ )
2993 {
2994 int i;
2995
2996 dh->priv_key = NULL;
2997
2998 // ����������������(X)������
2999 for (i = 0 ; i < 10 ; i++) { // retry counter
3000 if (dh->priv_key != NULL) {
3001 BN_clear_free(dh->priv_key);
3002 }
3003 dh->priv_key = BN_new();
3004 if (dh->priv_key == NULL)
3005 goto error;
3006 if (BN_rand(dh->priv_key, 2*(we_need*8), 0, 0) == 0)
3007 goto error;
3008 if (DH_generate_key(dh) == 0)
3009 goto error;
3010 if (dh_pub_is_valid(dh, dh->pub_key))
3011 break;
3012 }
3013 if (i >= 10) {
3014 goto error;
3015 }
3016 return;
3017
3018 error:;
3019 notify_fatal_error(pvar, "error occurred @ dh_gen_key()");
3020
3021 }
3022
3023 //
3024 // KEX_DH_GRP1_SHA1 or KEX_DH_GRP14_SHA1
3025 //
3026 static void SSH2_dh_kex_init(PTInstVar pvar)
3027 {
3028 DH *dh = NULL;
3029 char *s, *t;
3030 buffer_t *msg = NULL;
3031 unsigned char *outmsg;
3032 int len;
3033
3034 // Diffie-Hellman key agreement
3035 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
3036 dh = dh_new_group1();
3037 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
3038 dh = dh_new_group14();
3039 } else {
3040 goto error;
3041 }
3042
3043 // ����������������(X)������
3044 dh_gen_key(pvar, dh, pvar->we_need);
3045
3046 s = BN_bn2hex(dh->priv_key);
3047 t = BN_bn2hex(dh->pub_key);
3048
3049
3050 msg = buffer_init();
3051 if (msg == NULL) {
3052 // TODO: error check
3053 return;
3054 }
3055
3056 buffer_put_bignum2(msg, dh->pub_key);
3057
3058 len = buffer_len(msg);
3059 outmsg = begin_send_packet(pvar, SSH2_MSG_KEXDH_INIT, len);
3060 memcpy(outmsg, buffer_ptr(msg), len);
3061 finish_send_packet(pvar);
3062
3063 if (pvar->kexdh != NULL) {
3064 DH_free(dh);
3065 }
3066 pvar->kexdh = dh;
3067
3068 SSH2_dispatch_init(2);
3069 SSH2_dispatch_add_message(SSH2_MSG_KEXDH_REPLY);
3070
3071 buffer_free(msg);
3072 return;
3073
3074 error:;
3075 DH_free(dh);
3076 buffer_free(msg);
3077
3078 notify_fatal_error(pvar, "error occurred @ SSH2_dh_kex_init()");
3079 }
3080
3081
3082
3083 //
3084 // KEX_DH_GEX_SHA1
3085 //
3086 // cf. Diffie-Hellman Group Exchange for the SSH Transport Layer Protocol
3087 // (draft-ietf-secsh-dh-group-exchange-04.txt)
3088 //
3089
3090 static int dh_estimate(int bits)
3091 {
3092 if (bits <= 128)
3093 return (1024); /* O(2**86) */
3094 if (bits <= 192)
3095 return (2048); /* O(2**116) */
3096 return (4096); /* O(2**156) */
3097 }
3098
3099 static void SSH2_dh_gex_kex_init(PTInstVar pvar)
3100 {
3101 buffer_t *msg = NULL;
3102 unsigned char *outmsg;
3103 int len;
3104 int bits, min, max;
3105
3106 msg = buffer_init();
3107 if (msg == NULL) {
3108 goto error;
3109 }
3110
3111 // �T�[�o���������������������r�b�g�����������iwe_need���o�C�g�j�B
3112 bits = dh_estimate(pvar->we_need * 8);
3113 min = 1024;
3114 max = 8192;
3115
3116 // �T�[�o��group size���������Ap �� g ���������������B
3117 buffer_put_int(msg, min);
3118 buffer_put_int(msg, bits);
3119 buffer_put_int(msg, max);
3120 len = buffer_len(msg);
3121 outmsg = begin_send_packet(pvar, SSH2_MSG_KEX_DH_GEX_REQUEST, len);
3122 memcpy(outmsg, buffer_ptr(msg), len);
3123 finish_send_packet(pvar);
3124
3125 // �������n�b�V���v�Z���g�����������������B
3126 pvar->kexgex_min = min;
3127 pvar->kexgex_bits = bits;
3128 pvar->kexgex_max = max;
3129
3130 SSH2_dispatch_init(2);
3131 SSH2_dispatch_add_message(SSH2_MSG_KEX_DH_GEX_GROUP);
3132
3133 buffer_free(msg);
3134 return;
3135
3136 error:;
3137 buffer_free(msg);
3138
3139 notify_fatal_error(pvar, "error occurred @ SSH2_dh_gex_kex_init()");
3140 }
3141
3142
3143 // SSH2_MSG_KEX_DH_GEX_GROUP
3144 static BOOL handle_SSH2_dh_gex_group(PTInstVar pvar)
3145 {
3146 char *data;
3147 int len;
3148 BIGNUM *p = NULL, *g = NULL;
3149 DH *dh = NULL;
3150 buffer_t *msg = NULL;
3151 unsigned char *outmsg;
3152
3153 // 6byte�i�T�C�Y�{�p�f�B���O�{�^�C�v�j���������������~���y�C���[�h
3154 data = pvar->ssh_state.payload;
3155 // �p�P�b�g�T�C�Y - (�p�f�B���O�T�C�Y+1)�G�^���p�P�b�g�T�C�Y
3156 len = pvar->ssh_state.payloadlen;
3157
3158 p = BN_new();
3159 g = BN_new();
3160 if (p == NULL || g == NULL)
3161 goto error;
3162
3163 buffer_get_bignum2(&data, p); // �f��������
3164 buffer_get_bignum2(&data, g); // ������������
3165
3166 dh = DH_new();
3167 if (dh == NULL)
3168 goto error;
3169 dh->p = p;
3170 dh->g = g;
3171
3172 // ����������������(X)������
3173 dh_gen_key(pvar, dh, pvar->we_need);
3174
3175 // ���J�����T�[�o�����M
3176 msg = buffer_init();
3177 if (msg == NULL) {
3178 goto error;
3179 }
3180 buffer_put_bignum2(msg, dh->pub_key);
3181 len = buffer_len(msg);
3182 outmsg = begin_send_packet(pvar, SSH2_MSG_KEX_DH_GEX_INIT, len);
3183 memcpy(outmsg, buffer_ptr(msg), len);
3184 finish_send_packet(pvar);
3185
3186 // ��������������DH�����A�������n�b�V���v�Z���g�����������������B(2004.10.31 yutaka)
3187 pvar->kexdh = dh;
3188
3189 SSH2_dispatch_init(2);
3190 SSH2_dispatch_add_message(SSH2_MSG_KEX_DH_GEX_REPLY);
3191
3192 buffer_free(msg);
3193
3194 return TRUE;
3195
3196 error:;
3197 BN_free(p);
3198 BN_free(g);
3199 DH_free(dh);
3200
3201 return FALSE;
3202 }
3203
3204
3205
3206 // SHA-1(160bit)��������
3207 unsigned char *kex_dh_hash(
3208 char *client_version_string,
3209 char *server_version_string,
3210 char *ckexinit, int ckexinitlen,
3211 char *skexinit, int skexinitlen,
3212 u_char *serverhostkeyblob, int sbloblen,
3213 BIGNUM *client_dh_pub,
3214 BIGNUM *server_dh_pub,
3215 BIGNUM *shared_secret)
3216 {
3217 buffer_t *b;
3218 static unsigned char digest[EVP_MAX_MD_SIZE];
3219 const EVP_MD *evp_md = EVP_sha1();
3220 EVP_MD_CTX md;
3221
3222 b = buffer_init();
3223 buffer_put_string(b, client_version_string, strlen(client_version_string));
3224 buffer_put_string(b, server_version_string, strlen(server_version_string));
3225
3226 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
3227 buffer_put_int(b, ckexinitlen+1);
3228 buffer_put_char(b, SSH2_MSG_KEXINIT);
3229 buffer_append(b, ckexinit, ckexinitlen);
3230 buffer_put_int(b, skexinitlen+1);
3231 buffer_put_char(b, SSH2_MSG_KEXINIT);
3232 buffer_append(b, skexinit, skexinitlen);
3233
3234 buffer_put_string(b, serverhostkeyblob, sbloblen);
3235 buffer_put_bignum2(b, client_dh_pub);
3236 buffer_put_bignum2(b, server_dh_pub);
3237 buffer_put_bignum2(b, shared_secret);
3238
3239 // yutaka
3240 //debug_print(38, buffer_ptr(b), buffer_len(b));
3241
3242 EVP_DigestInit(&md, evp_md);
3243 EVP_DigestUpdate(&md, buffer_ptr(b), buffer_len(b));
3244 EVP_DigestFinal(&md, digest, NULL);
3245
3246 buffer_free(b);
3247
3248 //write_buffer_file(digest, EVP_MD_size(evp_md));
3249
3250 return digest;
3251 }
3252
3253
3254 int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
3255