diff options
author | Ben Lindstrom <mouring@eviladmin.org> | 2001-04-08 18:30:26 +0000 |
---|---|---|
committer | Ben Lindstrom <mouring@eviladmin.org> | 2001-04-08 18:30:26 +0000 |
commit | 3bb4f9da7382e62dc08eb72ba8307c28d4ccc566 (patch) | |
tree | 543bfbb95923d8b21e28086d1d60641a8d4f8f28 | |
parent | 3fcf1a22b52ed8e66d2cf548d5d4528f67377af9 (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.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | buffer.c | 4 | ||||
-rw-r--r-- | channels.c | 228 | ||||
-rw-r--r-- | channels.h | 5 | ||||
-rw-r--r-- | readconf.c | 17 | ||||
-rw-r--r-- | ssh.c | 13 |
6 files changed, 220 insertions, 55 deletions
@@ -15,6 +15,12 @@ | |||
15 | do gid/groups-swap in addition to uid-swap, should help if /home/group | 15 | do gid/groups-swap in addition to uid-swap, should help if /home/group |
16 | is chmod 750 + chgrp grp /home/group/, work be deraadt and me, thanks | 16 | is chmod 750 + chgrp grp /home/group/, work be deraadt and me, thanks |
17 | to olar@openwall.com is comments. we had many requests for this. | 17 | to olar@openwall.com is comments. we had many requests for this. |
18 | - markus@cvs.openbsd.org 2001/04/07 08:55:18 | ||
19 | [buffer.c channels.c channels.h readconf.c ssh.c] | ||
20 | allow the ssh client act as a SOCKS4 proxy (dynamic local | ||
21 | portforwarding). work by Dan Kaminsky <dankamin@cisco.com> and me. | ||
22 | thanks to Dan for this great patch: use 'ssh -D 1080 host' and make | ||
23 | netscape use localhost:1080 as a socks proxy. | ||
18 | 24 | ||
19 | 20010408 | 25 | 20010408 |
20 | - OpenBSD CVS Sync | 26 | - OpenBSD CVS Sync |
@@ -4955,4 +4961,4 @@ | |||
4955 | - Wrote replacements for strlcpy and mkdtemp | 4961 | - Wrote replacements for strlcpy and mkdtemp |
4956 | - Released 1.0pre1 | 4962 | - Released 1.0pre1 |
4957 | 4963 | ||
4958 | $Id: ChangeLog,v 1.1083 2001/04/08 18:26:59 mouring Exp $ | 4964 | $Id: ChangeLog,v 1.1084 2001/04/08 18:30:26 mouring Exp $ |
@@ -12,7 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include "includes.h" | 14 | #include "includes.h" |
15 | RCSID("$OpenBSD: buffer.c,v 1.11 2001/04/05 21:02:46 markus Exp $"); | 15 | RCSID("$OpenBSD: buffer.c,v 1.12 2001/04/07 08:55:15 markus Exp $"); |
16 | 16 | ||
17 | #include "xmalloc.h" | 17 | #include "xmalloc.h" |
18 | #include "buffer.h" | 18 | #include "buffer.h" |
@@ -156,5 +156,5 @@ buffer_dump(Buffer *buffer) | |||
156 | 156 | ||
157 | for (i = buffer->offset; i < buffer->end; i++) | 157 | for (i = buffer->offset; i < buffer->end; i++) |
158 | fprintf(stderr, " %02x", ucp[i]); | 158 | fprintf(stderr, " %02x", ucp[i]); |
159 | fprintf(stderr, "\n"); | 159 | fprintf(stderr, "\r\n"); |
160 | } | 160 | } |
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" |
43 | RCSID("$OpenBSD: channels.c,v 1.102 2001/04/06 21:00:10 markus Exp $"); | 43 | RCSID("$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 */ |
134 | extern int IPv4or6; | 135 | extern int IPv4or6; |
135 | 136 | ||
137 | void port_open_helper(Channel *c, char *rtype); | ||
138 | |||
136 | /* Sets specific protocol options. */ | 139 | /* Sets specific protocol options. */ |
137 | 140 | ||
138 | void | 141 | void |
@@ -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 | |||
547 | void | ||
548 | channel_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. */ |
543 | void | 629 | void |
544 | channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) | 630 | channel_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 | ||
680 | void | ||
681 | port_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 | */ |
597 | void | 733 | void |
598 | channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) | 734 | channel_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 | ||
896 | void | 1018 | void |
1019 | channel_post_dynamic(Channel *c, fd_set * readset, fd_set * writeset) | ||
1020 | { | ||
1021 | channel_handle_rfd(c, readset, writeset); | ||
1022 | } | ||
1023 | |||
1024 | void | ||
897 | channel_handler_init_20(void) | 1025 | channel_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 | ||
915 | void | 1045 | void |
@@ -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 | ||
935 | void | 1067 | void |
@@ -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 | ||
952 | void | 1086 | void |
@@ -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: |
diff --git a/channels.h b/channels.h index 2cd82148e..23e6ece83 100644 --- a/channels.h +++ b/channels.h | |||
@@ -32,7 +32,7 @@ | |||
32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | */ | 34 | */ |
35 | /* RCSID("$OpenBSD: channels.h,v 1.29 2001/04/04 20:25:36 markus Exp $"); */ | 35 | /* RCSID("$OpenBSD: channels.h,v 1.30 2001/04/07 08:55:17 markus Exp $"); */ |
36 | 36 | ||
37 | #ifndef CHANNELS_H | 37 | #ifndef CHANNELS_H |
38 | #define CHANNELS_H | 38 | #define CHANNELS_H |
@@ -53,7 +53,8 @@ | |||
53 | #define SSH_CHANNEL_LARVAL 10 /* larval session */ | 53 | #define SSH_CHANNEL_LARVAL 10 /* larval session */ |
54 | #define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ | 54 | #define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ |
55 | #define SSH_CHANNEL_CONNECTING 12 | 55 | #define SSH_CHANNEL_CONNECTING 12 |
56 | #define SSH_CHANNEL_MAX_TYPE 13 | 56 | #define SSH_CHANNEL_DYNAMIC 13 |
57 | #define SSH_CHANNEL_MAX_TYPE 14 | ||
57 | 58 | ||
58 | /* | 59 | /* |
59 | * Data structure for channel data. This is iniailized in channel_allocate | 60 | * Data structure for channel data. This is iniailized in channel_allocate |
diff --git a/readconf.c b/readconf.c index 365f67eb0..007056d4d 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -12,7 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include "includes.h" | 14 | #include "includes.h" |
15 | RCSID("$OpenBSD: readconf.c,v 1.70 2001/04/02 14:20:23 stevesk Exp $"); | 15 | RCSID("$OpenBSD: readconf.c,v 1.71 2001/04/07 08:55:17 markus Exp $"); |
16 | 16 | ||
17 | #include "ssh.h" | 17 | #include "ssh.h" |
18 | #include "xmalloc.h" | 18 | #include "xmalloc.h" |
@@ -110,7 +110,7 @@ typedef enum { | |||
110 | oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, | 110 | oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, |
111 | oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, | 111 | oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, |
112 | oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, | 112 | oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, |
113 | oPreferredAuthentications | 113 | oDynamicForward, oPreferredAuthentications |
114 | } OpCodes; | 114 | } OpCodes; |
115 | 115 | ||
116 | /* Textual representations of the tokens. */ | 116 | /* Textual representations of the tokens. */ |
@@ -172,6 +172,7 @@ static struct { | |||
172 | { "keepalive", oKeepAlives }, | 172 | { "keepalive", oKeepAlives }, |
173 | { "numberofpasswordprompts", oNumberOfPasswordPrompts }, | 173 | { "numberofpasswordprompts", oNumberOfPasswordPrompts }, |
174 | { "loglevel", oLogLevel }, | 174 | { "loglevel", oLogLevel }, |
175 | { "dynamicforward", oDynamicForward }, | ||
175 | { "preferredauthentications", oPreferredAuthentications }, | 176 | { "preferredauthentications", oPreferredAuthentications }, |
176 | { NULL, 0 } | 177 | { NULL, 0 } |
177 | }; | 178 | }; |
@@ -583,6 +584,18 @@ parse_int: | |||
583 | add_local_forward(options, fwd_port, buf, fwd_host_port); | 584 | add_local_forward(options, fwd_port, buf, fwd_host_port); |
584 | break; | 585 | break; |
585 | 586 | ||
587 | case oDynamicForward: | ||
588 | arg = strdelim(&s); | ||
589 | if (!arg || *arg == '\0') | ||
590 | fatal("%.200s line %d: Missing port argument.", | ||
591 | filename, linenum); | ||
592 | if (arg[0] < '0' || arg[0] > '9') | ||
593 | fatal("%.200s line %d: Badly formatted port number.", | ||
594 | filename, linenum); | ||
595 | fwd_port = atoi(arg); | ||
596 | add_local_forward(options, fwd_port, "socks4", 0); | ||
597 | break; | ||
598 | |||
586 | case oHost: | 599 | case oHost: |
587 | *activep = 0; | 600 | *activep = 0; |
588 | while ((arg = strdelim(&s)) != NULL && *arg != '\0') | 601 | while ((arg = strdelim(&s)) != NULL && *arg != '\0') |
@@ -39,7 +39,7 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include "includes.h" | 41 | #include "includes.h" |
42 | RCSID("$OpenBSD: ssh.c,v 1.107 2001/04/06 21:00:13 markus Exp $"); | 42 | RCSID("$OpenBSD: ssh.c,v 1.108 2001/04/07 08:55:18 markus Exp $"); |
43 | 43 | ||
44 | #include <openssl/evp.h> | 44 | #include <openssl/evp.h> |
45 | #include <openssl/err.h> | 45 | #include <openssl/err.h> |
@@ -178,6 +178,9 @@ usage(void) | |||
178 | fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n"); | 178 | fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n"); |
179 | fprintf(stderr, " These cause %s to listen for connections on a port, and\n", __progname); | 179 | fprintf(stderr, " These cause %s to listen for connections on a port, and\n", __progname); |
180 | fprintf(stderr, " forward them to the other side by connecting to host:port.\n"); | 180 | fprintf(stderr, " forward them to the other side by connecting to host:port.\n"); |
181 | fprintf(stderr, " -D port Dynamically forward local port to multiple remote addresses.\n"); | ||
182 | fprintf(stderr, " Allows SSH to act as an application-layer proxy.\n"); | ||
183 | fprintf(stderr, " Protocols Supported: SOCKS4\n"); | ||
181 | fprintf(stderr, " -C Enable compression.\n"); | 184 | fprintf(stderr, " -C Enable compression.\n"); |
182 | fprintf(stderr, " -N Do not execute a shell or command.\n"); | 185 | fprintf(stderr, " -N Do not execute a shell or command.\n"); |
183 | fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n"); | 186 | fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n"); |
@@ -314,7 +317,7 @@ main(int ac, char **av) | |||
314 | opt = av[optind][1]; | 317 | opt = av[optind][1]; |
315 | if (!opt) | 318 | if (!opt) |
316 | usage(); | 319 | usage(); |
317 | if (strchr("eilcmpLRo", opt)) { /* options with arguments */ | 320 | if (strchr("eilcmpLRDo", opt)) { /* options with arguments */ |
318 | optarg = av[optind] + 2; | 321 | optarg = av[optind] + 2; |
319 | if (strcmp(optarg, "") == 0) { | 322 | if (strcmp(optarg, "") == 0) { |
320 | if (optind >= ac - 1) | 323 | if (optind >= ac - 1) |
@@ -480,6 +483,12 @@ main(int ac, char **av) | |||
480 | } | 483 | } |
481 | add_local_forward(&options, fwd_port, buf, fwd_host_port); | 484 | add_local_forward(&options, fwd_port, buf, fwd_host_port); |
482 | break; | 485 | break; |
486 | |||
487 | case 'D': | ||
488 | fwd_port = atoi(optarg); | ||
489 | add_local_forward(&options, fwd_port, "socks4", 0); | ||
490 | break; | ||
491 | |||
483 | case 'C': | 492 | case 'C': |
484 | options.compression = 1; | 493 | options.compression = 1; |
485 | break; | 494 | break; |