summaryrefslogtreecommitdiff
path: root/src/usr.bin/nc/netcat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr.bin/nc/netcat.c')
-rw-r--r--src/usr.bin/nc/netcat.c761
1 files changed, 761 insertions, 0 deletions
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
new file mode 100644
index 0000000000..df5c44a8ce
--- /dev/null
+++ b/src/usr.bin/nc/netcat.c
@@ -0,0 +1,761 @@
1/* $OpenBSD: netcat.c,v 1.64 2003/10/19 22:50:35 deraadt 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 <sys/types.h>
35#include <sys/socket.h>
36#include <sys/time.h>
37#include <sys/un.h>
38
39#include <netinet/in.h>
40#include <arpa/telnet.h>
41
42#include <err.h>
43#include <errno.h>
44#include <netdb.h>
45#include <poll.h>
46#include <stdarg.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51#include <fcntl.h>
52
53#ifndef SUN_LEN
54#define SUN_LEN(su) \
55 (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
56#endif
57
58#define PORT_MAX 65535
59#define PORT_MAX_LEN 6
60
61/* Command Line Options */
62int iflag; /* Interval Flag */
63int kflag; /* More than one connect */
64int lflag; /* Bind to local port */
65int nflag; /* Dont do name lookup */
66char *pflag; /* Localport flag */
67int rflag; /* Random ports flag */
68char *sflag; /* Source Address */
69int tflag; /* Telnet Emulation */
70int uflag; /* UDP - Default to TCP */
71int vflag; /* Verbosity */
72int xflag; /* Socks proxy */
73int zflag; /* Port Scan Flag */
74
75int timeout = -1;
76int family = AF_UNSPEC;
77char *portlist[PORT_MAX+1];
78
79ssize_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
80void atelnet(int, unsigned char *, unsigned int);
81void build_ports(char *);
82void help(void);
83int local_listen(char *, char *, struct addrinfo);
84void readwrite(int);
85int remote_connect(char *, char *, struct addrinfo);
86int socks_connect(char *, char *, struct addrinfo, char *, char *,
87 struct addrinfo, int);
88int udptest(int);
89int unix_connect(char *);
90int unix_listen(char *);
91void usage(int);
92
93int
94main(int argc, char *argv[])
95{
96 int ch, s, ret, socksv;
97 char *host, *uport, *endp;
98 struct addrinfo hints;
99 struct servent *sv;
100 socklen_t len;
101 struct sockaddr *cliaddr;
102 char *proxy;
103 char *proxyhost = "", *proxyport = NULL;
104 struct addrinfo proxyhints;
105
106 ret = 1;
107 s = 0;
108 socksv = 5;
109 host = NULL;
110 uport = NULL;
111 endp = NULL;
112 sv = NULL;
113
114 while ((ch = getopt(argc, argv, "46UX:hi:klnp:rs:tuvw:x:z")) != -1) {
115 switch (ch) {
116 case '4':
117 family = AF_INET;
118 break;
119 case '6':
120 family = AF_INET6;
121 break;
122 case 'U':
123 family = AF_UNIX;
124 break;
125 case 'X':
126 socksv = (int)strtoul(optarg, &endp, 10);
127 if ((socksv != 4 && socksv != 5) || *endp != '\0')
128 errx(1, "only SOCKS version 4 and 5 supported");
129 break;
130 case 'h':
131 help();
132 break;
133 case 'i':
134 iflag = (int)strtoul(optarg, &endp, 10);
135 if (iflag < 0 || *endp != '\0')
136 errx(1, "interval cannot be negative");
137 break;
138 case 'k':
139 kflag = 1;
140 break;
141 case 'l':
142 lflag = 1;
143 break;
144 case 'n':
145 nflag = 1;
146 break;
147 case 'p':
148 pflag = optarg;
149 break;
150 case 'r':
151 rflag = 1;
152 break;
153 case 's':
154 sflag = optarg;
155 break;
156 case 't':
157 tflag = 1;
158 break;
159 case 'u':
160 uflag = 1;
161 break;
162 case 'v':
163 vflag = 1;
164 break;
165 case 'w':
166 timeout = (int)strtoul(optarg, &endp, 10);
167 if (timeout < 0 || *endp != '\0')
168 errx(1, "timeout cannot be negative");
169 if (timeout >= (INT_MAX / 1000))
170 errx(1, "timeout too large");
171 timeout *= 1000;
172 break;
173 case 'x':
174 xflag = 1;
175 if ((proxy = strdup(optarg)) == NULL)
176 err(1, NULL);
177 break;
178 case 'z':
179 zflag = 1;
180 break;
181 default:
182 usage(1);
183 }
184 }
185 argc -= optind;
186 argv += optind;
187
188 /* Cruft to make sure options are clean, and used properly. */
189 if (argv[0] && !argv[1] && family == AF_UNIX) {
190 if (uflag)
191 errx(1, "cannot use -u and -U");
192 host = argv[0];
193 uport = NULL;
194 } else if (argv[0] && !argv[1]) {
195 if (!lflag)
196 usage(1);
197 uport = argv[0];
198 host = NULL;
199 } else if (argv[0] && argv[1]) {
200 host = argv[0];
201 uport = argv[1];
202 } else
203 usage(1);
204
205 if (lflag && sflag)
206 errx(1, "cannot use -s and -l");
207 if (lflag && pflag)
208 errx(1, "cannot use -p and -l");
209 if (lflag && zflag)
210 errx(1, "cannot use -z and -l");
211 if (!lflag && kflag)
212 errx(1, "must use -l with -k");
213
214 /* Initialize addrinfo structure */
215 if (family != AF_UNIX) {
216 memset(&hints, 0, sizeof(struct addrinfo));
217 hints.ai_family = family;
218 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
219 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
220 if (nflag)
221 hints.ai_flags |= AI_NUMERICHOST;
222 }
223
224 if (xflag) {
225 if (uflag)
226 errx(1, "no proxy support for UDP mode");
227
228 if (lflag)
229 errx(1, "no proxy support for listen");
230
231 if (family == AF_UNIX)
232 errx(1, "no proxy support for unix sockets");
233
234 /* XXX IPv6 transport to proxy would probably work */
235 if (family == AF_INET6)
236 errx(1, "no proxy support for IPv6");
237
238 if (sflag)
239 errx(1, "no proxy support for local source address");
240
241 proxyhost = strsep(&proxy, ":");
242 proxyport = proxy;
243
244 memset(&proxyhints, 0, sizeof(struct addrinfo));
245 proxyhints.ai_family = family;
246 proxyhints.ai_socktype = SOCK_STREAM;
247 proxyhints.ai_protocol = IPPROTO_TCP;
248 if (nflag)
249 proxyhints.ai_flags |= AI_NUMERICHOST;
250 }
251
252 if (lflag) {
253 int connfd;
254 ret = 0;
255
256 if (family == AF_UNIX)
257 s = unix_listen(host);
258
259 /* Allow only one connection at a time, but stay alive */
260 for (;;) {
261 if (family != AF_UNIX)
262 s = local_listen(host, uport, hints);
263 if (s < 0)
264 err(1, NULL);
265 /*
266 * For UDP, we will use recvfrom() initially
267 * to wait for a caller, then use the regular
268 * functions to talk to the caller.
269 */
270 if (uflag) {
271 int rv;
272 char buf[1024];
273 struct sockaddr_storage z;
274
275 len = sizeof(z);
276 rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
277 (struct sockaddr *)&z, &len);
278 if (rv < 0)
279 err(1, "recvfrom");
280
281 rv = connect(s, (struct sockaddr *)&z, len);
282 if (rv < 0)
283 err(1, "connect");
284
285 connfd = s;
286 } else {
287 connfd = accept(s, (struct sockaddr *)&cliaddr,
288 &len);
289 }
290
291 readwrite(connfd);
292 close(connfd);
293 if (family != AF_UNIX)
294 close(s);
295
296 if (!kflag)
297 break;
298 }
299 } else if (family == AF_UNIX) {
300 ret = 0;
301
302 if ((s = unix_connect(host)) > 0 && !zflag) {
303 readwrite(s);
304 close(s);
305 } else
306 ret = 1;
307
308 exit(ret);
309
310 } else {
311 int i = 0;
312
313 /* construct the portlist[] array */
314 build_ports(uport);
315
316 /* Cycle through portlist, connecting to each port */
317 for (i = 0; portlist[i] != NULL; i++) {
318 if (s)
319 close(s);
320
321 if (xflag)
322 s = socks_connect(host, portlist[i], hints,
323 proxyhost, proxyport, proxyhints, socksv);
324 else
325 s = remote_connect(host, portlist[i], hints);
326
327 if (s < 0)
328 continue;
329
330 ret = 0;
331 if (vflag || zflag) {
332 /* For UDP, make sure we are connected */
333 if (uflag) {
334 if (udptest(s) == -1) {
335 ret = 1;
336 continue;
337 }
338 }
339
340 /* Don't lookup port if -n */
341 if (nflag)
342 sv = NULL;
343 else {
344 sv = getservbyport(
345 ntohs(atoi(portlist[i])),
346 uflag ? "udp" : "tcp");
347 }
348
349 printf("Connection to %s %s port [%s/%s] succeeded!\n",
350 host, portlist[i], uflag ? "udp" : "tcp",
351 sv ? sv->s_name : "*");
352 }
353 if (!zflag)
354 readwrite(s);
355 }
356 }
357
358 if (s)
359 close(s);
360
361 exit(ret);
362}
363
364/*
365 * unix_connect()
366 * Return's a socket connected to a local unix socket. Return's -1 on failure.
367 */
368int
369unix_connect(char *path)
370{
371 struct sockaddr_un sun;
372 int s;
373
374 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
375 return (-1);
376 (void)fcntl(s, F_SETFD, 1);
377
378 memset(&sun, 0, sizeof(struct sockaddr_un));
379 sun.sun_family = AF_UNIX;
380
381 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
382 sizeof(sun.sun_path)) {
383 close(s);
384 errno = ENAMETOOLONG;
385 return (-1);
386 }
387 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
388 close(s);
389 return (-1);
390 }
391 return (s);
392
393}
394
395/*
396 * unix_listen()
397 * create a unix domain socket, and listen on it.
398 */
399int
400unix_listen(char *path)
401{
402 struct sockaddr_un sun;
403 int s;
404
405 /* create unix domain socket */
406 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
407 return (-1);
408
409 memset(&sun, 0, sizeof(struct sockaddr_un));
410 sun.sun_family = AF_UNIX;
411
412 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
413 sizeof(sun.sun_path)) {
414 close(s);
415 errno = ENAMETOOLONG;
416 return (-1);
417 }
418
419 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
420 close(s);
421 return (-1);
422 }
423
424 if (listen(s, 5) < 0) {
425 close(s);
426 return (-1);
427 }
428 return (s);
429}
430
431/*
432 * remote_connect()
433 * Return's a socket connected to a remote host. Properly bind's to a local
434 * port or source address if needed. Return's -1 on failure.
435 */
436int
437remote_connect(char *host, char *port, struct addrinfo hints)
438{
439 struct addrinfo *res, *res0;
440 int s, error;
441
442 if ((error = getaddrinfo(host, port, &hints, &res)))
443 errx(1, "getaddrinfo: %s", gai_strerror(error));
444
445 res0 = res;
446 do {
447 if ((s = socket(res0->ai_family, res0->ai_socktype,
448 res0->ai_protocol)) < 0)
449 continue;
450
451 /* Bind to a local port or source address if specified */
452 if (sflag || pflag) {
453 struct addrinfo ahints, *ares;
454
455 if (!(sflag && pflag)) {
456 if (!sflag)
457 sflag = NULL;
458 else
459 pflag = NULL;
460 }
461
462 memset(&ahints, 0, sizeof(struct addrinfo));
463 ahints.ai_family = res0->ai_family;
464 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
465 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
466 ahints.ai_flags = AI_PASSIVE;
467 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
468 errx(1, "getaddrinfo: %s", gai_strerror(error));
469
470 if (bind(s, (struct sockaddr *)ares->ai_addr,
471 ares->ai_addrlen) < 0)
472 errx(1, "bind failed: %s", strerror(errno));
473 freeaddrinfo(ares);
474 }
475
476 if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
477 break;
478
479 close(s);
480 s = -1;
481 } while ((res0 = res0->ai_next) != NULL);
482
483 freeaddrinfo(res);
484
485 return (s);
486}
487
488/*
489 * local_listen()
490 * Return's a socket listening on a local port, binds to specified source
491 * address. Return's -1 on failure.
492 */
493int
494local_listen(char *host, char *port, struct addrinfo hints)
495{
496 struct addrinfo *res, *res0;
497 int s, ret, x = 1;
498 int error;
499
500 /* Allow nodename to be null */
501 hints.ai_flags |= AI_PASSIVE;
502
503 /*
504 * In the case of binding to a wildcard address
505 * default to binding to an ipv4 address.
506 */
507 if (host == NULL && hints.ai_family == AF_UNSPEC)
508 hints.ai_family = AF_INET;
509
510 if ((error = getaddrinfo(host, port, &hints, &res)))
511 errx(1, "getaddrinfo: %s", gai_strerror(error));
512
513 res0 = res;
514 do {
515 if ((s = socket(res0->ai_family, res0->ai_socktype,
516 res0->ai_protocol)) == 0)
517 continue;
518
519 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
520 if (ret == -1)
521 err(1, NULL);
522
523 if (bind(s, (struct sockaddr *)res0->ai_addr,
524 res0->ai_addrlen) == 0)
525 break;
526
527 close(s);
528 s = -1;
529 } while ((res0 = res0->ai_next) != NULL);
530
531 if (!uflag && s != -1) {
532 if (listen(s, 1) < 0)
533 err(1, "listen");
534 }
535
536 freeaddrinfo(res);
537
538 return (s);
539}
540
541/*
542 * readwrite()
543 * Loop that polls on the network file descriptor and stdin.
544 */
545void
546readwrite(int nfd)
547{
548 struct pollfd pfd[2];
549 char buf[BUFSIZ];
550 int wfd = fileno(stdin), n, ret;
551 int lfd = fileno(stdout);
552
553 /* Setup Network FD */
554 pfd[0].fd = nfd;
555 pfd[0].events = POLLIN;
556
557 /* Setup STDIN FD */
558 pfd[1].fd = wfd;
559 pfd[1].events = POLLIN;
560
561 while (pfd[0].fd != -1) {
562 if (iflag)
563 sleep(iflag);
564
565 if ((n = poll(pfd, 2, timeout)) < 0) {
566 close(nfd);
567 err(1, "Polling Error");
568 }
569
570 if (n == 0)
571 return;
572
573 if (pfd[0].revents & POLLIN) {
574 if ((n = read(nfd, buf, sizeof(buf))) < 0)
575 return;
576 else if (n == 0) {
577 shutdown(nfd, SHUT_RD);
578 pfd[0].fd = -1;
579 pfd[0].events = 0;
580 } else {
581 if (tflag)
582 atelnet(nfd, buf, n);
583 if ((ret = atomicio(
584 (ssize_t (*)(int, void *, size_t))write,
585 lfd, buf, n)) != n)
586 return;
587 }
588 }
589
590 if (pfd[1].revents & POLLIN) {
591 if ((n = read(wfd, buf, sizeof(buf))) < 0)
592 return;
593 else if (n == 0) {
594 shutdown(nfd, SHUT_WR);
595 pfd[1].fd = -1;
596 pfd[1].events = 0;
597 } else {
598 if((ret = atomicio(
599 (ssize_t (*)(int, void *, size_t))write,
600 nfd, buf, n)) != n)
601 return;
602 }
603 }
604 }
605}
606
607/* Deal with RFC854 WILL/WONT DO/DONT negotiation */
608void
609atelnet(int nfd, unsigned char *buf, unsigned int size)
610{
611 int ret;
612 unsigned char *p, *end;
613 unsigned char obuf[4];
614
615 end = buf + size;
616 obuf[0] = '\0';
617
618 for (p = buf; p < end; p++) {
619 if (*p != IAC)
620 break;
621
622 obuf[0] = IAC;
623 p++;
624 if ((*p == WILL) || (*p == WONT))
625 obuf[1] = DONT;
626 if ((*p == DO) || (*p == DONT))
627 obuf[1] = WONT;
628 if (obuf) {
629 p++;
630 obuf[2] = *p;
631 obuf[3] = '\0';
632 if ((ret = atomicio(
633 (ssize_t (*)(int, void *, size_t))write,
634 nfd, obuf, 3)) != 3)
635 warnx("Write Error!");
636 obuf[0] = '\0';
637 }
638 }
639}
640
641/*
642 * build_ports()
643 * Build an array or ports in portlist[], listing each port
644 * that we should try to connect too.
645 */
646void
647build_ports(char *p)
648{
649 char *n, *endp;
650 int hi, lo, cp;
651 int x = 0;
652
653 if ((n = strchr(p, '-')) != NULL) {
654 if (lflag)
655 errx(1, "Cannot use -l with multiple ports!");
656
657 *n = '\0';
658 n++;
659
660 /* Make sure the ports are in order: lowest->highest */
661 hi = (int)strtoul(n, &endp, 10);
662 if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
663 errx(1, "port range not valid");
664 lo = (int)strtoul(p, &endp, 10);
665 if (lo <= 0 || lo > PORT_MAX || *endp != '\0')
666 errx(1, "port range not valid");
667
668 if (lo > hi) {
669 cp = hi;
670 hi = lo;
671 lo = cp;
672 }
673
674 /* Load ports sequentially */
675 for (cp = lo; cp <= hi; cp++) {
676 portlist[x] = calloc(1, PORT_MAX_LEN);
677 if (portlist[x] == NULL)
678 err(1, NULL);
679 snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
680 x++;
681 }
682
683 /* Randomly swap ports */
684 if (rflag) {
685 int y;
686 char *c;
687
688 for (x = 0; x <= (hi - lo); x++) {
689 y = (arc4random() & 0xFFFF) % (hi - lo);
690 c = portlist[x];
691 portlist[x] = portlist[y];
692 portlist[y] = c;
693 }
694 }
695 } else {
696 hi = (int)strtoul(p, &endp, 10);
697 if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
698 errx(1, "port range not valid");
699 portlist[0] = calloc(1, PORT_MAX_LEN);
700 if (portlist[0] == NULL)
701 err(1, NULL);
702 portlist[0] = p;
703 }
704}
705
706/*
707 * udptest()
708 * Do a few writes to see if the UDP port is there.
709 * XXX - Better way of doing this? Doesn't work for IPv6
710 * Also fails after around 100 ports checked.
711 */
712int
713udptest(int s)
714{
715 int i, rv, ret;
716
717 for (i = 0; i <= 3; i++) {
718 if ((rv = write(s, "X", 1)) == 1)
719 ret = 1;
720 else
721 ret = -1;
722 }
723 return (ret);
724}
725
726void
727help(void)
728{
729 usage(0);
730 fprintf(stderr, "\tCommand Summary:\n\
731 \t-4 Use IPv4\n\
732 \t-6 Use IPv6\n\
733 \t-U Use UNIX domain socket\n\
734 \t-X vers\t SOCKS version (4 or 5)\n\
735 \t-h This help text\n\
736 \t-i secs\t Delay interval for lines sent, ports scanned\n\
737 \t-k Keep inbound sockets open for multiple connects\n\
738 \t-l Listen mode, for inbound connects\n\
739 \t-n Suppress name/port resolutions\n\
740 \t-p port\t Specify local port for remote connects\n\
741 \t-r Randomize remote ports\n\
742 \t-s addr\t Local source address\n\
743 \t-t Answer TELNET negotiation\n\
744 \t-u UDP mode\n\
745 \t-v Verbose\n\
746 \t-w secs\t Timeout for connects and final net reads\n\
747 \t-x addr[:port]\tSpecify socks proxy address and port\n\
748 \t-z Zero-I/O mode [used for scanning]\n\
749 Port numbers can be individual or ranges: lo-hi [inclusive]\n");
750 exit(1);
751}
752
753void
754usage(int ret)
755{
756 fprintf(stderr, "usage: nc [-46Uhklnrtuvz] [-i interval] [-p source port]\n");
757 fprintf(stderr, "\t [-s ip address] [-w timeout] [-X vers] [-x proxy address [:port]]\n");
758 fprintf(stderr, "\t [hostname] [port[s...]]\n");
759 if (ret)
760 exit(1);
761}