summaryrefslogtreecommitdiff
path: root/src/usr.bin
diff options
context:
space:
mode:
authordjm <>2004-10-17 03:13:55 +0000
committerdjm <>2004-10-17 03:13:55 +0000
commit91294475ad30114d23728b4a7599c81a0e1a99a3 (patch)
tree1f23c7ad55ad26e1dda318b65e9a34e4e26af6f1 /src/usr.bin
parent8a16cf0bfbdc91bb8136c9cedf795be3e0496e8c (diff)
downloadopenbsd-91294475ad30114d23728b4a7599c81a0e1a99a3.tar.gz
openbsd-91294475ad30114d23728b4a7599c81a0e1a99a3.tar.bz2
openbsd-91294475ad30114d23728b4a7599c81a0e1a99a3.zip
http proxy CONNECT support; ok beck@
Diffstat (limited to 'src/usr.bin')
-rw-r--r--src/usr.bin/nc/nc.132
-rw-r--r--src/usr.bin/nc/netcat.c19
-rw-r--r--src/usr.bin/nc/socks.c86
3 files changed, 111 insertions, 26 deletions
diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1
index 182950a952..44cdb14bbc 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.32 2004/07/15 15:07:52 markus Exp $ 1.\" $OpenBSD: nc.1,v 1.33 2004/10/17 03:13:55 djm Exp $
2.\" 2.\"
3.\" Copyright (c) 1996 David Sacerdote 3.\" Copyright (c) 1996 David Sacerdote
4.\" All rights reserved. 4.\" All rights reserved.
@@ -39,7 +39,7 @@
39.Op Fl p Ar source_port 39.Op Fl p Ar source_port
40.Op Fl s Ar source_ip_address 40.Op Fl s Ar source_ip_address
41.Op Fl w Ar timeout 41.Op Fl w Ar timeout
42.Op Fl X Ar socks_version 42.Op Fl X Ar proxy_protocol
43.Oo Xo 43.Oo Xo
44.Fl x Ar proxy_address Ns Oo : Ns 44.Fl x Ar proxy_address Ns Oo : Ns
45.Ar port Oc Oc 45.Ar port Oc Oc
@@ -78,6 +78,9 @@ shell-script based HTTP clients and servers
78.It 78.It
79network daemon testing 79network daemon testing
80.It 80.It
81a SOCKS or HTTP ProxyCommand for
82.Xr ssh 1
83.It
81and much, much more 84and much, much more
82.El 85.El
83.Pp 86.Pp
@@ -171,13 +174,19 @@ will listen forever for a connection, with or without the
171.Fl w 174.Fl w
172flag. 175flag.
173The default is no timeout. 176The default is no timeout.
174.It Fl X Ar socks_version 177.It Fl X Ar proxy_version
175Requests that 178Requests that
176.Nm 179.Nm
177should use the specified version of the SOCKS protocol when talking to 180should use the specified protocol when talking to the proxy server.
178a SOCKS proxy. 181Supported protocols are
179SOCKS versions 4 and 5 are currently supported. 182.Dq 4
180If the version is not specified, SOCKS version 5 is used. 183(SOCKS v.4),
184.Dq 5
185(SOCKS v.5)
186and
187.Dq connect
188(HTTPS proxy).
189If the protocol is not specified, SOCKS version 5 is used.
181.It Xo 190.It Xo
182.Fl x Ar proxy_address Ns Oo : Ns 191.Fl x Ar proxy_address Ns Oo : Ns
183.Ar port Oc 192.Ar port Oc
@@ -186,13 +195,14 @@ Requests that
186.Nm 195.Nm
187should connect to 196should connect to
188.Ar hostname 197.Ar hostname
189using a SOCKS proxy at 198using a proxy at
190.Ar proxy_address 199.Ar proxy_address
191and 200and
192.Ar port . 201.Ar port .
193If 202If
194.Ar port 203.Ar port
195is not specified, port 1080 is used. 204is not specified, the well-known port for the proxy protocol is used (1080
205for SOCKS, 3128 for HTTPS).
196.It Fl z 206.It Fl z
197Specifies that 207Specifies that
198.Nm 208.Nm
@@ -342,6 +352,10 @@ responded with an ICMP packet after three seconds:
342Create and listen on a Unix Domain Socket: 352Create and listen on a Unix Domain Socket:
343.Pp 353.Pp
344.Dl $ nc -lU /var/tmp/dsocket 354.Dl $ nc -lU /var/tmp/dsocket
355.Pp
356Connect to port 42 of hostname via an HTTP proxy at 10.2.3.4:
357.Pp
358.Dl $ nc -x10.2.3.4:8080 -Xconnect hostname 42
345.Sh SEE ALSO 359.Sh SEE ALSO
346.Xr cat 1 360.Xr cat 1
347.Sh AUTHORS 361.Sh AUTHORS
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
index a2cb168e32..5e034466d4 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.74 2004/09/15 18:44:45 deraadt Exp $ */ 1/* $OpenBSD: netcat.c,v 1.75 2004/10/17 03:13:55 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 * 4 *
@@ -127,9 +127,14 @@ main(int argc, char *argv[])
127 family = AF_UNIX; 127 family = AF_UNIX;
128 break; 128 break;
129 case 'X': 129 case 'X':
130 socksv = (int)strtoul(optarg, &endp, 10); 130 if (strcasecmp(optarg, "connect") == 0)
131 if ((socksv != 4 && socksv != 5) || *endp != '\0') 131 socksv = -1; /* HTTP proxy CONNECT */
132 errx(1, "only SOCKS version 4 and 5 supported"); 132 else if (strcmp(optarg, "4") == 0)
133 socksv = 4; /* SOCKS v.4 */
134 else if (strcmp(optarg, "5") == 0)
135 socksv = 5; /* SOCKS v.5 */
136 else
137 errx(1, "unsupported proxy protocol");
133 break; 138 break;
134 case 'd': 139 case 'd':
135 dflag = 1; 140 dflag = 1;
@@ -779,8 +784,8 @@ help(void)
779 \t-u UDP mode\n\ 784 \t-u UDP mode\n\
780 \t-v Verbose\n\ 785 \t-v Verbose\n\
781 \t-w secs\t Timeout for connects and final net reads\n\ 786 \t-w secs\t Timeout for connects and final net reads\n\
782 \t-X vers\t SOCKS version (4 or 5)\n\ 787 \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
783 \t-x addr[:port]\tSpecify socks proxy address and port\n\ 788 \t-x addr[:port]\tSpecify proxy address and port\n\
784 \t-z Zero-I/O mode [used for scanning]\n\ 789 \t-z Zero-I/O mode [used for scanning]\n\
785 Port numbers can be individual or ranges: lo-hi [inclusive]\n"); 790 Port numbers can be individual or ranges: lo-hi [inclusive]\n");
786 exit(1); 791 exit(1);
@@ -790,7 +795,7 @@ void
790usage(int ret) 795usage(int ret)
791{ 796{
792 fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-p source_port]\n"); 797 fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-p source_port]\n");
793 fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X socks_version]\n"); 798 fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X proxy_version]\n");
794 fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n"); 799 fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n");
795 if (ret) 800 if (ret)
796 exit(1); 801 exit(1);
diff --git a/src/usr.bin/nc/socks.c b/src/usr.bin/nc/socks.c
index a6b4fdd7e3..e7d35b601a 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.8 2003/07/07 21:36:23 deraadt Exp $ */ 1/* $OpenBSD: socks.c,v 1.9 2004/10/17 03:13:55 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. 4 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
@@ -30,6 +30,7 @@
30#include <arpa/inet.h> 30#include <arpa/inet.h>
31 31
32#include <err.h> 32#include <err.h>
33#include <errno.h>
33#include <netdb.h> 34#include <netdb.h>
34#include <stdio.h> 35#include <stdio.h>
35#include <stdlib.h> 36#include <stdlib.h>
@@ -37,13 +38,15 @@
37#include <unistd.h> 38#include <unistd.h>
38 39
39#define SOCKS_PORT "1080" 40#define SOCKS_PORT "1080"
41#define HTTP_PROXY_PORT "3128"
42#define HTTP_MAXHDRS 64
40#define SOCKS_V5 5 43#define SOCKS_V5 5
41#define SOCKS_V4 4 44#define SOCKS_V4 4
42#define SOCKS_NOAUTH 0 45#define SOCKS_NOAUTH 0
43#define SOCKS_NOMETHOD 0xff 46#define SOCKS_NOMETHOD 0xff
44#define SOCKS_CONNECT 1 47#define SOCKS_CONNECT 1
45#define SOCKS_IPV4 1 48#define SOCKS_IPV4 1
46#define SOCKS_MAXCMDSZ 10 49
47 50
48int remote_connect(char *, char *, struct addrinfo); 51int remote_connect(char *, char *, struct addrinfo);
49int socks_connect(char *host, char *port, struct addrinfo hints, 52int socks_connect(char *host, char *port, struct addrinfo hints,
@@ -81,21 +84,46 @@ decode_port(const char *s)
81 errx (1, "cannot decode port \"%s\"", s); 84 errx (1, "cannot decode port \"%s\"", s);
82} 85}
83 86
87static int
88proxy_read_line(int fd, char *buf, int bufsz)
89{
90 int r, off;
91
92 for(off = 0;;) {
93 if (off >= bufsz)
94 errx(1, "proxy read too long");
95 if ((r = read(fd, buf + off, 1)) <= 0) {
96 if (r == -1 && errno == EINTR)
97 continue;
98 err(1, "proxy read");
99 }
100 /* Skip CR */
101 if (buf[off] == '\r')
102 continue;
103 if (buf[off] == '\n') {
104 buf[off] = '\0';
105 break;
106 }
107 off++;
108 }
109 return (off);
110}
111
84int 112int
85socks_connect(char *host, char *port, struct addrinfo hints, 113socks_connect(char *host, char *port, struct addrinfo hints,
86 char *proxyhost, char *proxyport, struct addrinfo proxyhints, 114 char *proxyhost, char *proxyport, struct addrinfo proxyhints,
87 int socksv) 115 int socksv)
88{ 116{
89 int proxyfd; 117 int proxyfd, r;
90 unsigned char buf[SOCKS_MAXCMDSZ]; 118 unsigned char buf[1024];
91 ssize_t cnt; 119 ssize_t cnt;
92 in_addr_t serveraddr; 120 in_addr_t serveraddr;
93 in_port_t serverport; 121 in_port_t serverport;
94 122
95 if (proxyport) 123 if (proxyport == NULL)
96 proxyfd = remote_connect(proxyhost, proxyport, proxyhints); 124 proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
97 else 125
98 proxyfd = remote_connect(proxyhost, SOCKS_PORT, proxyhints); 126 proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
99 127
100 if (proxyfd < 0) 128 if (proxyfd < 0)
101 return -1; 129 return -1;
@@ -141,7 +169,7 @@ socks_connect(char *host, char *port, struct addrinfo hints,
141 errx (1, "unexpected reply size %d (expected 10)", cnt); 169 errx (1, "unexpected reply size %d (expected 10)", cnt);
142 if (buf[1] != 0) 170 if (buf[1] != 0)
143 errx (1, "connection failed, SOCKS error %d", buf[1]); 171 errx (1, "connection failed, SOCKS error %d", buf[1]);
144 } else { 172 } else if (socksv == 4) {
145 /* Version 4 */ 173 /* Version 4 */
146 buf[0] = SOCKS_V4; 174 buf[0] = SOCKS_V4;
147 buf[1] = SOCKS_CONNECT; /* connect */ 175 buf[1] = SOCKS_CONNECT; /* connect */
@@ -163,7 +191,45 @@ socks_connect(char *host, char *port, struct addrinfo hints,
163 errx (1, "unexpected reply size %d (expected 8)", cnt); 191 errx (1, "unexpected reply size %d (expected 8)", cnt);
164 if (buf[1] != 90) 192 if (buf[1] != 90)
165 errx (1, "connection failed, SOCKS error %d", buf[1]); 193 errx (1, "connection failed, SOCKS error %d", buf[1]);
166 } 194 } else if (socksv == -1) {
195 /* HTTP proxy CONNECT */
196
197 /* Disallow bad chars in hostname */
198 if (strcspn(host, "\r\n\t []:") != strlen(host))
199 errx (1, "Invalid hostname");
200
201 /* Try to be sane about numeric IPv6 addresses */
202 if (strchr(host, ':') != NULL) {
203 r = snprintf(buf, sizeof(buf),
204 "CONNECT [%s]:%d HTTP/1.0\r\n\r\n",
205 host, ntohs(serverport));
206 } else {
207 r = snprintf(buf, sizeof(buf),
208 "CONNECT %s:%d HTTP/1.0\r\n\r\n",
209 host, ntohs(serverport));
210 }
211 if (r == -1 || r >= sizeof(buf))
212 errx (1, "hostname too long");
213 r = strlen(buf);
214
215 /* XXX atomicio */
216 cnt = write (proxyfd, buf, r);
217 if (cnt == -1)
218 err (1, "write failed");
219 if (cnt != r)
220 errx (1, "short write, %d (expected %d)", cnt, r);
221
222 /* Read reply */
223 for (r = 0; r < HTTP_MAXHDRS; r++) {
224 proxy_read_line(proxyfd, buf, sizeof(buf));
225 if (r == 0 && strncmp(buf, "HTTP/1.0 200 ", 12) != 0)
226 errx (1, "Proxy error: \"%s\"", buf);
227 /* Discard headers until we hit an empty line */
228 if (*buf == '\0')
229 break;
230 }
231 } else
232 errx (1, "Unknown proxy protocol %d", socksv);
167 233
168 return proxyfd; 234 return proxyfd;
169} 235}