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 2957 - (show annotations) (download) (as text)
Sun Feb 4 13:45:47 2007 UTC (17 years, 2 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 197227 byte(s)
パケット送信関数が失敗した場合、WSAGetLastError()がWSABASEERR(10000)未満であれば、成功したものと見なすようにした。

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