Annotation of src/usr.bin/nc/netcat.c, Revision 1.32
1.32 ! ericj 1: /* $OpenBSD: netcat.c,v 1.31 2001/06/27 07:23:58 ericj Exp $ */
1.21 ericj 2: /*
3: * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
1.7 deraadt 4: *
1.21 ericj 5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
1.7 deraadt 8: *
1.21 ericj 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.
1.7 deraadt 16: *
1.21 ericj 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: */
1.1 deraadt 28:
1.24 ericj 29: /*
30: * Re-written nc(1) for OpenBSD. Original implementation by
1.21 ericj 31: * *Hobbit* <hobbit@avian.org>.
32: */
1.1 deraadt 33:
1.7 deraadt 34: #include <sys/types.h>
1.21 ericj 35: #include <sys/socket.h>
1.7 deraadt 36: #include <sys/time.h>
1.21 ericj 37:
1.7 deraadt 38: #include <netinet/in.h>
1.21 ericj 39: #include <arpa/telnet.h>
1.29 smart 40:
1.11 ericj 41: #include <err.h>
1.7 deraadt 42: #include <errno.h>
1.21 ericj 43: #include <netdb.h>
44: #include <poll.h>
1.13 ericj 45: #include <stdarg.h>
1.21 ericj 46: #include <stdio.h>
1.1 deraadt 47: #include <stdlib.h>
1.21 ericj 48: #include <string.h>
1.5 art 49: #include <unistd.h>
1.1 deraadt 50:
1.31 ericj 51: #define PORT_MAX 65535
52:
1.21 ericj 53: /* Command Line Options */
54: int iflag; /* Interval Flag */
55: int kflag; /* More than one connect */
56: int lflag; /* Bind to local port */
57: int nflag; /* Dont do name lookup */
58: char *pflag; /* Localport flag */
59: int rflag; /* Random ports flag */
60: char *sflag; /* Source Address */
61: int tflag; /* Telnet Emulation */
62: int uflag; /* UDP - Default to TCP */
63: int vflag; /* Verbosity */
64: int zflag; /* Port Scan Flag */
65:
66: int timeout;
67: int family = AF_UNSPEC;
1.31 ericj 68: char *portlist[PORT_MAX];
1.21 ericj 69:
1.29 smart 70: ssize_t atomicio __P((ssize_t (*)(), int, void *, size_t));
71: void atelnet __P((int, unsigned char *, unsigned int));
72: void build_ports __P((char *));
73: void help __P((void));
74: int local_listen __P((char *, char *, struct addrinfo));
75: void readwrite __P((int));
76: int remote_connect __P((char *, char *, struct addrinfo));
77: int udptest __P((int));
78: void usage __P((int));
1.1 deraadt 79:
1.21 ericj 80: int
81: main(argc, argv)
82: int argc;
83: char *argv[];
84: {
1.29 smart 85: int ch, s, ret;
1.26 ericj 86: char *host, *uport, *endp;
1.21 ericj 87: struct addrinfo hints;
1.29 smart 88: struct servent *sv;
1.21 ericj 89: socklen_t len;
90: struct sockaddr *cliaddr;
1.11 ericj 91:
1.29 smart 92: ret = 1;
93: s = 0;
94: host = NULL;
95: uport = NULL;
96: endp = NULL;
97: sv = NULL;
98:
1.21 ericj 99: while ((ch = getopt(argc, argv, "46hi:klnp:rs:tuvw:z")) != -1) {
100: switch (ch) {
101: case '4':
102: family = AF_INET;
103: break;
104: case '6':
105: family = AF_INET6;
106: break;
107: case 'h':
108: help();
109: break;
110: case 'i':
1.26 ericj 111: iflag = (int)strtoul(optarg, &endp, 10);
112: if (iflag < 0 || *endp != '\0')
113: errx(1, "interval cannot be negative");
1.21 ericj 114: break;
115: case 'k':
116: kflag = 1;
117: break;
118: case 'l':
119: lflag = 1;
120: break;
121: case 'n':
122: nflag = 1;
123: break;
124: case 'p':
125: pflag = optarg;
126: break;
127: case 'r':
128: rflag = 1;
129: break;
130: case 's':
131: sflag = optarg;
132: break;
133: case 't':
134: tflag = 1;
135: break;
136: case 'u':
137: uflag = 1;
138: break;
139: case 'v':
140: vflag = 1;
141: break;
1.26 ericj 142: case 'w':
143: timeout = (int)strtoul(optarg, &endp, 10);
144: if (timeout < 0 || *endp != '\0')
145: errx(1, "timeout cannot be negative");
1.21 ericj 146: break;
147: case 'z':
148: zflag = 1;
149: break;
150: default:
151: usage(1);
152: }
153: }
154: argc -= optind;
155: argv += optind;
1.11 ericj 156:
1.21 ericj 157: /* Cruft to make sure options are clean, and used properly. */
158: if (argv[0] && !argv[1]) {
159: if (!lflag)
160: usage(1);
161: uport = argv[0];
162: host = NULL;
163: } else if (argv[0] && argv[1]) {
164: host = argv[0];
165: uport = argv[1];
166: } else
167: usage(1);
1.1 deraadt 168:
1.21 ericj 169: if (lflag && sflag)
170: errx(1, "cannot use -s and -l");
171: if (lflag && pflag)
172: errx(1, "cannot use -p and -l");
173: if (lflag && zflag)
1.32 ! ericj 174: errx(1, "cannot use -z and -l");
1.21 ericj 175: if (!lflag && kflag)
1.32 ! ericj 176: errx(1, "must use -l with -k");
1.21 ericj 177:
178: /* Initialize addrinfo structure */
179: memset(&hints, 0, sizeof(struct addrinfo));
180: hints.ai_family = family;
181: hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
182: hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
183: if (nflag)
184: hints.ai_flags |= AI_NUMERICHOST;
1.1 deraadt 185:
1.21 ericj 186: if (lflag) {
187: int connfd;
1.27 ericj 188: ret = 0;
1.1 deraadt 189:
1.21 ericj 190: /* Allow only one connection at a time, but stay alive */
191: for (;;) {
1.27 ericj 192: if ((s = local_listen(host, uport, hints)) < 0)
1.30 smart 193: err(1, NULL);
1.21 ericj 194: /*
195: * For UDP, we will use recvfrom() initially
196: * to wait for a caller, then use the regular
197: * functions to talk to the caller.
198: */
199: if (uflag) {
1.23 ericj 200: int rv;
1.21 ericj 201: char buf[1024];
202: struct sockaddr_storage z;
203:
204: len = sizeof(z);
1.23 ericj 205: rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
1.21 ericj 206: (struct sockaddr *)&z, &len);
1.23 ericj 207: if (rv < 0)
1.21 ericj 208: errx(1, "%s", strerror(errno));
209:
1.23 ericj 210: rv = connect(s, (struct sockaddr *)&z,
1.21 ericj 211: len);
1.23 ericj 212: if (rv < 0)
1.21 ericj 213: errx(1, "%s", strerror(errno));
1.1 deraadt 214:
1.21 ericj 215: connfd = s;
216: } else {
217: connfd = accept(s, (struct sockaddr *)&cliaddr,
218: &len);
219: }
1.1 deraadt 220:
1.21 ericj 221: readwrite(connfd);
222: close(connfd);
1.27 ericj 223: close(s);
224:
1.21 ericj 225: if (!kflag)
226: break;
1.11 ericj 227: }
1.21 ericj 228: } else {
229: int i = 0;
1.6 deraadt 230:
1.21 ericj 231: /* construct the portlist[] array */
232: build_ports(uport);
1.1 deraadt 233:
1.21 ericj 234: /* Cycle through portlist, connecting to each port */
235: for (i = 0; portlist[i] != NULL; i++) {
236:
237: if (s)
238: close(s);
239:
240: if ((s = remote_connect(host, portlist[i], hints)) < 0)
241: continue;
1.1 deraadt 242:
1.21 ericj 243: ret = 0;
244: if (vflag || zflag) {
245: /* For UDP, make sure we are connected */
246: if (uflag) {
247: if ((udptest(s)) == -1) {
248: ret = 1;
249: continue;
250: }
251: }
1.1 deraadt 252:
1.21 ericj 253: /* Don't lookup port if -n */
254: if (nflag)
255: sv = NULL;
256: else {
257: sv = getservbyport(
258: ntohs(atoi(portlist[i])),
259: uflag ? "udp" : "tcp");
260: }
261:
262: printf("Connection to %s %s port [%s/%s] succeeded!\n",
263: host, portlist[i], uflag ? "udp" : "tcp",
264: sv ? sv->s_name : "*");
265: }
266: if (!zflag)
267: readwrite(s);
1.7 deraadt 268: }
1.11 ericj 269: }
1.1 deraadt 270:
1.21 ericj 271: if (s)
272: close(s);
273:
274: exit(ret);
1.7 deraadt 275: }
1.1 deraadt 276:
1.11 ericj 277: /*
1.21 ericj 278: * remote_connect()
279: * Return's a socket connected to a remote host. Properly bind's to a local
280: * port or source address if needed. Return's -1 on failure.
1.11 ericj 281: */
1.21 ericj 282: int
283: remote_connect(host, port, hints)
284: char *host, *port;
285: struct addrinfo hints;
286: {
287: struct addrinfo *res, *res0;
288: int s, error;
289:
290: if ((error = getaddrinfo(host, port, &hints, &res)))
291: errx(1, "%s", gai_strerror(error));
292:
293: res0 = res;
294: do {
295: if ((s = socket(res0->ai_family, res0->ai_socktype,
296: res0->ai_protocol)) < 0)
297: continue;
298:
299: /* Bind to a local port or source address if specified */
300: if (sflag || pflag) {
301: struct addrinfo ahints, *ares;
302:
303: if (!(sflag && pflag)) {
304: if (!sflag)
305: sflag = NULL;
306: else
307: pflag = NULL;
308: }
1.6 deraadt 309:
1.21 ericj 310: memset(&ahints, 0, sizeof(struct addrinfo));
311: ahints.ai_family = res0->ai_family;
312: ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
313: ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
1.25 ericj 314: ahints.ai_flags = AI_PASSIVE;
1.21 ericj 315: if (getaddrinfo(sflag, pflag, &ahints, &ares))
316: errx(1, "%s", gai_strerror(error));
317:
318: if (bind(s, (struct sockaddr *)ares->ai_addr,
319: ares->ai_addrlen) < 0) {
320: errx(1, "bind failed: %s", strerror(errno));
321: freeaddrinfo(ares);
322: continue;
323: }
324: freeaddrinfo(ares);
1.6 deraadt 325: }
326:
1.21 ericj 327: if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
1.6 deraadt 328: break;
1.21 ericj 329:
330: close(s);
331: s = -1;
332: } while ((res0 = res0->ai_next) != NULL);
333:
334: freeaddrinfo(res);
1.1 deraadt 335:
1.21 ericj 336: return (s);
1.7 deraadt 337: }
1.1 deraadt 338:
1.11 ericj 339: /*
1.21 ericj 340: * local_listen()
341: * Return's a socket listening on a local port, binds to specified source
342: * address. Return's -1 on failure.
1.11 ericj 343: */
1.21 ericj 344: int
345: local_listen(host, port, hints)
346: char *host, *port;
347: struct addrinfo hints;
348: {
349: struct addrinfo *res, *res0;
350: int s, ret, x = 1;
351: int error;
1.6 deraadt 352:
1.21 ericj 353: /* Allow nodename to be null */
354: hints.ai_flags |= AI_PASSIVE;
1.7 deraadt 355:
1.21 ericj 356: /*
357: * In the case of binding to a wildcard address
358: * default to binding to an ipv4 address.
359: */
360: if (host == NULL && hints.ai_family == AF_UNSPEC)
361: hints.ai_family = AF_INET;
1.1 deraadt 362:
1.21 ericj 363: if ((error = getaddrinfo(host, port, &hints, &res)))
364: errx(1, "%s", gai_strerror(error));
1.14 ericj 365:
1.21 ericj 366: res0 = res;
367: do {
368: if ((s = socket(res0->ai_family, res0->ai_socktype,
369: res0->ai_protocol)) == 0)
370: continue;
1.1 deraadt 371:
1.21 ericj 372: ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
373: if (ret == -1)
1.30 smart 374: err(1, NULL);
1.1 deraadt 375:
1.21 ericj 376: if (bind(s, (struct sockaddr *)res0->ai_addr,
377: res0->ai_addrlen) == 0)
378: break;
1.1 deraadt 379:
1.21 ericj 380: close(s);
381: s = -1;
382: } while ((res0 = res0->ai_next) != NULL);
1.1 deraadt 383:
1.21 ericj 384: if (!uflag) {
385: if (listen(s, 1) < 0)
386: errx(1, "%s", strerror(errno));
1.12 ericj 387: }
1.1 deraadt 388:
1.21 ericj 389: freeaddrinfo(res);
1.1 deraadt 390:
1.21 ericj 391: return (s);
1.7 deraadt 392: }
393:
1.11 ericj 394: /*
1.21 ericj 395: * readwrite()
396: * Loop that polls on the network file descriptor and stdin.
1.11 ericj 397: */
1.21 ericj 398: void
399: readwrite(nfd)
400: int nfd;
1.6 deraadt 401: {
1.21 ericj 402: struct pollfd *pfd;
403: char buf[BUFSIZ];
404: int wfd = fileno(stdin), n, ret;
405: int lfd = fileno(stdout);
406:
407: pfd = malloc(2 * sizeof(struct pollfd));
408:
409: /* Setup Network FD */
410: pfd[0].fd = nfd;
411: pfd[0].events = POLLIN;
412:
413: /* Setup STDIN FD */
414: pfd[1].fd = wfd;
415: pfd[1].events = POLLIN;
416:
417: for (;;) {
418: if (iflag)
419: sleep(iflag);
420:
421: if (poll(pfd, 2, timeout) < 0) {
422: close(nfd);
423: close(wfd);
424: free(pfd);
425: errx(1, "Polling Error");
426: }
427:
428: if (pfd[0].revents & POLLIN) {
429: if ((n = read(nfd, buf, sizeof(buf))) <= 0) {
430: return;
431: } else {
432: if (tflag)
433: atelnet(nfd, buf, n);
434: if ((ret = atomicio(write, lfd, buf, n)) != n)
435: return;
1.6 deraadt 436: }
1.21 ericj 437: }
438:
439: if (pfd[1].revents & POLLIN) {
440: if ((n = read(wfd, buf, sizeof(buf))) <= 0) {
441: return;
442: } else
443: if((ret = atomicio(write, nfd, buf, n)) != n)
444: return;
445: }
1.11 ericj 446: }
1.7 deraadt 447: }
1.24 ericj 448: /* Deal with RFC854 WILL/WONT DO/DONT negotiation */
1.21 ericj 449: void
450: atelnet(nfd, buf, size)
451: int nfd;
452: unsigned char *buf;
1.6 deraadt 453: unsigned int size;
454: {
1.28 ericj 455: int ret;
1.24 ericj 456: unsigned char *p, *end;
457: unsigned char obuf[4];
458:
459: end = buf + size;
460: obuf[0] = '\0';
461:
462: for (p = buf; p < end; p++) {
1.21 ericj 463: if (*p != IAC)
1.24 ericj 464: break;
465:
1.25 ericj 466: obuf[0] = IAC;
1.24 ericj 467: p++;
468: if ((*p == WILL) || (*p == WONT)) {
469: obuf[1] = DONT;
470: }
471: if ((*p == DO) || (*p == DONT)) {
472: obuf[1] = WONT;
473: }
474: if (obuf) {
475: p++;
1.11 ericj 476: obuf[2] = *p;
1.24 ericj 477: obuf[3] = '\0';
1.21 ericj 478: if ((ret = atomicio(write , nfd, obuf, 3)) != 3)
479: warnx("Write Error!");
1.24 ericj 480: obuf[0] = '\0';
1.11 ericj 481: }
482: }
1.7 deraadt 483: }
484:
1.11 ericj 485: /*
1.21 ericj 486: * build_ports()
487: * Build an array or ports in portlist[], listing each port
488: * that we should try to connect too.
1.11 ericj 489: */
1.21 ericj 490: void
491: build_ports(p)
492: char *p;
1.6 deraadt 493: {
1.26 ericj 494: char *n, *endp;
1.21 ericj 495: int hi, lo, cp;
496: int x = 0;
497:
498: if ((n = strchr(p, '-')) != NULL) {
499: if (lflag)
500: errx(1, "Cannot use -l with multiple ports!");
501:
502: *n = '\0';
503: n++;
504:
505: /* Make sure the ports are in order: lowest->highest */
1.26 ericj 506: hi = (int)strtoul(n, &endp, 10);
1.31 ericj 507: if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
1.26 ericj 508: errx(1, "port range not valid");
509: lo = (int)strtoul(p, &endp, 10);
1.31 ericj 510: if (lo <= 0 || lo > PORT_MAX || *endp != '\0')
1.26 ericj 511: errx(1, "port range not valid");
1.21 ericj 512:
513: if (lo > hi) {
514: cp = hi;
515: hi = lo;
516: lo = cp;
517: }
518:
519: /* Load ports sequentially */
520: for (cp = lo; cp <= hi; cp++) {
1.31 ericj 521: portlist[x] = malloc(sizeof(PORT_MAX));
1.21 ericj 522: sprintf(portlist[x], "%d", cp);
523: x++;
524: }
525:
526: /* Randomly swap ports */
527: if (rflag) {
528: int y;
529: char *c;
530:
531: for (x = 0; x <= (hi - lo); x++) {
532: y = (arc4random() & 0xFFFF) % (hi - lo);
533: c = portlist[x];
534: portlist[x] = portlist[y];
535: portlist[y] = c;
1.6 deraadt 536: }
1.11 ericj 537: }
1.21 ericj 538: } else {
1.26 ericj 539: hi = (int)strtoul(p, &endp, 10);
1.31 ericj 540: if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
1.26 ericj 541: errx(1, "port range not valid");
1.31 ericj 542: portlist[0] = malloc(sizeof(PORT_MAX));
1.21 ericj 543: portlist[0] = p;
1.11 ericj 544: }
1.13 ericj 545: }
546:
547: /*
1.21 ericj 548: * udptest()
549: * Do a few writes to see if the UDP port is there.
550: * XXX - Better way of doing this? Doesn't work for IPv6
551: * Also fails after around 100 ports checked.
1.13 ericj 552: */
1.21 ericj 553: int
554: udptest(s)
555: int s;
1.13 ericj 556: {
1.21 ericj 557: int i, rv, ret;
1.13 ericj 558:
1.21 ericj 559: for (i=0; i <= 3; i++) {
560: if ((rv = write(s, "X", 1)) == 1)
561: ret = 1;
1.14 ericj 562: else
1.21 ericj 563: ret = -1;
1.14 ericj 564: }
1.21 ericj 565: return (ret);
1.7 deraadt 566: }
1.1 deraadt 567:
1.11 ericj 568: void
1.21 ericj 569: help()
1.1 deraadt 570: {
1.21 ericj 571: usage(0);
572: fprintf(stderr, "\tCommand Summary:\n\
573: \t-4 Use IPv4\n\
574: \t-6 Use IPv6\n\
575: \t-h This help text\n\
576: \t-i secs\t Delay interval for lines sent, ports scanned\n\
577: \t-k Keep inbound sockets open for multiple connects\n\
578: \t-l Listen mode, for inbound connects\n\
1.22 jasoni 579: \t-n Suppress name/port resolutions\n\
1.21 ericj 580: \t-p Specify local port for remote connects\n\
581: \t-r Randomize remote ports\n\
582: \t-s addr\t Local source address\n\
583: \t-t Answer TELNET negotiation\n\
584: \t-u UDP mode\n\
585: \t-v Verbose\n\
586: \t-w secs\t Timeout for connects and final net reads\n\
587: \t-z Zero-I/O mode [used for scanning]\n\
588: Port numbers can be individual or ranges: lo-hi [inclusive]\n");
589: exit(1);
1.11 ericj 590: }
591:
592: void
1.21 ericj 593: usage(ret)
594: int ret;
1.11 ericj 595: {
1.21 ericj 596: fprintf(stderr, "usage: nc [-46hklnrtuvz] [-i interval] [-p source port]\n");
597: fprintf(stderr, "\t [-s ip address] [-w timeout] [hostname] [port[s...]]\n");
598: if (ret)
599: exit(1);
1.7 deraadt 600: }