summaryrefslogtreecommitdiff
path: root/src/usr.bin/nc/socks.c
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/nc/socks.c
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/nc/socks.c')
-rw-r--r--src/usr.bin/nc/socks.c86
1 files changed, 76 insertions, 10 deletions
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}