[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.
This commit is contained in:
Ben Lindstrom 2001-04-08 18:30:26 +00:00
Родитель 3fcf1a22b5
Коммит 3bb4f9da73
6 изменённых файлов: 220 добавлений и 55 удалений

Просмотреть файл

@ -15,6 +15,12 @@
do gid/groups-swap in addition to uid-swap, should help if /home/group
is chmod 750 + chgrp grp /home/group/, work be deraadt and me, thanks
to olar@openwall.com is comments. we had many requests for this.
- 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.
20010408
- OpenBSD CVS Sync
@ -4955,4 +4961,4 @@
- Wrote replacements for strlcpy and mkdtemp
- Released 1.0pre1
$Id: ChangeLog,v 1.1083 2001/04/08 18:26:59 mouring Exp $
$Id: ChangeLog,v 1.1084 2001/04/08 18:30:26 mouring Exp $

Просмотреть файл

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: buffer.c,v 1.11 2001/04/05 21:02:46 markus Exp $");
RCSID("$OpenBSD: buffer.c,v 1.12 2001/04/07 08:55:15 markus Exp $");
#include "xmalloc.h"
#include "buffer.h"
@ -156,5 +156,5 @@ buffer_dump(Buffer *buffer)
for (i = buffer->offset; i < buffer->end; i++)
fprintf(stderr, " %02x", ucp[i]);
fprintf(stderr, "\n");
fprintf(stderr, "\r\n");
}

Просмотреть файл

@ -40,7 +40,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: channels.c,v 1.102 2001/04/06 21:00:10 markus Exp $");
RCSID("$OpenBSD: channels.c,v 1.103 2001/04/07 08:55:17 markus Exp $");
#include <openssl/rsa.h>
#include <openssl/dsa.h>
@ -51,6 +51,7 @@ RCSID("$OpenBSD: channels.c,v 1.102 2001/04/06 21:00:10 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
#include "uidswap.h"
#include "log.h"
#include "misc.h"
@ -133,6 +134,8 @@ static int have_hostname_in_open = 0;
/* AF_UNSPEC or AF_INET or AF_INET6 */
extern int IPv4or6;
void port_open_helper(Channel *c, char *rtype);
/* Sets specific protocol options. */
void
@ -539,6 +542,89 @@ channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset)
}
}
#define SSH_SOCKS_HEAD 1+1+2+4
void
channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
{
u_char *p, *host;
int len, i, done, have;
char username[256];
struct {
u_int8_t version;
u_int8_t command;
u_int16_t dest_port;
struct in_addr dest_ip;
} s4_req, s4_rsp;
have = buffer_len(&c->input);
debug("channel %d: pre_dynamic have: %d", c->self, have);
/*buffer_dump(&c->input);*/
/* Check if the fixed size part of the packet is in buffer. */
if (have < SSH_SOCKS_HEAD + 1) {
/* need more */
FD_SET(c->sock, readset);
return;
}
/* Check for end of username */
p = buffer_ptr(&c->input);
done = 0;
for (i = SSH_SOCKS_HEAD; i < have; i++) {
if (p[i] == '\0') {
done = 1;
break;
}
}
if (!done) {
/* need more */
FD_SET(c->sock, readset);
return;
}
buffer_get(&c->input, (char *)&s4_req.version, 1);
buffer_get(&c->input, (char *)&s4_req.command, 1);
buffer_get(&c->input, (char *)&s4_req.dest_port, 2);
buffer_get(&c->input, (char *)&s4_req.dest_ip, 4);
p = buffer_ptr(&c->input);
len = strlen(p);
have = buffer_len(&c->input);
debug2("channel %d: pre_dynamic user: %s/%d", c->self, p, len);
if (len > have)
fatal("channel %d: pre_dynamic: len %d > have %d",
c->self, len, have);
strlcpy(username, p, sizeof(username));
buffer_consume(&c->input, len);
buffer_consume(&c->input, 1); /* trailing '\0' */
host = inet_ntoa(s4_req.dest_ip);
strlcpy(c->path, host, sizeof(c->path));
c->host_port = ntohs(s4_req.dest_port);
debug("channel %d: dynamic request received: "
"socks%x://%s@%s:%u/command?%u",
c->self, s4_req.version, username, host, c->host_port,
s4_req.command);
if ((s4_req.version != 4) || (s4_req.command != 1)) {
debug("channel %d: cannot handle: socks VN %d CN %d",
c->self, s4_req.version, s4_req.command);
channel_free(c->self);
return;
}
s4_rsp.version = 0; /* VN: version of reply code */
s4_rsp.command = 90; /* CD: request granted */
s4_rsp.dest_port = 0; /* ignored */
s4_rsp.dest_ip.s_addr = INADDR_ANY; /* ignored */
buffer_append(&c->output, (char *)&s4_rsp, sizeof(s4_rsp));
/* switch to next state */
c->type = SSH_CHANNEL_OPENING;
port_open_helper(c, "direct-tcpip");
}
/* This is our fake X11 server socket. */
void
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)
}
}
void
port_open_helper(Channel *c, char *rtype)
{
int direct;
char buf[1024];
char *remote_ipaddr = get_peer_ipaddr(c->sock);
u_short remote_port = get_peer_port(c->sock);
direct = (strcmp(rtype, "direct-tcpip") == 0);
snprintf(buf, sizeof buf,
"%s: listening port %d for %.100s port %d, "
"connect from %.200s port %d",
rtype, c->listening_port, c->path, c->host_port,
remote_ipaddr, remote_port);
xfree(c->remote_name);
c->remote_name = xstrdup(buf);
if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring(rtype);
packet_put_int(c->self);
packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket);
if (direct) {
/* target host, port */
packet_put_cstring(c->path);
packet_put_int(c->host_port);
} else {
/* listen address, port */
packet_put_cstring(c->path);
packet_put_int(c->listening_port);
}
/* originator host and port */
packet_put_cstring(remote_ipaddr);
packet_put_int(remote_port);
packet_send();
} else {
packet_start(SSH_MSG_PORT_OPEN);
packet_put_int(c->self);
packet_put_cstring(c->path);
packet_put_int(c->host_port);
if (have_hostname_in_open)
packet_put_cstring(c->remote_name);
packet_send();
}
xfree(remote_ipaddr);
}
/*
* This socket is listening for connections to a forwarded TCP/IP port.
*/
void
channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
{
Channel *nc;
struct sockaddr addr;
int newsock, newch;
int newsock, newch, nextstate;
socklen_t addrlen;
char buf[1024], *remote_ipaddr, *rtype;
int remote_port;
rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
"forwarded-tcpip" : "direct-tcpip";
char *rtype;
if (FD_ISSET(c->sock, readset)) {
debug("Connection to port %d forwarding "
"to %.100s port %d requested.",
c->listening_port, c->path, c->host_port);
rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
"forwarded-tcpip" : "direct-tcpip";
nextstate = (c->host_port == 0) ? SSH_CHANNEL_DYNAMIC :
SSH_CHANNEL_OPENING;
addrlen = sizeof(addr);
newsock = accept(c->sock, &addr, &addrlen);
if (newsock < 0) {
error("accept: %.100s", strerror(errno));
return;
}
remote_ipaddr = get_peer_ipaddr(newsock);
remote_port = get_peer_port(newsock);
snprintf(buf, sizeof buf,
"listen port %d for %.100s port %d, "
"connect from %.200s port %d",
c->listening_port, c->path, c->host_port,
remote_ipaddr, remote_port);
newch = channel_new(rtype,
SSH_CHANNEL_OPENING, newsock, newsock, -1,
nextstate, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket,
0, xstrdup(buf), 1);
if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring(rtype);
packet_put_int(newch);
packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket);
if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
/* listen address, port */
packet_put_string(c->path, strlen(c->path));
packet_put_int(c->listening_port);
} else {
/* target host, port */
packet_put_string(c->path, strlen(c->path));
packet_put_int(c->host_port);
}
/* originator host and port */
packet_put_cstring(remote_ipaddr);
packet_put_int(remote_port);
packet_send();
} else {
packet_start(SSH_MSG_PORT_OPEN);
packet_put_int(newch);
packet_put_string(c->path, strlen(c->path));
packet_put_int(c->host_port);
if (have_hostname_in_open) {
packet_put_string(buf, strlen(buf));
}
packet_send();
0, xstrdup(rtype), 1);
nc = channel_lookup(newch);
if (nc == NULL) {
error("xxx: no new channel:");
return;
}
xfree(remote_ipaddr);
nc->listening_port = c->listening_port;
nc->host_port = c->host_port;
strlcpy(nc->path, c->path, sizeof(nc->path));
if (nextstate != SSH_CHANNEL_DYNAMIC)
port_open_helper(nc, rtype);
}
}
@ -733,6 +846,15 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
if (len <= 0) {
debug("channel %d: read<=0 rfd %d len %d",
c->self, c->rfd, len);
if (c->type == SSH_CHANNEL_DYNAMIC) {
/*
* we are not yet connected to a remote peer,
* so the connection-close protocol won't work
*/
debug("channel %d: dynamic: closed", c->self);
channel_free(c->self);
return -1;
}
if (compat13) {
buffer_consume(&c->output, buffer_len(&c->output));
c->type = SSH_CHANNEL_INPUT_DRAINING;
@ -893,6 +1015,12 @@ channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)
}
}
void
channel_post_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
{
channel_handle_rfd(c, readset, writeset);
}
void
channel_handler_init_20(void)
{
@ -903,6 +1031,7 @@ channel_handler_init_20(void)
channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2;
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
@ -910,6 +1039,7 @@ channel_handler_init_20(void)
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic;
}
void
@ -923,6 +1053,7 @@ channel_handler_init_13(void)
channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining;
channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining;
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1;
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
@ -930,6 +1061,7 @@ channel_handler_init_13(void)
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13;
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic;
}
void
@ -941,12 +1073,14 @@ channel_handler_init_15(void)
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1;
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_dynamic;
}
void
@ -1500,6 +1634,7 @@ channel_still_open()
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_AUTH_SOCKET:
case SSH_CHANNEL_DYNAMIC:
case SSH_CHANNEL_CONNECTING: /* XXX ??? */
continue;
case SSH_CHANNEL_LARVAL:
@ -1551,6 +1686,7 @@ channel_open_message()
case SSH_CHANNEL_LARVAL:
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_DYNAMIC:
case SSH_CHANNEL_OPEN:
case SSH_CHANNEL_X11_OPEN:
case SSH_CHANNEL_INPUT_DRAINING:

Просмотреть файл

@ -32,7 +32,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* RCSID("$OpenBSD: channels.h,v 1.29 2001/04/04 20:25:36 markus Exp $"); */
/* RCSID("$OpenBSD: channels.h,v 1.30 2001/04/07 08:55:17 markus Exp $"); */
#ifndef CHANNELS_H
#define CHANNELS_H
@ -53,7 +53,8 @@
#define SSH_CHANNEL_LARVAL 10 /* larval session */
#define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */
#define SSH_CHANNEL_CONNECTING 12
#define SSH_CHANNEL_MAX_TYPE 13
#define SSH_CHANNEL_DYNAMIC 13
#define SSH_CHANNEL_MAX_TYPE 14
/*
* Data structure for channel data. This is iniailized in channel_allocate

Просмотреть файл

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: readconf.c,v 1.70 2001/04/02 14:20:23 stevesk Exp $");
RCSID("$OpenBSD: readconf.c,v 1.71 2001/04/07 08:55:17 markus Exp $");
#include "ssh.h"
#include "xmalloc.h"
@ -110,7 +110,7 @@ typedef enum {
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
oPreferredAuthentications
oDynamicForward, oPreferredAuthentications
} OpCodes;
/* Textual representations of the tokens. */
@ -172,6 +172,7 @@ static struct {
{ "keepalive", oKeepAlives },
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
{ "loglevel", oLogLevel },
{ "dynamicforward", oDynamicForward },
{ "preferredauthentications", oPreferredAuthentications },
{ NULL, 0 }
};
@ -583,6 +584,18 @@ parse_int:
add_local_forward(options, fwd_port, buf, fwd_host_port);
break;
case oDynamicForward:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing port argument.",
filename, linenum);
if (arg[0] < '0' || arg[0] > '9')
fatal("%.200s line %d: Badly formatted port number.",
filename, linenum);
fwd_port = atoi(arg);
add_local_forward(options, fwd_port, "socks4", 0);
break;
case oHost:
*activep = 0;
while ((arg = strdelim(&s)) != NULL && *arg != '\0')

13
ssh.c
Просмотреть файл

@ -39,7 +39,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh.c,v 1.107 2001/04/06 21:00:13 markus Exp $");
RCSID("$OpenBSD: ssh.c,v 1.108 2001/04/07 08:55:18 markus Exp $");
#include <openssl/evp.h>
#include <openssl/err.h>
@ -178,6 +178,9 @@ usage(void)
fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n");
fprintf(stderr, " These cause %s to listen for connections on a port, and\n", __progname);
fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
fprintf(stderr, " -D port Dynamically forward local port to multiple remote addresses.\n");
fprintf(stderr, " Allows SSH to act as an application-layer proxy.\n");
fprintf(stderr, " Protocols Supported: SOCKS4\n");
fprintf(stderr, " -C Enable compression.\n");
fprintf(stderr, " -N Do not execute a shell or command.\n");
fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n");
@ -314,7 +317,7 @@ main(int ac, char **av)
opt = av[optind][1];
if (!opt)
usage();
if (strchr("eilcmpLRo", opt)) { /* options with arguments */
if (strchr("eilcmpLRDo", opt)) { /* options with arguments */
optarg = av[optind] + 2;
if (strcmp(optarg, "") == 0) {
if (optind >= ac - 1)
@ -480,6 +483,12 @@ main(int ac, char **av)
}
add_local_forward(&options, fwd_port, buf, fwd_host_port);
break;
case 'D':
fwd_port = atoi(optarg);
add_local_forward(&options, fwd_port, "socks4", 0);
break;
case 'C':
options.compression = 1;
break;