diff options
Diffstat (limited to '')
| -rw-r--r-- | src/usr.bin/nc/nc.1 | 13 | ||||
| -rw-r--r-- | src/usr.bin/nc/netcat.c | 16 | ||||
| -rw-r--r-- | src/usr.bin/nc/socks.c | 89 |
3 files changed, 95 insertions, 23 deletions
diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1 index 85e18a53f7..2b87caa915 100644 --- a/src/usr.bin/nc/nc.1 +++ b/src/usr.bin/nc/nc.1 | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | .\" $OpenBSD: nc.1,v 1.41 2005/10/25 03:51:06 dtucker Exp $ | 1 | .\" $OpenBSD: nc.1,v 1.42 2006/01/25 23:21:37 djm Exp $ |
| 2 | .\" | 2 | .\" |
| 3 | .\" Copyright (c) 1996 David Sacerdote | 3 | .\" Copyright (c) 1996 David Sacerdote |
| 4 | .\" All rights reserved. | 4 | .\" All rights reserved. |
| @@ -36,6 +36,7 @@ | |||
| 36 | .Bk -words | 36 | .Bk -words |
| 37 | .Op Fl 46DdhklnrStUuvz | 37 | .Op Fl 46DdhklnrStUuvz |
| 38 | .Op Fl i Ar interval | 38 | .Op Fl i Ar interval |
| 39 | .Op Fl P Ar proxy_username | ||
| 39 | .Op Fl p Ar source_port | 40 | .Op Fl p Ar source_port |
| 40 | .Op Fl s Ar source_ip_address | 41 | .Op Fl s Ar source_ip_address |
| 41 | .Op Fl T Ar ToS | 42 | .Op Fl T Ar ToS |
| @@ -128,6 +129,10 @@ option are ignored. | |||
| 128 | .It Fl n | 129 | .It Fl n |
| 129 | Do not do any DNS or service lookups on any specified addresses, | 130 | Do not do any DNS or service lookups on any specified addresses, |
| 130 | hostnames or ports. | 131 | hostnames or ports. |
| 132 | .It Fl P Ar proxy_username | ||
| 133 | Specifies a username to present to a proxy server that requires authentication. | ||
| 134 | If no username is specified then authentication will not be attempted. | ||
| 135 | Proxy authentication is only supported for HTTP CONNECT proxies at present. | ||
| 131 | .It Fl p Ar source_port | 136 | .It Fl p Ar source_port |
| 132 | Specifies the source port | 137 | Specifies the source port |
| 133 | .Nm | 138 | .Nm |
| @@ -386,6 +391,12 @@ directive in | |||
| 386 | for more information. | 391 | for more information. |
| 387 | .Pp | 392 | .Pp |
| 388 | .Dl $ nc -x10.2.3.4:8080 -Xconnect host.example.com 42 | 393 | .Dl $ nc -x10.2.3.4:8080 -Xconnect host.example.com 42 |
| 394 | .Pp | ||
| 395 | The same example again, this time enabling proxy authentication with username | ||
| 396 | .Dq ruser | ||
| 397 | if the proxy requires it: | ||
| 398 | .Pp | ||
| 399 | .Dl $ nc -x10.2.3.4:8080 -Xconnect -Pruser host.example.com 42 | ||
| 389 | .Sh SEE ALSO | 400 | .Sh SEE ALSO |
| 390 | .Xr cat 1 , | 401 | .Xr cat 1 , |
| 391 | .Xr ssh 1 | 402 | .Xr ssh 1 |
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c index a10a8954c5..cec87ff731 100644 --- a/src/usr.bin/nc/netcat.c +++ b/src/usr.bin/nc/netcat.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: netcat.c,v 1.85 2006/01/20 00:01:20 millert Exp $ */ | 1 | /* $OpenBSD: netcat.c,v 1.86 2006/01/25 23:21:37 djm Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> | 3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> |
| 4 | * | 4 | * |
| @@ -70,6 +70,7 @@ int jflag; /* use jumbo frames if we can */ | |||
| 70 | int kflag; /* More than one connect */ | 70 | int kflag; /* More than one connect */ |
| 71 | int lflag; /* Bind to local port */ | 71 | int lflag; /* Bind to local port */ |
| 72 | int nflag; /* Don't do name look up */ | 72 | int nflag; /* Don't do name look up */ |
| 73 | char *Pflag; /* Proxy username */ | ||
| 73 | char *pflag; /* Localport flag */ | 74 | char *pflag; /* Localport flag */ |
| 74 | int rflag; /* Random ports flag */ | 75 | int rflag; /* Random ports flag */ |
| 75 | char *sflag; /* Source Address */ | 76 | char *sflag; /* Source Address */ |
| @@ -92,8 +93,8 @@ void help(void); | |||
| 92 | int local_listen(char *, char *, struct addrinfo); | 93 | int local_listen(char *, char *, struct addrinfo); |
| 93 | void readwrite(int); | 94 | void readwrite(int); |
| 94 | int remote_connect(const char *, const char *, struct addrinfo); | 95 | int remote_connect(const char *, const char *, struct addrinfo); |
| 95 | int socks_connect(const char *, const char *, struct addrinfo, const char *, const char *, | 96 | int socks_connect(const char *, const char *, struct addrinfo, |
| 96 | struct addrinfo, int); | 97 | const char *, const char *, struct addrinfo, int, const char *); |
| 97 | int udptest(int); | 98 | int udptest(int); |
| 98 | int unix_connect(char *); | 99 | int unix_connect(char *); |
| 99 | int unix_listen(char *); | 100 | int unix_listen(char *); |
| @@ -123,7 +124,7 @@ main(int argc, char *argv[]) | |||
| 123 | sv = NULL; | 124 | sv = NULL; |
| 124 | 125 | ||
| 125 | while ((ch = getopt(argc, argv, | 126 | while ((ch = getopt(argc, argv, |
| 126 | "46Ddhi:jklnp:rSs:tT:Uuvw:X:x:z")) != -1) { | 127 | "46Ddhi:jklnP:p:rSs:tT:Uuvw:X:x:z")) != -1) { |
| 127 | switch (ch) { | 128 | switch (ch) { |
| 128 | case '4': | 129 | case '4': |
| 129 | family = AF_INET; | 130 | family = AF_INET; |
| @@ -167,6 +168,9 @@ main(int argc, char *argv[]) | |||
| 167 | case 'n': | 168 | case 'n': |
| 168 | nflag = 1; | 169 | nflag = 1; |
| 169 | break; | 170 | break; |
| 171 | case 'P': | ||
| 172 | Pflag = optarg; | ||
| 173 | break; | ||
| 170 | case 'p': | 174 | case 'p': |
| 171 | pflag = optarg; | 175 | pflag = optarg; |
| 172 | break; | 176 | break; |
| @@ -354,7 +358,8 @@ main(int argc, char *argv[]) | |||
| 354 | 358 | ||
| 355 | if (xflag) | 359 | if (xflag) |
| 356 | s = socks_connect(host, portlist[i], hints, | 360 | s = socks_connect(host, portlist[i], hints, |
| 357 | proxyhost, proxyport, proxyhints, socksv); | 361 | proxyhost, proxyport, proxyhints, socksv, |
| 362 | Pflag); | ||
| 358 | else | 363 | else |
| 359 | s = remote_connect(host, portlist[i], hints); | 364 | s = remote_connect(host, portlist[i], hints); |
| 360 | 365 | ||
| @@ -818,6 +823,7 @@ help(void) | |||
| 818 | \t-k Keep inbound sockets open for multiple connects\n\ | 823 | \t-k Keep inbound sockets open for multiple connects\n\ |
| 819 | \t-l Listen mode, for inbound connects\n\ | 824 | \t-l Listen mode, for inbound connects\n\ |
| 820 | \t-n Suppress name/port resolutions\n\ | 825 | \t-n Suppress name/port resolutions\n\ |
| 826 | \t-P proxyuser\tUsername for proxy authentication\n\ | ||
| 821 | \t-p port\t Specify local port for remote connects\n\ | 827 | \t-p port\t Specify local port for remote connects\n\ |
| 822 | \t-r Randomize remote ports\n\ | 828 | \t-r Randomize remote ports\n\ |
| 823 | \t-S Enable the TCP MD5 signature option\n\ | 829 | \t-S Enable the TCP MD5 signature option\n\ |
diff --git a/src/usr.bin/nc/socks.c b/src/usr.bin/nc/socks.c index de61439400..daed99712e 100644 --- a/src/usr.bin/nc/socks.c +++ b/src/usr.bin/nc/socks.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: socks.c,v 1.15 2005/05/24 20:13:28 avsm Exp $ */ | 1 | /* $OpenBSD: socks.c,v 1.16 2006/01/25 23:21:37 djm Exp $ */ |
| 2 | 2 | ||
| 3 | /* | 3 | /* |
| 4 | * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. | 4 | * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. |
| @@ -37,6 +37,8 @@ | |||
| 37 | #include <stdlib.h> | 37 | #include <stdlib.h> |
| 38 | #include <string.h> | 38 | #include <string.h> |
| 39 | #include <unistd.h> | 39 | #include <unistd.h> |
| 40 | #include <resolv.h> | ||
| 41 | #include <readpassphrase.h> | ||
| 40 | #include "atomicio.h" | 42 | #include "atomicio.h" |
| 41 | 43 | ||
| 42 | #define SOCKS_PORT "1080" | 44 | #define SOCKS_PORT "1080" |
| @@ -52,9 +54,9 @@ | |||
| 52 | #define SOCKS_IPV6 4 | 54 | #define SOCKS_IPV6 4 |
| 53 | 55 | ||
| 54 | int remote_connect(const char *, const char *, struct addrinfo); | 56 | int remote_connect(const char *, const char *, struct addrinfo); |
| 55 | int socks_connect(const char *host, const char *port, struct addrinfo hints, | 57 | int socks_connect(const char *, const char *, struct addrinfo, |
| 56 | const char *proxyhost, const char *proxyport, struct addrinfo proxyhints, | 58 | const char *, const char *, struct addrinfo, int, |
| 57 | int socksv); | 59 | const char *); |
| 58 | 60 | ||
| 59 | static int | 61 | static int |
| 60 | decode_addrport(const char *h, const char *p, struct sockaddr *addr, | 62 | 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) | |||
| 107 | return (off); | 109 | return (off); |
| 108 | } | 110 | } |
| 109 | 111 | ||
| 112 | static const char * | ||
| 113 | getproxypass(const char *proxyuser, const char *proxyhost) | ||
| 114 | { | ||
| 115 | char prompt[512]; | ||
| 116 | static char pw[256]; | ||
| 117 | |||
| 118 | snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ", | ||
| 119 | proxyuser, proxyhost); | ||
| 120 | if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL) | ||
| 121 | errx(1, "Unable to read proxy passphrase"); | ||
| 122 | return (pw); | ||
| 123 | } | ||
| 124 | |||
| 110 | int | 125 | int |
| 111 | socks_connect(const char *host, const char *port, | 126 | socks_connect(const char *host, const char *port, |
| 112 | struct addrinfo hints __attribute__ ((__unused__)), | 127 | struct addrinfo hints __attribute__ ((__unused__)), |
| 113 | const char *proxyhost, const char *proxyport, struct addrinfo proxyhints, | 128 | const char *proxyhost, const char *proxyport, struct addrinfo proxyhints, |
| 114 | int socksv) | 129 | int socksv, const char *proxyuser) |
| 115 | { | 130 | { |
| 116 | int proxyfd, r; | 131 | int proxyfd, r, authretry = 0; |
| 117 | size_t hlen, wlen; | 132 | size_t hlen, wlen; |
| 118 | unsigned char buf[1024]; | 133 | unsigned char buf[1024]; |
| 119 | size_t cnt; | 134 | size_t cnt; |
| @@ -121,21 +136,26 @@ socks_connect(const char *host, const char *port, | |||
| 121 | struct sockaddr_in *in4 = (struct sockaddr_in *)&addr; | 136 | struct sockaddr_in *in4 = (struct sockaddr_in *)&addr; |
| 122 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr; | 137 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr; |
| 123 | in_port_t serverport; | 138 | in_port_t serverport; |
| 139 | const char *proxypass = NULL; | ||
| 124 | 140 | ||
| 125 | if (proxyport == NULL) | 141 | if (proxyport == NULL) |
| 126 | proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT; | 142 | proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT; |
| 127 | 143 | ||
| 128 | proxyfd = remote_connect(proxyhost, proxyport, proxyhints); | ||
| 129 | |||
| 130 | if (proxyfd < 0) | ||
| 131 | return (-1); | ||
| 132 | |||
| 133 | /* Abuse API to lookup port */ | 144 | /* Abuse API to lookup port */ |
| 134 | if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr, | 145 | if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr, |
| 135 | sizeof(addr), 1, 1) == -1) | 146 | sizeof(addr), 1, 1) == -1) |
| 136 | errx(1, "unknown port \"%.64s\"", port); | 147 | errx(1, "unknown port \"%.64s\"", port); |
| 137 | serverport = in4->sin_port; | 148 | serverport = in4->sin_port; |
| 138 | 149 | ||
| 150 | again: | ||
| 151 | if (authretry++ > 3) | ||
| 152 | errx(1, "Too many authentication failures"); | ||
| 153 | |||
| 154 | proxyfd = remote_connect(proxyhost, proxyport, proxyhints); | ||
| 155 | |||
| 156 | if (proxyfd < 0) | ||
| 157 | return (-1); | ||
| 158 | |||
| 139 | if (socksv == 5) { | 159 | if (socksv == 5) { |
| 140 | if (decode_addrport(host, port, (struct sockaddr *)&addr, | 160 | if (decode_addrport(host, port, (struct sockaddr *)&addr, |
| 141 | sizeof(addr), 0, 1) == -1) | 161 | sizeof(addr), 0, 1) == -1) |
| @@ -239,11 +259,11 @@ socks_connect(const char *host, const char *port, | |||
| 239 | /* Try to be sane about numeric IPv6 addresses */ | 259 | /* Try to be sane about numeric IPv6 addresses */ |
| 240 | if (strchr(host, ':') != NULL) { | 260 | if (strchr(host, ':') != NULL) { |
| 241 | r = snprintf(buf, sizeof(buf), | 261 | r = snprintf(buf, sizeof(buf), |
| 242 | "CONNECT [%s]:%d HTTP/1.0\r\n\r\n", | 262 | "CONNECT [%s]:%d HTTP/1.0\r\n", |
| 243 | host, ntohs(serverport)); | 263 | host, ntohs(serverport)); |
| 244 | } else { | 264 | } else { |
| 245 | r = snprintf(buf, sizeof(buf), | 265 | r = snprintf(buf, sizeof(buf), |
| 246 | "CONNECT %s:%d HTTP/1.0\r\n\r\n", | 266 | "CONNECT %s:%d HTTP/1.0\r\n", |
| 247 | host, ntohs(serverport)); | 267 | host, ntohs(serverport)); |
| 248 | } | 268 | } |
| 249 | if (r == -1 || (size_t)r >= sizeof(buf)) | 269 | if (r == -1 || (size_t)r >= sizeof(buf)) |
| @@ -254,15 +274,50 @@ socks_connect(const char *host, const char *port, | |||
| 254 | if (cnt != r) | 274 | if (cnt != r) |
| 255 | err(1, "write failed (%d/%d)", cnt, r); | 275 | err(1, "write failed (%d/%d)", cnt, r); |
| 256 | 276 | ||
| 257 | /* Read reply */ | 277 | if (authretry > 1) { |
| 278 | char resp[1024]; | ||
| 279 | |||
| 280 | proxypass = getproxypass(proxyuser, proxyhost); | ||
| 281 | r = snprintf(buf, sizeof(buf), "%s:%s", | ||
| 282 | proxyuser, proxypass); | ||
| 283 | if (r == -1 || (size_t)r >= sizeof(buf) || | ||
| 284 | b64_ntop(buf, strlen(buf), resp, | ||
| 285 | sizeof(resp)) == -1) | ||
| 286 | errx(1, "Proxy username/password too long"); | ||
| 287 | r = snprintf(buf, sizeof(buf), "Proxy-Authorization: " | ||
| 288 | "Basic %s\r\n", resp); | ||
| 289 | if (r == -1 || (size_t)r >= sizeof(buf)) | ||
| 290 | errx(1, "Proxy auth response too long"); | ||
| 291 | r = strlen(buf); | ||
| 292 | if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r) | ||
| 293 | err(1, "write failed (%d/%d)", cnt, r); | ||
| 294 | } | ||
| 295 | |||
| 296 | /* Terminate headers */ | ||
| 297 | if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2) | ||
| 298 | err(1, "write failed (2/%d)", r); | ||
| 299 | |||
| 300 | /* Read status reply */ | ||
| 301 | proxy_read_line(proxyfd, buf, sizeof(buf)); | ||
| 302 | if (proxyuser != NULL && | ||
| 303 | strncmp(buf, "HTTP/1.0 407 ", 12) == 0) { | ||
| 304 | if (authretry > 1) { | ||
| 305 | fprintf(stderr, "Proxy authentication " | ||
| 306 | "failed\n"); | ||
| 307 | } | ||
| 308 | close(proxyfd); | ||
| 309 | goto again; | ||
| 310 | } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0) | ||
| 311 | errx(1, "Proxy error: \"%s\"", buf); | ||
| 312 | |||
| 313 | /* Headers continue until we hit an empty line */ | ||
| 258 | for (r = 0; r < HTTP_MAXHDRS; r++) { | 314 | for (r = 0; r < HTTP_MAXHDRS; r++) { |
| 259 | proxy_read_line(proxyfd, buf, sizeof(buf)); | 315 | proxy_read_line(proxyfd, buf, sizeof(buf)); |
| 260 | if (r == 0 && strncmp(buf, "HTTP/1.0 200 ", 12) != 0) | ||
| 261 | errx(1, "Proxy error: \"%s\"", buf); | ||
| 262 | /* Discard headers until we hit an empty line */ | ||
| 263 | if (*buf == '\0') | 316 | if (*buf == '\0') |
| 264 | break; | 317 | break; |
| 265 | } | 318 | } |
| 319 | if (*buf != '\0') | ||
| 320 | errx(1, "Too many proxy headers received"); | ||
| 266 | } else | 321 | } else |
| 267 | errx(1, "Unknown proxy protocol %d", socksv); | 322 | errx(1, "Unknown proxy protocol %d", socksv); |
| 268 | 323 | ||
