summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@google.com>2014-12-22 16:30:42 +1100
committerDamien Miller <djm@google.com>2014-12-23 08:38:12 +1100
commit293cac52dcda123244b2e594d15592e5e481c55e (patch)
tree71bf4c530501609978a2a00bfa09fde01e4e9d61
parent8f6784f0cb56dc4fd00af3e81a10050a5785228d (diff)
include and use OpenBSD netcat in regress/
-rw-r--r--Makefile.in5
-rw-r--r--regress/Makefile2
-rw-r--r--regress/multiplex.sh23
-rw-r--r--regress/netcat.c1638
4 files changed, 1649 insertions, 19 deletions
diff --git a/Makefile.in b/Makefile.in
index 06be3d5d5..9b485fba8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -436,6 +436,10 @@ regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c
436 $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ 436 $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \
437 $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) 437 $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
438 438
439regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c
440 $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \
441 $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
442
439UNITTESTS_TEST_HELPER_OBJS=\ 443UNITTESTS_TEST_HELPER_OBJS=\
440 regress/unittests/test_helper/test_helper.o \ 444 regress/unittests/test_helper/test_helper.o \
441 regress/unittests/test_helper/fuzz.o 445 regress/unittests/test_helper/fuzz.o
@@ -476,6 +480,7 @@ regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \
476REGRESS_BINARIES=\ 480REGRESS_BINARIES=\
477 regress/modpipe$(EXEEXT) \ 481 regress/modpipe$(EXEEXT) \
478 regress/setuid-allowed$(EXEEXT) \ 482 regress/setuid-allowed$(EXEEXT) \
483 regress/netcat$(EXEEXT) \
479 regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ 484 regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \
480 regress/unittests/sshkey/test_sshkey$(EXEEXT) 485 regress/unittests/sshkey/test_sshkey$(EXEEXT)
481 486
diff --git a/regress/Makefile b/regress/Makefile
index 27c4e79e1..ac1ee2d5f 100644
--- a/regress/Makefile
+++ b/regress/Makefile
@@ -92,7 +92,7 @@ CLEANFILES= t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \
92 regress.log failed-regress.log ssh-log-wrapper.sh \ 92 regress.log failed-regress.log ssh-log-wrapper.sh \
93 sftp-server.sh sftp-server.log sftp.log setuid-allowed \ 93 sftp-server.sh sftp-server.log sftp.log setuid-allowed \
94 data ed25519-agent ed25519-agent.pub key.ed25519-512 \ 94 data ed25519-agent ed25519-agent.pub key.ed25519-512 \
95 key.ed25519-512.pub 95 key.ed25519-512.pub netcat
96 96
97SUDO_CLEAN+= /var/run/testdata_${USER} /var/run/keycommand_${USER} 97SUDO_CLEAN+= /var/run/testdata_${USER} /var/run/keycommand_${USER}
98 98
diff --git a/regress/multiplex.sh b/regress/multiplex.sh
index c75dee900..617615355 100644
--- a/regress/multiplex.sh
+++ b/regress/multiplex.sh
@@ -5,20 +5,7 @@ CTL=/tmp/openssh.regress.ctl-sock.$$
5 5
6tid="connection multiplexing" 6tid="connection multiplexing"
7 7
8if have_prog nc ; then 8NC=$OBJ/netcat
9 if nc -h 2>&1 | grep -- -N >/dev/null; then
10 NC="nc -N";
11 elif nc -h 2>&1 | grep -- "-U.*Use UNIX" >/dev/null ; then
12 NC="nc"
13 else
14 echo "nc is incompatible"
15 fi
16fi
17
18if test -z "$NC" ; then
19 echo "skipped (no compatible nc found)"
20 exit 0
21fi
22 9
23trace "will use ProxyCommand $proxycmd" 10trace "will use ProxyCommand $proxycmd"
24if config_defined DISABLE_FD_PASSING ; then 11if config_defined DISABLE_FD_PASSING ; then
@@ -90,20 +77,20 @@ cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}"
90rm -f ${COPY} 77rm -f ${COPY}
91verbose "test $tid: forward" 78verbose "test $tid: forward"
92trace "forward over TCP/IP and check result" 79trace "forward over TCP/IP and check result"
93$NC -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null & 80$NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null &
94netcat_pid=$! 81netcat_pid=$!
95${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1 82${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1
96$NC -d 127.0.0.1 $((${PORT} + 2)) > ${COPY} < /dev/null 83$NC 127.0.0.1 $((${PORT} + 2)) < /dev/null > ${COPY}
97cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}" 84cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
98kill $netcat_pid 2>/dev/null 85kill $netcat_pid 2>/dev/null
99rm -f ${COPY} $OBJ/unix-[123].fwd 86rm -f ${COPY} $OBJ/unix-[123].fwd
100 87
101trace "forward over UNIX and check result" 88trace "forward over UNIX and check result"
102$NC -Ul $OBJ/unix-1.fwd < ${DATA} > /dev/null & 89$NC -N -Ul $OBJ/unix-1.fwd < ${DATA} > /dev/null &
103netcat_pid=$! 90netcat_pid=$!
104${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1 91${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
105${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1 92${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
106$NC -d -U $OBJ/unix-3.fwd > ${COPY} < /dev/null 93$NC -U $OBJ/unix-3.fwd < /dev/null > ${COPY}
107cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}" 94cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
108kill $netcat_pid 2>/dev/null 95kill $netcat_pid 2>/dev/null
109rm -f ${COPY} $OBJ/unix-[123].fwd 96rm -f ${COPY} $OBJ/unix-[123].fwd
diff --git a/regress/netcat.c b/regress/netcat.c
new file mode 100644
index 000000000..c14d8164c
--- /dev/null
+++ b/regress/netcat.c
@@ -0,0 +1,1638 @@
1/* $OpenBSD: netcat.c,v 1.126 2014/10/30 16:08:31 tedu Exp $ */
2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * Re-written nc(1) for OpenBSD. Original implementation by
31 * *Hobbit* <hobbit@avian.org>.
32 */
33
34#include "includes.h"
35
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <sys/time.h>
39#include <sys/uio.h>
40#include <sys/un.h>
41
42#include <netinet/in.h>
43#include <netinet/tcp.h>
44#include <netinet/ip.h>
45#include <arpa/telnet.h>
46
47#include <err.h>
48#include <errno.h>
49#include <netdb.h>
50#include <poll.h>
51#include <stdarg.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55#include <unistd.h>
56#include <fcntl.h>
57#include <limits.h>
58#include "atomicio.h"
59
60#ifndef SUN_LEN
61#define SUN_LEN(su) \
62 (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
63#endif
64
65#define PORT_MAX 65535
66#define PORT_MAX_LEN 6
67#define UNIX_DG_TMP_SOCKET_SIZE 19
68
69#define POLL_STDIN 0
70#define POLL_NETOUT 1
71#define POLL_NETIN 2
72#define POLL_STDOUT 3
73#define BUFSIZE 16384
74
75/* Command Line Options */
76int dflag; /* detached, no stdin */
77int Fflag; /* fdpass sock to stdout */
78unsigned int iflag; /* Interval Flag */
79int kflag; /* More than one connect */
80int lflag; /* Bind to local port */
81int Nflag; /* shutdown() network socket */
82int nflag; /* Don't do name look up */
83char *Pflag; /* Proxy username */
84char *pflag; /* Localport flag */
85int rflag; /* Random ports flag */
86char *sflag; /* Source Address */
87int tflag; /* Telnet Emulation */
88int uflag; /* UDP - Default to TCP */
89int vflag; /* Verbosity */
90int xflag; /* Socks proxy */
91int zflag; /* Port Scan Flag */
92int Dflag; /* sodebug */
93int Iflag; /* TCP receive buffer size */
94int Oflag; /* TCP send buffer size */
95int Sflag; /* TCP MD5 signature option */
96int Tflag = -1; /* IP Type of Service */
97int rtableid = -1;
98
99int timeout = -1;
100int family = AF_UNSPEC;
101char *portlist[PORT_MAX+1];
102char *unix_dg_tmp_socket;
103
104void atelnet(int, unsigned char *, unsigned int);
105void build_ports(char *);
106void help(void);
107int local_listen(char *, char *, struct addrinfo);
108void readwrite(int);
109void fdpass(int nfd) __attribute__((noreturn));
110int remote_connect(const char *, const char *, struct addrinfo);
111int timeout_connect(int, const struct sockaddr *, socklen_t);
112int socks_connect(const char *, const char *, struct addrinfo,
113 const char *, const char *, struct addrinfo, int, const char *);
114int udptest(int);
115int unix_bind(char *);
116int unix_connect(char *);
117int unix_listen(char *);
118void set_common_sockopts(int);
119int map_tos(char *, int *);
120void report_connect(const struct sockaddr *, socklen_t);
121void usage(int);
122ssize_t drainbuf(int, unsigned char *, size_t *);
123ssize_t fillbuf(int, unsigned char *, size_t *);
124
125int
126main(int argc, char *argv[])
127{
128 int ch, s, ret, socksv;
129 char *host, *uport;
130 struct addrinfo hints;
131 struct servent *sv;
132 socklen_t len;
133 struct sockaddr_storage cliaddr;
134 char *proxy = NULL;
135 const char *errstr, *proxyhost = "", *proxyport = NULL;
136 struct addrinfo proxyhints;
137 char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
138
139 ret = 1;
140 s = 0;
141 socksv = 5;
142 host = NULL;
143 uport = NULL;
144 sv = NULL;
145
146 while ((ch = getopt(argc, argv,
147 "46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
148 switch (ch) {
149 case '4':
150 family = AF_INET;
151 break;
152 case '6':
153 family = AF_INET6;
154 break;
155 case 'U':
156 family = AF_UNIX;
157 break;
158 case 'X':
159 if (strcasecmp(optarg, "connect") == 0)
160 socksv = -1; /* HTTP proxy CONNECT */
161 else if (strcmp(optarg, "4") == 0)
162 socksv = 4; /* SOCKS v.4 */
163 else if (strcmp(optarg, "5") == 0)
164 socksv = 5; /* SOCKS v.5 */
165 else
166 errx(1, "unsupported proxy protocol");
167 break;
168 case 'd':
169 dflag = 1;
170 break;
171 case 'F':
172 Fflag = 1;
173 break;
174 case 'h':
175 help();
176 break;
177 case 'i':
178 iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
179 if (errstr)
180 errx(1, "interval %s: %s", errstr, optarg);
181 break;
182 case 'k':
183 kflag = 1;
184 break;
185 case 'l':
186 lflag = 1;
187 break;
188 case 'N':
189 Nflag = 1;
190 break;
191 case 'n':
192 nflag = 1;
193 break;
194 case 'P':
195 Pflag = optarg;
196 break;
197 case 'p':
198 pflag = optarg;
199 break;
200 case 'r':
201 rflag = 1;
202 break;
203 case 's':
204 sflag = optarg;
205 break;
206 case 't':
207 tflag = 1;
208 break;
209 case 'u':
210 uflag = 1;
211 break;
212#ifdef SO_RTABLE
213 case 'V':
214 rtableid = (int)strtonum(optarg, 0,
215 RT_TABLEID_MAX, &errstr);
216 if (errstr)
217 errx(1, "rtable %s: %s", errstr, optarg);
218 break;
219#endif
220 case 'v':
221 vflag = 1;
222 break;
223 case 'w':
224 timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
225 if (errstr)
226 errx(1, "timeout %s: %s", errstr, optarg);
227 timeout *= 1000;
228 break;
229 case 'x':
230 xflag = 1;
231 if ((proxy = strdup(optarg)) == NULL)
232 err(1, NULL);
233 break;
234 case 'z':
235 zflag = 1;
236 break;
237 case 'D':
238 Dflag = 1;
239 break;
240 case 'I':
241 Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
242 if (errstr != NULL)
243 errx(1, "TCP receive window %s: %s",
244 errstr, optarg);
245 break;
246 case 'O':
247 Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
248 if (errstr != NULL)
249 errx(1, "TCP send window %s: %s",
250 errstr, optarg);
251 break;
252 case 'S':
253 Sflag = 1;
254 break;
255 case 'T':
256 errstr = NULL;
257 errno = 0;
258 if (map_tos(optarg, &Tflag))
259 break;
260 if (strlen(optarg) > 1 && optarg[0] == '0' &&
261 optarg[1] == 'x')
262 Tflag = (int)strtol(optarg, NULL, 16);
263 else
264 Tflag = (int)strtonum(optarg, 0, 255,
265 &errstr);
266 if (Tflag < 0 || Tflag > 255 || errstr || errno)
267 errx(1, "illegal tos value %s", optarg);
268 break;
269 default:
270 usage(1);
271 }
272 }
273 argc -= optind;
274 argv += optind;
275
276 /* Cruft to make sure options are clean, and used properly. */
277 if (argv[0] && !argv[1] && family == AF_UNIX) {
278 host = argv[0];
279 uport = NULL;
280 } else if (argv[0] && !argv[1]) {
281 if (!lflag)
282 usage(1);
283 uport = argv[0];
284 host = NULL;
285 } else if (argv[0] && argv[1]) {
286 host = argv[0];
287 uport = argv[1];
288 } else
289 usage(1);
290
291 if (lflag && sflag)
292 errx(1, "cannot use -s and -l");
293 if (lflag && pflag)
294 errx(1, "cannot use -p and -l");
295 if (lflag && zflag)
296 errx(1, "cannot use -z and -l");
297 if (!lflag && kflag)
298 errx(1, "must use -l with -k");
299
300 /* Get name of temporary socket for unix datagram client */
301 if ((family == AF_UNIX) && uflag && !lflag) {
302 if (sflag) {
303 unix_dg_tmp_socket = sflag;
304 } else {
305 strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
306 UNIX_DG_TMP_SOCKET_SIZE);
307 if (mktemp(unix_dg_tmp_socket_buf) == NULL)
308 err(1, "mktemp");
309 unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
310 }
311 }
312
313 /* Initialize addrinfo structure. */
314 if (family != AF_UNIX) {
315 memset(&hints, 0, sizeof(struct addrinfo));
316 hints.ai_family = family;
317 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
318 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
319 if (nflag)
320 hints.ai_flags |= AI_NUMERICHOST;
321 }
322
323 if (xflag) {
324 if (uflag)
325 errx(1, "no proxy support for UDP mode");
326
327 if (lflag)
328 errx(1, "no proxy support for listen");
329
330 if (family == AF_UNIX)
331 errx(1, "no proxy support for unix sockets");
332
333 /* XXX IPv6 transport to proxy would probably work */
334 if (family == AF_INET6)
335 errx(1, "no proxy support for IPv6");
336
337 if (sflag)
338 errx(1, "no proxy support for local source address");
339
340 proxyhost = strsep(&proxy, ":");
341 proxyport = proxy;
342
343 memset(&proxyhints, 0, sizeof(struct addrinfo));
344 proxyhints.ai_family = family;
345 proxyhints.ai_socktype = SOCK_STREAM;
346 proxyhints.ai_protocol = IPPROTO_TCP;
347 if (nflag)
348 proxyhints.ai_flags |= AI_NUMERICHOST;
349 }
350
351 if (lflag) {
352 int connfd;
353 ret = 0;
354
355 if (family == AF_UNIX) {
356 if (uflag)
357 s = unix_bind(host);
358 else
359 s = unix_listen(host);
360 }
361
362 /* Allow only one connection at a time, but stay alive. */
363 for (;;) {
364 if (family != AF_UNIX)
365 s = local_listen(host, uport, hints);
366 if (s < 0)
367 err(1, NULL);
368 /*
369 * For UDP and -k, don't connect the socket, let it
370 * receive datagrams from multiple socket pairs.
371 */
372 if (uflag && kflag)
373 readwrite(s);
374 /*
375 * For UDP and not -k, we will use recvfrom() initially
376 * to wait for a caller, then use the regular functions
377 * to talk to the caller.
378 */
379 else if (uflag && !kflag) {
380 int rv, plen;
381 char buf[16384];
382 struct sockaddr_storage z;
383
384 len = sizeof(z);
385 plen = 2048;
386 rv = recvfrom(s, buf, plen, MSG_PEEK,
387 (struct sockaddr *)&z, &len);
388 if (rv < 0)
389 err(1, "recvfrom");
390
391 rv = connect(s, (struct sockaddr *)&z, len);
392 if (rv < 0)
393 err(1, "connect");
394
395 if (vflag)
396 report_connect((struct sockaddr *)&z, len);
397
398 readwrite(s);
399 } else {
400 len = sizeof(cliaddr);
401 connfd = accept(s, (struct sockaddr *)&cliaddr,
402 &len);
403 if (connfd == -1) {
404 /* For now, all errnos are fatal */
405 err(1, "accept");
406 }
407 if (vflag)
408 report_connect((struct sockaddr *)&cliaddr, len);
409
410 readwrite(connfd);
411 close(connfd);
412 }
413
414 if (family != AF_UNIX)
415 close(s);
416 else if (uflag) {
417 if (connect(s, NULL, 0) < 0)
418 err(1, "connect");
419 }
420
421 if (!kflag)
422 break;
423 }
424 } else if (family == AF_UNIX) {
425 ret = 0;
426
427 if ((s = unix_connect(host)) > 0 && !zflag) {
428 readwrite(s);
429 close(s);
430 } else
431 ret = 1;
432
433 if (uflag)
434 unlink(unix_dg_tmp_socket);
435 exit(ret);
436
437 } else {
438 int i = 0;
439
440 /* Construct the portlist[] array. */
441 build_ports(uport);
442
443 /* Cycle through portlist, connecting to each port. */
444 for (i = 0; portlist[i] != NULL; i++) {
445 if (s)
446 close(s);
447
448 if (xflag)
449 s = socks_connect(host, portlist[i], hints,
450 proxyhost, proxyport, proxyhints, socksv,
451 Pflag);
452 else
453 s = remote_connect(host, portlist[i], hints);
454
455 if (s < 0)
456 continue;
457
458 ret = 0;
459 if (vflag || zflag) {
460 /* For UDP, make sure we are connected. */
461 if (uflag) {
462 if (udptest(s) == -1) {
463 ret = 1;
464 continue;
465 }
466 }
467
468 /* Don't look up port if -n. */
469 if (nflag)
470 sv = NULL;
471 else {
472 sv = getservbyport(
473 ntohs(atoi(portlist[i])),
474 uflag ? "udp" : "tcp");
475 }
476
477 fprintf(stderr,
478 "Connection to %s %s port [%s/%s] "
479 "succeeded!\n", host, portlist[i],
480 uflag ? "udp" : "tcp",
481 sv ? sv->s_name : "*");
482 }
483 if (Fflag)
484 fdpass(s);
485 else if (!zflag)
486 readwrite(s);
487 }
488 }
489
490 if (s)
491 close(s);
492
493 exit(ret);
494}
495
496/*
497 * unix_bind()
498 * Returns a unix socket bound to the given path
499 */
500int
501unix_bind(char *path)
502{
503 struct sockaddr_un sun;
504 int s;
505
506 /* Create unix domain socket. */
507 if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
508 0)) < 0)
509 return (-1);
510
511 memset(&sun, 0, sizeof(struct sockaddr_un));
512 sun.sun_family = AF_UNIX;
513
514 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
515 sizeof(sun.sun_path)) {
516 close(s);
517 errno = ENAMETOOLONG;
518 return (-1);
519 }
520
521 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
522 close(s);
523 return (-1);
524 }
525 return (s);
526}
527
528/*
529 * unix_connect()
530 * Returns a socket connected to a local unix socket. Returns -1 on failure.
531 */
532int
533unix_connect(char *path)
534{
535 struct sockaddr_un sun;
536 int s;
537
538 if (uflag) {
539 if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
540 return (-1);
541 } else {
542 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
543 return (-1);
544 }
545 (void)fcntl(s, F_SETFD, FD_CLOEXEC);
546
547 memset(&sun, 0, sizeof(struct sockaddr_un));
548 sun.sun_family = AF_UNIX;
549
550 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
551 sizeof(sun.sun_path)) {
552 close(s);
553 errno = ENAMETOOLONG;
554 return (-1);
555 }
556 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
557 close(s);
558 return (-1);
559 }
560 return (s);
561
562}
563
564/*
565 * unix_listen()
566 * Create a unix domain socket, and listen on it.
567 */
568int
569unix_listen(char *path)
570{
571 int s;
572 if ((s = unix_bind(path)) < 0)
573 return (-1);
574
575 if (listen(s, 5) < 0) {
576 close(s);
577 return (-1);
578 }
579 return (s);
580}
581
582/*
583 * remote_connect()
584 * Returns a socket connected to a remote host. Properly binds to a local
585 * port or source address if needed. Returns -1 on failure.
586 */
587int
588remote_connect(const char *host, const char *port, struct addrinfo hints)
589{
590 struct addrinfo *res, *res0;
591 int s, error;
592#ifdef SO_RTABLE
593 int on = 1;
594#endif
595
596 if ((error = getaddrinfo(host, port, &hints, &res)))
597 errx(1, "getaddrinfo: %s", gai_strerror(error));
598
599 res0 = res;
600 do {
601 if ((s = socket(res0->ai_family, res0->ai_socktype,
602 res0->ai_protocol)) < 0)
603 continue;
604
605#ifdef SO_RTABLE
606 if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
607 &rtableid, sizeof(rtableid)) == -1))
608 err(1, "setsockopt SO_RTABLE");
609#endif
610 /* Bind to a local port or source address if specified. */
611 if (sflag || pflag) {
612 struct addrinfo ahints, *ares;
613
614#ifdef SO_BINDANY
615 /* try SO_BINDANY, but don't insist */
616 setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
617#endif
618 memset(&ahints, 0, sizeof(struct addrinfo));
619 ahints.ai_family = res0->ai_family;
620 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
621 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
622 ahints.ai_flags = AI_PASSIVE;
623 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
624 errx(1, "getaddrinfo: %s", gai_strerror(error));
625
626 if (bind(s, (struct sockaddr *)ares->ai_addr,
627 ares->ai_addrlen) < 0)
628 err(1, "bind failed");
629 freeaddrinfo(ares);
630 }
631
632 set_common_sockopts(s);
633
634 if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
635 break;
636 else if (vflag)
637 warn("connect to %s port %s (%s) failed", host, port,
638 uflag ? "udp" : "tcp");
639
640 close(s);
641 s = -1;
642 } while ((res0 = res0->ai_next) != NULL);
643
644 freeaddrinfo(res);
645
646 return (s);
647}
648
649int
650timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
651{
652 struct pollfd pfd;
653 socklen_t optlen;
654 int flags = 0, optval;
655 int ret;
656
657 if (timeout != -1) {
658 flags = fcntl(s, F_GETFL, 0);
659 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
660 err(1, "set non-blocking mode");
661 }
662
663 if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
664 pfd.fd = s;
665 pfd.events = POLLOUT;
666 if ((ret = poll(&pfd, 1, timeout)) == 1) {
667 optlen = sizeof(optval);
668 if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
669 &optval, &optlen)) == 0) {
670 errno = optval;
671 ret = optval == 0 ? 0 : -1;
672 }
673 } else if (ret == 0) {
674 errno = ETIMEDOUT;
675 ret = -1;
676 } else
677 err(1, "poll failed");
678 }
679
680 if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
681 err(1, "restoring flags");
682
683 return (ret);
684}
685
686/*
687 * local_listen()
688 * Returns a socket listening on a local port, binds to specified source
689 * address. Returns -1 on failure.
690 */
691int
692local_listen(char *host, char *port, struct addrinfo hints)
693{
694 struct addrinfo *res, *res0;
695 int s, ret, x = 1;
696 int error;
697
698 /* Allow nodename to be null. */
699 hints.ai_flags |= AI_PASSIVE;
700
701 /*
702 * In the case of binding to a wildcard address
703 * default to binding to an ipv4 address.
704 */
705 if (host == NULL && hints.ai_family == AF_UNSPEC)
706 hints.ai_family = AF_INET;
707
708 if ((error = getaddrinfo(host, port, &hints, &res)))
709 errx(1, "getaddrinfo: %s", gai_strerror(error));
710
711 res0 = res;
712 do {
713 if ((s = socket(res0->ai_family, res0->ai_socktype,
714 res0->ai_protocol)) < 0)
715 continue;
716
717#ifdef SO_RTABLE
718 if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
719 &rtableid, sizeof(rtableid)) == -1))
720 err(1, "setsockopt SO_RTABLE");
721#endif
722
723 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
724 if (ret == -1)
725 err(1, NULL);
726
727 set_common_sockopts(s);
728
729 if (bind(s, (struct sockaddr *)res0->ai_addr,
730 res0->ai_addrlen) == 0)
731 break;
732
733 close(s);
734 s = -1;
735 } while ((res0 = res0->ai_next) != NULL);
736
737 if (!uflag && s != -1) {
738 if (listen(s, 1) < 0)
739 err(1, "listen");
740 }
741
742 freeaddrinfo(res);
743
744 return (s);
745}
746
747/*
748 * readwrite()
749 * Loop that polls on the network file descriptor and stdin.
750 */
751void
752readwrite(int net_fd)
753{
754 struct pollfd pfd[4];
755 int stdin_fd = STDIN_FILENO;
756 int stdout_fd = STDOUT_FILENO;
757 unsigned char netinbuf[BUFSIZE];
758 size_t netinbufpos = 0;
759 unsigned char stdinbuf[BUFSIZE];
760 size_t stdinbufpos = 0;
761 int n, num_fds;
762 ssize_t ret;
763
764 /* don't read from stdin if requested */
765 if (dflag)
766 stdin_fd = -1;
767
768 /* stdin */
769 pfd[POLL_STDIN].fd = stdin_fd;
770 pfd[POLL_STDIN].events = POLLIN;
771
772 /* network out */
773 pfd[POLL_NETOUT].fd = net_fd;
774 pfd[POLL_NETOUT].events = 0;
775
776 /* network in */
777 pfd[POLL_NETIN].fd = net_fd;
778 pfd[POLL_NETIN].events = POLLIN;
779
780 /* stdout */
781 pfd[POLL_STDOUT].fd = stdout_fd;
782 pfd[POLL_STDOUT].events = 0;
783
784 while (1) {
785 /* both inputs are gone, buffers are empty, we are done */
786 if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1
787 && stdinbufpos == 0 && netinbufpos == 0) {
788 close(net_fd);
789 return;
790 }
791 /* both outputs are gone, we can't continue */
792 if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) {
793 close(net_fd);
794 return;
795 }
796 /* listen and net in gone, queues empty, done */
797 if (lflag && pfd[POLL_NETIN].fd == -1
798 && stdinbufpos == 0 && netinbufpos == 0) {
799 close(net_fd);
800 return;
801 }
802
803 /* help says -i is for "wait between lines sent". We read and
804 * write arbitrary amounts of data, and we don't want to start
805 * scanning for newlines, so this is as good as it gets */
806 if (iflag)
807 sleep(iflag);
808
809 /* poll */
810 num_fds = poll(pfd, 4, timeout);
811
812 /* treat poll errors */
813 if (num_fds == -1) {
814 close(net_fd);
815 err(1, "polling error");
816 }
817
818 /* timeout happened */
819 if (num_fds == 0)
820 return;
821
822 /* treat socket error conditions */
823 for (n = 0; n < 4; n++) {
824 if (pfd[n].revents & (POLLERR|POLLNVAL)) {
825 pfd[n].fd = -1;
826 }
827 }
828 /* reading is possible after HUP */
829 if (pfd[POLL_STDIN].events & POLLIN &&
830 pfd[POLL_STDIN].revents & POLLHUP &&
831 ! (pfd[POLL_STDIN].revents & POLLIN))
832 pfd[POLL_STDIN].fd = -1;
833
834 if (pfd[POLL_NETIN].events & POLLIN &&
835 pfd[POLL_NETIN].revents & POLLHUP &&
836 ! (pfd[POLL_NETIN].revents & POLLIN))
837 pfd[POLL_NETIN].fd = -1;
838
839 if (pfd[POLL_NETOUT].revents & POLLHUP) {
840 if (Nflag)
841 shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
842 pfd[POLL_NETOUT].fd = -1;
843 }
844 /* if HUP, stop watching stdout */
845 if (pfd[POLL_STDOUT].revents & POLLHUP)
846 pfd[POLL_STDOUT].fd = -1;
847 /* if no net out, stop watching stdin */
848 if (pfd[POLL_NETOUT].fd == -1)
849 pfd[POLL_STDIN].fd = -1;
850 /* if no stdout, stop watching net in */
851 if (pfd[POLL_STDOUT].fd == -1) {
852 if (pfd[POLL_NETIN].fd != -1)
853 shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
854 pfd[POLL_NETIN].fd = -1;
855 }
856
857 /* try to read from stdin */
858 if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
859 ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
860 &stdinbufpos);
861 /* error or eof on stdin - remove from pfd */
862 if (ret == 0 || ret == -1)
863 pfd[POLL_STDIN].fd = -1;
864 /* read something - poll net out */
865 if (stdinbufpos > 0)
866 pfd[POLL_NETOUT].events = POLLOUT;
867 /* filled buffer - remove self from polling */
868 if (stdinbufpos == BUFSIZE)
869 pfd[POLL_STDIN].events = 0;
870 }
871 /* try to write to network */
872 if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
873 ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
874 &stdinbufpos);
875 if (ret == -1)
876 pfd[POLL_NETOUT].fd = -1;
877 /* buffer empty - remove self from polling */
878 if (stdinbufpos == 0)
879 pfd[POLL_NETOUT].events = 0;
880 /* buffer no longer full - poll stdin again */
881 if (stdinbufpos < BUFSIZE)
882 pfd[POLL_STDIN].events = POLLIN;
883 }
884 /* try to read from network */
885 if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
886 ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
887 &netinbufpos);
888 if (ret == -1)
889 pfd[POLL_NETIN].fd = -1;
890 /* eof on net in - remove from pfd */
891 if (ret == 0) {
892 shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
893 pfd[POLL_NETIN].fd = -1;
894 }
895 /* read something - poll stdout */
896 if (netinbufpos > 0)
897 pfd[POLL_STDOUT].events = POLLOUT;
898 /* filled buffer - remove self from polling */
899 if (netinbufpos == BUFSIZE)
900 pfd[POLL_NETIN].events = 0;
901 /* handle telnet */
902 if (tflag)
903 atelnet(pfd[POLL_NETIN].fd, netinbuf,
904 netinbufpos);
905 }
906 /* try to write to stdout */
907 if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
908 ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
909 &netinbufpos);
910 if (ret == -1)
911 pfd[POLL_STDOUT].fd = -1;
912 /* buffer empty - remove self from polling */
913 if (netinbufpos == 0)
914 pfd[POLL_STDOUT].events = 0;
915 /* buffer no longer full - poll net in again */
916 if (netinbufpos < BUFSIZE)
917 pfd[POLL_NETIN].events = POLLIN;
918 }
919
920 /* stdin gone and queue empty? */
921 if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) {
922 if (pfd[POLL_NETOUT].fd != -1 && Nflag)
923 shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
924 pfd[POLL_NETOUT].fd = -1;
925 }
926 /* net in gone and queue empty? */
927 if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) {
928 pfd[POLL_STDOUT].fd = -1;
929 }
930 }
931}
932
933ssize_t
934drainbuf(int fd, unsigned char *buf, size_t *bufpos)
935{
936 ssize_t n;
937 ssize_t adjust;
938
939 n = write(fd, buf, *bufpos);
940 /* don't treat EAGAIN, EINTR as error */
941 if (n == -1 && (errno == EAGAIN || errno == EINTR))
942 n = -2;
943 if (n <= 0)
944 return n;
945 /* adjust buffer */
946 adjust = *bufpos - n;
947 if (adjust > 0)
948 memmove(buf, buf + n, adjust);
949 *bufpos -= n;
950 return n;
951}
952
953
954ssize_t
955fillbuf(int fd, unsigned char *buf, size_t *bufpos)
956{
957 size_t num = BUFSIZE - *bufpos;
958 ssize_t n;
959
960 n = read(fd, buf + *bufpos, num);
961 /* don't treat EAGAIN, EINTR as error */
962 if (n == -1 && (errno == EAGAIN || errno == EINTR))
963 n = -2;
964 if (n <= 0)
965 return n;
966 *bufpos += n;
967 return n;
968}
969
970/*
971 * fdpass()
972 * Pass the connected file descriptor to stdout and exit.
973 */
974void
975fdpass(int nfd)
976{
977 struct msghdr mh;
978 union {
979 struct cmsghdr hdr;
980 char buf[CMSG_SPACE(sizeof(int))];
981 } cmsgbuf;
982 struct cmsghdr *cmsg;
983 struct iovec iov;
984 char c = '\0';
985 ssize_t r;
986 struct pollfd pfd;
987
988 /* Avoid obvious stupidity */
989 if (isatty(STDOUT_FILENO))
990 errx(1, "Cannot pass file descriptor to tty");
991
992 bzero(&mh, sizeof(mh));
993 bzero(&cmsgbuf, sizeof(cmsgbuf));
994 bzero(&iov, sizeof(iov));
995 bzero(&pfd, sizeof(pfd));
996
997 mh.msg_control = (caddr_t)&cmsgbuf.buf;
998 mh.msg_controllen = sizeof(cmsgbuf.buf);
999 cmsg = CMSG_FIRSTHDR(&mh);
1000 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1001 cmsg->cmsg_level = SOL_SOCKET;
1002 cmsg->cmsg_type = SCM_RIGHTS;
1003 *(int *)CMSG_DATA(cmsg) = nfd;
1004
1005 iov.iov_base = &c;
1006 iov.iov_len = 1;
1007 mh.msg_iov = &iov;
1008 mh.msg_iovlen = 1;
1009
1010 bzero(&pfd, sizeof(pfd));
1011 pfd.fd = STDOUT_FILENO;
1012 for (;;) {
1013 r = sendmsg(STDOUT_FILENO, &mh, 0);
1014 if (r == -1) {
1015 if (errno == EAGAIN || errno == EINTR) {
1016 pfd.events = POLLOUT;
1017 if (poll(&pfd, 1, -1) == -1)
1018 err(1, "poll");
1019 continue;
1020 }
1021 err(1, "sendmsg");
1022 } else if (r == -1)
1023 errx(1, "sendmsg: unexpected return value %zd", r);
1024 else
1025 break;
1026 }
1027 exit(0);
1028}
1029
1030/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
1031void
1032atelnet(int nfd, unsigned char *buf, unsigned int size)
1033{
1034 unsigned char *p, *end;
1035 unsigned char obuf[4];
1036
1037 if (size < 3)
1038 return;
1039 end = buf + size - 2;
1040
1041 for (p = buf; p < end; p++) {
1042 if (*p != IAC)
1043 continue;
1044
1045 obuf[0] = IAC;
1046 p++;
1047 if ((*p == WILL) || (*p == WONT))
1048 obuf[1] = DONT;
1049 else if ((*p == DO) || (*p == DONT))
1050 obuf[1] = WONT;
1051 else
1052 continue;
1053
1054 p++;
1055 obuf[2] = *p;
1056 if (atomicio(vwrite, nfd, obuf, 3) != 3)
1057 warn("Write Error!");
1058 }
1059}
1060
1061/*
1062 * build_ports()
1063 * Build an array of ports in portlist[], listing each port
1064 * that we should try to connect to.
1065 */
1066void
1067build_ports(char *p)
1068{
1069 const char *errstr;
1070 char *n;
1071 int hi, lo, cp;
1072 int x = 0;
1073
1074 if ((n = strchr(p, '-')) != NULL) {
1075 *n = '\0';
1076 n++;
1077
1078 /* Make sure the ports are in order: lowest->highest. */
1079 hi = strtonum(n, 1, PORT_MAX, &errstr);
1080 if (errstr)
1081 errx(1, "port number %s: %s", errstr, n);
1082 lo = strtonum(p, 1, PORT_MAX, &errstr);
1083 if (errstr)
1084 errx(1, "port number %s: %s", errstr, p);
1085
1086 if (lo > hi) {
1087 cp = hi;
1088 hi = lo;
1089 lo = cp;
1090 }
1091
1092 /* Load ports sequentially. */
1093 for (cp = lo; cp <= hi; cp++) {
1094 portlist[x] = calloc(1, PORT_MAX_LEN);
1095 if (portlist[x] == NULL)
1096 err(1, NULL);
1097 snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
1098 x++;
1099 }
1100
1101 /* Randomly swap ports. */
1102 if (rflag) {
1103 int y;
1104 char *c;
1105
1106 for (x = 0; x <= (hi - lo); x++) {
1107 y = (arc4random() & 0xFFFF) % (hi - lo);
1108 c = portlist[x];
1109 portlist[x] = portlist[y];
1110 portlist[y] = c;
1111 }
1112 }
1113 } else {
1114 hi = strtonum(p, 1, PORT_MAX, &errstr);
1115 if (errstr)
1116 errx(1, "port number %s: %s", errstr, p);
1117 portlist[0] = strdup(p);
1118 if (portlist[0] == NULL)
1119 err(1, NULL);
1120 }
1121}
1122
1123/*
1124 * udptest()
1125 * Do a few writes to see if the UDP port is there.
1126 * Fails once PF state table is full.
1127 */
1128int
1129udptest(int s)
1130{
1131 int i, ret;
1132
1133 for (i = 0; i <= 3; i++) {
1134 if (write(s, "X", 1) == 1)
1135 ret = 1;
1136 else
1137 ret = -1;
1138 }
1139 return (ret);
1140}
1141
1142void
1143set_common_sockopts(int s)
1144{
1145 int x = 1;
1146
1147 if (Sflag) {
1148 if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
1149 &x, sizeof(x)) == -1)
1150 err(1, NULL);
1151 }
1152 if (Dflag) {
1153 if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
1154 &x, sizeof(x)) == -1)
1155 err(1, NULL);
1156 }
1157 if (Tflag != -1) {
1158 if (setsockopt(s, IPPROTO_IP, IP_TOS,
1159 &Tflag, sizeof(Tflag)) == -1)
1160 err(1, "set IP ToS");
1161 }
1162 if (Iflag) {
1163 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
1164 &Iflag, sizeof(Iflag)) == -1)
1165 err(1, "set TCP receive buffer size");
1166 }
1167 if (Oflag) {
1168 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
1169 &Oflag, sizeof(Oflag)) == -1)
1170 err(1, "set TCP send buffer size");
1171 }
1172}
1173
1174int
1175map_tos(char *s, int *val)
1176{
1177 /* DiffServ Codepoints and other TOS mappings */
1178 const struct toskeywords {
1179 const char *keyword;
1180 int val;
1181 } *t, toskeywords[] = {
1182 { "af11", IPTOS_DSCP_AF11 },
1183 { "af12", IPTOS_DSCP_AF12 },
1184 { "af13", IPTOS_DSCP_AF13 },
1185 { "af21", IPTOS_DSCP_AF21 },
1186 { "af22", IPTOS_DSCP_AF22 },
1187 { "af23", IPTOS_DSCP_AF23 },
1188 { "af31", IPTOS_DSCP_AF31 },
1189 { "af32", IPTOS_DSCP_AF32 },
1190 { "af33", IPTOS_DSCP_AF33 },
1191 { "af41", IPTOS_DSCP_AF41 },
1192 { "af42", IPTOS_DSCP_AF42 },
1193 { "af43", IPTOS_DSCP_AF43 },
1194 { "critical", IPTOS_PREC_CRITIC_ECP },
1195 { "cs0", IPTOS_DSCP_CS0 },
1196 { "cs1", IPTOS_DSCP_CS1 },
1197 { "cs2", IPTOS_DSCP_CS2 },
1198 { "cs3", IPTOS_DSCP_CS3 },
1199 { "cs4", IPTOS_DSCP_CS4 },
1200 { "cs5", IPTOS_DSCP_CS5 },
1201 { "cs6", IPTOS_DSCP_CS6 },
1202 { "cs7", IPTOS_DSCP_CS7 },
1203 { "ef", IPTOS_DSCP_EF },
1204 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
1205 { "lowdelay", IPTOS_LOWDELAY },
1206 { "netcontrol", IPTOS_PREC_NETCONTROL },
1207 { "reliability", IPTOS_RELIABILITY },
1208 { "throughput", IPTOS_THROUGHPUT },
1209 { NULL, -1 },
1210 };
1211
1212 for (t = toskeywords; t->keyword != NULL; t++) {
1213 if (strcmp(s, t->keyword) == 0) {
1214 *val = t->val;
1215 return (1);
1216 }
1217 }
1218
1219 return (0);
1220}
1221
1222void
1223report_connect(const struct sockaddr *sa, socklen_t salen)
1224{
1225 char remote_host[NI_MAXHOST];
1226 char remote_port[NI_MAXSERV];
1227 int herr;
1228 int flags = NI_NUMERICSERV;
1229
1230 if (nflag)
1231 flags |= NI_NUMERICHOST;
1232
1233 if ((herr = getnameinfo(sa, salen,
1234 remote_host, sizeof(remote_host),
1235 remote_port, sizeof(remote_port),
1236 flags)) != 0) {
1237 if (herr == EAI_SYSTEM)
1238 err(1, "getnameinfo");
1239 else
1240 errx(1, "getnameinfo: %s", gai_strerror(herr));
1241 }
1242
1243 fprintf(stderr,
1244 "Connection from %s %s "
1245 "received!\n", remote_host, remote_port);
1246}
1247
1248void
1249help(void)
1250{
1251 usage(0);
1252 fprintf(stderr, "\tCommand Summary:\n\
1253 \t-4 Use IPv4\n\
1254 \t-6 Use IPv6\n\
1255 \t-D Enable the debug socket option\n\
1256 \t-d Detach from stdin\n\
1257 \t-F Pass socket fd\n\
1258 \t-h This help text\n\
1259 \t-I length TCP receive buffer length\n\
1260 \t-i secs\t Delay interval for lines sent, ports scanned\n\
1261 \t-k Keep inbound sockets open for multiple connects\n\
1262 \t-l Listen mode, for inbound connects\n\
1263 \t-N Shutdown the network socket after EOF on stdin\n\
1264 \t-n Suppress name/port resolutions\n\
1265 \t-O length TCP send buffer length\n\
1266 \t-P proxyuser\tUsername for proxy authentication\n\
1267 \t-p port\t Specify local port for remote connects\n\
1268 \t-r Randomize remote ports\n\
1269 \t-S Enable the TCP MD5 signature option\n\
1270 \t-s addr\t Local source address\n\
1271 \t-T toskeyword\tSet IP Type of Service\n\
1272 \t-t Answer TELNET negotiation\n\
1273 \t-U Use UNIX domain socket\n\
1274 \t-u UDP mode\n\
1275 \t-V rtable Specify alternate routing table\n\
1276 \t-v Verbose\n\
1277 \t-w secs\t Timeout for connects and final net reads\n\
1278 \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
1279 \t-x addr[:port]\tSpecify proxy address and port\n\
1280 \t-z Zero-I/O mode [used for scanning]\n\
1281 Port numbers can be individual or ranges: lo-hi [inclusive]\n");
1282 exit(1);
1283}
1284
1285void
1286usage(int ret)
1287{
1288 fprintf(stderr,
1289 "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"
1290 "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
1291 "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n"
1292 "\t [-x proxy_address[:port]] [destination] [port]\n");
1293 if (ret)
1294 exit(1);
1295}
1296
1297/* *** src/usr.bin/nc/socks.c *** */
1298
1299
1300/* $OpenBSD: socks.c,v 1.20 2012/03/08 09:56:28 espie Exp $ */
1301
1302/*
1303 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
1304 * Copyright (c) 2004, 2005 Damien Miller. All rights reserved.
1305 *
1306 * Redistribution and use in source and binary forms, with or without
1307 * modification, are permitted provided that the following conditions
1308 * are met:
1309 * 1. Redistributions of source code must retain the above copyright
1310 * notice, this list of conditions and the following disclaimer.
1311 * 2. Redistributions in binary form must reproduce the above copyright
1312 * notice, this list of conditions and the following disclaimer in the
1313 * documentation and/or other materials provided with the distribution.
1314 *
1315 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1316 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1317 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1318 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1319 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1320 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1321 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1322 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1323 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1324 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1325 */
1326
1327#include <sys/types.h>
1328#include <sys/socket.h>
1329#include <netinet/in.h>
1330#include <arpa/inet.h>
1331
1332#include <err.h>
1333#include <errno.h>
1334#include <netdb.h>
1335#include <stdio.h>
1336#include <stdlib.h>
1337#include <string.h>
1338#include <unistd.h>
1339#include <resolv.h>
1340
1341#define SOCKS_PORT "1080"
1342#define HTTP_PROXY_PORT "3128"
1343#define HTTP_MAXHDRS 64
1344#define SOCKS_V5 5
1345#define SOCKS_V4 4
1346#define SOCKS_NOAUTH 0
1347#define SOCKS_NOMETHOD 0xff
1348#define SOCKS_CONNECT 1
1349#define SOCKS_IPV4 1
1350#define SOCKS_DOMAIN 3
1351#define SOCKS_IPV6 4
1352
1353int remote_connect(const char *, const char *, struct addrinfo);
1354int socks_connect(const char *, const char *, struct addrinfo,
1355 const char *, const char *, struct addrinfo, int,
1356 const char *);
1357
1358static int
1359decode_addrport(const char *h, const char *p, struct sockaddr *addr,
1360 socklen_t addrlen, int v4only, int numeric)
1361{
1362 int r;
1363 struct addrinfo hints, *res;
1364
1365 bzero(&hints, sizeof(hints));
1366 hints.ai_family = v4only ? PF_INET : PF_UNSPEC;
1367 hints.ai_flags = numeric ? AI_NUMERICHOST : 0;
1368 hints.ai_socktype = SOCK_STREAM;
1369 r = getaddrinfo(h, p, &hints, &res);
1370 /* Don't fatal when attempting to convert a numeric address */
1371 if (r != 0) {
1372 if (!numeric) {
1373 errx(1, "getaddrinfo(\"%.64s\", \"%.64s\"): %s", h, p,
1374 gai_strerror(r));
1375 }
1376 return (-1);
1377 }
1378 if (addrlen < res->ai_addrlen) {
1379 freeaddrinfo(res);
1380 errx(1, "internal error: addrlen < res->ai_addrlen");
1381 }
1382 memcpy(addr, res->ai_addr, res->ai_addrlen);
1383 freeaddrinfo(res);
1384 return (0);
1385}
1386
1387static int
1388proxy_read_line(int fd, char *buf, size_t bufsz)
1389{
1390 size_t off;
1391
1392 for(off = 0;;) {
1393 if (off >= bufsz)
1394 errx(1, "proxy read too long");
1395 if (atomicio(read, fd, buf + off, 1) != 1)
1396 err(1, "proxy read");
1397 /* Skip CR */
1398 if (buf[off] == '\r')
1399 continue;
1400 if (buf[off] == '\n') {
1401 buf[off] = '\0';
1402 break;
1403 }
1404 off++;
1405 }
1406 return (off);
1407}
1408
1409static const char *
1410getproxypass(const char *proxyuser, const char *proxyhost)
1411{
1412 char prompt[512];
1413 static char pw[256];
1414
1415 snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ",
1416 proxyuser, proxyhost);
1417 if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL)
1418 errx(1, "Unable to read proxy passphrase");
1419 return (pw);
1420}
1421
1422int
1423socks_connect(const char *host, const char *port,
1424 struct addrinfo hints __attribute__ ((__unused__)),
1425 const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,
1426 int socksv, const char *proxyuser)
1427{
1428 int proxyfd, r, authretry = 0;
1429 size_t hlen, wlen;
1430 unsigned char buf[1024];
1431 size_t cnt;
1432 struct sockaddr_storage addr;
1433 struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;
1434 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;
1435 in_port_t serverport;
1436 const char *proxypass = NULL;
1437
1438 if (proxyport == NULL)
1439 proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
1440
1441 /* Abuse API to lookup port */
1442 if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr,
1443 sizeof(addr), 1, 1) == -1)
1444 errx(1, "unknown port \"%.64s\"", port);
1445 serverport = in4->sin_port;
1446
1447 again:
1448 if (authretry++ > 3)
1449 errx(1, "Too many authentication failures");
1450
1451 proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
1452
1453 if (proxyfd < 0)
1454 return (-1);
1455
1456 if (socksv == 5) {
1457 if (decode_addrport(host, port, (struct sockaddr *)&addr,
1458 sizeof(addr), 0, 1) == -1)
1459 addr.ss_family = 0; /* used in switch below */
1460
1461 /* Version 5, one method: no authentication */
1462 buf[0] = SOCKS_V5;
1463 buf[1] = 1;
1464 buf[2] = SOCKS_NOAUTH;
1465 cnt = atomicio(vwrite, proxyfd, buf, 3);
1466 if (cnt != 3)
1467 err(1, "write failed (%zu/3)", cnt);
1468
1469 cnt = atomicio(read, proxyfd, buf, 2);
1470 if (cnt != 2)
1471 err(1, "read failed (%zu/3)", cnt);
1472
1473 if (buf[1] == SOCKS_NOMETHOD)
1474 errx(1, "authentication method negotiation failed");
1475
1476 switch (addr.ss_family) {
1477 case 0:
1478 /* Version 5, connect: domain name */
1479
1480 /* Max domain name length is 255 bytes */
1481 hlen = strlen(host);
1482 if (hlen > 255)
1483 errx(1, "host name too long for SOCKS5");
1484 buf[0] = SOCKS_V5;
1485 buf[1] = SOCKS_CONNECT;
1486 buf[2] = 0;
1487 buf[3] = SOCKS_DOMAIN;
1488 buf[4] = hlen;
1489 memcpy(buf + 5, host, hlen);
1490 memcpy(buf + 5 + hlen, &serverport, sizeof serverport);
1491 wlen = 7 + hlen;
1492 break;
1493 case AF_INET:
1494 /* Version 5, connect: IPv4 address */
1495 buf[0] = SOCKS_V5;
1496 buf[1] = SOCKS_CONNECT;
1497 buf[2] = 0;
1498 buf[3] = SOCKS_IPV4;
1499 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
1500 memcpy(buf + 8, &in4->sin_port, sizeof in4->sin_port);
1501 wlen = 10;
1502 break;
1503 case AF_INET6:
1504 /* Version 5, connect: IPv6 address */
1505 buf[0] = SOCKS_V5;
1506 buf[1] = SOCKS_CONNECT;
1507 buf[2] = 0;
1508 buf[3] = SOCKS_IPV6;
1509 memcpy(buf + 4, &in6->sin6_addr, sizeof in6->sin6_addr);
1510 memcpy(buf + 20, &in6->sin6_port,
1511 sizeof in6->sin6_port);
1512 wlen = 22;
1513 break;
1514 default:
1515 errx(1, "internal error: silly AF");
1516 }
1517
1518 cnt = atomicio(vwrite, proxyfd, buf, wlen);
1519 if (cnt != wlen)
1520 err(1, "write failed (%zu/%zu)", cnt, wlen);
1521
1522 cnt = atomicio(read, proxyfd, buf, 4);
1523 if (cnt != 4)
1524 err(1, "read failed (%zu/4)", cnt);
1525 if (buf[1] != 0)
1526 errx(1, "connection failed, SOCKS error %d", buf[1]);
1527 switch (buf[3]) {
1528 case SOCKS_IPV4:
1529 cnt = atomicio(read, proxyfd, buf + 4, 6);
1530 if (cnt != 6)
1531 err(1, "read failed (%zu/6)", cnt);
1532 break;
1533 case SOCKS_IPV6:
1534 cnt = atomicio(read, proxyfd, buf + 4, 18);
1535 if (cnt != 18)
1536 err(1, "read failed (%zu/18)", cnt);
1537 break;
1538 default:
1539 errx(1, "connection failed, unsupported address type");
1540 }
1541 } else if (socksv == 4) {
1542 /* This will exit on lookup failure */
1543 decode_addrport(host, port, (struct sockaddr *)&addr,
1544 sizeof(addr), 1, 0);
1545
1546 /* Version 4 */
1547 buf[0] = SOCKS_V4;
1548 buf[1] = SOCKS_CONNECT; /* connect */
1549 memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port);
1550 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
1551 buf[8] = 0; /* empty username */
1552 wlen = 9;
1553
1554 cnt = atomicio(vwrite, proxyfd, buf, wlen);
1555 if (cnt != wlen)
1556 err(1, "write failed (%zu/%zu)", cnt, wlen);
1557
1558 cnt = atomicio(read, proxyfd, buf, 8);
1559 if (cnt != 8)
1560 err(1, "read failed (%zu/8)", cnt);
1561 if (buf[1] != 90)
1562 errx(1, "connection failed, SOCKS error %d", buf[1]);
1563 } else if (socksv == -1) {
1564 /* HTTP proxy CONNECT */
1565
1566 /* Disallow bad chars in hostname */
1567 if (strcspn(host, "\r\n\t []:") != strlen(host))
1568 errx(1, "Invalid hostname");
1569
1570 /* Try to be sane about numeric IPv6 addresses */
1571 if (strchr(host, ':') != NULL) {
1572 r = snprintf(buf, sizeof(buf),
1573 "CONNECT [%s]:%d HTTP/1.0\r\n",
1574 host, ntohs(serverport));
1575 } else {
1576 r = snprintf(buf, sizeof(buf),
1577 "CONNECT %s:%d HTTP/1.0\r\n",
1578 host, ntohs(serverport));
1579 }
1580 if (r == -1 || (size_t)r >= sizeof(buf))
1581 errx(1, "hostname too long");
1582 r = strlen(buf);
1583
1584 cnt = atomicio(vwrite, proxyfd, buf, r);
1585 if (cnt != (size_t)r)
1586 err(1, "write failed (%zu/%d)", cnt, r);
1587
1588 if (authretry > 1) {
1589 char resp[1024];
1590
1591 proxypass = getproxypass(proxyuser, proxyhost);
1592 r = snprintf(buf, sizeof(buf), "%s:%s",
1593 proxyuser, proxypass);
1594 if (r == -1 || (size_t)r >= sizeof(buf) ||
1595 b64_ntop(buf, strlen(buf), resp,
1596 sizeof(resp)) == -1)
1597 errx(1, "Proxy username/password too long");
1598 r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
1599 "Basic %s\r\n", resp);
1600 if (r == -1 || (size_t)r >= sizeof(buf))
1601 errx(1, "Proxy auth response too long");
1602 r = strlen(buf);
1603 if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != (size_t)r)
1604 err(1, "write failed (%zu/%d)", cnt, r);
1605 }
1606
1607 /* Terminate headers */
1608 if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
1609 err(1, "write failed (2/%d)", r);
1610
1611 /* Read status reply */
1612 proxy_read_line(proxyfd, buf, sizeof(buf));
1613 if (proxyuser != NULL &&
1614 strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
1615 if (authretry > 1) {
1616 fprintf(stderr, "Proxy authentication "
1617 "failed\n");
1618 }
1619 close(proxyfd);
1620 goto again;
1621 } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 &&
1622 strncmp(buf, "HTTP/1.1 200 ", 12) != 0)
1623 errx(1, "Proxy error: \"%s\"", buf);
1624
1625 /* Headers continue until we hit an empty line */
1626 for (r = 0; r < HTTP_MAXHDRS; r++) {
1627 proxy_read_line(proxyfd, buf, sizeof(buf));
1628 if (*buf == '\0')
1629 break;
1630 }
1631 if (*buf != '\0')
1632 errx(1, "Too many proxy headers received");
1633 } else
1634 errx(1, "Unknown proxy protocol %d", socksv);
1635
1636 return (proxyfd);
1637}
1638