summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/nc/nc.132
-rw-r--r--usr.bin/nc/netcat.c19
-rw-r--r--usr.bin/nc/socks.c86
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;
}