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 2795 - (show annotations) (download) (as text)
Sat Mar 5 10:19:05 2005 UTC (19 years, 1 month ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 134551 byte(s)
Tru64 UNIX(HP-UX)向けworkaroundを追加。

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