summaryrefslogtreecommitdiffstats
path: root/channels.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2009-01-28 16:24:41 +1100
committerDamien Miller <djm@mindrot.org>2009-01-28 16:24:41 +1100
commit1781f53d7540778fa50991d9b5aaf8f4b4a2eafd (patch)
treec53cf1aa2ea3c62479f37ac954020a0df316d018 /channels.c
parentccf7e224ab73a8134175504ff09d72655ba50fb2 (diff)
- djm@cvs.openbsd.org 2009/01/14 01:38:06
[channels.c] support SOCKS4A protocol, from dwmw2 AT infradead.org via bz#1482; "looks ok" markus@
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/channels.c b/channels.c
index d138882b..2319afd4 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.291 2009/01/01 21:14:35 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.292 2009/01/14 01:38:06 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -980,7 +980,7 @@ static int
channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
{
char *p, *host;
- u_int len, have, i, found;
+ u_int len, have, i, found, need;
char username[256];
struct {
u_int8_t version;
@@ -996,10 +996,20 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
if (have < len)
return 0;
p = buffer_ptr(&c->input);
+
+ need = 1;
+ /* SOCKS4A uses an invalid IP address 0.0.0.x */
+ if (p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] != 0) {
+ debug2("channel %d: socks4a request", c->self);
+ /* ... and needs an extra string (the hostname) */
+ need = 2;
+ }
+ /* Check for terminating NUL on the string(s) */
for (found = 0, i = len; i < have; i++) {
if (p[i] == '\0') {
- found = 1;
- break;
+ found++;
+ if (found == need)
+ break;
}
if (i > 1024) {
/* the peer is probably sending garbage */
@@ -1008,7 +1018,7 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
return -1;
}
}
- if (!found)
+ if (found < need)
return 0;
buffer_get(&c->input, (char *)&s4_req.version, 1);
buffer_get(&c->input, (char *)&s4_req.command, 1);
@@ -1018,23 +1028,41 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
p = buffer_ptr(&c->input);
len = strlen(p);
debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);
+ len++; /* trailing '\0' */
if (len > have)
fatal("channel %d: decode socks4: 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_addr);
- strlcpy(c->path, host, sizeof(c->path));
+ if (need == 1) { /* SOCKS4: one string */
+ host = inet_ntoa(s4_req.dest_addr);
+ strlcpy(c->path, host, sizeof(c->path));
+ } else { /* SOCKS4A: two strings */
+ have = buffer_len(&c->input);
+ p = buffer_ptr(&c->input);
+ len = strlen(p);
+ debug2("channel %d: decode socks4a: host %s/%d",
+ c->self, p, len);
+ len++; /* trailing '\0' */
+ if (len > have)
+ fatal("channel %d: decode socks4a: len %d > have %d",
+ c->self, len, have);
+ if (strlcpy(c->path, p, sizeof(c->path)) >= sizeof(c->path)) {
+ error("channel %d: hostname \"%.100s\" too long",
+ c->self, p);
+ return -1;
+ }
+ buffer_consume(&c->input, len);
+ }
c->host_port = ntohs(s4_req.dest_port);
debug2("channel %d: dynamic request: socks4 host %s port %u command %u",
- c->self, host, c->host_port, s4_req.command);
+ c->self, c->path, c->host_port, s4_req.command);
if (s4_req.command != 1) {
- debug("channel %d: cannot handle: socks4 cn %d",
- c->self, s4_req.command);
+ debug("channel %d: cannot handle: %s cn %d",
+ c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command);
return -1;
}
s4_rsp.version = 0; /* vn: 0 for reply */