summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--channels.c186
2 files changed, 124 insertions, 70 deletions
diff --git a/ChangeLog b/ChangeLog
index e59bf4e9e..0039e9026 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
120010412
2 - OpenBSD CVS Sync
3 - markus@cvs.openbsd.org 2001/04/10 07:46:58
4 [channels.c]
5 cleanup socks4 handling
6
120010410 720010410
2 - OpenBSD CVS Sync 8 - OpenBSD CVS Sync
3 - deraadt@cvs.openbsd.org 2001/04/08 20:52:55 9 - deraadt@cvs.openbsd.org 2001/04/08 20:52:55
@@ -4990,4 +4996,4 @@
4990 - Wrote replacements for strlcpy and mkdtemp 4996 - Wrote replacements for strlcpy and mkdtemp
4991 - Released 1.0pre1 4997 - Released 1.0pre1
4992 4998
4993$Id: ChangeLog,v 1.1093 2001/04/10 02:48:50 mouring Exp $ 4999$Id: ChangeLog,v 1.1094 2001/04/11 15:57:50 mouring Exp $
diff --git a/channels.c b/channels.c
index 0e334db88..008ff64b9 100644
--- a/channels.c
+++ b/channels.c
@@ -40,7 +40,7 @@
40 */ 40 */
41 41
42#include "includes.h" 42#include "includes.h"
43RCSID("$OpenBSD: channels.c,v 1.103 2001/04/07 08:55:17 markus Exp $"); 43RCSID("$OpenBSD: channels.c,v 1.104 2001/04/10 07:46:58 markus Exp $");
44 44
45#include <openssl/rsa.h> 45#include <openssl/rsa.h>
46#include <openssl/dsa.h> 46#include <openssl/dsa.h>
@@ -542,88 +542,142 @@ channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset)
542 } 542 }
543} 543}
544 544
545#define SSH_SOCKS_HEAD 1+1+2+4
546 545
547void 546int
548channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset) 547channel_decode_helper(Channel *c, int start, int lookfor)
548{
549 u_char *p;
550 int i, have;
551
552 p = buffer_ptr(&c->input);
553 have = buffer_len(&c->input);
554 debug2("channel %d: decode_helper: start %d have %d lookfor %d",
555 c->self, start, have, lookfor);
556 if (have < start)
557 return 0;
558 for (i = start; i < have; i++) {
559 if (p[i] == lookfor) {
560 debug2("channel %d: decode_helper: matched at %d",
561 c->self, i);
562 if (lookfor == '\0' ||
563 (i+3 < have &&
564 p[i+1] == '\n' &&
565 p[i+2] == '\r' &&
566 p[i+3] == '\n'))
567 return i;
568 }
569 if (i > 4096) {
570 /* the peer is probably sending garbage */
571 debug("channel %d: decode_helper: too long",
572 c->self);
573 return -1;
574 }
575 }
576 return 0; /* need more */
577}
578
579/* try to decode a socks4 header */
580int
581channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
549{ 582{
550 u_char *p, *host; 583 u_char *p, *host;
551 int len, i, done, have; 584 int len, have, ret;
552 char username[256]; 585 char username[256];
553 struct { 586 struct {
554 u_int8_t version; 587 u_int8_t version;
555 u_int8_t command; 588 u_int8_t command;
556 u_int16_t dest_port; 589 u_int16_t dest_port;
557 struct in_addr dest_ip; 590 struct in_addr dest_addr;
558 } s4_req, s4_rsp; 591 } s4_req, s4_rsp;
559 592
560 have = buffer_len(&c->input); 593 debug2("channel %d: decode socks4", c->self);
561 594 ret = channel_decode_helper(c, sizeof(s4_req), '\0');
562 debug("channel %d: pre_dynamic have: %d", c->self, have); 595 if (ret <= 0)
563 /*buffer_dump(&c->input);*/ 596 return ret;
564
565 /* Check if the fixed size part of the packet is in buffer. */
566 if (have < SSH_SOCKS_HEAD + 1) {
567 /* need more */
568 FD_SET(c->sock, readset);
569 return;
570 }
571 /* Check for end of username */
572 p = buffer_ptr(&c->input);
573 done = 0;
574 for (i = SSH_SOCKS_HEAD; i < have; i++) {
575 if (p[i] == '\0') {
576 done = 1;
577 break;
578 }
579 }
580 if (!done) {
581 /* need more */
582 FD_SET(c->sock, readset);
583 return;
584 }
585 buffer_get(&c->input, (char *)&s4_req.version, 1); 597 buffer_get(&c->input, (char *)&s4_req.version, 1);
586 buffer_get(&c->input, (char *)&s4_req.command, 1); 598 buffer_get(&c->input, (char *)&s4_req.command, 1);
587 buffer_get(&c->input, (char *)&s4_req.dest_port, 2); 599 buffer_get(&c->input, (char *)&s4_req.dest_port, 2);
588 buffer_get(&c->input, (char *)&s4_req.dest_ip, 4); 600 buffer_get(&c->input, (char *)&s4_req.dest_addr, 4);
589 p = buffer_ptr(&c->input); 601 p = buffer_ptr(&c->input);
590 len = strlen(p); 602 len = strlen(p);
591 have = buffer_len(&c->input); 603 have = buffer_len(&c->input);
592 debug2("channel %d: pre_dynamic user: %s/%d", c->self, p, len); 604 debug2("channel %d: pre_dynamic: user %s/%d", c->self, p, len);
593 if (len > have) 605 if (len > have)
594 fatal("channel %d: pre_dynamic: len %d > have %d", 606 fatal("channel %d: decode socks4: len %d > have %d",
595 c->self, len, have); 607 c->self, len, have);
596 strlcpy(username, p, sizeof(username)); 608 strlcpy(username, p, sizeof(username));
597 buffer_consume(&c->input, len); 609 buffer_consume(&c->input, len);
598 buffer_consume(&c->input, 1); /* trailing '\0' */ 610 buffer_consume(&c->input, 1); /* trailing '\0' */
599 611
600 host = inet_ntoa(s4_req.dest_ip); 612 host = inet_ntoa(s4_req.dest_addr);
601 strlcpy(c->path, host, sizeof(c->path)); 613 strlcpy(c->path, host, sizeof(c->path));
602 c->host_port = ntohs(s4_req.dest_port); 614 c->host_port = ntohs(s4_req.dest_port);
603 615
604 debug("channel %d: dynamic request received: " 616 debug("channel %d: dynamic request: "
605 "socks%x://%s@%s:%u/command?%u", 617 "socks%x://%s@%s:%u/command?%u",
606 c->self, s4_req.version, username, host, c->host_port, 618 c->self, s4_req.version, username, host, c->host_port,
607 s4_req.command); 619 s4_req.command);
608 620
609 if ((s4_req.version != 4) || (s4_req.command != 1)) { 621 if (s4_req.command != 1) {
610 debug("channel %d: cannot handle: socks VN %d CN %d", 622 debug("channel %d: cannot handle: socks4 cn %d",
611 c->self, s4_req.version, s4_req.command); 623 c->self, s4_req.command);
612 channel_free(c->self); 624 return -1;
613 return;
614 } 625 }
615 626 s4_rsp.version = 0; /* vn: 0 for reply */
616 s4_rsp.version = 0; /* VN: version of reply code */ 627 s4_rsp.command = 90; /* cd: req granted */
617 s4_rsp.command = 90; /* CD: request granted */
618 s4_rsp.dest_port = 0; /* ignored */ 628 s4_rsp.dest_port = 0; /* ignored */
619 s4_rsp.dest_ip.s_addr = INADDR_ANY; /* ignored */ 629 s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */
620 buffer_append(&c->output, (char *)&s4_rsp, sizeof(s4_rsp)); 630 buffer_append(&c->output, (char *)&s4_rsp, sizeof(s4_rsp));
621 631 return 1;
622 /* switch to next state */
623 c->type = SSH_CHANNEL_OPENING;
624 port_open_helper(c, "direct-tcpip");
625} 632}
626 633
634/* dynamic port forwarding */
635void
636channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
637{
638 u_char *p;
639 int have, ret;
640
641 have = buffer_len(&c->input);
642
643 debug2("channel %d: pre_dynamic: have %d", c->self, have);
644 buffer_dump(&c->input);
645 /* check if the fixed size part of the packet is in buffer. */
646 if (have < 4) {
647 /* need more */
648 FD_SET(c->sock, readset);
649 return;
650 }
651 /* try to guess the protocol */
652 p = buffer_ptr(&c->input);
653 switch (p[0]) {
654 case 0x04:
655 ret = channel_decode_socks4(c, readset, writeset);
656 break;
657#if 0
658 case 'C':
659 ret = channel_decode_https(c, readset, writeset);
660 break;
661 case 0x05:
662 ret = channel_decode_socks5(c, readset, writeset);
663 break;
664#endif
665 default:
666 ret = -1;
667 break;
668 }
669 if (ret < 0) {
670 channel_free(c->self);
671 } else if (ret == 0) {
672 debug2("channel %d: pre_dynamic: need more", c->self);
673 /* need more */
674 FD_SET(c->sock, readset);
675 } else {
676 /* switch to the next state */
677 c->type = SSH_CHANNEL_OPENING;
678 port_open_helper(c, "direct-tcpip");
679 }
680}
627 681
628/* This is our fake X11 server socket. */ 682/* This is our fake X11 server socket. */
629void 683void
@@ -846,16 +900,11 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
846 if (len <= 0) { 900 if (len <= 0) {
847 debug("channel %d: read<=0 rfd %d len %d", 901 debug("channel %d: read<=0 rfd %d len %d",
848 c->self, c->rfd, len); 902 c->self, c->rfd, len);
849 if (c->type == SSH_CHANNEL_DYNAMIC) { 903 if (c->type != SSH_CHANNEL_OPEN) {
850 /* 904 debug("channel %d: not open", c->self);
851 * we are not yet connected to a remote peer,
852 * so the connection-close protocol won't work
853 */
854 debug("channel %d: dynamic: closed", c->self);
855 channel_free(c->self); 905 channel_free(c->self);
856 return -1; 906 return -1;
857 } 907 } else if (compat13) {
858 if (compat13) {
859 buffer_consume(&c->output, buffer_len(&c->output)); 908 buffer_consume(&c->output, buffer_len(&c->output));
860 c->type = SSH_CHANNEL_INPUT_DRAINING; 909 c->type = SSH_CHANNEL_INPUT_DRAINING;
861 debug("Channel %d status set to input draining.", c->self); 910 debug("Channel %d status set to input draining.", c->self);
@@ -890,7 +939,11 @@ channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset)
890 if (len < 0 && (errno == EINTR || errno == EAGAIN)) 939 if (len < 0 && (errno == EINTR || errno == EAGAIN))
891 return 1; 940 return 1;
892 if (len <= 0) { 941 if (len <= 0) {
893 if (compat13) { 942 if (c->type != SSH_CHANNEL_OPEN) {
943 debug("channel %d: not open", c->self);
944 channel_free(c->self);
945 return -1;
946 } else if (compat13) {
894 buffer_consume(&c->output, buffer_len(&c->output)); 947 buffer_consume(&c->output, buffer_len(&c->output));
895 debug("Channel %d status set to input draining.", c->self); 948 debug("Channel %d status set to input draining.", c->self);
896 c->type = SSH_CHANNEL_INPUT_DRAINING; 949 c->type = SSH_CHANNEL_INPUT_DRAINING;
@@ -967,7 +1020,8 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
967int 1020int
968channel_check_window(Channel *c) 1021channel_check_window(Channel *c)
969{ 1022{
970 if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && 1023 if (c->type == SSH_CHANNEL_OPEN &&
1024 !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
971 c->local_window < c->local_window_max/2 && 1025 c->local_window < c->local_window_max/2 &&
972 c->local_consumed > 0) { 1026 c->local_consumed > 0) {
973 packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); 1027 packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
@@ -1016,12 +1070,6 @@ channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)
1016} 1070}
1017 1071
1018void 1072void
1019channel_post_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
1020{
1021 channel_handle_rfd(c, readset, writeset);
1022}
1023
1024void
1025channel_handler_init_20(void) 1073channel_handler_init_20(void)
1026{ 1074{
1027 channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20; 1075 channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20;
@@ -1039,7 +1087,7 @@ channel_handler_init_20(void)
1039 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; 1087 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
1040 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 1088 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
1041 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 1089 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
1042 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic; 1090 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open_2;
1043} 1091}
1044 1092
1045void 1093void
@@ -1061,7 +1109,7 @@ channel_handler_init_13(void)
1061 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 1109 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
1062 channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13; 1110 channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13;
1063 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 1111 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
1064 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic; 1112 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open_1;
1065} 1113}
1066 1114
1067void 1115void
@@ -1080,7 +1128,7 @@ channel_handler_init_15(void)
1080 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 1128 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
1081 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1; 1129 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1;
1082 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 1130 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
1083 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic; 1131 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open_1;
1084} 1132}
1085 1133
1086void 1134void