summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2006-01-25 23:21:38 +0000
committerDamien Miller <djm@cvs.openbsd.org>2006-01-25 23:21:38 +0000
commit533413b06519c03d69024b68a33596d2e542421c (patch)
tree25b0a59f2e01d71ea3701ace6c283db5b51eae6c /usr.bin
parentc3a3bbf91cbd1a22022e229332492e8573e212df (diff)
implement HTTP proxy authentication support, very useful in a ssh_config
ProxyCommand; ok beck@
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/nc/nc.113
-rw-r--r--usr.bin/nc/netcat.c16
-rw-r--r--usr.bin/nc/socks.c89
3 files changed, 95 insertions, 23 deletions
diff --git a/usr.bin/nc/nc.1 b/usr.bin/nc/nc.1
index 85e18a53f71..2b87caa9158 100644
--- a/usr.bin/nc/nc.1
+++ b/usr.bin/nc/nc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: nc.1,v 1.41 2005/10/25 03:51:06 dtucker Exp $
+.\" $OpenBSD: nc.1,v 1.42 2006/01/25 23:21:37 djm Exp $
.\"
.\" Copyright (c) 1996 David Sacerdote
.\" All rights reserved.
@@ -36,6 +36,7 @@
.Bk -words
.Op Fl 46DdhklnrStUuvz
.Op Fl i Ar interval
+.Op Fl P Ar proxy_username
.Op Fl p Ar source_port
.Op Fl s Ar source_ip_address
.Op Fl T Ar ToS
@@ -128,6 +129,10 @@ option are ignored.
.It Fl n
Do not do any DNS or service lookups on any specified addresses,
hostnames or ports.
+.It Fl P Ar proxy_username
+Specifies a username to present to a proxy server that requires authentication.
+If no username is specified then authentication will not be attempted.
+Proxy authentication is only supported for HTTP CONNECT proxies at present.
.It Fl p Ar source_port
Specifies the source port
.Nm
@@ -386,6 +391,12 @@ directive in
for more information.
.Pp
.Dl $ nc -x10.2.3.4:8080 -Xconnect host.example.com 42
+.Pp
+The same example again, this time enabling proxy authentication with username
+.Dq ruser
+if the proxy requires it:
+.Pp
+.Dl $ nc -x10.2.3.4:8080 -Xconnect -Pruser host.example.com 42
.Sh SEE ALSO
.Xr cat 1 ,
.Xr ssh 1
diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c
index a10a8954c52..cec87ff7316 100644
--- a/usr.bin/nc/netcat.c
+++ b/usr.bin/nc/netcat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.85 2006/01/20 00:01:20 millert Exp $ */
+/* $OpenBSD: netcat.c,v 1.86 2006/01/25 23:21:37 djm Exp $ */
/*
* Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
*
@@ -70,6 +70,7 @@ int jflag; /* use jumbo frames if we can */
int kflag; /* More than one connect */
int lflag; /* Bind to local port */
int nflag; /* Don't do name look up */
+char *Pflag; /* Proxy username */
char *pflag; /* Localport flag */
int rflag; /* Random ports flag */
char *sflag; /* Source Address */
@@ -92,8 +93,8 @@ void help(void);
int local_listen(char *, char *, struct addrinfo);
void readwrite(int);
int remote_connect(const char *, const char *, struct addrinfo);
-int socks_connect(const char *, const char *, struct addrinfo, const char *, const char *,
- struct addrinfo, int);
+int socks_connect(const char *, const char *, struct addrinfo,
+ const char *, const char *, struct addrinfo, int, const char *);
int udptest(int);
int unix_connect(char *);
int unix_listen(char *);
@@ -123,7 +124,7 @@ main(int argc, char *argv[])
sv = NULL;
while ((ch = getopt(argc, argv,
- "46Ddhi:jklnp:rSs:tT:Uuvw:X:x:z")) != -1) {
+ "46Ddhi:jklnP:p:rSs:tT:Uuvw:X:x:z")) != -1) {
switch (ch) {
case '4':
family = AF_INET;
@@ -167,6 +168,9 @@ main(int argc, char *argv[])
case 'n':
nflag = 1;
break;
+ case 'P':
+ Pflag = optarg;
+ break;
case 'p':
pflag = optarg;
break;
@@ -354,7 +358,8 @@ main(int argc, char *argv[])
if (xflag)
s = socks_connect(host, portlist[i], hints,
- proxyhost, proxyport, proxyhints, socksv);
+ proxyhost, proxyport, proxyhints, socksv,
+ Pflag);
else
s = remote_connect(host, portlist[i], hints);
@@ -818,6 +823,7 @@ help(void)
\t-k Keep inbound sockets open for multiple connects\n\
\t-l Listen mode, for inbound connects\n\
\t-n Suppress name/port resolutions\n\
+ \t-P proxyuser\tUsername for proxy authentication\n\
\t-p port\t Specify local port for remote connects\n\
\t-r Randomize remote ports\n\
\t-S Enable the TCP MD5 signature option\n\
diff --git a/usr.bin/nc/socks.c b/usr.bin/nc/socks.c
index de61439400d..daed99712e3 100644
--- a/usr.bin/nc/socks.c
+++ b/usr.bin/nc/socks.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: socks.c,v 1.15 2005/05/24 20:13:28 avsm Exp $ */
+/* $OpenBSD: socks.c,v 1.16 2006/01/25 23:21:37 djm Exp $ */
/*
* Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
@@ -37,6 +37,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <resolv.h>
+#include <readpassphrase.h>
#include "atomicio.h"
#define SOCKS_PORT "1080"
@@ -52,9 +54,9 @@
#define SOCKS_IPV6 4
int remote_connect(const char *, const char *, struct addrinfo);
-int socks_connect(const char *host, const char *port, struct addrinfo hints,
- const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,
- int socksv);
+int socks_connect(const char *, const char *, struct addrinfo,
+ const char *, const char *, struct addrinfo, int,
+ const char *);
static int
decode_addrport(const char *h, const char *p, struct sockaddr *addr,
@@ -107,13 +109,26 @@ proxy_read_line(int fd, char *buf, size_t bufsz)
return (off);
}
+static const char *
+getproxypass(const char *proxyuser, const char *proxyhost)
+{
+ char prompt[512];
+ static char pw[256];
+
+ snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ",
+ proxyuser, proxyhost);
+ if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL)
+ errx(1, "Unable to read proxy passphrase");
+ return (pw);
+}
+
int
socks_connect(const char *host, const char *port,
struct addrinfo hints __attribute__ ((__unused__)),
const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,
- int socksv)
+ int socksv, const char *proxyuser)
{
- int proxyfd, r;
+ int proxyfd, r, authretry = 0;
size_t hlen, wlen;
unsigned char buf[1024];
size_t cnt;
@@ -121,21 +136,26 @@ socks_connect(const char *host, const char *port,
struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;
in_port_t serverport;
+ const char *proxypass = NULL;
if (proxyport == NULL)
proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
- proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
-
- if (proxyfd < 0)
- return (-1);
-
/* Abuse API to lookup port */
if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr,
sizeof(addr), 1, 1) == -1)
errx(1, "unknown port \"%.64s\"", port);
serverport = in4->sin_port;
+ again:
+ if (authretry++ > 3)
+ errx(1, "Too many authentication failures");
+
+ proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
+
+ if (proxyfd < 0)
+ return (-1);
+
if (socksv == 5) {
if (decode_addrport(host, port, (struct sockaddr *)&addr,
sizeof(addr), 0, 1) == -1)
@@ -239,11 +259,11 @@ socks_connect(const char *host, const char *port,
/* 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",
+ "CONNECT [%s]:%d HTTP/1.0\r\n",
host, ntohs(serverport));
} else {
r = snprintf(buf, sizeof(buf),
- "CONNECT %s:%d HTTP/1.0\r\n\r\n",
+ "CONNECT %s:%d HTTP/1.0\r\n",
host, ntohs(serverport));
}
if (r == -1 || (size_t)r >= sizeof(buf))
@@ -254,15 +274,50 @@ socks_connect(const char *host, const char *port,
if (cnt != r)
err(1, "write failed (%d/%d)", cnt, r);
- /* Read reply */
+ if (authretry > 1) {
+ char resp[1024];
+
+ proxypass = getproxypass(proxyuser, proxyhost);
+ r = snprintf(buf, sizeof(buf), "%s:%s",
+ proxyuser, proxypass);
+ if (r == -1 || (size_t)r >= sizeof(buf) ||
+ b64_ntop(buf, strlen(buf), resp,
+ sizeof(resp)) == -1)
+ errx(1, "Proxy username/password too long");
+ r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
+ "Basic %s\r\n", resp);
+ if (r == -1 || (size_t)r >= sizeof(buf))
+ errx(1, "Proxy auth response too long");
+ r = strlen(buf);
+ if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r)
+ err(1, "write failed (%d/%d)", cnt, r);
+ }
+
+ /* Terminate headers */
+ if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
+ err(1, "write failed (2/%d)", r);
+
+ /* Read status reply */
+ proxy_read_line(proxyfd, buf, sizeof(buf));
+ if (proxyuser != NULL &&
+ strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
+ if (authretry > 1) {
+ fprintf(stderr, "Proxy authentication "
+ "failed\n");
+ }
+ close(proxyfd);
+ goto again;
+ } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0)
+ errx(1, "Proxy error: \"%s\"", buf);
+
+ /* Headers continue until we hit an empty line */
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;
}
+ if (*buf != '\0')
+ errx(1, "Too many proxy headers received");
} else
errx(1, "Unknown proxy protocol %d", socksv);