diff options
-rw-r--r-- | usr.bin/nc/nc.1 | 32 | ||||
-rw-r--r-- | usr.bin/nc/netcat.c | 19 | ||||
-rw-r--r-- | usr.bin/nc/socks.c | 86 |
3 files changed, 111 insertions, 26 deletions
diff --git a/usr.bin/nc/nc.1 b/usr.bin/nc/nc.1 index 182950a9524..44cdb14bbca 100644 --- a/usr.bin/nc/nc.1 +++ b/usr.bin/nc/nc.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: nc.1,v 1.32 2004/07/15 15:07:52 markus Exp $ +.\" $OpenBSD: nc.1,v 1.33 2004/10/17 03:13:55 djm Exp $ .\" .\" Copyright (c) 1996 David Sacerdote .\" All rights reserved. @@ -39,7 +39,7 @@ .Op Fl p Ar source_port .Op Fl s Ar source_ip_address .Op Fl w Ar timeout -.Op Fl X Ar socks_version +.Op Fl X Ar proxy_protocol .Oo Xo .Fl x Ar proxy_address Ns Oo : Ns .Ar port Oc Oc @@ -78,6 +78,9 @@ shell-script based HTTP clients and servers .It network daemon testing .It +a SOCKS or HTTP ProxyCommand for +.Xr ssh 1 +.It and much, much more .El .Pp @@ -171,13 +174,19 @@ will listen forever for a connection, with or without the .Fl w flag. The default is no timeout. -.It Fl X Ar socks_version +.It Fl X Ar proxy_version Requests that .Nm -should use the specified version of the SOCKS protocol when talking to -a SOCKS proxy. -SOCKS versions 4 and 5 are currently supported. -If the version is not specified, SOCKS version 5 is used. +should use the specified protocol when talking to the proxy server. +Supported protocols are +.Dq 4 +(SOCKS v.4), +.Dq 5 +(SOCKS v.5) +and +.Dq connect +(HTTPS proxy). +If the protocol is not specified, SOCKS version 5 is used. .It Xo .Fl x Ar proxy_address Ns Oo : Ns .Ar port Oc @@ -186,13 +195,14 @@ Requests that .Nm should connect to .Ar hostname -using a SOCKS proxy at +using a proxy at .Ar proxy_address and .Ar port . If .Ar port -is not specified, port 1080 is used. +is not specified, the well-known port for the proxy protocol is used (1080 +for SOCKS, 3128 for HTTPS). .It Fl z Specifies that .Nm @@ -342,6 +352,10 @@ responded with an ICMP packet after three seconds: Create and listen on a Unix Domain Socket: .Pp .Dl $ nc -lU /var/tmp/dsocket +.Pp +Connect to port 42 of hostname via an HTTP proxy at 10.2.3.4: +.Pp +.Dl $ nc -x10.2.3.4:8080 -Xconnect hostname 42 .Sh SEE ALSO .Xr cat 1 .Sh AUTHORS diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c index a2cb168e32c..5e034466d47 100644 --- a/usr.bin/nc/netcat.c +++ b/usr.bin/nc/netcat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netcat.c,v 1.74 2004/09/15 18:44:45 deraadt Exp $ */ +/* $OpenBSD: netcat.c,v 1.75 2004/10/17 03:13:55 djm Exp $ */ /* * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> * @@ -127,9 +127,14 @@ main(int argc, char *argv[]) family = AF_UNIX; break; case 'X': - socksv = (int)strtoul(optarg, &endp, 10); - if ((socksv != 4 && socksv != 5) || *endp != '\0') - errx(1, "only SOCKS version 4 and 5 supported"); + if (strcasecmp(optarg, "connect") == 0) + socksv = -1; /* HTTP proxy CONNECT */ + else if (strcmp(optarg, "4") == 0) + socksv = 4; /* SOCKS v.4 */ + else if (strcmp(optarg, "5") == 0) + socksv = 5; /* SOCKS v.5 */ + else + errx(1, "unsupported proxy protocol"); break; case 'd': dflag = 1; @@ -779,8 +784,8 @@ help(void) \t-u UDP mode\n\ \t-v Verbose\n\ \t-w secs\t Timeout for connects and final net reads\n\ - \t-X vers\t SOCKS version (4 or 5)\n\ - \t-x addr[:port]\tSpecify socks proxy address and port\n\ + \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ + \t-x addr[:port]\tSpecify proxy address and port\n\ \t-z Zero-I/O mode [used for scanning]\n\ Port numbers can be individual or ranges: lo-hi [inclusive]\n"); exit(1); @@ -790,7 +795,7 @@ void usage(int ret) { fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-p source_port]\n"); - fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X socks_version]\n"); + fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X proxy_version]\n"); fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n"); if (ret) exit(1); diff --git a/usr.bin/nc/socks.c b/usr.bin/nc/socks.c index a6b4fdd7e33..e7d35b601a0 100644 --- a/usr.bin/nc/socks.c +++ b/usr.bin/nc/socks.c @@ -1,4 +1,4 @@ -/* $OpenBSD: socks.c,v 1.8 2003/07/07 21:36:23 deraadt Exp $ */ +/* $OpenBSD: socks.c,v 1.9 2004/10/17 03:13:55 djm Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. @@ -30,6 +30,7 @@ #include <arpa/inet.h> #include <err.h> +#include <errno.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> @@ -37,13 +38,15 @@ #include <unistd.h> #define SOCKS_PORT "1080" +#define HTTP_PROXY_PORT "3128" +#define HTTP_MAXHDRS 64 #define SOCKS_V5 5 #define SOCKS_V4 4 #define SOCKS_NOAUTH 0 #define SOCKS_NOMETHOD 0xff #define SOCKS_CONNECT 1 #define SOCKS_IPV4 1 -#define SOCKS_MAXCMDSZ 10 + int remote_connect(char *, char *, struct addrinfo); int socks_connect(char *host, char *port, struct addrinfo hints, @@ -81,21 +84,46 @@ decode_port(const char *s) errx (1, "cannot decode port \"%s\"", s); } +static int +proxy_read_line(int fd, char *buf, int bufsz) +{ + int r, off; + + for(off = 0;;) { + if (off >= bufsz) + errx(1, "proxy read too long"); + if ((r = read(fd, buf + off, 1)) <= 0) { + if (r == -1 && errno == EINTR) + continue; + err(1, "proxy read"); + } + /* Skip CR */ + if (buf[off] == '\r') + continue; + if (buf[off] == '\n') { + buf[off] = '\0'; + break; + } + off++; + } + return (off); +} + int socks_connect(char *host, char *port, struct addrinfo hints, char *proxyhost, char *proxyport, struct addrinfo proxyhints, int socksv) { - int proxyfd; - unsigned char buf[SOCKS_MAXCMDSZ]; + int proxyfd, r; + unsigned char buf[1024]; ssize_t cnt; in_addr_t serveraddr; in_port_t serverport; - if (proxyport) - proxyfd = remote_connect(proxyhost, proxyport, proxyhints); - else - proxyfd = remote_connect(proxyhost, SOCKS_PORT, proxyhints); + if (proxyport == NULL) + proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT; + + proxyfd = remote_connect(proxyhost, proxyport, proxyhints); if (proxyfd < 0) return -1; @@ -141,7 +169,7 @@ socks_connect(char *host, char *port, struct addrinfo hints, errx (1, "unexpected reply size %d (expected 10)", cnt); if (buf[1] != 0) errx (1, "connection failed, SOCKS error %d", buf[1]); - } else { + } else if (socksv == 4) { /* Version 4 */ buf[0] = SOCKS_V4; buf[1] = SOCKS_CONNECT; /* connect */ @@ -163,7 +191,45 @@ socks_connect(char *host, char *port, struct addrinfo hints, errx (1, "unexpected reply size %d (expected 8)", cnt); if (buf[1] != 90) errx (1, "connection failed, SOCKS error %d", buf[1]); - } + } else if (socksv == -1) { + /* HTTP proxy CONNECT */ + + /* Disallow bad chars in hostname */ + if (strcspn(host, "\r\n\t []:") != strlen(host)) + errx (1, "Invalid hostname"); + + /* Try to be sane about numeric IPv6 addresses */ + if (strchr(host, ':') != NULL) { + r = snprintf(buf, sizeof(buf), + "CONNECT [%s]:%d HTTP/1.0\r\n\r\n", + host, ntohs(serverport)); + } else { + r = snprintf(buf, sizeof(buf), + "CONNECT %s:%d HTTP/1.0\r\n\r\n", + host, ntohs(serverport)); + } + if (r == -1 || r >= sizeof(buf)) + errx (1, "hostname too long"); + r = strlen(buf); + + /* XXX atomicio */ + cnt = write (proxyfd, buf, r); + if (cnt == -1) + err (1, "write failed"); + if (cnt != r) + errx (1, "short write, %d (expected %d)", cnt, r); + + /* Read reply */ + for (r = 0; r < HTTP_MAXHDRS; r++) { + proxy_read_line(proxyfd, buf, sizeof(buf)); + if (r == 0 && strncmp(buf, "HTTP/1.0 200 ", 12) != 0) + errx (1, "Proxy error: \"%s\"", buf); + /* Discard headers until we hit an empty line */ + if (*buf == '\0') + break; + } + } else + errx (1, "Unknown proxy protocol %d", socksv); return proxyfd; } |