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 2748 - (show annotations) (download) (as text)
Sat Dec 11 07:31:00 2004 UTC (19 years, 4 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 117218 byte(s)
SSH heartbeatスレッドの追加した。これにより、IPマスカレード環境において、ルータの
NATテーブルクリアにより、SSHコネクションが切断される現象が回避される。
それに合わせて、teraterm.iniのTTSSHセクションに、HeartBeat エントリを追加。

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