1 /* $OpenBSD: netcat.c,v 1.32 2001/08/02 21:00:14 ericj 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 38 #include <netinet/in.h> 39 #include <arpa/telnet.h> 40 41 #include <err.h> 42 #include <errno.h> 43 #include <netdb.h> 44 #include <poll.h> 45 #include <stdarg.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <unistd.h> 50 51 #define PORT_MAX 65535 52 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; 68 char *portlist[PORT_MAX]; 69 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)); 79 80 int 81 main(argc, argv) 82 int argc; 83 char *argv[]; 84 { 85 int ch, s, ret; 86 char *host, *uport, *endp; 87 struct addrinfo hints; 88 struct servent *sv; 89 socklen_t len; 90 struct sockaddr *cliaddr; 91 92 ret = 1; 93 s = 0; 94 host = NULL; 95 uport = NULL; 96 endp = NULL; 97 sv = NULL; 98 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': 111 iflag = (int)strtoul(optarg, &endp, 10); 112 if (iflag < 0 || *endp != '\0') 113 errx(1, "interval cannot be negative"); 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; 142 case 'w': 143 timeout = (int)strtoul(optarg, &endp, 10); 144 if (timeout < 0 || *endp != '\0') 145 errx(1, "timeout cannot be negative"); 146 break; 147 case 'z': 148 zflag = 1; 149 break; 150 default: 151 usage(1); 152 } 153 } 154 argc -= optind; 155 argv += optind; 156 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); 168 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) 174 errx(1, "cannot use -z and -l"); 175 if (!lflag && kflag) 176 errx(1, "must use -l with -k"); 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; 185 186 if (lflag) { 187 int connfd; 188 ret = 0; 189 190 /* Allow only one connection at a time, but stay alive */ 191 for (;;) { 192 if ((s = local_listen(host, uport, hints)) < 0) 193 err(1, NULL); 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) { 200 int rv; 201 char buf[1024]; 202 struct sockaddr_storage z; 203 204 len = sizeof(z); 205 rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK, 206 (struct sockaddr *)&z, &len); 207 if (rv < 0) 208 errx(1, "%s", strerror(errno)); 209 210 rv = connect(s, (struct sockaddr *)&z, 211 len); 212 if (rv < 0) 213 errx(1, "%s", strerror(errno)); 214 215 connfd = s; 216 } else { 217 connfd = accept(s, (struct sockaddr *)&cliaddr, 218 &len); 219 } 220 221 readwrite(connfd); 222 close(connfd); 223 close(s); 224 225 if (!kflag) 226 break; 227 } 228 } else { 229 int i = 0; 230 231 /* construct the portlist[] array */ 232 build_ports(uport); 233 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; 242 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 } 252 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); 268 } 269 } 270 271 if (s) 272 close(s); 273 274 exit(ret); 275 } 276 277 /* 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. 281 */ 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 } 309 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; 314 ahints.ai_flags = AI_PASSIVE; 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); 325 } 326 327 if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0) 328 break; 329 330 close(s); 331 s = -1; 332 } while ((res0 = res0->ai_next) != NULL); 333 334 freeaddrinfo(res); 335 336 return (s); 337 } 338 339 /* 340 * local_listen() 341 * Return's a socket listening on a local port, binds to specified source 342 * address. Return's -1 on failure. 343 */ 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; 352 353 /* Allow nodename to be null */ 354 hints.ai_flags |= AI_PASSIVE; 355 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; 362 363 if ((error = getaddrinfo(host, port, &hints, &res))) 364 errx(1, "%s", gai_strerror(error)); 365 366 res0 = res; 367 do { 368 if ((s = socket(res0->ai_family, res0->ai_socktype, 369 res0->ai_protocol)) == 0) 370 continue; 371 372 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); 373 if (ret == -1) 374 err(1, NULL); 375 376 if (bind(s, (struct sockaddr *)res0->ai_addr, 377 res0->ai_addrlen) == 0) 378 break; 379 380 close(s); 381 s = -1; 382 } while ((res0 = res0->ai_next) != NULL); 383 384 if (!uflag) { 385 if (listen(s, 1) < 0) 386 errx(1, "%s", strerror(errno)); 387 } 388 389 freeaddrinfo(res); 390 391 return (s); 392 } 393 394 /* 395 * readwrite() 396 * Loop that polls on the network file descriptor and stdin. 397 */ 398 void 399 readwrite(nfd) 400 int nfd; 401 { 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; 436 } 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 } 446 } 447 } 448 /* Deal with RFC854 WILL/WONT DO/DONT negotiation */ 449 void 450 atelnet(nfd, buf, size) 451 int nfd; 452 unsigned char *buf; 453 unsigned int size; 454 { 455 int ret; 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++) { 463 if (*p != IAC) 464 break; 465 466 obuf[0] = IAC; 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++; 476 obuf[2] = *p; 477 obuf[3] = '\0'; 478 if ((ret = atomicio(write , nfd, obuf, 3)) != 3) 479 warnx("Write Error!"); 480 obuf[0] = '\0'; 481 } 482 } 483 } 484 485 /* 486 * build_ports() 487 * Build an array or ports in portlist[], listing each port 488 * that we should try to connect too. 489 */ 490 void 491 build_ports(p) 492 char *p; 493 { 494 char *n, *endp; 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 */ 506 hi = (int)strtoul(n, &endp, 10); 507 if (hi <= 0 || hi > PORT_MAX || *endp != '\0') 508 errx(1, "port range not valid"); 509 lo = (int)strtoul(p, &endp, 10); 510 if (lo <= 0 || lo > PORT_MAX || *endp != '\0') 511 errx(1, "port range not valid"); 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++) { 521 portlist[x] = malloc(sizeof(PORT_MAX)); 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; 536 } 537 } 538 } else { 539 hi = (int)strtoul(p, &endp, 10); 540 if (hi <= 0 || hi > PORT_MAX || *endp != '\0') 541 errx(1, "port range not valid"); 542 portlist[0] = malloc(sizeof(PORT_MAX)); 543 portlist[0] = p; 544 } 545 } 546 547 /* 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. 552 */ 553 int 554 udptest(s) 555 int s; 556 { 557 int i, rv, ret; 558 559 for (i=0; i <= 3; i++) { 560 if ((rv = write(s, "X", 1)) == 1) 561 ret = 1; 562 else 563 ret = -1; 564 } 565 return (ret); 566 } 567 568 void 569 help() 570 { 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\ 579 \t-n Suppress name/port resolutions\n\ 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); 590 } 591 592 void 593 usage(ret) 594 int ret; 595 { 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); 600 } 601