diff options
author | Damien Miller <djm@cvs.openbsd.org> | 2006-01-25 23:21:38 +0000 |
---|---|---|
committer | Damien Miller <djm@cvs.openbsd.org> | 2006-01-25 23:21:38 +0000 |
commit | 533413b06519c03d69024b68a33596d2e542421c (patch) | |
tree | 25b0a59f2e01d71ea3701ace6c283db5b51eae6c /usr.bin | |
parent | c3a3bbf91cbd1a22022e229332492e8573e212df (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.1 | 13 | ||||
-rw-r--r-- | usr.bin/nc/netcat.c | 16 | ||||
-rw-r--r-- | usr.bin/nc/socks.c | 89 |
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); |