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