summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
authorBen Lindstrom <mouring@eviladmin.org>2001-04-08 18:30:26 +0000
committerBen Lindstrom <mouring@eviladmin.org>2001-04-08 18:30:26 +0000
commit3bb4f9da7382e62dc08eb72ba8307c28d4ccc566 (patch)
tree543bfbb95923d8b21e28086d1d60641a8d4f8f28 /channels.c
parent3fcf1a22b52ed8e66d2cf548d5d4528f67377af9 (diff)
- markus@cvs.openbsd.org 2001/04/07 08:55:18
[buffer.c channels.c channels.h readconf.c ssh.c] allow the ssh client act as a SOCKS4 proxy (dynamic local portforwarding). work by Dan Kaminsky <dankamin@cisco.com> and me. thanks to Dan for this great patch: use 'ssh -D 1080 host' and make netscape use localhost:1080 as a socks proxy.
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c228
1 files changed, 182 insertions, 46 deletions
diff --git a/channels.c b/channels.c
index d5526fb83..0e334db88 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.102 2001/04/06 21:00:10 markus Exp $"); 43RCSID("$OpenBSD: channels.c,v 1.103 2001/04/07 08:55:17 markus Exp $");
44 44
45#include <openssl/rsa.h> 45#include <openssl/rsa.h>
46#include <openssl/dsa.h> 46#include <openssl/dsa.h>
@@ -51,6 +51,7 @@ RCSID("$OpenBSD: channels.c,v 1.102 2001/04/06 21:00:10 markus Exp $");
51#include "packet.h" 51#include "packet.h"
52#include "xmalloc.h" 52#include "xmalloc.h"
53#include "buffer.h" 53#include "buffer.h"
54#include "bufaux.h"
54#include "uidswap.h" 55#include "uidswap.h"
55#include "log.h" 56#include "log.h"
56#include "misc.h" 57#include "misc.h"
@@ -133,6 +134,8 @@ static int have_hostname_in_open = 0;
133/* AF_UNSPEC or AF_INET or AF_INET6 */ 134/* AF_UNSPEC or AF_INET or AF_INET6 */
134extern int IPv4or6; 135extern int IPv4or6;
135 136
137void port_open_helper(Channel *c, char *rtype);
138
136/* Sets specific protocol options. */ 139/* Sets specific protocol options. */
137 140
138void 141void
@@ -539,6 +542,89 @@ channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset)
539 } 542 }
540} 543}
541 544
545#define SSH_SOCKS_HEAD 1+1+2+4
546
547void
548channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
549{
550 u_char *p, *host;
551 int len, i, done, have;
552 char username[256];
553 struct {
554 u_int8_t version;
555 u_int8_t command;
556 u_int16_t dest_port;
557 struct in_addr dest_ip;
558 } s4_req, s4_rsp;
559
560 have = buffer_len(&c->input);
561
562 debug("channel %d: pre_dynamic have: %d", c->self, have);
563 /*buffer_dump(&c->input);*/
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);
586 buffer_get(&c->input, (char *)&s4_req.command, 1);
587 buffer_get(&c->input, (char *)&s4_req.dest_port, 2);
588 buffer_get(&c->input, (char *)&s4_req.dest_ip, 4);
589 p = buffer_ptr(&c->input);
590 len = strlen(p);
591 have = buffer_len(&c->input);
592 debug2("channel %d: pre_dynamic user: %s/%d", c->self, p, len);
593 if (len > have)
594 fatal("channel %d: pre_dynamic: len %d > have %d",
595 c->self, len, have);
596 strlcpy(username, p, sizeof(username));
597 buffer_consume(&c->input, len);
598 buffer_consume(&c->input, 1); /* trailing '\0' */
599
600 host = inet_ntoa(s4_req.dest_ip);
601 strlcpy(c->path, host, sizeof(c->path));
602 c->host_port = ntohs(s4_req.dest_port);
603
604 debug("channel %d: dynamic request received: "
605 "socks%x://%s@%s:%u/command?%u",
606 c->self, s4_req.version, username, host, c->host_port,
607 s4_req.command);
608
609 if ((s4_req.version != 4) || (s4_req.command != 1)) {
610 debug("channel %d: cannot handle: socks VN %d CN %d",
611 c->self, s4_req.version, s4_req.command);
612 channel_free(c->self);
613 return;
614 }
615
616 s4_rsp.version = 0; /* VN: version of reply code */
617 s4_rsp.command = 90; /* CD: request granted */
618 s4_rsp.dest_port = 0; /* ignored */
619 s4_rsp.dest_ip.s_addr = INADDR_ANY; /* ignored */
620 buffer_append(&c->output, (char *)&s4_rsp, sizeof(s4_rsp));
621
622 /* switch to next state */
623 c->type = SSH_CHANNEL_OPENING;
624 port_open_helper(c, "direct-tcpip");
625}
626
627
542/* This is our fake X11 server socket. */ 628/* This is our fake X11 server socket. */
543void 629void
544channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) 630channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
@@ -591,73 +677,100 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
591 } 677 }
592} 678}
593 679
680void
681port_open_helper(Channel *c, char *rtype)
682{
683 int direct;
684 char buf[1024];
685 char *remote_ipaddr = get_peer_ipaddr(c->sock);
686 u_short remote_port = get_peer_port(c->sock);
687
688 direct = (strcmp(rtype, "direct-tcpip") == 0);
689
690 snprintf(buf, sizeof buf,
691 "%s: listening port %d for %.100s port %d, "
692 "connect from %.200s port %d",
693 rtype, c->listening_port, c->path, c->host_port,
694 remote_ipaddr, remote_port);
695
696 xfree(c->remote_name);
697 c->remote_name = xstrdup(buf);
698
699 if (compat20) {
700 packet_start(SSH2_MSG_CHANNEL_OPEN);
701 packet_put_cstring(rtype);
702 packet_put_int(c->self);
703 packet_put_int(c->local_window_max);
704 packet_put_int(c->local_maxpacket);
705 if (direct) {
706 /* target host, port */
707 packet_put_cstring(c->path);
708 packet_put_int(c->host_port);
709 } else {
710 /* listen address, port */
711 packet_put_cstring(c->path);
712 packet_put_int(c->listening_port);
713 }
714 /* originator host and port */
715 packet_put_cstring(remote_ipaddr);
716 packet_put_int(remote_port);
717 packet_send();
718 } else {
719 packet_start(SSH_MSG_PORT_OPEN);
720 packet_put_int(c->self);
721 packet_put_cstring(c->path);
722 packet_put_int(c->host_port);
723 if (have_hostname_in_open)
724 packet_put_cstring(c->remote_name);
725 packet_send();
726 }
727 xfree(remote_ipaddr);
728}
729
594/* 730/*
595 * This socket is listening for connections to a forwarded TCP/IP port. 731 * This socket is listening for connections to a forwarded TCP/IP port.
596 */ 732 */
597void 733void
598channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) 734channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
599{ 735{
736 Channel *nc;
600 struct sockaddr addr; 737 struct sockaddr addr;
601 int newsock, newch; 738 int newsock, newch, nextstate;
602 socklen_t addrlen; 739 socklen_t addrlen;
603 char buf[1024], *remote_ipaddr, *rtype; 740 char *rtype;
604 int remote_port;
605
606 rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
607 "forwarded-tcpip" : "direct-tcpip";
608 741
609 if (FD_ISSET(c->sock, readset)) { 742 if (FD_ISSET(c->sock, readset)) {
610 debug("Connection to port %d forwarding " 743 debug("Connection to port %d forwarding "
611 "to %.100s port %d requested.", 744 "to %.100s port %d requested.",
612 c->listening_port, c->path, c->host_port); 745 c->listening_port, c->path, c->host_port);
746
747 rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
748 "forwarded-tcpip" : "direct-tcpip";
749 nextstate = (c->host_port == 0) ? SSH_CHANNEL_DYNAMIC :
750 SSH_CHANNEL_OPENING;
751
613 addrlen = sizeof(addr); 752 addrlen = sizeof(addr);
614 newsock = accept(c->sock, &addr, &addrlen); 753 newsock = accept(c->sock, &addr, &addrlen);
615 if (newsock < 0) { 754 if (newsock < 0) {
616 error("accept: %.100s", strerror(errno)); 755 error("accept: %.100s", strerror(errno));
617 return; 756 return;
618 } 757 }
619 remote_ipaddr = get_peer_ipaddr(newsock);
620 remote_port = get_peer_port(newsock);
621 snprintf(buf, sizeof buf,
622 "listen port %d for %.100s port %d, "
623 "connect from %.200s port %d",
624 c->listening_port, c->path, c->host_port,
625 remote_ipaddr, remote_port);
626
627 newch = channel_new(rtype, 758 newch = channel_new(rtype,
628 SSH_CHANNEL_OPENING, newsock, newsock, -1, 759 nextstate, newsock, newsock, -1,
629 c->local_window_max, c->local_maxpacket, 760 c->local_window_max, c->local_maxpacket,
630 0, xstrdup(buf), 1); 761 0, xstrdup(rtype), 1);
631 if (compat20) { 762
632 packet_start(SSH2_MSG_CHANNEL_OPEN); 763 nc = channel_lookup(newch);
633 packet_put_cstring(rtype); 764 if (nc == NULL) {
634 packet_put_int(newch); 765 error("xxx: no new channel:");
635 packet_put_int(c->local_window_max); 766 return;
636 packet_put_int(c->local_maxpacket);
637 if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
638 /* listen address, port */
639 packet_put_string(c->path, strlen(c->path));
640 packet_put_int(c->listening_port);
641 } else {
642 /* target host, port */
643 packet_put_string(c->path, strlen(c->path));
644 packet_put_int(c->host_port);
645 }
646 /* originator host and port */
647 packet_put_cstring(remote_ipaddr);
648 packet_put_int(remote_port);
649 packet_send();
650 } else {
651 packet_start(SSH_MSG_PORT_OPEN);
652 packet_put_int(newch);
653 packet_put_string(c->path, strlen(c->path));
654 packet_put_int(c->host_port);
655 if (have_hostname_in_open) {
656 packet_put_string(buf, strlen(buf));
657 }
658 packet_send();
659 } 767 }
660 xfree(remote_ipaddr); 768 nc->listening_port = c->listening_port;
769 nc->host_port = c->host_port;
770 strlcpy(nc->path, c->path, sizeof(nc->path));
771
772 if (nextstate != SSH_CHANNEL_DYNAMIC)
773 port_open_helper(nc, rtype);
661 } 774 }
662} 775}
663 776
@@ -733,6 +846,15 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
733 if (len <= 0) { 846 if (len <= 0) {
734 debug("channel %d: read<=0 rfd %d len %d", 847 debug("channel %d: read<=0 rfd %d len %d",
735 c->self, c->rfd, len); 848 c->self, c->rfd, len);
849 if (c->type == SSH_CHANNEL_DYNAMIC) {
850 /*
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);
856 return -1;
857 }
736 if (compat13) { 858 if (compat13) {
737 buffer_consume(&c->output, buffer_len(&c->output)); 859 buffer_consume(&c->output, buffer_len(&c->output));
738 c->type = SSH_CHANNEL_INPUT_DRAINING; 860 c->type = SSH_CHANNEL_INPUT_DRAINING;
@@ -894,6 +1016,12 @@ channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)
894} 1016}
895 1017
896void 1018void
1019channel_post_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
1020{
1021 channel_handle_rfd(c, readset, writeset);
1022}
1023
1024void
897channel_handler_init_20(void) 1025channel_handler_init_20(void)
898{ 1026{
899 channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20; 1027 channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20;
@@ -903,6 +1031,7 @@ channel_handler_init_20(void)
903 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; 1031 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
904 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; 1032 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
905 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; 1033 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
1034 channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
906 1035
907 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2; 1036 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2;
908 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; 1037 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
@@ -910,6 +1039,7 @@ channel_handler_init_20(void)
910 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; 1039 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
911 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 1040 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
912 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 1041 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
1042 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic;
913} 1043}
914 1044
915void 1045void
@@ -923,6 +1053,7 @@ channel_handler_init_13(void)
923 channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining; 1053 channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining;
924 channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining; 1054 channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining;
925 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; 1055 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
1056 channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
926 1057
927 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1; 1058 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1;
928 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; 1059 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
@@ -930,6 +1061,7 @@ channel_handler_init_13(void)
930 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 1061 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
931 channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13; 1062 channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13;
932 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 1063 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
1064 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic;
933} 1065}
934 1066
935void 1067void
@@ -941,12 +1073,14 @@ channel_handler_init_15(void)
941 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; 1073 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
942 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; 1074 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
943 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; 1075 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
1076 channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
944 1077
945 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; 1078 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
946 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; 1079 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
947 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 1080 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
948 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1; 1081 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1;
949 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 1082 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
1083 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic;
950} 1084}
951 1085
952void 1086void
@@ -1500,6 +1634,7 @@ channel_still_open()
1500 case SSH_CHANNEL_RPORT_LISTENER: 1634 case SSH_CHANNEL_RPORT_LISTENER:
1501 case SSH_CHANNEL_CLOSED: 1635 case SSH_CHANNEL_CLOSED:
1502 case SSH_CHANNEL_AUTH_SOCKET: 1636 case SSH_CHANNEL_AUTH_SOCKET:
1637 case SSH_CHANNEL_DYNAMIC:
1503 case SSH_CHANNEL_CONNECTING: /* XXX ??? */ 1638 case SSH_CHANNEL_CONNECTING: /* XXX ??? */
1504 continue; 1639 continue;
1505 case SSH_CHANNEL_LARVAL: 1640 case SSH_CHANNEL_LARVAL:
@@ -1551,6 +1686,7 @@ channel_open_message()
1551 case SSH_CHANNEL_LARVAL: 1686 case SSH_CHANNEL_LARVAL:
1552 case SSH_CHANNEL_OPENING: 1687 case SSH_CHANNEL_OPENING:
1553 case SSH_CHANNEL_CONNECTING: 1688 case SSH_CHANNEL_CONNECTING:
1689 case SSH_CHANNEL_DYNAMIC:
1554 case SSH_CHANNEL_OPEN: 1690 case SSH_CHANNEL_OPEN:
1555 case SSH_CHANNEL_X11_OPEN: 1691 case SSH_CHANNEL_X11_OPEN:
1556 case SSH_CHANNEL_INPUT_DRAINING: 1692 case SSH_CHANNEL_INPUT_DRAINING: