summaryrefslogtreecommitdiff
path: root/src/usr.bin
diff options
context:
space:
mode:
authorderaadt <>1996-09-05 08:55:43 +0000
committerderaadt <>1996-09-05 08:55:43 +0000
commitc7823c0917675fd1ab482937ee1bd01d837b081c (patch)
treede25439975bbe0baac0f70799dad301539b7be3b /src/usr.bin
parentc215a9e8412ead0190b788622f09bcdbb08794fa (diff)
downloadopenbsd-c7823c0917675fd1ab482937ee1bd01d837b081c.tar.gz
openbsd-c7823c0917675fd1ab482937ee1bd01d837b081c.tar.bz2
openbsd-c7823c0917675fd1ab482937ee1bd01d837b081c.zip
nc is *hobbit*'s netcat; let the sysadm have the same tools the crackers
have, so that he may learn what the network is about and protect it better.
Diffstat (limited to 'src/usr.bin')
-rw-r--r--src/usr.bin/nc/Makefile8
-rw-r--r--src/usr.bin/nc/README946
-rw-r--r--src/usr.bin/nc/data/Makefile10
-rw-r--r--src/usr.bin/nc/data/README9
-rw-r--r--src/usr.bin/nc/data/data.c274
-rw-r--r--src/usr.bin/nc/data/dns-any.d36
-rw-r--r--src/usr.bin/nc/data/nfs-0.d59
-rw-r--r--src/usr.bin/nc/data/pm.d8
-rw-r--r--src/usr.bin/nc/data/pmap-dump.d60
-rw-r--r--src/usr.bin/nc/data/pmap-mnt.d78
-rw-r--r--src/usr.bin/nc/data/rip.d52
-rw-r--r--src/usr.bin/nc/data/rservice.c68
-rw-r--r--src/usr.bin/nc/data/showmount.d63
-rw-r--r--src/usr.bin/nc/data/xor.c92
-rw-r--r--src/usr.bin/nc/generic.h377
-rw-r--r--src/usr.bin/nc/nc.1213
-rw-r--r--src/usr.bin/nc/netcat.blurb61
-rw-r--r--src/usr.bin/nc/netcat.c1668
-rw-r--r--src/usr.bin/nc/scripts/README5
-rw-r--r--src/usr.bin/nc/scripts/alta33
-rw-r--r--src/usr.bin/nc/scripts/bsh29
-rw-r--r--src/usr.bin/nc/scripts/dist.sh23
-rw-r--r--src/usr.bin/nc/scripts/irc79
-rw-r--r--src/usr.bin/nc/scripts/iscan35
-rw-r--r--src/usr.bin/nc/scripts/ncp46
-rw-r--r--src/usr.bin/nc/scripts/probe50
-rw-r--r--src/usr.bin/nc/scripts/web148
-rw-r--r--src/usr.bin/nc/scripts/webproxy138
-rw-r--r--src/usr.bin/nc/scripts/webrelay44
-rw-r--r--src/usr.bin/nc/scripts/websearch77
30 files changed, 4789 insertions, 0 deletions
diff --git a/src/usr.bin/nc/Makefile b/src/usr.bin/nc/Makefile
new file mode 100644
index 0000000000..9170bcaba9
--- /dev/null
+++ b/src/usr.bin/nc/Makefile
@@ -0,0 +1,8 @@
1# $OpenBSD: Makefile,v 1.1 1996/09/05 08:55:31 deraadt Exp $
2# $NetBSD: Makefile,v 1.11 1995/10/03 21:42:34 thorpej Exp $
3
4CFLAGS+= -DTELNET
5PROG= nc
6SRCS= netcat.c
7
8.include <bsd.prog.mk>
diff --git a/src/usr.bin/nc/README b/src/usr.bin/nc/README
new file mode 100644
index 0000000000..4235bc41ac
--- /dev/null
+++ b/src/usr.bin/nc/README
@@ -0,0 +1,946 @@
1Netcat 1.10
2=========== /\_/\
3 / 0 0 \
4Netcat is a simple Unix utility which reads and writes data ====v====
5across network connections, using TCP or UDP protocol. \ W /
6It is designed to be a reliable "back-end" tool that can | | _
7be used directly or easily driven by other programs and / ___ \ /
8scripts. At the same time, it is a feature-rich network / / \ \ |
9debugging and exploration tool, since it can create almost (((-----)))-'
10any kind of connection you would need and has several /
11interesting built-in capabilities. Netcat, or "nc" as the ( ___
12actual program is named, should have been supplied long ago \__.=|___E
13as another one of those cryptic but standard Unix tools. /
14
15In the simplest usage, "nc host port" creates a TCP connection to the given
16port on the given target host. Your standard input is then sent to the host,
17and anything that comes back across the connection is sent to your standard
18output. This continues indefinitely, until the network side of the connection
19shuts down. Note that this behavior is different from most other applications
20which shut everything down and exit after an end-of-file on the standard input.
21
22Netcat can also function as a server, by listening for inbound connections
23on arbitrary ports and then doing the same reading and writing. With minor
24limitations, netcat doesn't really care if it runs in "client" or "server"
25mode -- it still shovels data back and forth until there isn't any more left.
26In either mode, shutdown can be forced after a configurable time of inactivity
27on the network side.
28
29And it can do this via UDP too, so netcat is possibly the "udp telnet-like"
30application you always wanted for testing your UDP-mode servers. UDP, as the
31"U" implies, gives less reliable data transmission than TCP connections and
32some systems may have trouble sending large amounts of data that way, but it's
33still a useful capability to have.
34
35You may be asking "why not just use telnet to connect to arbitrary ports?"
36Valid question, and here are some reasons. Telnet has the "standard input
37EOF" problem, so one must introduce calculated delays in driving scripts to
38allow network output to finish. This is the main reason netcat stays running
39until the *network* side closes. Telnet also will not transfer arbitrary
40binary data, because certain characters are interpreted as telnet options and
41are thus removed from the data stream. Telnet also emits some of its
42diagnostic messages to standard output, where netcat keeps such things
43religiously separated from its *output* and will never modify any of the real
44data in transit unless you *really* want it to. And of course telnet is
45incapable of listening for inbound connections, or using UDP instead. Netcat
46doesn't have any of these limitations, is much smaller and faster than telnet,
47and has many other advantages.
48
49Some of netcat's major features are:
50
51 Outbound or inbound connections, TCP or UDP, to or from any ports
52 Full DNS forward/reverse checking, with appropriate warnings
53 Ability to use any local source port
54 Ability to use any locally-configured network source address
55 Built-in port-scanning capabilities, with randomizer
56 Built-in loose source-routing capability
57 Can read command line arguments from standard input
58 Slow-send mode, one line every N seconds
59 Hex dump of transmitted and received data
60 Optional ability to let another program service established connections
61 Optional telnet-options responder
62
63Efforts have been made to have netcat "do the right thing" in all its various
64modes. If you believe that it is doing the wrong thing under whatever
65circumstances, please notify me and tell me how you think it should behave.
66If netcat is not able to do some task you think up, minor tweaks to the code
67will probably fix that. It provides a basic and easily-modified template for
68writing other network applications, and I certainly encourage people to make
69custom mods and send in any improvements they make to it. This is the second
70release; the overall differences from 1.00 are relatively minor and have mostly
71to do with portability and bugfixes. Many people provided greatly appreciated
72fixes and comments on the 1.00 release. Continued feedback from the Internet
73community is always welcome!
74
75Netcat is entirely my own creation, although plenty of other code was used as
76examples. It is freely given away to the Internet community in the hope that
77it will be useful, with no restrictions except giving credit where it is due.
78No GPLs, Berkeley copyrights or any of that nonsense. The author assumes NO
79responsibility for how anyone uses it. If netcat makes you rich somehow and
80you're feeling generous, mail me a check. If you are affiliated in any way
81with Microsoft Network, get a life. Always ski in control. Comments,
82questions, and patches to hobbit@avian.org.
83
84Building
85========
86
87Compiling is fairly straightforward. Examine the Makefile for a SYSTYPE that
88matches yours, and do "make <systype>". The executable "nc" should appear.
89If there is no relevant SYSTYPE section, try "generic". If you create new
90sections for generic.h and Makefile to support another platform, please follow
91the given format and mail back the diffs.
92
93There are a couple of other settable #defines in netcat.c, which you can
94include as DFLAGS="-DTHIS -DTHAT" to your "make" invocation without having to
95edit the Makefile. See the following discussions for what they are and do.
96
97If you want to link against the resolver library on SunOS [recommended] and
98you have BIND 4.9.x, you may need to change XLIBS=-lresolv in the Makefile to
99XLIBS="-lresolv -l44bsd".
100
101Linux sys/time.h does not really support presetting of FD_SETSIZE; a harmless
102warning is issued.
103
104Some systems may warn about pointer types for signal(). No problem, though.
105
106Exploration of features
107=======================
108
109Where to begin? Netcat is at the same time so simple and versatile, it's like
110trying to describe everything you can do with your Swiss Army knife. This will
111go over the basics; you should also read the usage examples and notes later on
112which may give you even more ideas about what this sort of tool is good for.
113
114If no command arguments are given at all, netcat asks for them, reads a line
115from standard input, and breaks it up into arguments internally. This can be
116useful when driving netcat from certain types of scripts, with the side effect
117of hiding your command line arguments from "ps" displays.
118
119The host argument can be a name or IP address. If -n is specified, netcat
120will only accept numeric IP addresses and do no DNS lookups for anything. If
121-n is not given and -v is turned on, netcat will do a full forward and reverse
122name and address lookup for the host, and warn you about the all-too-common
123problem of mismatched names in the DNS. This often takes a little longer for
124connection setup, but is useful to know about. There are circumstances under
125which this can *save* time, such as when you want to know the name for some IP
126address and also connect there. Netcat will just tell you all about it, saving
127the manual steps of looking up the hostname yourself. Normally mismatch-
128checking is case-insensitive per the DNS spec, but you can define ANAL at
129compile time to make it case-sensitive -- sometimes useful for uncovering minor
130errors in your own DNS files while poking around your networks.
131
132A port argument is required for outbound connections, and can be numeric or a
133name as listed in /etc/services. If -n is specified, only numeric arguments
134are valid. Special syntax and/or more than one port argument cause different
135behavior -- see details below about port-scanning.
136
137The -v switch controls the verbosity level of messages sent to standard error.
138You will probably want to run netcat most of the time with -v turned on, so you
139can see info about the connections it is trying to make. You will probably
140also want to give a smallish -w argument, which limits the time spent trying to
141make a connection. I usually alias "nc" to "nc -v -w 3", which makes it
142function just about the same for things I would otherwise use telnet to do.
143The timeout is easily changed by a subsequent -w argument which overrides the
144earlier one. Specifying -v more than once makes diagnostic output MORE
145verbose. If -v is not specified at all, netcat silently does its work unless
146some error happens, whereupon it describes the error and exits with a nonzero
147status. Refused network connections are generally NOT considered to be errors,
148unless you only asked for a single TCP port and it was refused.
149
150Note that -w also sets the network inactivity timeout. This does not have any
151effect until standard input closes, but then if nothing further arrives from
152the network in the next <timeout> seconds, netcat tries to read the net once
153more for good measure, and then closes and exits. There are a lot of network
154services now that accept a small amount of input and return a large amount of
155output, such as Gopher and Web servers, which is the main reason netcat was
156written to "block" on the network staying open rather than standard input.
157Handling the timeout this way gives uniform behavior with network servers that
158*don't* close by themselves until told to.
159
160UDP connections are opened instead of TCP when -u is specified. These aren't
161really "connections" per se since UDP is a connectionless protocol, although
162netcat does internally use the "connected UDP socket" mechanism that most
163kernels support. Although netcat claims that an outgoing UDP connection is
164"open" immediately, no data is sent until something is read from standard
165input. Only thereafter is it possible to determine whether there really is a
166UDP server on the other end, and often you just can't tell. Most UDP protocols
167use timeouts and retries to do their thing and in many cases won't bother
168answering at all, so you should specify a timeout and hope for the best. You
169will get more out of UDP connections if standard input is fed from a source
170of data that looks like various kinds of server requests.
171
172To obtain a hex dump file of the data sent either way, use "-o logfile". The
173dump lines begin with "<" or ">" to respectively indicate "from the net" or
174"to the net", and contain the total count per direction, and hex and ascii
175representations of the traffic. Capturing a hex dump naturally slows netcat
176down a bit, so don't use it where speed is critical.
177
178Netcat can bind to any local port, subject to privilege restrictions and ports
179that are already in use. It is also possible to use a specific local network
180source address if it is that of a network interface on your machine. [Note:
181this does not work correctly on all platforms.] Use "-p portarg" to grab a
182specific local port, and "-s ip-addr" or "-s name" to have that be your source
183IP address. This is often referred to as "anchoring the socket". Root users
184can grab any unused source port including the "reserved" ones less than 1024.
185Absence of -p will bind to whatever unused port the system gives you, just like
186any other normal client connection, unless you use -r [see below].
187
188Listen mode will cause netcat to wait for an inbound connection, and then the
189same data transfer happens. Thus, you can do "nc -l -p 1234 < filename" and
190when someone else connects to your port 1234, the file is sent to them whether
191they wanted it or not. Listen mode is generally used along with a local port
192argument -- this is required for UDP mode, while TCP mode can have the system
193assign one and tell you what it is if -v is turned on. If you specify a target
194host and optional port in listen mode, netcat will accept an inbound connection
195only from that host and if you specify one, only from that foreign source port.
196In verbose mode you'll be informed about the inbound connection, including what
197address and port it came from, and since listening on "any" applies to several
198possibilities, which address it came *to* on your end. If the system supports
199IP socket options, netcat will attempt to retrieve any such options from an
200inbound connection and print them out in hex.
201
202If netcat is compiled with -DGAPING_SECURITY_HOLE, the -e argument specifies
203a program to exec after making or receiving a successful connection. In the
204listening mode, this works similarly to "inetd" but only for a single instance.
205Use with GREAT CARE. This piece of the code is normally not enabled; if you
206know what you're doing, have fun. This hack also works in UDP mode. Note that
207you can only supply -e with the name of the program, but no arguments. If you
208want to launch something with an argument list, write a two-line wrapper script
209or just use inetd like always.
210
211If netcat is compiled with -DTELNET, the -t argument enables it to respond
212to telnet option negotiation [always in the negative, i.e. DONT or WONT].
213This allows it to connect to a telnetd and get past the initial negotiation
214far enough to get a login prompt from the server. Since this feature has
215the potential to modify the data stream, it is not enabled by default. You
216have to understand why you might need this and turn on the #define yourself.
217
218Data from the network connection is always delivered to standard output as
219efficiently as possible, using large 8K reads and writes. Standard input is
220normally sent to the net the same way, but the -i switch specifies an "interval
221time" which slows this down considerably. Standard input is still read in
222large batches, but netcat then tries to find where line breaks exist and sends
223one line every interval time. Note that if standard input is a terminal, data
224is already read line by line, so unless you make the -i interval rather long,
225what you type will go out at a fairly normal rate. -i is really designed
226for use when you want to "measure out" what is read from files or pipes.
227
228Port-scanning is a popular method for exploring what's out there. Netcat
229accepts its commands with options first, then the target host, and everything
230thereafter is interpreted as port names or numbers, or ranges of ports in M-N
231syntax. CAVEAT: some port names in /etc/services contain hyphens -- netcat
232currently will not correctly parse those, so specify ranges using numbers if
233you can. If more than one port is thus specified, netcat connects to *all* of
234them, sending the same batch of data from standard input [up to 8K worth] to
235each one that is successfully connected to. Specifying multiple ports also
236suppresses diagnostic messages about refused connections, unless -v is
237specified twice for "more verbosity". This way you normally get notified only
238about genuinely open connections. Example: "nc -v -w 2 -z target 20-30" will
239try connecting to every port between 20 and 30 [inclusive] at the target, and
240will likely inform you about an FTP server, telnet server, and mailer along the
241way. The -z switch prevents sending any data to a TCP connection and very
242limited probe data to a UDP connection, and is thus useful as a fast scanning
243mode just to see what ports the target is listening on. To limit scanning
244speed if desired, -i will insert a delay between each port probe. There are
245some pitfalls with regard to UDP scanning, described later, but in general it
246works well.
247
248For each range of ports specified, scanning is normally done downward within
249that range. If the -r switch is used, scanning hops randomly around within
250that range and reports open ports as it finds them. [If you want them listed
251in order regardless, pipe standard error through "sort"...] In addition, if
252random mode is in effect, the local source ports are also randomized. This
253prevents netcat from exhibiting any kind of regular pattern in its scanning.
254You can exert fairly fine control over your scan by judicious use of -r and
255selected port ranges to cover. If you use -r for a single connection, the
256source port will have a random value above 8192, rather than the next one the
257kernel would have assigned you. Note that selecting a specific local port
258with -p overrides any local-port randomization.
259
260Many people are interested in testing network connectivity using IP source
261routing, even if it's only to make sure their own firewalls are blocking
262source-routed packets. On systems that support it, the -g switch can be used
263multiple times [up to 8] to construct a loose-source-routed path for your
264connection, and the -G argument positions the "hop pointer" within the list.
265If your network allows source-routed traffic in and out, you can test
266connectivity to your own services via remote points in the internet. Note that
267although newer BSD-flavor telnets also have source-routing capability, it isn't
268clearly documented and the command syntax is somewhat clumsy. Netcat's
269handling of "-g" is modeled after "traceroute".
270
271Netcat tries its best to behave just like "cat". It currently does nothing to
272terminal input modes, and does no end-of-line conversion. Standard input from
273a terminal is read line by line with normal editing characters in effect. You
274can freely suspend out of an interactive connection and resume. ^C or whatever
275your interrupt character is will make netcat close the network connection and
276exit. A switch to place the terminal in raw mode has been considered, but so
277far has not been necessary. You can send raw binary data by reading it out of
278a file or piping from another program, so more meaningful effort would be spent
279writing an appropriate front-end driver.
280
281Netcat is not an "arbitrary packet generator", but the ability to talk to raw
282sockets and/or nit/bpf/dlpi may appear at some point. Such things are clearly
283useful; I refer you to Darren Reed's excellent ip_filter package, which now
284includes a tool to construct and send raw packets with any contents you want.
285
286Example uses -- the light side
287==============================
288
289Again, this is a very partial list of possibilities, but it may get you to
290think up more applications for netcat. Driving netcat with simple shell or
291expect scripts is an easy and flexible way to do fairly complex tasks,
292especially if you're not into coding network tools in C. My coding isn't
293particularly strong either [although undoubtedly better after writing this
294thing!], so I tend to construct bare-metal tools like this that I can trivially
295plug into other applications. Netcat doubles as a teaching tool -- one can
296learn a great deal about more complex network protocols by trying to simulate
297them through raw connections!
298
299An example of netcat as a backend for something else is the shell-script
300Web browser, which simply asks for the relevant parts of a URL and pipes
301"GET /what/ever" into a netcat connection to the server. I used to do this
302with telnet, and had to use calculated sleep times and other stupidity to
303kludge around telnet's limitations. Netcat guarantees that I get the whole
304page, and since it transfers all the data unmodified, I can even pull down
305binary image files and display them elsewhere later. Some folks may find the
306idea of a shell-script web browser silly and strange, but it starts up and
307gets me my info a hell of a lot faster than a GUI browser and doesn't hide
308any contents of links and forms and such. This is included, as scripts/web,
309along with several other web-related examples.
310
311Netcat is an obvious replacement for telnet as a tool for talking to daemons.
312For example, it is easier to type "nc host 25", talk to someone's mailer, and
313just ^C out than having to type ^]c or QUIT as telnet would require you to do.
314You can quickly catalog the services on your network by telling netcat to
315connect to well-known services and collect greetings, or at least scan for open
316ports. You'll probably want to collect netcat's diagnostic messages in your
317output files, so be sure to include standard error in the output using
318`>& file' in *csh or `> file 2>&1' in bourne shell.
319
320A scanning example: "echo QUIT | nc -v -w 5 target 20-250 500-600 5990-7000"
321will inform you about a target's various well-known TCP servers, including
322r-services, X, IRC, and maybe a few you didn't expect. Sending in QUIT and
323using the timeout will almost guarantee that you see some kind of greeting or
324error from each service, which usually indicates what it is and what version.
325[Beware of the "chargen" port, though...] SATAN uses exactly this technique to
326collect host information, and indeed some of the ideas herein were taken from
327the SATAN backend tools. If you script this up to try every host in your
328subnet space and just let it run, you will not only see all the services,
329you'll find out about hosts that aren't correctly listed in your DNS. Then you
330can compare new snapshots against old snapshots to see changes. For going
331after particular services, a more intrusive example is in scripts/probe.
332
333Netcat can be used as a simple data transfer agent, and it doesn't really
334matter which end is the listener and which end is the client -- input at one
335side arrives at the other side as output. It is helpful to start the listener
336at the receiving side with no timeout specified, and then give the sending side
337a small timeout. That way the listener stays listening until you contact it,
338and after data stops flowing the client will time out, shut down, and take the
339listener with it. Unless the intervening network is fraught with problems,
340this should be completely reliable, and you can always increase the timeout. A
341typical example of something "rsh" is often used for: on one side,
342
343 nc -l -p 1234 | uncompress -c | tar xvfp -
344
345and then on the other side
346
347 tar cfp - /some/dir | compress -c | nc -w 3 othermachine 1234
348
349will transfer the contents of a directory from one machine to another, without
350having to worry about .rhosts files, user accounts, or inetd configurations
351at either end. Again, it matters not which is the listener or receiver; the
352"tarring" machine could just as easily be running the listener instead. One
353could conceivably use a scheme like this for backups, by having cron-jobs fire
354up listeners and backup handlers [which can be restricted to specific addresses
355and ports between each other] and pipe "dump" or "tar" on one machine to "dd
356of=/dev/tapedrive" on another as usual. Since netcat returns a nonzero exit
357status for a denied listener connection, scripts to handle such tasks could
358easily log and reject connect attempts from third parties, and then retry.
359
360Another simple data-transfer example: shipping things to a PC that doesn't have
361any network applications yet except a TCP stack and a web browser. Point the
362browser at an arbitrary port on a Unix server by telling it to download
363something like http://unixbox:4444/foo, and have a listener on the Unix side
364ready to ship out a file when the connect comes in. The browser may pervert
365binary data when told to save the URL, but you can dig the raw data out of
366the on-disk cache.
367
368If you build netcat with GAPING_SECURITY_HOLE defined, you can use it as an
369"inetd" substitute to test experimental network servers that would otherwise
370run under "inetd". A script or program will have its input and output hooked
371to the network the same way, perhaps sans some fancier signal handling. Given
372that most network services do not bind to a particular local address, whether
373they are under "inetd" or not, it is possible for netcat avoid the "address
374already in use" error by binding to a specific address. This lets you [as
375root, for low ports] place netcat "in the way" of a standard service, since
376inbound connections are generally sent to such specifically-bound listeners
377first and fall back to the ones bound to "any". This allows for a one-off
378experimental simulation of some service, without having to screw around with
379inetd.conf. Running with -v turned on and collecting a connection log from
380standard error is recommended.
381
382Netcat as well can make an outbound connection and then run a program or script
383on the originating end, with input and output connected to the same network
384port. This "inverse inetd" capability could enhance the backup-server concept
385described above or help facilitate things such as a "network dialback" concept.
386The possibilities are many and varied here; if such things are intended as
387security mechanisms, it may be best to modify netcat specifically for the
388purpose instead of wrapping such functions in scripts.
389
390Speaking of inetd, netcat will function perfectly well *under* inetd as a TCP
391connection redirector for inbound services, like a "plug-gw" without the
392authentication step. This is very useful for doing stuff like redirecting
393traffic through your firewall out to other places like web servers and mail
394hubs, while posing no risk to the firewall machine itself. Put netcat behind
395inetd and tcp_wrappers, perhaps thusly:
396
397 www stream tcp nowait nobody /etc/tcpd /bin/nc -w 3 realwww 80
398
399and you have a simple and effective "application relay" with access control
400and logging. Note use of the wait time as a "safety" in case realwww isn't
401reachable or the calling user aborts the connection -- otherwise the relay may
402hang there forever.
403
404You can use netcat to generate huge amounts of useless network data for
405various performance testing. For example, doing
406
407 yes AAAAAAAAAAAAAAAAAAAAAA | nc -v -v -l -p 2222 > /dev/null
408
409on one side and then hitting it with
410
411 yes BBBBBBBBBBBBBBBBBBBBBB | nc othermachine 2222 > /dev/null
412
413from another host will saturate your wires with A's and B's. The "very
414verbose" switch usage will tell you how many of each were sent and received
415after you interrupt either side. Using UDP mode produces tremendously MORE
416trash per unit time in the form of fragmented 8 Kbyte mobygrams -- enough to
417stress-test kernels and network interfaces. Firing random binary data into
418various network servers may help expose bugs in their input handling, which
419nowadays is a popular thing to explore. A simple example data-generator is
420given in data/data.c included in this package, along with a small collection
421of canned input files to generate various packet contents. This program is
422documented in its beginning comments, but of interest here is using "%r" to
423generate random bytes at well-chosen points in a data stream. If you can
424crash your daemon, you likely have a security problem.
425
426The hex dump feature may be useful for debugging odd network protocols,
427especially if you don't have any network monitoring equipment handy or aren't
428root where you'd need to run "tcpdump" or something. Bind a listening netcat
429to a local port, and have it run a script which in turn runs another netcat
430to the real service and captures the hex dump to a log file. This sets up a
431transparent relay between your local port and wherever the real service is.
432Be sure that the script-run netcat does *not* use -v, or the extra info it
433sends to standard error may confuse the protocol. Note also that you cannot
434have the "listen/exec" netcat do the data capture, since once the connection
435arrives it is no longer netcat that is running.
436
437Binding to an arbitrary local port allows you to simulate things like r-service
438clients, if you are root locally. For example, feeding "^@root^@joe^@pwd^@"
439[where ^@ is a null, and root/joe could be any other local/remote username
440pair] into a "rsh" or "rlogin" server, FROM your port 1023 for example,
441duplicates what the server expects to receive. Thus, you can test for insecure
442.rhosts files around your network without having to create new user accounts on
443your client machine. The program data/rservice.c can aid this process by
444constructing the "rcmd" protocol bytes. Doing this also prevents "rshd" from
445trying to create that separate standard-error socket and still gives you an
446input path, as opposed to the usual action of "rsh -n". Using netcat for
447things like this can be really useful sometimes, because rsh and rlogin
448generally want a host *name* as an argument and won't accept IP addresses. If
449your client-end DNS is hosed, as may be true when you're trying to extract
450backup sets on to a dumb client, "netcat -n" wins where normal rsh/rlogin is
451useless.
452
453If you are unsure that a remote syslogger is working, test it with netcat.
454Make a UDP connection to port 514 and type in "<0>message", which should
455correspond to "kern.emerg" and cause syslogd to scream into every file it has
456open [and possibly all over users' terminals]. You can tame this down by
457using a different number and use netcat inside routine scripts to send syslog
458messages to places that aren't configured in syslog.conf. For example,
459"echo '<38>message' | nc -w 1 -u loggerhost 514" should send to auth.notice
460on loggerhost. The exact number may vary; check against your syslog.h first.
461
462Netcat provides several ways for you to test your own packet filters. If you
463bind to a port normally protected against outside access and make a connection
464to somewhere outside your own network, the return traffic will be coming to
465your chosen port from the "outside" and should be blocked. TCP may get through
466if your filter passes all "ack syn", but it shouldn't be even doing that to low
467ports on your network. Remember to test with UDP traffic as well! If your
468filter passes at least outbound source-routed IP packets, bouncing a connection
469back to yourself via some gateway outside your network will create "incoming"
470traffic with your source address, which should get dropped by a correctly
471configured anti-spoofing filter. This is a "non-test" if you're also dropping
472source-routing, but it's good to be able to test for that too. Any packet
473filter worth its salt will be blocking source-routed packets in both
474directions, but you never know what interesting quirks you might turn up by
475playing around with source ports and addresses and watching the wires with a
476network monitor.
477
478You can use netcat to protect your own workstation's X server against outside
479access. X is stupid enough to listen for connections on "any" and never tell
480you when new connections arrive, which is one reason it is so vulnerable. Once
481you have all your various X windows up and running you can use netcat to bind
482just to your ethernet address and listen to port 6000. Any new connections
483from outside the machine will hit netcat instead your X server, and you get a
484log of who's trying. You can either tell netcat to drop the connection, or
485perhaps run another copy of itself to relay to your actual X server on
486"localhost". This may not work for dedicated X terminals, but it may be
487possible to authorize your X terminal only for its boot server, and run a relay
488netcat over on the server that will in turn talk to your X terminal. Since
489netcat only handles one listening connection per run, make sure that whatever
490way you rig it causes another one to run and listen on 6000 soon afterward, or
491your real X server will be reachable once again. A very minimal script just
492to protect yourself could be
493
494 while true ; do
495 nc -v -l -s <your-addr> -p 6000 localhost 2
496 done
497
498which causes netcat to accept and then close any inbound connection to your
499workstation's normal ethernet address, and another copy is immediately run by
500the script. Send standard error to a file for a log of connection attempts.
501If your system can't do the "specific bind" thing all is not lost; run your
502X server on display ":1" or port 6001, and netcat can still function as a probe
503alarm by listening on 6000.
504
505Does your shell-account provider allow personal Web pages, but not CGI scripts?
506You can have netcat listen on a particular port to execute a program or script
507of your choosing, and then just point to the port with a URL in your homepage.
508The listener could even exist on a completely different machine, avoiding the
509potential ire of the homepage-host administrators. Since the script will get
510the raw browser query as input it won't look like a typical CGI script, and
511since it's running under your UID you need to write it carefully. You may want
512to write a netcat-based script as a wrapper that reads a query and sets up
513environment variables for a regular CGI script. The possibilities for using
514netcat and scripts to handle Web stuff are almost endless. Again, see the
515examples under scripts/.
516
517Example uses -- the dark side
518=============================
519
520Equal time is deserved here, since a versatile tool like this can be useful
521to any Shade of Hat. I could use my Victorinox to either fix your car or
522disassemble it, right? You can clearly use something like netcat to attack
523or defend -- I don't try to govern anyone's social outlook, I just build tools.
524Regardless of your intentions, you should still be aware of these threats to
525your own systems.
526
527The first obvious thing is scanning someone *else's* network for vulnerable
528services. Files containing preconstructed data, be it exploratory or
529exploitive, can be fed in as standard input, including command-line arguments
530to netcat itself to keep "ps" ignorant of your doings. The more random the
531scanning, the less likelihood of detection by humans, scan-detectors, or
532dynamic filtering, and with -i you'll wait longer but avoid loading down the
533target's network. Some examples for crafting various standard UDP probes are
534given in data/*.d.
535
536Some configurations of packet filters attempt to solve the FTP-data problem by
537just allowing such connections from the outside. These come FROM port 20, TO
538high TCP ports inside -- if you locally bind to port 20, you may find yourself
539able to bypass filtering in some cases. Maybe not to low ports "inside", but
540perhaps to TCP NFS servers, X servers, Prospero, ciscos that listen on 200x
541and 400x... Similar bypassing may be possible for UDP [and maybe TCP too] if a
542connection comes from port 53; a filter may assume it's a nameserver response.
543
544Using -e in conjunction with binding to a specific address can enable "server
545takeover" by getting in ahead of the real ones, whereupon you can snarf data
546sent in and feed your own back out. At the very least you can log a hex dump
547of someone else's session. If you are root, you can certainly use -s and -e to
548run various hacked daemons without having to touch inetd.conf or the real
549daemons themselves. You may not always have the root access to deal with low
550ports, but what if you are on a machine that also happens to be an NFS server?
551You might be able to collect some interesting things from port 2049, including
552local file handles. There are several other servers that run on high ports
553that are likely candidates for takeover, including many of the RPC services on
554some platforms [yppasswdd, anyone?]. Kerberos tickets, X cookies, and IRC
555traffic also come to mind. RADIUS-based terminal servers connect incoming
556users to shell-account machines on a high port, usually 1642 or thereabouts.
557SOCKS servers run on 1080. Do "netstat -a" and get creative.
558
559There are some daemons that are well-written enough to bind separately to all
560the local interfaces, possibly with an eye toward heading off this sort of
561problem. Named from recent BIND releases, and NTP, are two that come to mind.
562Netstat will show these listening on address.53 instead of *.53. You won't
563be able to get in front of these on any of the real interface addresses, which
564of course is especially interesting in the case of named, but these servers
565sometimes forget about things like "alias" interface addresses or interfaces
566that appear later on such as dynamic PPP links. There are some hacked web
567servers and versions of "inetd" floating around that specifically bind as well,
568based on a configuration file -- these generally *are* bound to alias addresses
569to offer several different address-based services from one machine.
570
571Using -e to start a remote backdoor shell is another obvious sort of thing,
572easier than constructing a file for inetd to listen on "ingreslock" or
573something, and you can access-control it against other people by specifying a
574client host and port. Experience with this truly demonstrates how fragile the
575barrier between being "logged in" or not really is, and is further expressed by
576scripts/bsh. If you're already behind a firewall, it may be easier to make an
577*outbound* connection and then run a shell; a small wrapper script can
578periodically try connecting to a known place and port, you can later listen
579there until the inbound connection arrives, and there's your shell. Running
580a shell via UDP has several interesting features, although be aware that once
581"connected", the UDP stub sockets tend to show up in "netstat" just like TCP
582connections and may not be quite as subtle as you wanted. Packets may also be
583lost, so use TCP if you need reliable connections. But since UDP is
584connectionless, a hookup of this sort will stick around almost forever, even if
585you ^C out of netcat or do a reboot on your side, and you only need to remember
586the ports you used on both ends to reestablish. And outbound UDP-plus-exec
587connection creates the connected socket and starts the program immediately. On
588a listening UDP connection, the socket is created once a first packet is
589received. In either case, though, such a "connection" has the interesting side
590effect that only your client-side IP address and [chosen?] source port will
591thereafter be able to talk to it. Instant access control! A non-local third
592party would have to do ALL of the following to take over such a session:
593
594 forge UDP with your source address [trivial to do; see below]
595 guess the port numbers of BOTH ends, or sniff the wire for them
596 arrange to block ICMP or UDP return traffic between it and your real
597 source, so the session doesn't die with a network write error.
598
599The companion program data/rservice.c is helpful in scripting up any sort of
600r-service username or password guessing attack. The arguments to "rservice"
601are simply the strings that get null-terminated and passed over an "rcmd"-style
602connection, with the assumption that the client does not need a separate
603standard-error port. Brute-force password banging is best done via "rexec" if
604it is available since it is less likely to log failed attempts. Thus, doing
605"rservice joe joespass pwd | nc target exec" should return joe's home dir if
606the password is right, or "Permission denied." Plug in a dictionary and go to
607town. If you're attacking rsh/rlogin, remember to be root and bind to a port
608between 512 and 1023 on your end, and pipe in "rservice joe joe pwd" and such.
609
610Netcat can prevent inadvertently sending extra information over a telnet
611connection. Use "nc -t" in place of telnet, and daemons that try to ask for
612things like USER and TERM environment variables will get no useful answers, as
613they otherwise would from a more recent telnet program. Some telnetds actually
614try to collect this stuff and then plug the USER variable into "login" so that
615the caller is then just asked for a password! This mechanism could cause a
616login attempt as YOUR real username to be logged over there if you use a
617Borman-based telnet instead of "nc -t".
618
619Got an unused network interface configured in your kernel [e.g. SLIP], or
620support for alias addresses? Ifconfig one to be any address you like, and bind
621to it with -s to enable all sorts of shenanigans with bogus source addresses.
622The interface probably has to be UP before this works; some SLIP versions
623need a far-end address before this is true. Hammering on UDP services is then
624a no-brainer. What you can do to an unfiltered syslog daemon should be fairly
625obvious; trimming the conf file can help protect against it. Many routers out
626there still blindly believe what they receive via RIP and other routing
627protocols. Although most UDP echo and chargen servers check if an incoming
628packet was sent from *another* "internal" UDP server, there are many that still
629do not, any two of which [or many, for that matter] could keep each other
630entertained for hours at the expense of bandwidth. And you can always make
631someone wonder why she's being probed by nsa.gov.
632
633Your TCP spoofing possibilities are mostly limited to destinations you can
634source-route to while locally bound to your phony address. Many sites block
635source-routed packets these days for precisely this reason. If your kernel
636does oddball things when sending source-routed packets, try moving the pointer
637around with -G. You may also have to fiddle with the routing on your own
638machine before you start receiving packets back. Warning: some machines still
639send out traffic using the source address of the outbound interface, regardless
640of your binding, especially in the case of localhost. Check first. If you can
641open a connection but then get no data back from it, the target host is
642probably killing the IP options on its end [this is an option inside TCP
643wrappers and several other packages], which happens after the 3-way handshake
644is completed. If you send some data and observe the "send-q" side of "netstat"
645for that connection increasing but never getting sent, that's another symptom.
646Beware: if Sendmail 8.7.x detects a source-routed SMTP connection, it extracts
647the hop list and sticks it in the Received: header!
648
649SYN bombing [sometimes called "hosing"] can disable many TCP servers, and if
650you hit one often enough, you can keep it unreachable for days. As is true of
651many other denial-of-service attacks, there is currently no defense against it
652except maybe at the human level. Making kernel SOMAXCONN considerably larger
653than the default and the half-open timeout smaller can help, and indeed some
654people running large high-performance web servers have *had* to do that just to
655handle normal traffic. Taking out mailers and web servers is sociopathic, but
656on the other hand it is sometimes useful to be able to, say, disable a site's
657identd daemon for a few minutes. If someone realizes what is going on,
658backtracing will still be difficult since the packets have a phony source
659address, but calls to enough ISP NOCs might eventually pinpoint the source.
660It is also trivial for a clueful ISP to watch for or even block outgoing
661packets with obviously fake source addresses, but as we know many of them are
662not clueful or willing to get involved in such hassles. Besides, outbound
663packets with an [otherwise unreachable] source address in one of their net
664blocks would look fairly legitimate.
665
666Notes
667=====
668
669A discussion of various caveats, subtleties, and the design of the innards.
670
671As of version 1.07 you can construct a single file containing command arguments
672and then some data to transfer. Netcat is now smart enough to pick out the
673first line and build the argument list, and send any remaining data across the
674net to one or multiple ports. The first release of netcat had trouble with
675this -- it called fgets() for the command line argument, which behind the
676scenes does a large read() from standard input, perhaps 4096 bytes or so, and
677feeds that out to the fgets() library routine. By the time netcat 1.00 started
678directly read()ing stdin for more data, 4096 bytes of it were gone. It now
679uses raw read() everywhere and does the right thing whether reading from files,
680pipes, or ttys. If you use this for multiple-port connections, the single
681block of data will now be a maximum of 8K minus the first line. Improvements
682have been made to the logic in sending the saved chunk to each new port. Note
683that any command-line arguments hidden using this mechanism could still be
684extracted from a core dump.
685
686When netcat receives an inbound UDP connection, it creates a "connected socket"
687back to the source of the connection so that it can also send out data using
688normal write(). Using this mechanism instead of recvfrom/sendto has several
689advantages -- the read/write select loop is simplified, and ICMP errors can in
690effect be received by non-root users. However, it has the subtle side effect
691that if further UDP packets arrive from the caller but from different source
692ports, the listener will not receive them. UDP listen mode on a multihomed
693machine may have similar quirks unless you specifically bind to one of its
694addresses. It is not clear that kernel support for UDP connected sockets
695and/or my understanding of it is entirely complete here, so experiment...
696
697You should be aware of some subtleties concerning UDP scanning. If -z is on,
698netcat attempts to send a single null byte to the target port, twice, with a
699small time in between. You can either use the -w timeout, or netcat will try
700to make a "sideline" TCP connection to the target to introduce a small time
701delay equal to the round-trip time between you and the target. Note that if
702you have a -w timeout and -i timeout set, BOTH take effect and you wait twice
703as long. The TCP connection is to a normally refused port to minimize traffic,
704but if you notice a UDP fast-scan taking somewhat longer than it should, it
705could be that the target is actually listening on the TCP port. Either way,
706any ICMP port-unreachable messages from the target should have arrived in the
707meantime. The second single-byte UDP probe is then sent. Under BSD kernels,
708the ICMP error is delivered to the "connected socket" and the second write
709returns an error, which tells netcat that there is NOT a UDP service there.
710While Linux seems to be a fortunate exception, under many SYSV derived kernels
711the ICMP is not delivered, and netcat starts reporting that *all* the ports are
712"open" -- clearly wrong. [Some systems may not even *have* the "udp connected
713socket" concept, and netcat in its current form will not work for UDP at all.]
714If -z is specified and only one UDP port is probed, netcat's exit status
715reflects whether the connection was "open" or "refused" as with TCP.
716
717It may also be that UDP packets are being blocked by filters with no ICMP error
718returns, in which case everything will time out and return "open". This all
719sounds backwards, but that's how UDP works. If you're not sure, try "echo
720w00gumz | nc -u -w 2 target 7" to see if you can reach its UDP echo port at
721all. You should have no trouble using a BSD-flavor system to scan for UDP
722around your own network, although flooding a target with the high activity that
723-z generates will cause it to occasionally drop packets and indicate false
724"opens". A more "correct" way to do this is collect and analyze the ICMP
725errors, as does SATAN's "udp_scan" backend, but then again there's no guarantee
726that the ICMP gets back to you either. Udp_scan also does the zero-byte
727probes but is excruciatingly careful to calculate its own round-trip timing
728average and dynamically set its own response timeouts along with decoding any
729ICMP received. Netcat uses a much sleazier method which is nonetheless quite
730effective. Cisco routers are known to have a "dead time" in between ICMP
731responses about unreachable UDP ports, so a fast scan of a cisco will show
732almost everything "open". If you are looking for a specific UDP service, you
733can construct a file containing the right bytes to trigger a response from the
734other end and send that as standard input. Netcat will read up to 8K of the
735file and send the same data to every UDP port given. Note that you must use a
736timeout in this case [as would any other UDP client application] since the
737two-write probe only happens if -z is specified.
738
739Many telnet servers insist on a specific set of option negotiations before
740presenting a login banner. On a raw connection you will see this as small
741amount of binary gook. My attempts to create fixed input bytes to make a
742telnetd happy worked some places but failed against newer BSD-flavor ones,
743possibly due to timing problems, but there are a couple of much better
744workarounds. First, compile with -DTELNET and use -t if you just want to get
745past the option negotiation and talk to something on a telnet port. You will
746still see the binary gook -- in fact you'll see a lot more of it as the options
747are responded to behind the scenes. The telnet responder does NOT update the
748total byte count, or show up in the hex dump -- it just responds negatively to
749any options read from the incoming data stream. If you want to use a normal
750full-blown telnet to get to something but also want some of netcat's features
751involved like settable ports or timeouts, construct a tiny "foo" script:
752
753 #! /bin/sh
754 exec nc -otheroptions targethost 23
755
756and then do
757
758 nc -l -p someport -e foo localhost &
759 telnet localhost someport
760
761and your telnet should connect transparently through the exec'ed netcat to
762the target, using whatever options you supplied in the "foo" script. Don't
763use -t inside the script, or you'll wind up sending *two* option responses.
764
765I've observed inconsistent behavior under some Linuxes [perhaps just older
766ones?] when binding in listen mode. Sometimes netcat binds only to "localhost"
767if invoked with no address or port arguments, and sometimes it is unable to
768bind to a specific address for listening if something else is already listening
769on "any". The former problem can be worked around by specifying "-s 0.0.0.0",
770which will do the right thing despite netcat claiming that it's listening on
771[127.0.0.1]. This is a known problem -- for example, there's a mention of it
772in the makefile for SOCKS. On the flip side, binding to localhost and sending
773packets to some other machine doesn't work as you'd expect -- they go out with
774the source address of the sending interface instead. The Linux kernel contains
775a specific check to ensure that packets from 127.0.0.1 are never sent to the
776wire; other kernels may contain similar code. Linux, of course, *still*
777doesn't support source-routing, but they claim that it and many other network
778improvements are at least breathing hard.
779
780There are several possible errors associated with making TCP connections, but
781to specifically see anything other than "refused", one must wait the full
782kernel-defined timeout for a connection to fail. Netcat's mechanism of
783wrapping an alarm timer around the connect prevents the *real* network error
784from being returned -- "errno" at that point indicates "interrupted system
785call" since the connect attempt was interrupted. Some old 4.3 BSD kernels
786would actually return things like "host unreachable" immediately if that was
787the case, but most newer kernels seem to wait the full timeout and *then* pass
788back the real error. Go figure. In this case, I'd argue that the old way was
789better, despite those same kernels generally being the ones that tear down
790*established* TCP connections when ICMP-bombed.
791
792Incoming socket options are passed to applications by the kernel in the
793kernel's own internal format. The socket-options structure for source-routing
794contains the "first-hop" IP address first, followed by the rest of the real
795options list. The kernel uses this as is when sending reply packets -- the
796structure is therefore designed to be more useful to the kernel than to humans,
797but the hex dump of it that netcat produces is still useful to have.
798
799Kernels treat source-routing options somewhat oddly, but it sort of makes sense
800once one understands what's going on internally. The options list of addresses
801must contain hop1, hop2, ..., destination. When a source-routed packet is sent
802by the kernel [at least BSD], the actual destination address becomes irrelevant
803because it is replaced with "hop1", "hop1" is removed from the options list,
804and all the other addresses in the list are shifted up to fill the hole. Thus
805the outbound packet is sent from your chosen source address to the first
806*gateway*, and the options list now contains hop2, ..., destination. During
807all this address shuffling, the kernel does NOT change the pointer value, which
808is why it is useful to be able to set the pointer yourself -- you can construct
809some really bizarre return paths, and send your traffic fairly directly to the
810target but around some larger loop on the way back. Some Sun kernels seem to
811never flip the source-route around if it contains less than three hops, never
812reset the pointer anyway, and tries to send the packet [with options containing
813a "completed" source route!!] directly back to the source. This is way broken,
814of course. [Maybe ipforwarding has to be on? I haven't had an opportunity to
815beat on it thoroughly yet.]
816
817"Credits" section: The original idea for netcat fell out of a long-standing
818desire and fruitless search for a tool resembling it and having the same
819features. After reading some other network code and realizing just how many
820cool things about sockets could be controlled by the calling user, I started
821on the basics and the rest fell together pretty quickly. Some port-scanning
822ideas were taken from Venema/Farmer's SATAN tool kit, and Pluvius' "pscan"
823utility. Healthy amounts of BSD kernel source were perused in an attempt to
824dope out socket options and source-route handling; additional help was obtained
825from Dave Borman's telnet sources. The select loop is loosely based on fairly
826well-known code from "rsh" and Richard Stevens' "sock" program [which itself is
827sort of a "netcat" with more obscure features], with some more paranoid
828sanity-checking thrown in to guard against the distinct likelihood that there
829are subtleties about such things I still don't understand. I found the
830argument-hiding method cleanly implemented in Barrett's "deslogin"; reading the
831line as input allows greater versatility and is much less prone to cause
832bizarre problems than the more common trick of overwriting the argv array.
833After the first release, several people contributed portability fixes; they are
834credited in generic.h and the Makefile. Lauren Burka inspired the ascii art
835for this revised document. Dean Gaudet at Wired supplied a precursor to
836the hex-dump code, and mudge@l0pht.com originally experimented with and
837supplied code for the telnet-options responder. Outbound "-e <prog>" resulted
838from a need to quietly bypass a firewall installation. Other suggestions and
839patches have rolled in for which I am always grateful, but there are only 26
840hours per day and a discussion of feature creep near the end of this document.
841
842Netcat was written with the Russian railroad in mind -- conservatively built
843and solid, but it *will* get you there. While the coding style is fairly
844"tight", I have attempted to present it cleanly [keeping *my* lines under 80
845characters, dammit] and put in plenty of comments as to why certain things
846are done. Items I know to be questionable are clearly marked with "XXX".
847Source code was made to be modified, but determining where to start is
848difficult with some of the tangles of spaghetti code that are out there.
849Here are some of the major points I feel are worth mentioning about netcat's
850internal design, whether or not you agree with my approach.
851
852Except for generic.h, which changes to adapt more platforms, netcat is a single
853source file. This has the distinct advantage of only having to include headers
854once and not having to re-declare all my functions in a billion different
855places. I have attempted to contain all the gross who's-got-what-.h-file
856things in one small dumping ground. Functions are placed "dependencies-first",
857such that when the compiler runs into the calls later, it already knows the
858type and arguments and won't complain. No function prototyping -- not even the
859__P(()) crock -- is used, since it is more portable and a file of this size is
860easy enough to check manually. Each function has a standard-format comment
861ahead of it, which is easily found using the regexp " :$". I freely use gotos.
862Loops and if-clauses are made as small and non-nested as possible, and the ends
863of same *marked* for clarity [I wish everyone would do this!!].
864
865Large structures and buffers are all malloc()ed up on the fly, slightly larger
866than the size asked for and zeroed out. This reduces the chances of damage
867from those "end of the buffer" fencepost errors or runaway pointers escaping
868off the end. These things are permanent per run, so nothing needs to be freed
869until the program exits.
870
871File descriptor zero is always expected to be standard input, even if it is
872closed. If a new network descriptor winds up being zero, a different one is
873asked for which will be nonzero, and fd zero is simply left kicking around
874for the rest of the run. Why? Because everything else assumes that stdin is
875always zero and "netfd" is always positive. This may seem silly, but it was a
876lot easier to code. The new fd is obtained directly as a new socket, because
877trying to simply dup() a new fd broke subsequent socket-style use of the new fd
878under Solaris' stupid streams handling in the socket library.
879
880The catch-all message and error handlers are implemented with an ample list of
881phoney arguments to get around various problems with varargs. Varargs seems
882like deliberate obfuscation in the first place, and using it would also
883require use of vfprintf() which not all platforms support. The trailing
884sleep in bail() is to allow output to flush, which is sometimes needed if
885netcat is already on the other end of a network connection.
886
887The reader may notice that the section that does DNS lookups seems much
888gnarlier and more confusing than other parts. This is NOT MY FAULT. The
889sockaddr and hostent abstractions are an abortion that forces the coder to
890deal with it. Then again, a lot of BSD kernel code looks like similar
891struct-pointer hell. I try to straighten it out somewhat by defining my own
892HINF structure, containing names, ascii-format IP addresses, and binary IP
893addresses. I fill this structure exactly once per host argument, and squirrel
894everything safely away and handy for whatever wants to reference it later.
895
896Where many other network apps use the FIONBIO ioctl to set non-blocking I/O
897on network sockets, netcat uses straightforward blocking I/O everywhere.
898This makes everything very lock-step, relying on the network and filesystem
899layers to feed in data when needed. Data read in is completely written out
900before any more is fetched. This may not be quite the right thing to do under
901some OSes that don't do timed select() right, but this remains to be seen.
902
903The hexdump routine is written to be as fast as possible, which is why it does
904so much work itself instead of just sprintf()ing everything together. Each
905dump line is built into a single buffer and atomically written out using the
906lowest level I/O calls. Further improvements could undoubtedly be made by
907using writev() and eliminating all sprintf()s, but it seems to fly right along
908as is. If both exec-a-prog mode and a hexdump file is asked for, the hexdump
909flag is deliberately turned off to avoid creating random zero-length files.
910Files are opened in "truncate" mode; if you want "append" mode instead, change
911the open flags in main().
912
913main() may look a bit hairy, but that's only because it has to go down the
914argv list and handle multiple ports, random mode, and exit status. Efforts
915have been made to place a minimum of code inside the getopt() loop. Any real
916work is sent off to functions in what is hopefully a straightforward way.
917
918Obligatory vendor-bash: If "nc" had become a standard utility years ago,
919the commercial vendors would have likely packaged it setuid root and with
920-DGAPING_SECURITY_HOLE turned on but not documented. It is hoped that netcat
921will aid people in finding and fixing the no-brainer holes of this sort that
922keep appearing, by allowing easier experimentation with the "bare metal" of
923the network layer.
924
925It could be argued that netcat already has too many features. I have tried
926to avoid "feature creep" by limiting netcat's base functionality only to those
927things which are truly relevant to making network connections and the everyday
928associated DNS lossage we're used to. Option switches already have slightly
929overloaded functionality. Random port mode is sort of pushing it. The
930hex-dump feature went in later because it *is* genuinely useful. The
931telnet-responder code *almost* verges on the gratuitous, especially since it
932mucks with the data stream, and is left as an optional piece. Many people have
933asked for example "how 'bout adding encryption?" and my response is that such
934things should be separate entities that could pipe their data *through* netcat
935instead of having their own networking code. I am therefore not completely
936enthusiastic about adding any more features to this thing, although you are
937still free to send along any mods you think are useful.
938
939Nonetheless, at this point I think of netcat as my tcp/ip swiss army knife,
940and the numerous companion programs and scripts to go with it as duct tape.
941Duct tape of course has a light side and a dark side and binds the universe
942together, and if I wrap enough of it around what I'm trying to accomplish,
943it *will* work. Alternatively, if netcat is a large hammer, there are many
944network protocols that are increasingly looking like nails by now...
945
946_H* 960320 v1.10 RELEASE -- happy spring!
diff --git a/src/usr.bin/nc/data/Makefile b/src/usr.bin/nc/data/Makefile
new file mode 100644
index 0000000000..65cf185358
--- /dev/null
+++ b/src/usr.bin/nc/data/Makefile
@@ -0,0 +1,10 @@
1all: data rservice xor
2
3data: data.c
4 cc -s -O -o data data.c
5rservice: rservice.c
6 cc -s -O -o rservice rservice.c
7xor: xor.c
8 cc -s -O -o xor xor.c
9clean:
10 rm -f *.o data rservice xor
diff --git a/src/usr.bin/nc/data/README b/src/usr.bin/nc/data/README
new file mode 100644
index 0000000000..7e4b9fbf63
--- /dev/null
+++ b/src/usr.bin/nc/data/README
@@ -0,0 +1,9 @@
1For now, read the header comments inside each of these for documentation.
2The programs are simple enough that they don't really need a Makefile any more
3complex than the one given; ymmv. Data and xor may also be useful on DOS,
4which is why there are hooks for it in the code.
5
6data.c a primitive atob / btoa byte generator
7*.d example input to "data -g"
8rservice.c a utility for scripting up rsh/rexec attacks
9xor.c generic xor handler
diff --git a/src/usr.bin/nc/data/data.c b/src/usr.bin/nc/data/data.c
new file mode 100644
index 0000000000..56c167fd96
--- /dev/null
+++ b/src/usr.bin/nc/data/data.c
@@ -0,0 +1,274 @@
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 <stdio.h>
19
20#ifdef MSDOS /* for MSC only at the moment... */
21#include <fcntl.h>
22#else /* MSDOS */
23#include <sys/file.h>
24#define HAVE_RANDOM /* XXX: might have to change */
25#endif /* MSDOS */
26
27static char buf_in [128];
28static char buf_raw [8192];
29static 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 */
34char * 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. */
60int 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
75main (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
147nextbuf: /* 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;
156wrong:
157 fprintf (stderr, surveysez); /* if both or neither */
158 exit (1);
159
160do_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
187hex:
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 */
211stuff: /* 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
234do_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
260do_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 */
diff --git a/src/usr.bin/nc/data/dns-any.d b/src/usr.bin/nc/data/dns-any.d
new file mode 100644
index 0000000000..77b014cf70
--- /dev/null
+++ b/src/usr.bin/nc/data/dns-any.d
@@ -0,0 +1,36 @@
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:
80 # query id = 2
92
10
111 # flags/opcodes = query, dorecurse
120
13
140 # qdcount, i.e. nqueries: 1
151
16
170 # ancount: answers, 0
180
19
200 # nscount: 0
210
22
230 # addl records: 0
240
25
26# end of fixed header
27
280 # name-len: 0 for ".", lenbyte plus name-bytes otherwise
29
300 # type: any, 255
310xff
32
330 # class: IN
341
35
36# i think that's it..
diff --git a/src/usr.bin/nc/data/nfs-0.d b/src/usr.bin/nc/data/nfs-0.d
new file mode 100644
index 0000000000..0360938227
--- /dev/null
+++ b/src/usr.bin/nc/data/nfs-0.d
@@ -0,0 +1,59 @@
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
4000 # XID: 4 trash bytes
5001
6002
7003
8
9000 # CALL: 0
10000
11000
12000
13
14000 # RPC version: 2
15000
16000
17002
18
19000 # nfs: 100003
20001
210x86
220xa3
23
24000 # version: 1
25000
26000
27001
28
29000 # procedure number: 0
30000
31000
32000
33
34000 # port: junk
35000
36000
37000
38
39000 # auth trash
40000
41000
42000
43
44000 # auth trash
45000
46000
47000
48
49000 # auth trash
50000
51000
52000
53
54000 # extra auth trash? probably not needed
55000
56000
57000
58
59# that's it!
diff --git a/src/usr.bin/nc/data/pm.d b/src/usr.bin/nc/data/pm.d
new file mode 100644
index 0000000000..fe327693a9
--- /dev/null
+++ b/src/usr.bin/nc/data/pm.d
@@ -0,0 +1,8 @@
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
7255 # 0xff # . 1
8243 # 0xf3 # . 2
diff --git a/src/usr.bin/nc/data/pmap-dump.d b/src/usr.bin/nc/data/pmap-dump.d
new file mode 100644
index 0000000000..bc6b63277d
--- /dev/null
+++ b/src/usr.bin/nc/data/pmap-dump.d
@@ -0,0 +1,60 @@
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
5001 # 0x01 # . # XID: 4 trash bytes
6002 # 0x02 # .
7003 # 0x03 # .
8004 # 0x04 # .
9
10000 # 0x00 # . # MSG: int 0=call, 1=reply
11000 # 0x00 # .
12000 # 0x00 # .
13000 # 0x00 # .
14
15000 # 0x00 # . # pmap call body: rpc version=2
16000 # 0x00 # .
17000 # 0x00 # .
18002 # 0x02 # .
19
20000 # 0x00 # . # pmap call body: prog=PMAP, 100000
21001 # 0x01 # .
22134 # 0x86 # .
23160 # 0xa0 # .
24
25000 # 0x00 # . # pmap call body: progversion=2
26000 # 0x00 # .
27000 # 0x00 # .
28002 # 0x02 # .
29
30000 # 0x00 # . # pmap call body: proc=DUMP, 4
31000 # 0x00 # .
32000 # 0x00 # .
33004 # 0x04 # .
34
35# with AUTH_NONE, there are 4 zero integers [16 bytes] here
36
37000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0
38000 # 0x00 # .
39000 # 0x00 # .
40000 # 0x00 # .
41
42000 # 0x00 # . # auth junk
43000 # 0x00 # .
44000 # 0x00 # .
45000 # 0x00 # .
46
47000 # 0x00 # . # auth junk
48000 # 0x00 # .
49000 # 0x00 # .
50000 # 0x00 # .
51
52000 # 0x00 # . # auth junk
53000 # 0x00 # .
54000 # 0x00 # .
55000 # 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...
diff --git a/src/usr.bin/nc/data/pmap-mnt.d b/src/usr.bin/nc/data/pmap-mnt.d
new file mode 100644
index 0000000000..00588ba41f
--- /dev/null
+++ b/src/usr.bin/nc/data/pmap-mnt.d
@@ -0,0 +1,78 @@
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
5001 # 0x01 # . # XID: 4 trash bytes
6002 # 0x02 # .
7003 # 0x03 # .
8004 # 0x04 # .
9
10000 # 0x00 # . # MSG: int 0=call, 1=reply
11000 # 0x00 # .
12000 # 0x00 # .
13000 # 0x00 # .
14
15000 # 0x00 # . # pmap call body: rpc version=2
16000 # 0x00 # .
17000 # 0x00 # .
18002 # 0x02 # .
19
20000 # 0x00 # . # pmap call body: prog=PMAP, 100000
21001 # 0x01 # .
22134 # 0x86 # .
23160 # 0xa0 # .
24
25000 # 0x00 # . # pmap call body: progversion=2
26000 # 0x00 # .
27000 # 0x00 # .
28002 # 0x02 # .
29
30000 # 0x00 # . # pmap call body: proc=GETPORT, 3
31000 # 0x00 # .
32000 # 0x00 # .
33003 # 0x03 # .
34
35# with AUTH_NONE, there are 4 zero integers [16 bytes] here
36
37000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0
38000 # 0x00 # .
39000 # 0x00 # .
40000 # 0x00 # .
41
42000 # 0x00 # . # auth junk
43000 # 0x00 # .
44000 # 0x00 # .
45000 # 0x00 # .
46
47000 # 0x00 # . # auth junk
48000 # 0x00 # .
49000 # 0x00 # .
50000 # 0x00 # .
51
52000 # 0x00 # . # auth junk
53000 # 0x00 # .
54000 # 0x00 # .
55000 # 0x00 # .
56
57000 # 0x00 # . # prog=MOUNT, 100005
58001 # 0x01 # .
59134 # 0x86 # .
60165 # 0xa5 # .
61
62000 # 0x00 # . # progversion=1
63000 # 0x00 # .
64000 # 0x00 # .
65001 # 0x01 # .
66
67000 # 0x00 # . # protocol=udp, 17
68000 # 0x00 # .
69000 # 0x00 # .
70017 # 0x11 # .
71
72000 # 0x00 # . # proc num = junk
73000 # 0x00 # .
74000 # 0x00 # .
75000 # 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.
diff --git a/src/usr.bin/nc/data/rip.d b/src/usr.bin/nc/data/rip.d
new file mode 100644
index 0000000000..da505e2143
--- /dev/null
+++ b/src/usr.bin/nc/data/rip.d
@@ -0,0 +1,52 @@
1# struct netinfo {
2# struct sockaddr rip_dst; /* destination net/host */
3# int rip_metric; /* cost of route */
4# };
5# struct rip {
6# u_char rip_cmd; /* request/response */
7# u_char rip_vers; /* protocol version # */
8# u_char rip_res1[2]; /* pad to 32-bit boundary */
9# union {
10# struct netinfo ru_nets[1]; /* variable length... */
11# char ru_tracefile[1]; /* ditto ... */
12# } ripun;
13#define rip_nets ripun.ru_nets
14#define rip_tracefile ripun.ru_tracefile
15#define RIPCMD_REQUEST 1 /* want info */
16#define RIPCMD_RESPONSE 2 /* responding to request */
17#define RIPCMD_TRACEON 3 /* turn tracing on */
18#define RIPCMD_TRACEOFF 4 /* turn it off */
19#define HOPCNT_INFINITY 16 /* per Xerox NS */
20#define MAXPACKETSIZE 512 /* max broadcast size */
21
22### RIP packet redux
23### UDP send FROM clued-rtr/520 to target/520
242 # RIPCMD_RESPONSE
251 # version
260 # padding
270
28
29# sockaddr-plus-metric structs begin, as many as necessary...
300 # len
312 # AF_INET
320 # port
330
34# addr bytes:
35X
36Y
37Z
38Q
390 # filler, out to 16 bytes [sizeof (sockaddr)] ...
400
410
420
430
440
450
460
470 # metric: net-order integer
480
490
501
51
52## that's it
diff --git a/src/usr.bin/nc/data/rservice.c b/src/usr.bin/nc/data/rservice.c
new file mode 100644
index 0000000000..1085d9cb78
--- /dev/null
+++ b/src/usr.bin/nc/data/rservice.c
@@ -0,0 +1,68 @@
1/* generate ^@string1^@string2^@cmd^@ input to netcat, for scripting up
2 rsh/rexec attacks. Needs to be a prog because shells strip out nulls.
3
4 args:
5 locuser remuser [cmd]
6 remuser passwd [cmd]
7
8 cmd defaults to "pwd".
9
10 ... whatever. _H*/
11
12#include <stdio.h>
13
14/* change if you like; "id" is a good one for figuring out if you won too */
15static char cmd[] = "pwd";
16
17static char buf [256];
18
19main(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
65wrong:
66 fprintf (stderr, "wrong! needs 2 or more args.\n");
67 exit (1);
68}
diff --git a/src/usr.bin/nc/data/showmount.d b/src/usr.bin/nc/data/showmount.d
new file mode 100644
index 0000000000..499794bc8a
--- /dev/null
+++ b/src/usr.bin/nc/data/showmount.d
@@ -0,0 +1,63 @@
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
8000 # XID: 4 trash bytes
9001
10002
11003
12
13000 # CALL: 0
14000
15000
16000
17
18000 # RPC version: 2
19000
20000
21002
22
23000 # mount: 100005
24001
250x86
260xa5
27
28000 # mount version: 1
29000
30000
31001
32
33000 # procedure number -- put what you need here:
34000 # 2 = dump [showmount -e]
35000 # 5 = exportlist [showmount -a]
36xxx # "sed s/xxx/$1/ | data -g | nc ..." or some such...
37
38000 # port: junk
39000
40000
41000
42
43000 # auth trash
44000
45000
46000
47
48000 # auth trash
49000
50000
51000
52
53000 # auth trash
54000
55000
56000
57
58000 # extra auth trash? probably not needed
59000
60000
61000
62
63# that's it!
diff --git a/src/usr.bin/nc/data/xor.c b/src/usr.bin/nc/data/xor.c
new file mode 100644
index 0000000000..9feead0cba
--- /dev/null
+++ b/src/usr.bin/nc/data/xor.c
@@ -0,0 +1,92 @@
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 <stdio.h>
17#include <fcntl.h>
18
19char buf[8192];
20char bytes[256];
21char * py;
22
23/* do the xor, in place. Uses global ptr "py" to maintain "bytes" state */
24xorb (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 */
44main (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
diff --git a/src/usr.bin/nc/generic.h b/src/usr.bin/nc/generic.h
new file mode 100644
index 0000000000..b3dd5f5dc6
--- /dev/null
+++ b/src/usr.bin/nc/generic.h
@@ -0,0 +1,377 @@
1/* generic.h -- anything you don't #undef at the end remains in effect.
2 The ONLY things that go in here are generic indicator flags; it's up
3 to your programs to declare and call things based on those flags.
4
5 You should only need to make changes via a minimal system-specific section
6 at the end of this file. To build a new section, rip through this and
7 check everything it mentions on your platform, and #undef that which needs
8 it. If you generate a system-specific section you didn't find in here,
9 please mail me a copy so I can update the "master".
10
11 I realize I'm probably inventing another pseudo-standard here, but
12 goddamnit, everybody ELSE has already, and I can't include all of their
13 hairball schemes too. HAVE_xx conforms to the gnu/autoconf usage and
14 seems to be the most common format. In fact, I dug a lot of these out
15 of autoconf and tried to common them all together using "stupidh" to
16 collect data from platforms.
17
18 In disgust... _H* 940910, 941115, 950511. Pseudo-version: 1.3
19
20 Updated 951104 with many patches from netcat feedback, and properly
21 closed a lot of slop in open-ended comments: version 1.4
22 960217 + nextstep: version 1.5
23*/
24
25#ifndef GENERIC_H /* only run through this once */
26#define GENERIC_H
27
28/* =============================== */
29/* System calls, lib routines, etc */
30/* =============================== */
31
32/* How does your system declare malloc, void or char? Usually void, but go
33 ask the SunOS people why they had to be different... */
34#define VOID_MALLOC
35
36/* notably from fwtk/firewall.h: posix locking? */
37#define HAVE_FLOCK /* otherwise it's lockf() */
38
39/* if you don't have setsid(), you might have setpgrp(). */
40#define HAVE_SETSID
41
42/* random() is generally considered better than rand() */
43#define HAVE_RANDOM
44
45/* the srand48/lrand48/etc family is s'posedly even better */
46#define HAVE_RAND48
47/* bmc@telebase and others have suggested these macros if a box *does* have
48 rand48. Will consider for later if we're doing something that really
49 requires stronger random numbers, but netcat and such certainly doesn't.
50#define srandom(seed) srand48((long) seed)
51#define random() lrand48() */
52
53/* if your machine doesn't have lstat(), it should have stat() [dos...] */
54#define HAVE_LSTAT
55
56/* different kinds of term ioctls. How to recognize them, very roughly:
57 sysv/POSIX_ME_HARDER: termio[s].h, struct termio[s], tty.c_*[]
58 bsd/old stuff: sgtty.h, ioctl(TIOCSETP), sgttyb.sg_*, tchars.t_* */
59#define HAVE_TERMIOS
60
61/* dbm vs ndbm */
62#define HAVE_NDBM
63
64/* extended utmp/wtmp stuff. MOST machines still do NOT have this SV-ism */
65#define UTMPX
66
67/* some systems have nice() which takes *relative* values... [resource.h] */
68#define HAVE_SETPRIORITY
69
70/* a sysvism, I think, but ... */
71#define HAVE_SYSINFO
72
73/* ============= */
74/* Include files */
75/* ============= */
76
77/* Presence of these can be determined via a script that sniffs them
78 out if you aren't sure. See "stupidh"... */
79
80/* stdlib comes with most modern compilers, but ya never know */
81#define HAVE_STDLIB_H
82
83/* not on a DOS box! */
84#define HAVE_UNISTD_H
85
86/* stdarg is a weird one */
87#define HAVE_STDARG_H
88
89/* dir.h or maybe ndir.h otherwise. */
90#define HAVE_DIRENT_H
91
92/* string or strings */
93#define HAVE_STRINGS_H
94
95/* if you don't have lastlog.h, what you want might be in login.h */
96#define HAVE_LASTLOG_H
97
98/* predefines for _PATH_various */
99#define HAVE_PATHS_H
100
101/* some SV-flavors break select stuff out separately */
102#define HAVE_SELECT_H
103
104/* assorted others */
105#define HAVE_PARAM_H /* in sys/ */
106#define HAVE_SYSMACROS_H /* in sys/ */
107#define HAVE_TTYENT_H /* securetty et al */
108
109/* ==================== */
110
111/* Still maybe have to do something about the following, if it's even
112 worth it. I just grepped a lot of these out of various code, without
113 looking them up yet:
114
115#define HAVE_EINPROGRESS
116#define HAVE_F_SETOWN
117HAVE_FILIO_H ... fionbio, fiosetown, etc... will need for hairier
118 select loops.
119#define HAVE_SETENV ... now *there's* a hairy one; **environ is portable
120#define BIG_ENDIAN/little_endian ... *please* try to avoid this stupidity
121 and LSBFIRST/MSBFIRST
122#define HAVE_GETUSERSHELL ... you could always pull it out of getpwent()
123#define HAVE_SETE[UG]ID ... lib or syscall, it varies on diff platforms
124#define HAVE_STRCHR ... should actually be handled by string/strings
125#define HAVE_PSTAT
126#define HAVE_ST_BLKSIZE ... a stat() thing?
127#define HAVE_IP_TOS
128#define HAVE_STRFTIME ... screw this, we'll just INCLUDE one for lame
129 old boxes that don't have it [sunos 3.x, early 4.x?]
130#define HAVE_VFPRINTF
131#define HAVE_SHADOW_PASSWD ... in its multitudinous schemes?? ... how
132 about sumpin' like #define SHADOW_PASSWD_TYPE ... could get grody.
133 ... looks like sysv /etc/shadow, getspent() family is common.
134#define SIG* ... what a swamp, punt for now; should all be in signal.h
135#define HAVE_STRCSPN ... see larry wall's comment in the fwtk regex code
136#define ULTRIX_AUTH ... bwahaha.
137#define HAVE_YP or NIS or whatever you wanna call it this week
138randomness about VARARGS??
139--- later stuff to be considered ---
140#define UINT4 ... u-int on alpha/osf, i.e. __alpha/__osf__, ulong elsewhere?
141 dont name it that, though, it'll conflict with extant .h files like md5
142randomness about machine/endian.h, machine/inline.h -- bsdi, net/2
143randomness about _PATH_WTMP vs WTMP_FILE and where they even live!!
144#define HAVE_SYS_ERRLIST ... whether it's in stdio.h or not [bsd 4.4]
145--- still more stuff
146#define HAVE_SETENV
147#define _PATH_UTMP vs UTMP_FILE, a la deslogind?!
148#define HAVE_DAEMON
149#define HAVE_INETADDR [vixie bind?]
150lseek: SEEK_SET vs L_SET and associated lossage [epi-notes, old 386Mach]
151bsdi: ioctl_compat.h ?
152--- takin' some ifdefs from CNS krb:
153F_GETOWN/F_SETOWN
154CRAY: long = 8 bytes, etc [class with alpha?]
155CGETENT
156SIGINFO
157SIGTSTP SIGTTOU SIGWINCH
158SPX?
159SYSV_TERMIO -- covered elsewhere, I hope
160TIOCEXT TIOCFLUSH TIOC[GS]WINSIZ
161NEWINIT: something about init cleaning up dead login processes [telnet?]
162PARENT_DOES_UTMP, too [telnet]
163VDISCARD
164VEOL/VEOL2/VLNEXT VREPRINT -- termios stuff?, and related...
165STREAMSPTY/STREAMSPTYEM
166AF_INET/AF_UNSPEC, PF_*
167ECHOCTL/ECHOKE
168F_ULOCK [?!]
169setpgrp/getpgrp() ONEARG business..
170HAVE_ALLOCA
171HAVE_GETUTENT
172HAVE_SYS_SELECT_H [irix!]
173HAVE_DIRENT [old 386mach has *direct.h*!]
174HAVE_SIGSET
175HAVE_VFORK_H and HAVE_VFORK
176HAVE_VHANGUP
177HAVE_VSPRINTF
178HAVE_IPTOS_*
179HAVE_STRCASECMP, STRNCASECMP
180HAVE_SYS_FCNTL_H
181HAVE_SYS_TIME_H
182HAVE_UTIMES
183NOTTYENT [?]
184HAVE_FCHMOD
185HAVE_GETUSERSHELL
186HAVE_SIGCONTEXT [stack hair, very machine-specific]
187YYLINENO?
188POSIX_SIGNALS
189POSIX_TERMIOS
190SETPROCTITLE -- breaks some places, like fbsd sendmail
191SIG* -- actual signal names? some are missing
192SIOCGIFCONF
193SO_BROADCAST
194SHMEM [krb tickets]
195VARARGS, or HAVE_VARARGS
196CBAUD
197... and B300, B9600, etc etc
198HAVE_BZERO vs memset/memcpy
199HAVE_SETVBUF
200HAVE_STRDUP
201HAVE_GETENV
202HAVE_STRSAVE
203HAVE_STBLKSIZE [stat?]
204HAVE_STREAM_H -- in sys/, ref sendmail 8.7 for IP_SRCROUTE
205FCHMOD
206INITGROUPS -- most machines seem to *have*
207SETREUID
208SNPRINTF
209SETPGRP semantics bsd vs. sys5 style
210
211There's also the issue about WHERE various .h files live, sys/ or otherwise.
212There's a BIG swamp lurking where network code of any sort lives.
213*/
214
215/* ======================== */
216/* System-specific sections */
217/* ======================== */
218
219/* By turning OFF various bits of the above, you can customize for
220 a given platform. Yes, we're ignoring the stock compiler predefines
221 and using our own plugged in via the Makefile. */
222
223/* DOS boxes, with MSC; you may need to adapt to a different compiler. */
224/* looks like later ones *do* have dirent.h, for example */
225#ifdef MSDOS
226#undef HAVE_FLOCK
227#undef HAVE_RANDOM
228#undef HAVE_LSTAT
229#undef HAVE_TERMIOS
230#undef UTMPX
231#undef HAVE_SYSINFO
232#undef HAVE_UNISTD_H
233#undef HAVE_DIRENT_H /* unless you have the k00l little wrapper from L5!! */
234#undef HAVE_STRINGS_H
235#undef HAVE_LASTLOG_H
236#undef HAVE_PATHS_H
237#undef HAVE_PARAM_H
238#undef HAVE_SYSMACROS_H
239#undef HAVE_SELECT_H
240#undef HAVE_TTYENT_H
241#endif /* MSDOS */
242
243/* buglix 4.x; dunno about 3.x on down. should be bsd4.2 */
244#ifdef ULTRIX
245#undef UTMPX
246#undef HAVE_PATHS_H
247#undef HAVE_SYSMACROS_H
248#undef HAVE_SELECT_H
249#endif /* buglix */
250
251/* some of this might still be broken on older sunoses */
252#ifdef SUNOS
253#undef VOID_MALLOC
254#undef UTMPX
255#undef HAVE_PATHS_H
256#undef HAVE_SELECT_H
257#endif /* sunos */
258
259/* "contact your vendor for a fix" */
260#ifdef SOLARIS
261/* has UTMPX */
262#undef HAVE_RANDOM
263#undef HAVE_SETPRIORITY
264#undef HAVE_STRINGS_H /* this is genuinely the case, go figure */
265#undef HAVE_PATHS_H
266#undef HAVE_SELECT_H
267#undef HAVE_TTYENT_H
268#endif /* SOLARIS */
269
270/* whatever aix variant MIT had at the time; 3.2.x?? */
271#ifdef AIX
272#undef UTMPX
273#undef HAVE_LASTLOG_H
274#define HAVE_LOGIN_H /* "special", in the educational sense */
275#endif /* aix */
276
277/* linux, which is trying as desperately as the gnu folks can to be
278 POSIXLY_CORRECT. I think I'm gonna hurl... */
279#ifdef LINUX
280#undef UTMPX
281#undef HAVE_SYSINFO
282#undef HAVE_SELECT_H
283#undef HAVE_TTYENT_H
284#endif /* linux */
285
286/* irix 5.x; may not be correct for earlier ones */
287#ifdef IRIX
288/* wow, does irix really have everything?! */
289#endif /* irix */
290
291/* osf on alphas */
292#ifdef OSF
293#undef UTMPX
294#undef HAVE_SELECT_H
295#endif /* osf */
296
297/* they's some FUCKED UP paths in this one! */
298#ifdef FREEBSD
299#undef UTMPX
300#undef HAVE_SYSINFO
301#undef HAVE_LASTLOG_H
302#undef HAVE_SYSMACROS_H
303#undef HAVE_SELECT_H /* actually a lie, but only for kernel */
304#endif /* freebsd */
305
306/* Originally from the sidewinder site, of all places, but subsequently
307 checked further under a more normal bsdi 2.0 */
308#ifdef BSDI
309#undef UTMPX
310#undef HAVE_LASTLOG_H
311#undef HAVE_SYSMACROS_H
312/* and their malloc.h was in sys/ ?! */
313#undef HAVE_SELECT_H
314#endif /* bsdi */
315
316/* netbsd/44lite, jives with amiga-netbsd from cactus */
317#ifdef NETBSD
318#undef UTMPX
319#undef HAVE_SYSINFO
320#undef HAVE_LASTLOG_H
321#undef HAVE_SELECT_H
322#endif /* netbsd */
323
324/* Hpux 9.0x, from BBN and various patches sent in */
325#ifdef HPUX
326#undef HAVE_RANDOM /* but *does* have ?rand48 -- need to consider.. */
327#undef HAVE_UTMPX
328#undef HAVE_LASTLOG_H /* has utmp/wtmp/btmp nonsense, and pututline() */
329#undef HAVE_PATHS_H
330#undef HAVE_SELECT_H
331#undef HAVE_TTYENT_H
332#endif /* hockeypux */
333
334/* Unixware [a loose definition of "unix", to be sure], 1.1.2 [at least]
335 from Brian Clapper. He wasn't sure about 2.0... */
336#ifdef UNIXWARE
337/* has UTMPX */
338#undef HAVE_SETPRIORITY
339/* NOTE: UnixWare does provide the BSD stuff, in "/usr/ucbinclude" (headers)
340 and "/usr/ucblib" (libraries). However, I've run into problems linking
341 stuff out of that version of the C library, when objects are also coming
342 out of the "regular" C library. My advice: Avoid the BSD compatibility
343 stuff wherever possible. Brian Clapper <bmc@telebase.com> */
344#undef HAVE_STRINGS_H
345#undef HAVE_PATHS_H
346#undef HAVE_TTYENT_H
347#endif /* UNIXWARE */
348
349/* A/UX 3.1.x from darieb@sandia.gov */
350#ifdef AUX
351#undef HAVE_RANDOM
352#undef HAVE_SELECT_H /* xxx: untested */
353#endif /* a/ux */
354
355/* NeXTSTEP 3.2 motorola mudge@l0pht.com xxx should also work with
356 white hardware and Sparc/HPPA. Should work with 3.3 too as it's
357 4.3 / 4.4 bsd wrapped around mach */
358#ifdef NEXT
359#undef UTMPX
360#undef HAVE_SELECT_X
361#endif /* NeXTSTEP 3.2 motorola */
362
363/* Make some "generic" assumptions if all else fails */
364#ifdef GENERIC
365#undef HAVE_FLOCK
366#if defined(SYSV) && (SYSV < 4) /* TW leftover: old SV doesnt have symlinks */
367#undef HAVE_LSTAT
368#endif /* old SYSV */
369#undef HAVE_TERMIOS
370#undef UTMPX
371#undef HAVE_PATHS_H
372#undef HAVE_SELECT_H
373#endif /* generic */
374
375/* ================ */
376#endif /* GENERIC_H */
377
diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1
new file mode 100644
index 0000000000..cffb9f637b
--- /dev/null
+++ b/src/usr.bin/nc/nc.1
@@ -0,0 +1,213 @@
1.\" $OpenBSD: nc.1,v 1.1 1996/09/05 08:55:32 deraadt Exp $
2.\"
3.\" Copyright (c) 1996 David Sacerdote
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. The name of the author may not be used to endorse or promote products
15.\" derived from this software without specific prior written permission
16.\"
17.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27.\"
28.Dd August 1, 1996
29.Dt nc 1
30.Sh NAME
31.Os
32.Nm nc
33.Nd
34Arbitrary tcp and udp connections and listens.
35.Pp
36.Nm nc
37.Op Fl e Ar command
38.Op Fl g Ar intermediates
39.Op Fl G Ar hopcount
40.Op Fl i Ar interval
41.Op Fl lnrtuvz
42.Op Fl o Ar filename
43.Op Fl p Ar source port
44.Op Fl s Ar ip address
45.Op Fl w Ar timeout
46.Op Ar hostname
47.Op Ar port[s...]
48.Pp
49.Sh DESCRIPTION
50The
51.Nm nc
52(or
53.Nm netcat )
54utility is used for just about anything under the sun
55involving TCP or UDP. It can open tcp connections, send udp packets,
56listen on arbitrary tcp and udp ports, do port scanning, and source
57routing. Unlike
58.Xr telnet 1 ,
59.Nm nc
60scripts nicely, and separates error messages onto standard error instead
61of sending them to standard output, as
62.Xr telnet 1
63does with some.
64.Pp
65Destination ports can be single integers, names as listed in
66.Xr /etc/services 5 ,
67or ranges. Ranges are in the form nn-mm, and several separate ports and/or
68ranges may be specified on the command line.
69.Pp
70Common uses include:
71.Bl -bullet
72.It
73simple tcp proxies
74.It
75shell\-script based http clients and servers
76.It
77network daemon testing
78.It
79source routing based connectivity testing
80.It
81and much, much more
82.El
83.Pp
84The options are as follows:
85.Bl -tag -width Ds
86.It Fl e Ar command
87Execute the specified command, using data from the network for stdin,
88and sending stdout and stderr to the network. This option is only present if
89.Nm nc
90was compiled with the GAPING_SECURITY_HOLE compile time option, since it
91allows users to make arbitrary programs available to anyone on the network.
92.It Fl g Ar intermediate-host
93Specifies a hop along a loose source routed path. Can be used more than
94once to build a chain of hop points.
95.It Fl G Ar pointer
96Positions the "hop counter" within the list of machines in the path of
97a source routed packet. Must be a multiple of 4.
98.It Fl i Ar seconds
99Specifies a delay time interval between lines of text sent and received.
100Also causes a delay time between connections to multiple ports.
101.It Fl l
102Is used to specify that
103.Nm nc
104should listen for an incoming connection, rather than initiate a
105connection to a remote host. Any hostname/ip address and port arguments
106restrict the source of inbound connections to only that address and
107source port.
108.It Fl n
109Do not do DNS lookups on any of the specified addresses or hostnames, or
110names of port numbers from /etc/services.
111.It Fl o Ar filename
112Create a hexadecimal log of data transferred in the specified file.
113Each line begins with < or >. < means "from the net" and > means
114"to the net."
115.It Fl p Ar port
116Specifies the source port
117.Nm nc
118should use, subject to privilege restrictions and availability.
119.It Fl r
120Specified that source and/or destination ports should be chosen semi-randomly
121instead of sequentially within a range or in the order that the
122system assigns.
123.It Fl s Ar hostname/ip-address
124Specifies the ip of the interface which is used to send the packets.
125On some platforms, this can be used for udp spoofing by using ifconfig
126to bring up a dummy interface with the desired source ip address.
127.It Fl t
128Causes
129.Nm nc
130to send RFC854 DON'T and WON'T responses to RFC854 DO
131and WILL requests. This makes it possible to use
132.Nm nc
133to script telnet sessions. The presence of this option can be
134enabled or disabled as a compile-time option.
135.It Fl u
136Use UDP instead of TCP.
137On most platforms,
138.Nm nc
139will behave as if a connection is established until it receives an
140ICMP packet indicating that there is no program listening to what it
141sends.
142.It Fl v
143Verbose. Cause
144.Nm nc
145to display connection information. Using \-v
146more than once will cause
147.Nm nc
148to become even more verbose.
149.It Fl w Ar timeout
150Specifies the number of seconds
151.Nm nc
152should wait before deciding that
153an attempt to establish a connection is hopeless.
154Also used to specify how long to wait for more network data after standard
155input closes.
156.It Fl z
157Specifies that
158.Nm nc
159should just scan for listening
160daemons, without sending any data to them. Diagnostic messages about refused
161connections will not be
162displayed unless \-v is specified twice.
163.Sh EXAMPLES
164.Pp
165.Bl -tag -width x
166.It Li "nc"
167Wait for the user to type what would normally be command-line
168arguments in at stdin.
169.It Li "nc example.host 42"
170Open a TCP connection to port 42 of example.host. If the connection
171fails, do not display any error messages, but simply exit.
172.It Li "nc -p 31337 example.host 42"
173Open a TCP connection to port 42 of example.host, and use port 31337
174as the source port.
175.It Li "nc -w 5 example.host 42"
176Open a tcp connection to port 42 of example.host, and time out after
177five seconds while attempting to connect.
178.It Li "nc -u example.host 53"
179Send any data from stdin
180to UDP port 53 of example.host, and display any data returned.
181.It Li "nc -s 10.1.2.3 example.host 42"
182Open a tcp connection to port 42 of example.host using 10.1.2.3 as the
183ip for the local end of the connection.
184.It Li "nc -v example.host 42"
185Open a tcp connection to port 42 of example.host, displaying some
186diagnostic messages on stderr.
187.It Li "nc -v -v example.host 42"
188Open a tcp connection to port 42 of example.host, displaying all
189diagnostic messages on stderr.
190.It Li "nc -v -z example.host 20-30"
191Attempt to open tcp connections to ports 20 through 30 of
192example.host, and report which ones
193.Nm nc
194was able to connect to.
195.It Li "nc -v -u -z -w 3 example.host 20-30"
196Send udp packets to ports 20-30 of example.host, and report which ones
197did not respond with an ICMP packet after three seconds.
198.It Li "nc -l -p 3000"
199Listen on TCP port 3000, and once there is a connection, send stdin to
200the remote host, and send data from the remote host to stdout.
201.It Li "echo foobar | nc example.host 1000"
202Connect to port 1000 of example.host, send the string "foobar"
203followed by a newline, and move data from port 1000 of example.host to
204stdout until example.host closes the connection.
205.El
206.Sh SEE ALSO
207.Xr telnet 1 ,
208.Xr cat 1 ,
209and the
210.Nm netcat
211.Pa README
212.Sh AUTHOR
213*Hobbit* [hobbit@avian.org]
diff --git a/src/usr.bin/nc/netcat.blurb b/src/usr.bin/nc/netcat.blurb
new file mode 100644
index 0000000000..2c540ad9dc
--- /dev/null
+++ b/src/usr.bin/nc/netcat.blurb
@@ -0,0 +1,61 @@
1Netcat 1.10 is an updated release of Netcat, a simple Unix utility which reads
2and writes data across network connections using TCP or UDP protocol. It is
3designed to be a reliable "back-end" tool that can be used directly or easily
4driven by other programs and scripts. At the same time it is a feature-rich
5network debugging and exploration tool, since it can create almost any kind of
6connection you would need and has several interesting built-in capabilities.
7
8Some of netcat's major features are:
9
10 Outbound or inbound connections, TCP or UDP, to or from any ports
11 Full DNS forward/reverse checking, with appropriate warnings
12 Ability to use any local source port
13 Ability to use any locally-configured network source address
14 Built-in port-scanning capabilities, with randomizer
15 Built-in loose source-routing capability
16 Can read command line arguments from standard input
17 Slow-send mode, one line every N seconds
18 Hex dump of transmitted and received data
19 Optional ability to let another program service established connections
20 Optional telnet-options responder
21
22A very short list of potential uses:
23
24 Script backends
25 Scanning ports and inventorying services, automated probes
26 Backup handlers
27 File transfers
28 Server testing, simulation, debugging, and hijacking
29 Firewall testing
30 Proxy gatewaying
31 Network performance testing
32 Address spoofing tests
33 Protecting X servers
34 1001 other uses you'll likely come up with
35
36Changes between the 1.00 release and this release:
37
38 Better portability -- updated generic.h and Makefile [thanx folks!]
39 Indication of local-end interface address on inbound connections
40 That's *Dave* Borman's telnet, not Paul Borman...
41 Better indication of DNS errors
42 Total byte counts printed if -v -v is used
43 A bunch of front-end driver companion programs and scripts
44 Better handling of stdin arguments-plus-data
45 Hex-dump feature
46 Telnet responder
47 Program exec works inbound or outbound now
48
49Netcat and the associated package is a product of Avian Research, and is freely
50available in full source form with no restrictions save an obligation to give
51credit where due. Get it via anonymous FTP at avian.org:/src/hacks/nc110.tgz
52which is a gzipped tar file and not to be confused with its version 1.00
53precursor, nc100.tgz. Other distribution formats can be accomodated upon
54request. Netcat is also mirrored at the following [faster] sites:
55
56 zippy.telcom.arizona.edu:/pub/mirrors/avian.org/hacks/nc110.tgz
57 ftp.sterling.com:/mirrors/avian.org/src/hacks/nc110.tgz
58 coast.cs.purdue.edu:/pub/tools/unix/netcat/nc110.tgz
59 ftp.rge.com:/pub/security/coast/mirrors/avian.org/netcat/nc110.tgz
60
61_H* 960320
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
new file mode 100644
index 0000000000..5ceb4f1d2f
--- /dev/null
+++ b/src/usr.bin/nc/netcat.c
@@ -0,0 +1,1668 @@
1/* Netcat 1.10 RELEASE 960320
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 conditional includes:
13 includes:
14 handy defines:
15 globals:
16 malloced globals:
17 cmd-flag globals:
18 support routines:
19 readwrite select loop:
20 main:
21
22 bluesky:
23 parse ranges of IP address as well as ports, perhaps
24 RAW mode!
25 backend progs to grab a pty and look like a real telnetd?!
26 backend progs to do various encryption modes??!?!
27*/
28
29#include "generic.h" /* same as with L5, skey, etc */
30
31/* conditional includes -- a very messy section which you may have to dink
32 for your own architecture [and please send diffs...]: */
33/* #undef _POSIX_SOURCE /* might need this for something? */
34#define HAVE_BIND /* ASSUMPTION -- seems to work everywhere! */
35#define HAVE_HELP /* undefine if you dont want the help text */
36/* #define ANAL /* if you want case-sensitive DNS matching */
37
38#ifdef HAVE_STDLIB_H
39#include <stdlib.h>
40#else
41#include <malloc.h>
42#endif
43#ifdef HAVE_SELECT_H /* random SV variants need this */
44#include <sys/select.h>
45#endif
46
47/* have to do this *before* including types.h. xxx: Linux still has it wrong */
48#ifdef FD_SETSIZE /* should be in types.h, butcha never know. */
49#undef FD_SETSIZE /* if we ever need more than 16 active */
50#endif /* fd's, something is horribly wrong! */
51#define FD_SETSIZE 16 /* <-- this'll give us a long anyways, wtf */
52#include <sys/types.h> /* *now* do it. Sigh, this is broken */
53
54#ifdef HAVE_RANDOM /* aficionados of ?rand48() should realize */
55#define SRAND srandom /* that this doesn't need *strong* random */
56#define RAND random /* numbers just to mix up port numbers!! */
57#else
58#define SRAND srand
59#define RAND rand
60#endif /* HAVE_RANDOM */
61
62/* includes: */
63#include <sys/time.h> /* timeval, time_t */
64#include <setjmp.h> /* jmp_buf et al */
65#include <sys/socket.h> /* basics, SO_ and AF_ defs, sockaddr, ... */
66#include <netinet/in.h> /* sockaddr_in, htons, in_addr */
67#include <netinet/in_systm.h> /* misc crud that netinet/ip.h references */
68#include <netinet/ip.h> /* IPOPT_LSRR, header stuff */
69#include <netdb.h> /* hostent, gethostby*, getservby* */
70#include <arpa/inet.h> /* inet_ntoa */
71#include <stdio.h>
72#include <string.h> /* strcpy, strchr, yadda yadda */
73#include <errno.h>
74#include <signal.h>
75#include <fcntl.h> /* O_WRONLY et al */
76
77/* handy stuff: */
78#define SA struct sockaddr /* socket overgeneralization braindeath */
79#define SAI struct sockaddr_in /* ... whoever came up with this model */
80#define IA struct in_addr /* ... should be taken out and shot, */
81 /* ... not that TLI is any better. sigh.. */
82#define SLEAZE_PORT 31337 /* for UDP-scan RTT trick, change if ya want */
83#define USHORT unsigned short /* use these for options an' stuff */
84#define BIGSIZ 8192 /* big buffers */
85
86#ifndef INADDR_NONE
87#define INADDR_NONE 0xffffffff
88#endif
89#ifdef MAXHOSTNAMELEN
90#undef MAXHOSTNAMELEN /* might be too small on aix, so fix it */
91#endif
92#define MAXHOSTNAMELEN 256
93
94struct host_poop {
95 char name[MAXHOSTNAMELEN]; /* dns name */
96 char addrs[8][24]; /* ascii-format IP addresses */
97 struct in_addr iaddrs[8]; /* real addresses: in_addr.s_addr: ulong */
98};
99#define HINF struct host_poop
100
101struct port_poop {
102 char name [64]; /* name in /etc/services */
103 char anum [8]; /* ascii-format number */
104 USHORT num; /* real host-order number */
105};
106#define PINF struct port_poop
107
108/* globals: */
109jmp_buf jbuf; /* timer crud */
110int jval = 0; /* timer crud */
111int netfd = -1;
112int ofd = 0; /* hexdump output fd */
113static char unknown[] = "(UNKNOWN)";
114static char p_tcp[] = "tcp"; /* for getservby* */
115static char p_udp[] = "udp";
116#ifdef HAVE_BIND
117extern int h_errno;
118/* stolen almost wholesale from bsd herror.c */
119static char * h_errs[] = {
120 "Error 0", /* but we *don't* use this */
121 "Unknown host", /* 1 HOST_NOT_FOUND */
122 "Host name lookup failure", /* 2 TRY_AGAIN */
123 "Unknown server error", /* 3 NO_RECOVERY */
124 "No address associated with name", /* 4 NO_ADDRESS */
125};
126#else
127int h_errno; /* just so we *do* have it available */
128#endif /* HAVE_BIND */
129int gatesidx = 0; /* LSRR hop count */
130int gatesptr = 4; /* initial LSRR pointer, settable */
131USHORT Single = 1; /* zero if scanning */
132unsigned int insaved = 0; /* stdin-buffer size for multi-mode */
133unsigned int wrote_out = 0; /* total stdout bytes */
134unsigned int wrote_net = 0; /* total net bytes */
135static char wrote_txt[] = " sent %d, rcvd %d";
136static char hexnibs[20] = "0123456789abcdef ";
137
138/* will malloc up the following globals: */
139struct timeval * timer1 = NULL;
140struct timeval * timer2 = NULL;
141SAI * lclend = NULL; /* sockaddr_in structs */
142SAI * remend = NULL;
143HINF ** gates = NULL; /* LSRR hop hostpoop */
144char * optbuf = NULL; /* LSRR or sockopts */
145char * bigbuf_in; /* data buffers */
146char * bigbuf_net;
147fd_set * ding1; /* for select loop */
148fd_set * ding2;
149PINF * portpoop = NULL; /* for getportpoop / getservby* */
150unsigned char * stage = NULL; /* hexdump line buffer */
151
152/* global cmd flags: */
153USHORT o_alla = 0;
154unsigned int o_interval = 0;
155USHORT o_listen = 0;
156USHORT o_nflag = 0;
157USHORT o_wfile = 0;
158USHORT o_random = 0;
159USHORT o_udpmode = 0;
160USHORT o_verbose = 0;
161unsigned int o_wait = 0;
162USHORT o_zero = 0;
163/* o_tn in optional section */
164
165/* Debug macro: squirt whatever message and sleep a bit so we can see it go
166 by. need to call like Debug ((stuff)) [with no ; ] so macro args match!
167 Beware: writes to stdOUT... */
168#ifdef DEBUG
169#define Debug(x) printf x; printf ("\n"); fflush (stdout); sleep (1);
170#else
171#define Debug(x) /* nil... */
172#endif
173
174
175/* support routines -- the bulk of this thing. Placed in such an order that
176 we don't have to forward-declare anything: */
177
178/* holler :
179 fake varargs -- need to do this way because we wind up calling through
180 more levels of indirection than vanilla varargs can handle, and not all
181 machines have vfprintf/vsyslog/whatever! 6 params oughta be enough. */
182void holler (str, p1, p2, p3, p4, p5, p6)
183 char * str;
184 char * p1, * p2, * p3, * p4, * p5, * p6;
185{
186 if (o_verbose) {
187 fprintf (stderr, str, p1, p2, p3, p4, p5, p6);
188#ifdef HAVE_BIND
189 if (h_errno) { /* if host-lookup variety of error ... */
190 if (h_errno > 4) /* oh no you don't, either */
191 fprintf (stderr, "preposterous h_errno: %d", h_errno);
192 else
193 fprintf (stderr, h_errs[h_errno]); /* handle it here */
194 h_errno = 0; /* and reset for next call */
195 }
196#endif
197 if (errno) { /* this gives funny-looking messages, but */
198 perror (" "); /* it's more portable than sys_errlist[]... */
199 } else /* xxx: do something better? */
200 fprintf (stderr, "\n");
201 fflush (stderr);
202 }
203} /* holler */
204
205/* bail :
206 error-exit handler, callable from anywhere */
207void bail (str, p1, p2, p3, p4, p5, p6)
208 char * str;
209 char * p1, * p2, * p3, * p4, * p5, * p6;
210{
211 o_verbose = 1;
212 holler (str, p1, p2, p3, p4, p5, p6);
213 close (netfd);
214 sleep (1);
215 exit (1);
216} /* bail */
217
218/* catch :
219 no-brainer interrupt handler */
220void catch ()
221{
222 errno = 0;
223 if (o_verbose > 1) /* normally we don't care */
224 bail (wrote_txt, wrote_net, wrote_out);
225 bail (" punt!");
226}
227
228/* timeout and other signal handling cruft */
229void tmtravel ()
230{
231 signal (SIGALRM, SIG_IGN);
232 alarm (0);
233 if (jval == 0)
234 bail ("spurious timer interrupt!");
235 longjmp (jbuf, jval);
236}
237
238/* arm :
239 set the timer. Zero secs arg means unarm */
240void arm (num, secs)
241 unsigned int num;
242 unsigned int secs;
243{
244 if (secs == 0) { /* reset */
245 signal (SIGALRM, SIG_IGN);
246 alarm (0);
247 jval = 0;
248 } else { /* set */
249 signal (SIGALRM, tmtravel);
250 alarm (secs);
251 jval = num;
252 } /* if secs */
253} /* arm */
254
255/* Hmalloc :
256 malloc up what I want, rounded up to *4, and pre-zeroed. Either succeeds
257 or bails out on its own, so that callers don't have to worry about it. */
258char * Hmalloc (size)
259 unsigned int size;
260{
261 unsigned int s = (size + 4) & 0xfffffffc; /* 4GB?! */
262 char * p = malloc (s);
263 if (p != NULL)
264 memset (p, 0, s);
265 else
266 bail ("Hmalloc %d failed", s);
267 return (p);
268} /* Hmalloc */
269
270/* findline :
271 find the next newline in a buffer; return inclusive size of that "line",
272 or the entire buffer size, so the caller knows how much to then write().
273 Not distinguishing \n vs \r\n for the nonce; it just works as is... */
274unsigned int findline (buf, siz)
275 char * buf;
276 unsigned int siz;
277{
278 register char * p;
279 register int x;
280 if (! buf) /* various sanity checks... */
281 return (0);
282 if (siz > BIGSIZ)
283 return (0);
284 x = siz;
285 for (p = buf; x > 0; x--) {
286 if (*p == '\n') {
287 x = (int) (p - buf);
288 x++; /* 'sokay if it points just past the end! */
289Debug (("findline returning %d", x))
290 return (x);
291 }
292 p++;
293 } /* for */
294Debug (("findline returning whole thing: %d", siz))
295 return (siz);
296} /* findline */
297
298/* comparehosts :
299 cross-check the host_poop we have so far against new gethostby*() info,
300 and holler about mismatches. Perhaps gratuitous, but it can't hurt to
301 point out when someone's DNS is fukt. Returns 1 if mismatch, in case
302 someone else wants to do something about it. */
303int comparehosts (poop, hp)
304 HINF * poop;
305 struct hostent * hp;
306{
307 errno = 0;
308 h_errno = 0;
309/* The DNS spec is officially case-insensitive, but for those times when you
310 *really* wanna see any and all discrepancies, by all means define this. */
311#ifdef ANAL
312 if (strcmp (poop->name, hp->h_name) != 0) { /* case-sensitive */
313#else
314 if (strcasecmp (poop->name, hp->h_name) != 0) { /* normal */
315#endif
316 holler ("DNS fwd/rev mismatch: %s != %s", poop->name, hp->h_name);
317 return (1);
318 }
319 return (0);
320/* ... do we need to do anything over and above that?? */
321} /* comparehosts */
322
323/* gethostpoop :
324 resolve a host 8 ways from sunday; return a new host_poop struct with its
325 info. The argument can be a name or [ascii] IP address; it will try its
326 damndest to deal with it. "numeric" governs whether we do any DNS at all,
327 and we also check o_verbose for what's appropriate work to do. */
328HINF * gethostpoop (name, numeric)
329 char * name;
330 USHORT numeric;
331{
332 struct hostent * hostent;
333 struct in_addr iaddr;
334 register HINF * poop = NULL;
335 register int x;
336
337/* I really want to strangle the twit who dreamed up all these sockaddr and
338 hostent abstractions, and then forced them all to be incompatible with
339 each other so you *HAVE* to do all this ridiculous casting back and forth.
340 If that wasn't bad enough, all the doc insists on referring to local ports
341 and addresses as "names", which makes NO sense down at the bare metal.
342
343 What an absolutely horrid paradigm, and to think of all the people who
344 have been wasting significant amounts of time fighting with this stupid
345 deliberate obfuscation over the last 10 years... then again, I like
346 languages wherein a pointer is a pointer, what you put there is your own
347 business, the compiler stays out of your face, and sheep are nervous.
348 Maybe that's why my C code reads like assembler half the time... */
349
350/* If we want to see all the DNS stuff, do the following hair --
351 if inet_addr, do reverse and forward with any warnings; otherwise try
352 to do forward and reverse with any warnings. In other words, as long
353 as we're here, do a complete DNS check on these clowns. Yes, it slows
354 things down a bit for a first run, but once it's cached, who cares? */
355
356 errno = 0;
357 h_errno = 0;
358 if (name)
359 poop = (HINF *) Hmalloc (sizeof (HINF));
360 if (! poop)
361 bail ("gethostpoop fuxored");
362 strcpy (poop->name, unknown); /* preload it */
363/* see wzv:workarounds.c for dg/ux return-a-struct inet_addr lossage */
364 iaddr.s_addr = inet_addr (name);
365
366 if (iaddr.s_addr == INADDR_NONE) { /* here's the great split: names... */
367 if (numeric)
368 bail ("Can't parse %s as an IP address", name);
369 hostent = gethostbyname (name);
370 if (! hostent)
371/* failure to look up a name is fatal, since we can't do anything with it */
372 bail ("%s: forward host lookup failed: ", name);
373 strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
374 for (x = 0; hostent->h_addr_list[x] && (x < 8); x++) {
375 memcpy (&poop->iaddrs[x], hostent->h_addr_list[x], sizeof (IA));
376 strncpy (poop->addrs[x], inet_ntoa (poop->iaddrs[x]),
377 sizeof (poop->addrs[0]));
378 } /* for x -> addrs, part A */
379 if (! o_verbose) /* if we didn't want to see the */
380 return (poop); /* inverse stuff, we're done. */
381/* do inverse lookups in separate loop based on our collected forward addrs,
382 since gethostby* tends to crap into the same buffer over and over */
383 for (x = 0; poop->iaddrs[x].s_addr && (x < 8); x++) {
384 hostent = gethostbyaddr ((char *)&poop->iaddrs[x],
385 sizeof (IA), AF_INET);
386 if ((! hostent) || (! hostent-> h_name))
387 holler ("Warning: inverse host lookup failed for %s: ",
388 poop->addrs[x]);
389 else
390 (void) comparehosts (poop, hostent);
391 } /* for x -> addrs, part B */
392
393 } else { /* not INADDR_NONE: numeric addresses... */
394 memcpy (poop->iaddrs, &iaddr, sizeof (IA));
395 strncpy (poop->addrs[0], inet_ntoa (iaddr), sizeof (poop->addrs));
396 if (numeric) /* if numeric-only, we're done */
397 return (poop);
398 if (! o_verbose) /* likewise if we don't want */
399 return (poop); /* the full DNS hair */
400 hostent = gethostbyaddr ((char *) &iaddr, sizeof (IA), AF_INET);
401/* numeric or not, failure to look up a PTR is *not* considered fatal */
402 if (! hostent)
403 holler ("%s: inverse host lookup failed: ", name);
404 else {
405 strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
406 hostent = gethostbyname (poop->name);
407 if ((! hostent) || (! hostent->h_addr_list[0]))
408 holler ("Warning: forward host lookup failed for %s: ",
409 poop->name);
410 else
411 (void) comparehosts (poop, hostent);
412 } /* if hostent */
413 } /* INADDR_NONE Great Split */
414
415/* whatever-all went down previously, we should now have a host_poop struct
416 with at least one IP address in it. */
417 h_errno = 0;
418 return (poop);
419} /* gethostpoop */
420
421/* getportpoop :
422 Same general idea as gethostpoop -- look up a port in /etc/services, fill
423 in global port_poop, but return the actual port *number*. Pass ONE of:
424 pstring to resolve stuff like "23" or "exec";
425 pnum to reverse-resolve something that's already a number.
426 If o_nflag is on, fill in what we can but skip the getservby??? stuff.
427 Might as well have consistent behavior here, and it *is* faster. */
428USHORT getportpoop (pstring, pnum)
429 char * pstring;
430 unsigned int pnum;
431{
432 struct servent * servent;
433 register int x;
434 register int y;
435 char * whichp = p_tcp;
436 if (o_udpmode)
437 whichp = p_udp;
438 portpoop->name[0] = '?'; /* fast preload */
439 portpoop->name[1] = '\0';
440
441/* case 1: reverse-lookup of a number; placed first since this case is much
442 more frequent if we're scanning */
443 if (pnum) {
444 if (pstring) /* one or the other, pleeze */
445 return (0);
446 x = pnum;
447 if (o_nflag) /* go faster, skip getservbyblah */
448 goto gp_finish;
449 y = htons (x); /* gotta do this -- see Fig.1 below */
450 servent = getservbyport (y, whichp);
451 if (servent) {
452 y = ntohs (servent->s_port);
453 if (x != y) /* "never happen" */
454 holler ("Warning: port-bynum mismatch, %d != %d", x, y);
455 strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name));
456 } /* if servent */
457 goto gp_finish;
458 } /* if pnum */
459
460/* case 2: resolve a string, but we still give preference to numbers instead
461 of trying to resolve conflicts. None of the entries in *my* extensive
462 /etc/services begins with a digit, so this should "always work" unless
463 you're at 3com and have some company-internal services defined... */
464 if (pstring) {
465 if (pnum) /* one or the other, pleeze */
466 return (0);
467 x = atoi (pstring);
468 if (x)
469 return (getportpoop (NULL, x)); /* recurse for numeric-string-arg */
470 if (o_nflag) /* can't use names! */
471 return (0);
472 servent = getservbyname (pstring, whichp);
473 if (servent) {
474 strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name));
475 x = ntohs (servent->s_port);
476 goto gp_finish;
477 } /* if servent */
478 } /* if pstring */
479
480 return (0); /* catches any problems so far */
481
482/* Obligatory netdb.h-inspired rant: servent.s_port is supposed to be an int.
483 Despite this, we still have to treat it as a short when copying it around.
484 Not only that, but we have to convert it *back* into net order for
485 getservbyport to work. Manpages generally aren't clear on all this, but
486 there are plenty of examples in which it is just quietly done. More BSD
487 lossage... since everything getserv* ever deals with is local to our own
488 host, why bother with all this network-order/host-order crap at all?!
489 That should be saved for when we want to actually plug the port[s] into
490 some real network calls -- and guess what, we have to *re*-convert at that
491 point as well. Fuckheads. */
492
493gp_finish:
494/* Fall here whether or not we have a valid servent at this point, with
495 x containing our [host-order and therefore useful, dammit] port number */
496 sprintf (portpoop->anum, "%d", x); /* always load any numeric specs! */
497 portpoop->num = (x & 0xffff); /* ushort, remember... */
498 return (portpoop->num);
499} /* getportpoop */
500
501/* nextport :
502 Come up with the next port to try, be it random or whatever. "block" is
503 a ptr to randports array, whose bytes [so far] carry these meanings:
504 0 ignore
505 1 to be tested
506 2 tested [which is set as we find them here]
507 returns a USHORT random port, or 0 if all the t-b-t ones are used up. */
508USHORT nextport (block)
509 char * block;
510{
511 register unsigned int x;
512 register unsigned int y;
513
514 y = 70000; /* high safety count for rnd-tries */
515 while (y > 0) {
516 x = (RAND() & 0xffff);
517 if (block[x] == 1) { /* try to find a not-done one... */
518 block[x] = 2;
519 break;
520 }
521 x = 0; /* bummer. */
522 y--;
523 } /* while y */
524 if (x)
525 return (x);
526
527 y = 65535; /* no random one, try linear downsearch */
528 while (y > 0) { /* if they're all used, we *must* be sure! */
529 if (block[y] == 1) {
530 block[y] = 2;
531 break;
532 }
533 y--;
534 } /* while y */
535 if (y)
536 return (y); /* at least one left */
537
538 return (0); /* no more left! */
539} /* nextport */
540
541/* loadports :
542 set "to be tested" indications in BLOCK, from LO to HI. Almost too small
543 to be a separate routine, but makes main() a little cleaner... */
544void loadports (block, lo, hi)
545 char * block;
546 USHORT lo;
547 USHORT hi;
548{
549 USHORT x;
550
551 if (! block)
552 bail ("loadports: no block?!");
553 if ((! lo) || (! hi))
554 bail ("loadports: bogus values %d, %d", lo, hi);
555 x = hi;
556 while (lo <= x) {
557 block[x] = 1;
558 x--;
559 }
560} /* loadports */
561
562#ifdef GAPING_SECURITY_HOLE
563char * pr00gie = NULL; /* global ptr to -e arg */
564
565/* doexec :
566 fiddle all the file descriptors around, and hand off to another prog. Sort
567 of like a one-off "poor man's inetd". This is the only section of code
568 that would be security-critical, which is why it's ifdefed out by default.
569 Use at your own hairy risk; if you leave shells lying around behind open
570 listening ports you deserve to lose!! */
571doexec (fd)
572 int fd;
573{
574 register char * p;
575
576 dup2 (fd, 0); /* the precise order of fiddlage */
577 close (fd); /* is apparently crucial; this is */
578 dup2 (0, 1); /* swiped directly out of "inetd". */
579 dup2 (0, 2);
580 p = strrchr (pr00gie, '/'); /* shorter argv[0] */
581 if (p)
582 p++;
583 else
584 p = pr00gie;
585Debug (("gonna exec %s as %s...", pr00gie, p))
586 execl (pr00gie, p, NULL);
587 bail ("exec %s failed", pr00gie); /* this gets sent out. Hmm... */
588} /* doexec */
589#endif /* GAPING_SECURITY_HOLE */
590
591/* doconnect :
592 do all the socket stuff, and return an fd for one of
593 an open outbound TCP connection
594 a UDP stub-socket thingie
595 with appropriate socket options set up if we wanted source-routing, or
596 an unconnected TCP or UDP socket to listen on.
597 Examines various global o_blah flags to figure out what-all to do. */
598int doconnect (rad, rp, lad, lp)
599 IA * rad;
600 USHORT rp;
601 IA * lad;
602 USHORT lp;
603{
604 register int nnetfd;
605 register int rr;
606 int x, y;
607 errno = 0;
608
609/* grab a socket; set opts */
610newskt:
611 if (o_udpmode)
612 nnetfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
613 else
614 nnetfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
615 if (nnetfd < 0)
616 bail ("Can't get socket");
617 if (nnetfd == 0) /* if stdin was closed this might *be* 0, */
618 goto newskt; /* so grab another. See text for why... */
619 x = 1;
620 rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x));
621 if (rr == -1)
622 holler ("nnetfd reuseaddr failed"); /* ??? */
623#ifdef SO_REUSEPORT /* doesnt exist everywhere... */
624 rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
625 if (rr == -1)
626 holler ("nnetfd reuseport failed"); /* ??? */
627#endif
628#if 0
629/* If you want to screw with RCVBUF/SNDBUF, do it here. Liudvikas Bukys at
630 Rochester sent this example, which would involve YET MORE options and is
631 just archived here in case you want to mess with it. o_xxxbuf are global
632 integers set in main() getopt loop, and check for rr == 0 afterward. */
633 rr = setsockopt(nnetfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf);
634 rr = setsockopt(nnetfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf);
635#endif
636
637 /* fill in all the right sockaddr crud */
638 lclend->sin_family = AF_INET;
639
640/* fill in all the right sockaddr crud */
641 lclend->sin_family = AF_INET;
642 remend->sin_family = AF_INET;
643
644/* if lad/lp, do appropriate binding */
645 if (lad)
646 memcpy (&lclend->sin_addr.s_addr, lad, sizeof (IA));
647 if (lp)
648 lclend->sin_port = htons (lp);
649 rr = 0;
650 if (lad || lp) {
651 x = (int) lp;
652/* try a few times for the local bind, a la ftp-data-port... */
653 for (y = 4; y > 0; y--) {
654 rr = bind (nnetfd, (SA *)lclend, sizeof (SA));
655 if (rr == 0)
656 break;
657 if (errno != EADDRINUSE)
658 break;
659 else {
660 holler ("retrying local %s:%d", inet_ntoa (lclend->sin_addr), lp);
661 sleep (2);
662 errno = 0; /* clear from sleep */
663 } /* if EADDRINUSE */
664 } /* for y counter */
665 } /* if lad or lp */
666 if (rr)
667 bail ("Can't grab %s:%d with bind",
668 inet_ntoa(lclend->sin_addr), lp);
669
670 if (o_listen)
671 return (nnetfd); /* thanks, that's all for today */
672
673 memcpy (&remend->sin_addr.s_addr, rad, sizeof (IA));
674 remend->sin_port = htons (rp);
675
676/* rough format of LSRR option and explanation of weirdness.
677Option comes after IP-hdr dest addr in packet, padded to *4, and ihl > 5.
678IHL is multiples of 4, i.e. real len = ip_hl << 2.
679 type 131 1 ; 0x83: copied, option class 0, number 3
680 len 1 ; of *whole* option!
681 pointer 1 ; nxt-hop-addr; 1-relative, not 0-relative
682 addrlist... var ; 4 bytes per hop-addr
683 pad-to-32 var ; ones, i.e. "NOP"
684
685If we want to route A -> B via hops C and D, we must add C, D, *and* B to the
686options list. Why? Because when we hand the kernel A -> B with list C, D, B
687the "send shuffle" inside the kernel changes it into A -> C with list D, B and
688the outbound packet gets sent to C. If B wasn't also in the hops list, the
689final destination would have been lost at this point.
690
691When C gets the packet, it changes it to A -> D with list C', B where C' is
692the interface address that C used to forward the packet. This "records" the
693route hop from B's point of view, i.e. which address points "toward" B. This
694is to make B better able to return the packets. The pointer gets bumped by 4,
695so that D does the right thing instead of trying to forward back to C.
696
697When B finally gets the packet, it sees that the pointer is at the end of the
698LSRR list and is thus "completed". B will then try to use the packet instead
699of forwarding it, i.e. deliver it up to some application.
700
701Note that by moving the pointer yourself, you could send the traffic directly
702to B but have it return via your preconstructed source-route. Playing with
703this and watching "tcpdump -v" is the best way to understand what's going on.
704
705Only works for TCP in BSD-flavor kernels. UDP is a loss; udp_input calls
706stripoptions() early on, and the code to save the srcrt is notdef'ed.
707Linux is also still a loss at 1.3.x it looks like; the lsrr code is { }...
708*/
709
710/* if any -g arguments were given, set up source-routing. We hit this after
711 the gates are all looked up and ready to rock, any -G pointer is set,
712 and gatesidx is now the *number* of hops */
713 if (gatesidx) { /* if we wanted any srcrt hops ... */
714/* don't even bother compiling if we can't do IP options here! */
715#ifdef IP_OPTIONS
716 if (! optbuf) { /* and don't already *have* a srcrt set */
717 char * opp; /* then do all this setup hair */
718 optbuf = Hmalloc (48);
719 opp = optbuf;
720 *opp++ = IPOPT_LSRR; /* option */
721 *opp++ = (char)
722 (((gatesidx + 1) * sizeof (IA)) + 3) & 0xff; /* length */
723 *opp++ = gatesptr; /* pointer */
724/* opp now points at first hop addr -- insert the intermediate gateways */
725 for ( x = 0; x < gatesidx; x++) {
726 memcpy (opp, gates[x]->iaddrs, sizeof (IA));
727 opp += sizeof (IA);
728 }
729/* and tack the final destination on the end [needed!] */
730 memcpy (opp, rad, sizeof (IA));
731 opp += sizeof (IA);
732 *opp = IPOPT_NOP; /* alignment filler */
733 } /* if empty optbuf */
734/* calculate length of whole option mess, which is (3 + [hops] + [final] + 1),
735 and apply it [have to do this every time through, of course] */
736 x = ((gatesidx + 1) * sizeof (IA)) + 4;
737 rr = setsockopt (nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, x);
738 if (rr == -1)
739 bail ("srcrt setsockopt fuxored");
740#else /* IP_OPTIONS */
741 holler ("Warning: source routing unavailable on this machine, ignoring");
742#endif /* IP_OPTIONS*/
743 } /* if gatesidx */
744
745/* wrap connect inside a timer, and hit it */
746 arm (1, o_wait);
747 if (setjmp (jbuf) == 0) {
748 rr = connect (nnetfd, (SA *)remend, sizeof (SA));
749 } else { /* setjmp: connect failed... */
750 rr = -1;
751 errno = ETIMEDOUT; /* fake it */
752 }
753 arm (0, 0);
754 if (rr == 0)
755 return (nnetfd);
756 close (nnetfd); /* clean up junked socket FD!! */
757 return (-1);
758} /* doconnect */
759
760/* dolisten :
761 just like doconnect, and in fact calls a hunk of doconnect, but listens for
762 incoming and returns an open connection *from* someplace. If we were
763 given host/port args, any connections from elsewhere are rejected. This
764 in conjunction with local-address binding should limit things nicely... */
765int dolisten (rad, rp, lad, lp)
766 IA * rad;
767 USHORT rp;
768 IA * lad;
769 USHORT lp;
770{
771 register int nnetfd;
772 register int rr;
773 HINF * whozis = NULL;
774 int x;
775 char * cp;
776 USHORT z;
777 errno = 0;
778
779/* Pass everything off to doconnect, who in o_listen mode just gets a socket */
780 nnetfd = doconnect (rad, rp, lad, lp);
781 if (nnetfd <= 0)
782 return (-1);
783 if (o_udpmode) { /* apparently UDP can listen ON */
784 if (! lp) /* "port 0", but that's not useful */
785 bail ("UDP listen needs -p arg");
786 } else {
787 rr = listen (nnetfd, 1); /* gotta listen() before we can get */
788 if (rr < 0) /* our local random port. sheesh. */
789 bail ("local listen fuxored");
790 }
791
792/* Various things that follow temporarily trash bigbuf_net, which might contain
793 a copy of any recvfrom()ed packet, but we'll read() another copy later. */
794
795/* I can't believe I have to do all this to get my own goddamn bound address
796 and port number. It should just get filled in during bind() or something.
797 All this is only useful if we didn't say -p for listening, since if we
798 said -p we *know* what port we're listening on. At any rate we won't bother
799 with it all unless we wanted to see it, although listening quietly on a
800 random unknown port is probably not very useful without "netstat". */
801 if (o_verbose) {
802 x = sizeof (SA); /* how 'bout getsockNUM instead, pinheads?! */
803 rr = getsockname (nnetfd, (SA *) lclend, &x);
804 if (rr < 0)
805 holler ("local getsockname failed");
806 strcpy (bigbuf_net, "listening on ["); /* buffer reuse... */
807 if (lclend->sin_addr.s_addr)
808 strcat (bigbuf_net, inet_ntoa (lclend->sin_addr));
809 else
810 strcat (bigbuf_net, "any");
811 strcat (bigbuf_net, "] %d ...");
812 z = ntohs (lclend->sin_port);
813 holler (bigbuf_net, z);
814 } /* verbose -- whew!! */
815
816/* UDP is a speeeeecial case -- we have to do I/O *and* get the calling
817 party's particulars all at once, listen() and accept() don't apply.
818 At least in the BSD universe, however, recvfrom/PEEK is enough to tell
819 us something came in, and we can set things up so straight read/write
820 actually does work after all. Yow. YMMV on strange platforms! */
821 if (o_udpmode) {
822 x = sizeof (SA); /* retval for recvfrom */
823 arm (2, o_wait); /* might as well timeout this, too */
824 if (setjmp (jbuf) == 0) { /* do timeout for initial connect */
825 rr = recvfrom /* and here we block... */
826 (nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (SA *) remend, &x);
827Debug (("dolisten/recvfrom ding, rr = %d, netbuf %s ", rr, bigbuf_net))
828 } else
829 goto dol_tmo; /* timeout */
830 arm (0, 0);
831/* I'm not completely clear on how this works -- BSD seems to make UDP
832 just magically work in a connect()ed context, but we'll undoubtedly run
833 into systems this deal doesn't work on. For now, we apparently have to
834 issue a connect() on our just-tickled socket so we can write() back.
835 Again, why the fuck doesn't it just get filled in and taken care of?!
836 This hack is anything but optimal. Basically, if you want your listener
837 to also be able to send data back, you need this connect() line, which
838 also has the side effect that now anything from a different source or even a
839 different port on the other end won't show up and will cause ICMP errors.
840 I guess that's what they meant by "connect".
841 Let's try to remember what the "U" is *really* for, eh? */
842 rr = connect (nnetfd, (SA *)remend, sizeof (SA));
843 goto whoisit;
844 } /* o_udpmode */
845
846/* fall here for TCP */
847 x = sizeof (SA); /* retval for accept */
848 arm (2, o_wait); /* wrap this in a timer, too; 0 = forever */
849 if (setjmp (jbuf) == 0) {
850 rr = accept (nnetfd, (SA *)remend, &x);
851 } else
852 goto dol_tmo; /* timeout */
853 arm (0, 0);
854 close (nnetfd); /* dump the old socket */
855 nnetfd = rr; /* here's our new one */
856
857whoisit:
858 if (rr < 0)
859 goto dol_err; /* bail out if any errors so far */
860
861/* If we can, look for any IP options. Useful for testing the receiving end of
862 such things, and is a good exercise in dealing with it. We do this before
863 the connect message, to ensure that the connect msg is uniformly the LAST
864 thing to emerge after all the intervening crud. Doesn't work for UDP on
865 any machines I've tested, but feel free to surprise me. */
866#ifdef IP_OPTIONS
867 if (! o_verbose) /* if we wont see it, we dont care */
868 goto dol_noop;
869 optbuf = Hmalloc (40);
870 x = 40;
871 rr = getsockopt (nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x);
872 if (rr < 0)
873 holler ("getsockopt failed");
874Debug (("ipoptions ret len %d", x))
875 if (x) { /* we've got options, lessee em... */
876 unsigned char * q = (unsigned char *) optbuf;
877 char * p = bigbuf_net; /* local variables, yuk! */
878 char * pp = &bigbuf_net[128]; /* get random space farther out... */
879 memset (bigbuf_net, 0, 256); /* clear it all first */
880 while (x > 0) {
881 sprintf (pp, "%2.2x ", *q); /* clumsy, but works: turn into hex */
882 strcat (p, pp); /* and build the final string */
883 q++; p++;
884 x--;
885 }
886 holler ("IP options: %s", bigbuf_net);
887 } /* if x, i.e. any options */
888dol_noop:
889#endif /* IP_OPTIONS */
890
891/* find out what address the connection was *to* on our end, in case we're
892 doing a listen-on-any on a multihomed machine. This allows one to
893 offer different services via different alias addresses, such as the
894 "virtual web site" hack. */
895 memset (bigbuf_net, 0, 64);
896 cp = &bigbuf_net[32];
897 x = sizeof (SA);
898 rr = getsockname (nnetfd, (SA *) lclend, &x);
899 if (rr < 0)
900 holler ("post-rcv getsockname failed");
901 strcpy (cp, inet_ntoa (lclend->sin_addr));
902
903/* now check out who it is. We don't care about mismatched DNS names here,
904 but any ADDR and PORT we specified had better fucking well match the caller.
905 Converting from addr to inet_ntoa and back again is a bit of a kludge, but
906 gethostpoop wants a string and there's much gnarlier code out there already,
907 so I don't feel bad.
908 The *real* question is why BFD sockets wasn't designed to allow listens for
909 connections *from* specific hosts/ports, instead of requiring the caller to
910 accept the connection and then reject undesireable ones by closing. In
911 other words, we need a TCP MSG_PEEK. */
912 z = ntohs (remend->sin_port);
913 strcpy (bigbuf_net, inet_ntoa (remend->sin_addr));
914 whozis = gethostpoop (bigbuf_net, o_nflag);
915 errno = 0;
916 x = 0; /* use as a flag... */
917 if (rad) /* xxx: fix to go down the *list* if we have one? */
918 if (memcmp (rad, whozis->iaddrs, sizeof (SA)))
919 x = 1;
920 if (rp)
921 if (z != rp)
922 x = 1;
923 if (x) /* guilty! */
924 bail ("invalid connection to [%s] from %s [%s] %d",
925 cp, whozis->name, whozis->addrs[0], z);
926 holler ("connect to [%s] from %s [%s] %d", /* oh, you're okay.. */
927 cp, whozis->name, whozis->addrs[0], z);
928 return (nnetfd); /* open! */
929
930dol_tmo:
931 errno = ETIMEDOUT; /* fake it */
932dol_err:
933 close (nnetfd);
934 return (-1);
935} /* dolisten */
936
937/* udptest :
938 fire a couple of packets at a UDP target port, just to see if it's really
939 there. On BSD kernels, ICMP host/port-unreachable errors get delivered to
940 our socket as ECONNREFUSED write errors. On SV kernels, we lose; we'll have
941 to collect and analyze raw ICMP ourselves a la satan's probe_udp_ports
942 backend. Guess where one could swipe the appropriate code from...
943
944 Use the time delay between writes if given, otherwise use the "tcp ping"
945 trick for getting the RTT. [I got that idea from pluvius, and warped it.]
946 Return either the original fd, or clean up and return -1. */
947udptest (fd, where)
948 int fd;
949 IA * where;
950{
951 register int rr;
952
953 rr = write (fd, bigbuf_in, 1);
954 if (rr != 1)
955 holler ("udptest first write failed?! errno %d", errno);
956 if (o_wait)
957 sleep (o_wait);
958 else {
959/* use the tcp-ping trick: try connecting to a normally refused port, which
960 causes us to block for the time that SYN gets there and RST gets back.
961 Not completely reliable, but it *does* mostly work. */
962 o_udpmode = 0; /* so doconnect does TCP this time */
963/* Set a temporary connect timeout, so packet filtration doesnt cause
964 us to hang forever, and hit it */
965 o_wait = 5; /* enough that we'll notice?? */
966 rr = doconnect (where, SLEAZE_PORT, 0, 0);
967 if (rr > 0)
968 close (rr); /* in case it *did* open */
969 o_wait = 0; /* reset it */
970 o_udpmode++; /* we *are* still doing UDP, right? */
971 } /* if o_wait */
972 errno = 0; /* clear from sleep */
973 rr = write (fd, bigbuf_in, 1);
974 if (rr == 1) /* if write error, no UDP listener */
975 return (fd);
976 close (fd); /* use it or lose it! */
977 return (-1);
978} /* udptest */
979
980/* oprint :
981 Hexdump bytes shoveled either way to a running logfile, in the format:
982D offset - - - - --- 16 bytes --- - - - - # .... ascii .....
983 where "which" sets the direction indicator, D:
984 0 -- sent to network, or ">"
985 1 -- rcvd and printed to stdout, or "<"
986 and "buf" and "n" are data-block and length. If the current block generates
987 a partial line, so be it; we *want* that lockstep indication of who sent
988 what when. Adapted from dgaudet's original example -- but must be ripping
989 *fast*, since we don't want to be too disk-bound... */
990void oprint (which, buf, n)
991 int which;
992 char * buf;
993 int n;
994{
995 int bc; /* in buffer count */
996 int obc; /* current "global" offset */
997 int soc; /* stage write count */
998 register unsigned char * p; /* main buf ptr; m.b. unsigned here */
999 register unsigned char * op; /* out hexdump ptr */
1000 register unsigned char * a; /* out asc-dump ptr */
1001 register int x;
1002 register unsigned int y;
1003
1004 if (! ofd)
1005 bail ("oprint called with no open fd?!");
1006 if (n == 0)
1007 return;
1008
1009 op = stage;
1010 if (which) {
1011 *op = '<';
1012 obc = wrote_out; /* use the globals! */
1013 } else {
1014 *op = '>';
1015 obc = wrote_net;
1016 }
1017 op++; /* preload "direction" */
1018 *op = ' ';
1019 p = (unsigned char *) buf;
1020 bc = n;
1021 stage[59] = '#'; /* preload separator */
1022 stage[60] = ' ';
1023
1024 while (bc) { /* for chunk-o-data ... */
1025 x = 16;
1026 soc = 78; /* len of whole formatted line */
1027 if (bc < x) {
1028 soc = soc - 16 + bc; /* fiddle for however much is left */
1029 x = (bc * 3) + 11; /* 2 digits + space per, after D & offset */
1030 op = &stage[x];
1031 x = 16 - bc;
1032 while (x) {
1033 *op++ = ' '; /* preload filler spaces */
1034 *op++ = ' ';
1035 *op++ = ' ';
1036 x--;
1037 }
1038 x = bc; /* re-fix current linecount */
1039 } /* if bc < x */
1040
1041 bc -= x; /* fix wrt current line size */
1042 sprintf (&stage[2], "%8.8x ", obc); /* xxx: still slow? */
1043 obc += x; /* fix current offset */
1044 op = &stage[11]; /* where hex starts */
1045 a = &stage[61]; /* where ascii starts */
1046
1047 while (x) { /* for line of dump, however long ... */
1048 y = (int)(*p >> 4); /* hi half */
1049 *op = hexnibs[y];
1050 op++;
1051 y = (int)(*p & 0x0f); /* lo half */
1052 *op = hexnibs[y];
1053 op++;
1054 *op = ' ';
1055 op++;
1056 if ((*p > 31) && (*p < 127))
1057 *a = *p; /* printing */
1058 else
1059 *a = '.'; /* nonprinting, loose def */
1060 a++;
1061 p++;
1062 x--;
1063 } /* while x */
1064 *a = '\n'; /* finish the line */
1065 x = write (ofd, stage, soc);
1066 if (x < 0)
1067 bail ("ofd write err");
1068 } /* while bc */
1069} /* oprint */
1070
1071#ifdef TELNET
1072USHORT o_tn = 0; /* global -t option */
1073
1074/* atelnet :
1075 Answer anything that looks like telnet negotiation with don't/won't.
1076 This doesn't modify any data buffers, update the global output count,
1077 or show up in a hexdump -- it just shits into the outgoing stream.
1078 Idea and codebase from Mudge@l0pht.com. */
1079void atelnet (buf, size)
1080 unsigned char * buf; /* has to be unsigned here! */
1081 unsigned int size;
1082{
1083 static unsigned char obuf [4]; /* tiny thing to build responses into */
1084 register int x;
1085 register unsigned char y;
1086 register unsigned char * p;
1087
1088 y = 0;
1089 p = buf;
1090 x = size;
1091 while (x > 0) {
1092 if (*p != 255) /* IAC? */
1093 goto notiac;
1094 obuf[0] = 255;
1095 p++; x--;
1096 if ((*p == 251) || (*p == 252)) /* WILL or WONT */
1097 y = 254; /* -> DONT */
1098 if ((*p == 253) || (*p == 254)) /* DO or DONT */
1099 y = 252; /* -> WONT */
1100 if (y) {
1101 obuf[1] = y;
1102 p++; x--;
1103 obuf[2] = *p; /* copy actual option byte */
1104 (void) write (netfd, obuf, 3);
1105/* if one wanted to bump wrote_net or do a hexdump line, here's the place */
1106 y = 0;
1107 } /* if y */
1108notiac:
1109 p++; x--;
1110 } /* while x */
1111} /* atelnet */
1112#endif /* TELNET */
1113
1114/* readwrite :
1115 handle stdin/stdout/network I/O. Bwahaha!! -- the select loop from hell.
1116 In this instance, return what might become our exit status. */
1117int readwrite (fd)
1118 int fd;
1119{
1120 register int rr;
1121 register char * zp; /* stdin buf ptr */
1122 register char * np; /* net-in buf ptr */
1123 unsigned int rzleft;
1124 unsigned int rnleft;
1125 USHORT netretry; /* net-read retry counter */
1126 USHORT wretry; /* net-write sanity counter */
1127 USHORT wfirst; /* one-shot flag to skip first net read */
1128
1129/* if you don't have all this FD_* macro hair in sys/types.h, you'll have to
1130 either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */
1131 if (fd > FD_SETSIZE) {
1132 holler ("Preposterous fd value %d", fd);
1133 return (1);
1134 }
1135 FD_SET (fd, ding1); /* global: the net is open */
1136 netretry = 2;
1137 wfirst = 0;
1138 rzleft = rnleft = 0;
1139 if (insaved) {
1140 rzleft = insaved; /* preload multi-mode fakeouts */
1141 zp = bigbuf_in;
1142 wfirst = 1;
1143 if (Single) /* if not scanning, this is a one-off first */
1144 insaved = 0; /* buffer left over from argv construction, */
1145 else {
1146 FD_CLR (0, ding1); /* OR we've already got our repeat chunk, */
1147 close (0); /* so we won't need any more stdin */
1148 } /* Single */
1149 } /* insaved */
1150 if (o_interval)
1151 sleep (o_interval); /* pause *before* sending stuff, too */
1152 errno = 0; /* clear from sleep, close, whatever */
1153
1154/* and now the big ol' select shoveling loop ... */
1155 while (FD_ISSET (fd, ding1)) { /* i.e. till the *net* closes! */
1156 wretry = 8200; /* more than we'll ever hafta write */
1157 if (wfirst) { /* any saved stdin buffer? */
1158 wfirst = 0; /* clear flag for the duration */
1159 goto shovel; /* and go handle it first */
1160 }
1161 *ding2 = *ding1; /* FD_COPY ain't portable... */
1162/* some systems, notably linux, crap into their select timers on return, so
1163 we create a expendable copy and give *that* to select. *Fuck* me ... */
1164 if (timer1)
1165 memcpy (timer2, timer1, sizeof (struct timeval));
1166 rr = select (16, ding2, 0, 0, timer2); /* here it is, kiddies */
1167 if (rr < 0) {
1168 if (errno != EINTR) { /* might have gotten ^Zed, etc ?*/
1169 holler ("select fuxored");
1170 close (fd);
1171 return (1);
1172 }
1173 } /* select fuckup */
1174/* if we have a timeout AND stdin is closed AND we haven't heard anything
1175 from the net during that time, assume it's dead and close it too. */
1176 if (rr == 0) {
1177 if (! FD_ISSET (0, ding1))
1178 netretry--; /* we actually try a coupla times. */
1179 if (! netretry) {
1180 if (o_verbose > 1) /* normally we don't care */
1181 holler ("net timeout");
1182 close (fd);
1183 return (0); /* not an error! */
1184 }
1185 } /* select timeout */
1186/* xxx: should we check the exception fds too? The read fds seem to give
1187 us the right info, and none of the examples I found bothered. */
1188
1189/* Ding!! Something arrived, go check all the incoming hoppers, net first */
1190 if (FD_ISSET (fd, ding2)) { /* net: ding! */
1191 rr = read (fd, bigbuf_net, BIGSIZ);
1192 if (rr <= 0) {
1193 FD_CLR (fd, ding1); /* net closed, we'll finish up... */
1194 rzleft = 0; /* can't write anymore: broken pipe */
1195 } else {
1196 rnleft = rr;
1197 np = bigbuf_net;
1198#ifdef TELNET
1199 if (o_tn)
1200 atelnet (np, rr); /* fake out telnet stuff */
1201#endif /* TELNET */
1202 } /* if rr */
1203Debug (("got %d from the net, errno %d", rr, errno))
1204 } /* net:ding */
1205
1206/* if we're in "slowly" mode there's probably still stuff in the stdin
1207 buffer, so don't read unless we really need MORE INPUT! MORE INPUT! */
1208 if (rzleft)
1209 goto shovel;
1210
1211/* okay, suck more stdin */
1212 if (FD_ISSET (0, ding2)) { /* stdin: ding! */
1213 rr = read (0, bigbuf_in, BIGSIZ);
1214/* Considered making reads here smaller for UDP mode, but 8192-byte
1215 mobygrams are kinda fun and exercise the reassembler. */
1216 if (rr <= 0) { /* at end, or fukt, or ... */
1217 FD_CLR (0, ding1); /* disable and close stdin */
1218 close (0);
1219 } else {
1220 rzleft = rr;
1221 zp = bigbuf_in;
1222/* special case for multi-mode -- we'll want to send this one buffer to every
1223 open TCP port or every UDP attempt, so save its size and clean up stdin */
1224 if (! Single) { /* we might be scanning... */
1225 insaved = rr; /* save len */
1226 FD_CLR (0, ding1); /* disable further junk from stdin */
1227 close (0); /* really, I mean it */
1228 } /* Single */
1229 } /* if rr/read */
1230 } /* stdin:ding */
1231
1232shovel:
1233/* now that we've dingdonged all our thingdings, send off the results.
1234 Geez, why does this look an awful lot like the big loop in "rsh"? ...
1235 not sure if the order of this matters, but write net -> stdout first. */
1236
1237/* sanity check. Works because they're both unsigned... */
1238 if ((rzleft > 8200) || (rnleft > 8200)) {
1239 holler ("Bogus buffers: %d, %d", rzleft, rnleft);
1240 rzleft = rnleft = 0;
1241 }
1242/* net write retries sometimes happen on UDP connections */
1243 if (! wretry) { /* is something hung? */
1244 holler ("too many output retries");
1245 return (1);
1246 }
1247 if (rnleft) {
1248 rr = write (1, np, rnleft);
1249 if (rr > 0) {
1250 if (o_wfile)
1251 oprint (1, np, rr); /* log the stdout */
1252 np += rr; /* fix up ptrs and whatnot */
1253 rnleft -= rr; /* will get sanity-checked above */
1254 wrote_out += rr; /* global count */
1255 }
1256Debug (("wrote %d to stdout, errno %d", rr, errno))
1257 } /* rnleft */
1258 if (rzleft) {
1259 if (o_interval) /* in "slowly" mode ?? */
1260 rr = findline (zp, rzleft);
1261 else
1262 rr = rzleft;
1263 rr = write (fd, zp, rr); /* one line, or the whole buffer */
1264 if (rr > 0) {
1265 if (o_wfile)
1266 oprint (0, zp, rr); /* log what got sent */
1267 zp += rr;
1268 rzleft -= rr;
1269 wrote_net += rr; /* global count */
1270 }
1271Debug (("wrote %d to net, errno %d", rr, errno))
1272 } /* rzleft */
1273 if (o_interval) { /* cycle between slow lines, or ... */
1274 sleep (o_interval);
1275 errno = 0; /* clear from sleep */
1276 continue; /* ...with hairy select loop... */
1277 }
1278 if ((rzleft) || (rnleft)) { /* shovel that shit till they ain't */
1279 wretry--; /* none left, and get another load */
1280 goto shovel;
1281 }
1282 } /* while ding1:netfd is open */
1283
1284/* XXX: maybe want a more graceful shutdown() here, or screw around with
1285 linger times?? I suspect that I don't need to since I'm always doing
1286 blocking reads and writes and my own manual "last ditch" efforts to read
1287 the net again after a timeout. I haven't seen any screwups yet, but it's
1288 not like my test network is particularly busy... */
1289 close (fd);
1290 return (0);
1291} /* readwrite */
1292
1293/* main :
1294 now we pull it all together... */
1295main (argc, argv)
1296 int argc;
1297 char ** argv;
1298{
1299#ifndef HAVE_GETOPT
1300 extern char * optarg;
1301 extern int optind, optopt;
1302#endif
1303 register int x;
1304 register char *cp;
1305 HINF * gp;
1306 HINF * whereto = NULL;
1307 HINF * wherefrom = NULL;
1308 IA * ouraddr = NULL;
1309 IA * themaddr = NULL;
1310 USHORT o_lport = 0;
1311 USHORT ourport = 0;
1312 USHORT loport = 0; /* for scanning stuff */
1313 USHORT hiport = 0;
1314 USHORT curport = 0;
1315 char * randports = NULL;
1316
1317#ifdef HAVE_BIND
1318/* can *you* say "cc -yaddayadda netcat.c -lresolv -l44bsd" on SunLOSs? */
1319 res_init();
1320#endif
1321/* I was in this barbershop quartet in Skokie IL ... */
1322/* round up the usual suspects, i.e. malloc up all the stuff we need */
1323 lclend = (SAI *) Hmalloc (sizeof (SA));
1324 remend = (SAI *) Hmalloc (sizeof (SA));
1325 bigbuf_in = Hmalloc (BIGSIZ);
1326 bigbuf_net = Hmalloc (BIGSIZ);
1327 ding1 = (fd_set *) Hmalloc (sizeof (fd_set));
1328 ding2 = (fd_set *) Hmalloc (sizeof (fd_set));
1329 portpoop = (PINF *) Hmalloc (sizeof (PINF));
1330
1331 errno = 0;
1332 gatesptr = 4;
1333 h_errno = 0;
1334
1335/* catch a signal or two for cleanup */
1336 signal (SIGINT, catch);
1337 signal (SIGQUIT, catch);
1338 signal (SIGTERM, catch);
1339/* and suppress others... */
1340#ifdef SIGURG
1341 signal (SIGURG, SIG_IGN);
1342#endif
1343#ifdef SIGPIPE
1344 signal (SIGPIPE, SIG_IGN); /* important! */
1345#endif
1346
1347/* if no args given at all, get 'em from stdin, construct an argv, and hand
1348 anything left over to readwrite(). */
1349 if (argc == 1) {
1350 cp = argv[0];
1351 argv = (char **) Hmalloc (128 * sizeof (char *)); /* XXX: 128? */
1352 argv[0] = cp; /* leave old prog name intact */
1353 cp = Hmalloc (BIGSIZ);
1354 argv[1] = cp; /* head of new arg block */
1355 fprintf (stderr, "Cmd line: ");
1356 fflush (stderr); /* I dont care if it's unbuffered or not! */
1357 insaved = read (0, cp, BIGSIZ); /* we're gonna fake fgets() here */
1358 if (insaved <= 0)
1359 bail ("wrong");
1360 x = findline (cp, insaved);
1361 if (x)
1362 insaved -= x; /* remaining chunk size to be sent */
1363 if (insaved) /* which might be zero... */
1364 memcpy (bigbuf_in, &cp[x], insaved);
1365 cp = strchr (argv[1], '\n');
1366 if (cp)
1367 *cp = '\0';
1368 cp = strchr (argv[1], '\r'); /* look for ^M too */
1369 if (cp)
1370 *cp = '\0';
1371
1372/* find and stash pointers to remaining new "args" */
1373 cp = argv[1];
1374 cp++; /* skip past first char */
1375 x = 2; /* we know argv 0 and 1 already */
1376 for (; *cp != '\0'; cp++) {
1377 if (*cp == ' ') {
1378 *cp = '\0'; /* smash all spaces */
1379 continue;
1380 } else {
1381 if (*(cp-1) == '\0') {
1382 argv[x] = cp;
1383 x++;
1384 }
1385 } /* if space */
1386 } /* for cp */
1387 argc = x;
1388 } /* if no args given */
1389
1390/* If your shitbox doesn't have getopt, step into the nineties already. */
1391/* optarg, optind = next-argv-component [i.e. flag arg]; optopt = last-char */
1392 while ((x = getopt (argc, argv, "ae:g:G:hi:lno:p:rs:tuvw:z")) != EOF) {
1393/* Debug (("in go: x now %c, optarg %x optind %d", x, optarg, optind)) */
1394 switch (x) {
1395 case 'a':
1396 bail ("all-A-records NIY");
1397 o_alla++; break;
1398#ifdef GAPING_SECURITY_HOLE
1399 case 'e': /* prog to exec */
1400 pr00gie = optarg;
1401 break;
1402#endif
1403 case 'G': /* srcrt gateways pointer val */
1404 x = atoi (optarg);
1405 if ((x) && (x == (x & 0x1c))) /* mask off bits of fukt values */
1406 gatesptr = x;
1407 else
1408 bail ("invalid hop pointer %d, must be multiple of 4 <= 28", x);
1409 break;
1410 case 'g': /* srcroute hop[s] */
1411 if (gatesidx > 8)
1412 bail ("too many -g hops");
1413 if (gates == NULL) /* eat this, Billy-boy */
1414 gates = (HINF **) Hmalloc (sizeof (HINF *) * 10);
1415 gp = gethostpoop (optarg, o_nflag);
1416 if (gp)
1417 gates[gatesidx] = gp;
1418 gatesidx++;
1419 break;
1420 case 'h':
1421 errno = 0;
1422#ifdef HAVE_HELP
1423 helpme(); /* exits by itself */
1424#else
1425 bail ("no help available, dork -- RTFS");
1426#endif
1427 case 'i': /* line-interval time */
1428 o_interval = atoi (optarg) & 0xffff;
1429 if (! o_interval)
1430 bail ("invalid interval time %s", optarg);
1431 break;
1432 case 'l': /* listen mode */
1433 o_listen++; break;
1434 case 'n': /* numeric-only, no DNS lookups */
1435 o_nflag++; break;
1436 case 'o': /* hexdump log */
1437 stage = (unsigned char *) optarg;
1438 o_wfile++; break;
1439 case 'p': /* local source port */
1440 o_lport = getportpoop (optarg, 0);
1441 if (o_lport == 0)
1442 bail ("invalid local port %s", optarg);
1443 break;
1444 case 'r': /* randomize various things */
1445 o_random++; break;
1446 case 's': /* local source address */
1447/* do a full lookup [since everything else goes through the same mill],
1448 unless -n was previously specified. In fact, careful placement of -n can
1449 be useful, so we'll still pass o_nflag here instead of forcing numeric. */
1450 wherefrom = gethostpoop (optarg, o_nflag);
1451 ouraddr = &wherefrom->iaddrs[0];
1452 break;
1453#ifdef TELNET
1454 case 't': /* do telnet fakeout */
1455 o_tn++; break;
1456#endif /* TELNET */
1457 case 'u': /* use UDP */
1458 o_udpmode++; break;
1459 case 'v': /* verbose */
1460 o_verbose++; break;
1461 case 'w': /* wait time */
1462 o_wait = atoi (optarg);
1463 if (o_wait <= 0)
1464 bail ("invalid wait-time %s", optarg);
1465 timer1 = (struct timeval *) Hmalloc (sizeof (struct timeval));
1466 timer2 = (struct timeval *) Hmalloc (sizeof (struct timeval));
1467 timer1->tv_sec = o_wait; /* we need two. see readwrite()... */
1468 break;
1469 case 'z': /* little or no data xfer */
1470 o_zero++;
1471 break;
1472 default:
1473 errno = 0;
1474 bail ("nc -h for help");
1475 } /* switch x */
1476 } /* while getopt */
1477
1478/* other misc initialization */
1479Debug (("fd_set size %d", sizeof (*ding1))) /* how big *is* it? */
1480 FD_SET (0, ding1); /* stdin *is* initially open */
1481 if (o_random) {
1482 SRAND (time (0));
1483 randports = Hmalloc (65536); /* big flag array for ports */
1484 }
1485#ifdef GAPING_SECURITY_HOLE
1486 if (pr00gie) {
1487 close (0); /* won't need stdin */
1488 o_wfile = 0; /* -o with -e is meaningless! */
1489 ofd = 0;
1490 }
1491#endif /* G_S_H */
1492 if (o_wfile) {
1493 ofd = open (stage, O_WRONLY | O_CREAT | O_TRUNC, 0664);
1494 if (ofd <= 0) /* must be > extant 0/1/2 */
1495 bail ("can't open %s", stage);
1496 stage = (unsigned char *) Hmalloc (100);
1497 }
1498
1499/* optind is now index of first non -x arg */
1500Debug (("after go: x now %c, optarg %x optind %d", x, optarg, optind))
1501/* Debug (("optind up to %d at host-arg %s", optind, argv[optind])) */
1502/* gonna only use first addr of host-list, like our IQ was normal; if you wanna
1503 get fancy with addresses, look up the list yourself and plug 'em in for now.
1504 unless we finally implement -a, that is. */
1505 if (argv[optind])
1506 whereto = gethostpoop (argv[optind], o_nflag);
1507 if (whereto && whereto->iaddrs)
1508 themaddr = &whereto->iaddrs[0];
1509 if (themaddr)
1510 optind++; /* skip past valid host lookup */
1511 errno = 0;
1512 h_errno = 0;
1513
1514/* Handle listen mode here, and exit afterward. Only does one connect;
1515 this is arguably the right thing to do. A "persistent listen-and-fork"
1516 mode a la inetd has been thought about, but not implemented. A tiny
1517 wrapper script can handle such things... */
1518 if (o_listen) {
1519 curport = 0; /* rem port *can* be zero here... */
1520 if (argv[optind]) { /* any rem-port-arg? */
1521 curport = getportpoop (argv[optind], 0);
1522 if (curport == 0) /* if given, demand correctness */
1523 bail ("invalid port %s", argv[optind]);
1524 } /* if port-arg */
1525 netfd = dolisten (themaddr, curport, ouraddr, o_lport);
1526/* dolisten does its own connect reporting, so we don't holler anything here */
1527 if (netfd > 0) {
1528#ifdef GAPING_SECURITY_HOLE
1529 if (pr00gie) /* -e given? */
1530 doexec (netfd);
1531#endif /* GAPING_SECURITY_HOLE */
1532 x = readwrite (netfd); /* it even works with UDP! */
1533 if (o_verbose > 1) /* normally we don't care */
1534 holler (wrote_txt, wrote_net, wrote_out);
1535 exit (x); /* "pack out yer trash" */
1536 } else /* if no netfd */
1537 bail ("no connection");
1538 } /* o_listen */
1539
1540/* fall thru to outbound connects. Now we're more picky about args... */
1541 if (! themaddr)
1542 bail ("no destination");
1543 if (argv[optind] == NULL)
1544 bail ("no port[s] to connect to");
1545 if (argv[optind + 1]) /* look ahead: any more port args given? */
1546 Single = 0; /* multi-mode, case A */
1547 ourport = o_lport; /* which can be 0 */
1548
1549/* everything from here down is treated as as ports and/or ranges thereof, so
1550 it's all enclosed in this big ol' argv-parsin' loop. Any randomization is
1551 done within each given *range*, but in separate chunks per each succeeding
1552 argument, so we can control the pattern somewhat. */
1553 while (argv[optind]) {
1554 hiport = loport = 0;
1555 cp = strchr (argv[optind], '-'); /* nn-mm range? */
1556 if (cp) {
1557 *cp = '\0';
1558 cp++;
1559 hiport = getportpoop (cp, 0);
1560 if (hiport == 0)
1561 bail ("invalid port %s", cp);
1562 } /* if found a dash */
1563 loport = getportpoop (argv[optind], 0);
1564 if (loport == 0)
1565 bail ("invalid port %s", argv[optind]);
1566 if (hiport > loport) { /* was it genuinely a range? */
1567 Single = 0; /* multi-mode, case B */
1568 curport = hiport; /* start high by default */
1569 if (o_random) { /* maybe populate the random array */
1570 loadports (randports, loport, hiport);
1571 curport = nextport (randports);
1572 }
1573 } else /* not a range, including args like "25-25" */
1574 curport = loport;
1575Debug (("Single %d, curport %d", Single, curport))
1576
1577/* Now start connecting to these things. curport is already preloaded. */
1578 while (loport <= curport) {
1579 if ((! o_lport) && (o_random)) { /* -p overrides random local-port */
1580 ourport = (RAND() & 0xffff); /* random local-bind -- well above */
1581 if (ourport < 8192) /* resv and any likely listeners??? */
1582 ourport += 8192; /* if it *still* conflicts, use -s. */
1583 }
1584 curport = getportpoop (NULL, curport);
1585 netfd = doconnect (themaddr, curport, ouraddr, ourport);
1586Debug (("netfd %d from port %d to port %d", netfd, ourport, curport))
1587 if (netfd > 0)
1588 if (o_zero && o_udpmode) /* if UDP scanning... */
1589 netfd = udptest (netfd, themaddr);
1590 if (netfd > 0) { /* Yow, are we OPEN YET?! */
1591 x = 0; /* pre-exit status */
1592 holler ("%s [%s] %d (%s) open",
1593 whereto->name, whereto->addrs[0], curport, portpoop->name);
1594#ifdef GAPING_SECURITY_HOLE
1595 if (pr00gie) /* exec is valid for outbound, too */
1596 doexec (netfd);
1597#endif /* GAPING_SECURITY_HOLE */
1598 if (! o_zero)
1599 x = readwrite (netfd); /* go shovel shit */
1600 } else { /* no netfd... */
1601 x = 1; /* preload exit status for later */
1602/* if we're scanning at a "one -v" verbosity level, don't print refusals.
1603 Give it another -v if you want to see everything. */
1604 if ((Single || (o_verbose > 1)) || (errno != ECONNREFUSED))
1605 holler ("%s [%s] %d (%s)",
1606 whereto->name, whereto->addrs[0], curport, portpoop->name);
1607 } /* if netfd */
1608 close (netfd); /* just in case we didn't already */
1609 if (o_interval)
1610 sleep (o_interval); /* if -i, delay between ports too */
1611 if (o_random)
1612 curport = nextport (randports);
1613 else
1614 curport--; /* just decrement... */
1615 } /* while curport within current range */
1616 optind++;
1617 } /* while remaining port-args -- end of big argv-ports loop*/
1618
1619 errno = 0;
1620 if (o_verbose > 1) /* normally we don't care */
1621 holler (wrote_txt, wrote_net, wrote_out);
1622 if (Single)
1623 exit (x); /* give us status on one connection */
1624 exit (0); /* otherwise, we're just done */
1625} /* main */
1626
1627#ifdef HAVE_HELP /* unless we wanna be *really* cryptic */
1628/* helpme :
1629 the obvious */
1630helpme()
1631{
1632 o_verbose = 1;
1633 holler ("[v1.10]\n\
1634connect to somewhere: nc [-options] hostname port[s] [ports] ... \n\
1635listen for inbound: nc -l -p port [-options] [hostname] [port]\n\
1636options:");
1637/* sigh, this necessarily gets messy. And the trailing \ characters may be
1638 interpreted oddly by some compilers, generating or not generating extra
1639 newlines as they bloody please. u-fix... */
1640#ifdef GAPING_SECURITY_HOLE /* needs to be separate holler() */
1641 holler ("\
1642 -e prog program to exec after connect [dangerous!!]");
1643#endif
1644 holler ("\
1645 -g gateway source-routing hop point[s], up to 8\n\
1646 -G num source-routing pointer: 4, 8, 12, ...\n\
1647 -h this cruft\n\
1648 -i secs delay interval for lines sent, ports scanned\n\
1649 -l listen mode, for inbound connects\n\
1650 -n numeric-only IP addresses, no DNS\n\
1651 -o file hex dump of traffic\n\
1652 -p port local port number\n\
1653 -r randomize local and remote ports\n\
1654 -s addr local source address");
1655#ifdef TELNET
1656 holler ("\
1657 -t answer TELNET negotiation");
1658#endif
1659 holler ("\
1660 -u UDP mode\n\
1661 -v verbose [use twice to be more verbose]\n\
1662 -w secs timeout for connects and final net reads\n\
1663 -z zero-I/O mode [used for scanning]");
1664 bail ("port numbers can be individual or ranges: lo-hi [inclusive]");
1665} /* helpme */
1666#endif /* HAVE_HELP */
1667
1668/* None genuine without this seal! _H*/
diff --git a/src/usr.bin/nc/scripts/README b/src/usr.bin/nc/scripts/README
new file mode 100644
index 0000000000..07aee0c8ea
--- /dev/null
+++ b/src/usr.bin/nc/scripts/README
@@ -0,0 +1,5 @@
1A collection of example scripts that use netcat as a backend, each
2documented by its own internal comments.
3
4I'll be the first to admit that some of these are seriously *sick*,
5but they do work and are quite useful to me on a daily basis.
diff --git a/src/usr.bin/nc/scripts/alta b/src/usr.bin/nc/scripts/alta
new file mode 100644
index 0000000000..7a091767e8
--- /dev/null
+++ b/src/usr.bin/nc/scripts/alta
@@ -0,0 +1,33 @@
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
7test "${1}" = "" && echo 'Needs an argument to search for!' && exit 1
8WHAT="web"
9test "${2}" && WHAT="${2}"
10
11# convert multiple args
12PLUSARG="`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
16QB="GET /cgi-bin/query?pg=q&what=${WHAT}&fmt=c&q=\"${PLUSARG}\""
17
18# ping 'em once, to get the routing warm
19nc -z -w 8 www.altavista.digital.com 24015 2> /dev/null
20echo "=== Altavista ==="
21
22for 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 '^<a href="http://'
26done
27
28exit 0
29
30# old filter stuff
31 sed -e '/Documents .* matching .* query /,/query?.*stq=.* Document/p' \
32 -e d
33
diff --git a/src/usr.bin/nc/scripts/bsh b/src/usr.bin/nc/scripts/bsh
new file mode 100644
index 0000000000..796e480354
--- /dev/null
+++ b/src/usr.bin/nc/scripts/bsh
@@ -0,0 +1,29 @@
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
5NC=nc
6
7case "$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 ;;
16esac
17
18# here we play inetd
19echo "-l -p $LPN -e $0" | $NC > /dev/null 2>&1 &
20
21while read qq ; do
22case "$qq" in
23# here's yer password
24 gimme )
25 cd /
26 exec csh -i
27 ;;
28esac
29done
diff --git a/src/usr.bin/nc/scripts/dist.sh b/src/usr.bin/nc/scripts/dist.sh
new file mode 100644
index 0000000000..4d2534a0e3
--- /dev/null
+++ b/src/usr.bin/nc/scripts/dist.sh
@@ -0,0 +1,23 @@
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
8PORT=31337
9
10sleep 1
11SRC=`tail -1 dist.log`
12echo "<36>elite: ${SRC}" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1
13echo ";;; Hi, ${SRC}..."
14echo ";;; This is a PRERELEASE version of 'netcat', tar/gzip/uuencoded."
15echo ";;; Unless you are capturing this somehow, it won't do you much good."
16echo ";;; Ready?? Here it comes! Have phun ..."
17sleep 8
18cat dist.file
19sleep 1
20./nc -v -l -p ${PORT} -e dist.sh < /dev/null >> dist.log 2>&1 &
21sleep 1
22echo "<36>elite: done" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1
23exit 0
diff --git a/src/usr.bin/nc/scripts/irc b/src/usr.bin/nc/scripts/irc
new file mode 100644
index 0000000000..3557d7a0c6
--- /dev/null
+++ b/src/usr.bin/nc/scripts/irc
@@ -0,0 +1,79 @@
1#! /bin/sh
2## Shit-simple script to supply the "privmsg <recipient>" 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
10if 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
18fi
19
20# top level: fire ourselves off as the keepalive process, and keep track of it
21sh $0 tick &
22ircpp=$!
23echo "[Keepalive: $ircpp]" >&2
24# catch our own batch of signals: hup int quit pipe alrm term urg
25trap 'kill -9 $ircpp ; exit 0' 1 2 3 13 14 15 16
26sleep 2
27
28sender=''
29savecmd=''
30
31# the big honkin' loop...
32while 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
74done
75
76# parting shot, if you want it
77echo "quit :Bye all!"
78kill -9 $ircpp
79exit 0
diff --git a/src/usr.bin/nc/scripts/iscan b/src/usr.bin/nc/scripts/iscan
new file mode 100644
index 0000000000..6279bc817f
--- /dev/null
+++ b/src/usr.bin/nc/scripts/iscan
@@ -0,0 +1,35 @@
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
11case "${2}" in
12 "" ) echo needs HOST and at least one PORT ; exit 1 ;;
13esac
14
15# ping 'em once and see if they *are* running identd
16nc -z -w 9 "$1" 113 || { echo "oops, $1 isn't running identd" ; exit 0 ; }
17
18# generate a randomish base port
19RP=`expr $$ % 999 + 31337`
20
21TRG="$1"
22shift
23
24while 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
34done
35
diff --git a/src/usr.bin/nc/scripts/ncp b/src/usr.bin/nc/scripts/ncp
new file mode 100644
index 0000000000..1931b03385
--- /dev/null
+++ b/src/usr.bin/nc/scripts/ncp
@@ -0,0 +1,46 @@
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.
9MYPORT=23456
10
11## if "nc" isn't systemwide or in your PATH, add the right place
12# PATH=${HOME}:${PATH} ; export PATH
13
14test "$3" && echo "too many args" && exit 1
15test ! "$1" && echo "no args?" && exit 1
16me=`echo $0 | sed 's+.*/++'`
17test "$me" = "nzp" && echo '[compressed mode]'
18
19# if second arg, it's a host to send an [extant] file to.
20if 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
29fi
30
31# fall here for receiver. Ask before trashing existing files
32if test -f "$1" ; then
33 echo -n "Overwrite $1? "
34 read aa
35 test ! "$aa" = "y" && echo "[punted!]" && exit 1
36fi
37# 30 seconds oughta be pleeeeenty of time, but change if you want.
38if test "$me" = "nzp" ; then
39 nc -v -w 30 -p $MYPORT -l < /dev/null | uncompress -c > "$1" && exit 0
40else
41 nc -v -w 30 -p $MYPORT -l < /dev/null > "$1" && exit 0
42fi
43echo "transfer FAILED!"
44# clean up, since even if the transfer failed, $1 is already trashed
45rm -f "$1"
46exit 1
diff --git a/src/usr.bin/nc/scripts/probe b/src/usr.bin/nc/scripts/probe
new file mode 100644
index 0000000000..c47dc3f495
--- /dev/null
+++ b/src/usr.bin/nc/scripts/probe
@@ -0,0 +1,50 @@
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
8DDIR=../data
9# address of some well-connected router that groks LSRR
10GATE=192.157.69.11
11
12# might conceivably wanna change this for different run styles
13UCMD='nc -v -w 8'
14
15test ! "$1" && echo Needs victim arg && exit 1
16
17echo '' | $UCMD -w 9 -r "$1" 13 79 6667 2>&1
18echo '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
23echo 'UDP echoecho!' | nc -u -p 7 -s `hostname` -w 3 "$1" 7 19 2>&1
24echo '113,10158' | $UCMD -p 10158 "$1" 113 2>&1
25rservice bin bin | $UCMD -p 1019 "$1" shell 2>&1
26echo 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
28echo ''
29echo PASV | $UCMD -r "$1" 21 2>&1
30echo 'GET /' | $UCMD -w 10 "$1" 80 81 210 70 2>&1
31# sometimes contains useful directory info:
32echo 'GET /robots.txt' | $UCMD -w 10 "$1" 80 2>&1
33# now the big red lights go on
34rservice bin bin 9600/9600 | $UCMD -p 1020 "$1" login 2>&1
35rservice root root | $UCMD -r "$1" exec 2>&1
36echo 'BEGIN big udp -- everything may look "open" if packet-filtered'
37data -g < ${DDIR}/nfs-0.d | $UCMD -i 1 -u "$1" 2049 | od -x 2>&1
38# no wait-time, uses RTT hack
39nc -v -z -u -r "$1" 111 66-70 88 53 87 161-164 121-123 213 49 2>&1
40nc -v -z -u -r "$1" 137-140 694-712 747-770 175-180 2103 510-530 2>&1
41echo '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!
44iscan "$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
46if nc -w 5 -z -u "$1" 111 ; then
47 showmount -e "$1" 2>&1
48 rpcinfo -p "$1" 2>&1
49fi
50exit 0
diff --git a/src/usr.bin/nc/scripts/web b/src/usr.bin/nc/scripts/web
new file mode 100644
index 0000000000..382b18e1e3
--- /dev/null
+++ b/src/usr.bin/nc/scripts/web
@@ -0,0 +1,148 @@
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
30if test "$1" = "" ; then
31 echo Needs hostname arg.
32 exit 1
33fi
34umask 022
35
36# optional PATH fixup
37# PATH=${HOME}:${PATH} ; export PATH
38
39test "${PAGER}" || PAGER=more
40BACKEND="nc -v -w 15"
41TMPAGE=/tmp/web$$
42host="$1"
43port="80"
44if test "$2" != "" ; then
45 port="$2"
46fi
47
48spec="/"
49specD="/"
50specF=''
51saving=''
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.
55rm -f ${TMPAGE}
56test -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.
60while 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
131done
132rm -f ${TMPAGE}
133exit 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...
diff --git a/src/usr.bin/nc/scripts/webproxy b/src/usr.bin/nc/scripts/webproxy
new file mode 100644
index 0000000000..cee2d29fd1
--- /dev/null
+++ b/src/usr.bin/nc/scripts/webproxy
@@ -0,0 +1,138 @@
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...
31PORT=8000
32# logfile spec: a real file or /dev/null if you don't care
33LFILE=${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.
41case "${1}${CLIENT}" in
42 "")
43 echo needs client hostname
44 exit 1
45 ;;
46esac
47
48case "${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 ;;
57esac
58
59# no client yet and had an arg, this checking can be much slower now
60umask 077
61
62if 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
97fi
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# <newline>
104
105read x1 x2 x3 x4
106echo "=== query: $x1 $x2 $x3 $x4" >> $LFILE
107test "$x4" && echo "extra junk after request: $x4" && exit 0
108# nuke questionable characters and split up the request
109hurl=`echo "$x2" | sed -e "s+.*//++" -e 's+[\`'\''|$;<>{}\\!*()"]++g'`
110# echo massaged hurl: $hurl >> $LFILE
111hh=`echo "$hurl" | sed -e "s+/.*++" -e "s+:.*++"`
112hp=`echo "$hurl" | sed -e "s+.*:++" -e "s+/.*++"`
113test "$hp" = "$hh" && hp=80
114hf=`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...
118if 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
125fi
126# check for non-GET *after* we log the query...
127test "$x1" != "GET" && echo "sorry, this proxy only does GETs" && exit 0
128# no, you can *not* phone home, you miserable piece of shit
129test "`echo $hh | fgrep -i netscap`" && \
130 echo "access to Netscam's servers <b>DENIED.</b>" && 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...
134echo "$x1 $hf" | nc -w 30 "$hh" "$hp" 2> /dev/null || \
135 echo "oops, can't get to $hh : $hp".
136echo "sent \"$x1 $hf\" to $hh : $hp" >> $LFILE
137exit 0
138
diff --git a/src/usr.bin/nc/scripts/webrelay b/src/usr.bin/nc/scripts/webrelay
new file mode 100644
index 0000000000..829a8b0708
--- /dev/null
+++ b/src/usr.bin/nc/scripts/webrelay
@@ -0,0 +1,44 @@
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...
12PORT=8000
13# any extra args to the listening "nc", for instance "-s inside-net-addr"
14XNC=''
15
16# functionality switch, which has to be done fast to start the next listener
17case "${1}${RDEST}" in
18 "")
19 echo needs hostname
20 exit 1
21 ;;
22esac
23
24case "${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 ;;
31esac
32
33# Fall here for setup; this can now be slower.
34RDEST="$1"
35RPORT="$2"
36test "$RPORT" || RPORT=80
37export 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.
41nc -v -w 600 -l -p $PORT -e "$0" $XNC < /dev/null > /dev/null &
42echo \
43 "Relay to ${RDEST}:${RPORT} running -- point your browser here on port $PORT"
44exit 0
diff --git a/src/usr.bin/nc/scripts/websearch b/src/usr.bin/nc/scripts/websearch
new file mode 100644
index 0000000000..60c3a3356a
--- /dev/null
+++ b/src/usr.bin/nc/scripts/websearch
@@ -0,0 +1,77 @@
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
11test "${1}" = "" && echo 'Needs argument[s] to search for!' && exit 1
12PLUSARG="`echo $* | sed 's/ /+/g'`"
13PIPEARG="`echo ${PLUSARG} | sed 's/+/|/g'`"
14IFILE=/tmp/.webq.$$
15
16# Don't have "nc"? Get "netcat" from avian.org and add it to your toolkit.
17doquery () {
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
23echo "=== Yahoo ==="
24doquery "/bin/search?p=${PLUSARG}&n=300&w=w&s=a" search.yahoo.com 80
25
26echo '' ; echo "=== Webcrawler ==="
27doquery "/cgi-bin/WebQuery?searchText=${PLUSARG}&maxHits=300" webcrawler.com 80
28
29# the infoseek lamers want "registration" before they do a real search, but...
30echo '' ; echo "=== Infoseek ==="
31echo " 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??
41echo '' ; echo "=== Opentext ==="
42doquery "/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
47echo '' ; echo "=== Inktomi ==="
48doquery "/query/?query=${PLUSARG}&hits=100" ink3.cs.berkeley.edu 1234 | \
49 sed '/^<IMG ALT.*inktomi.*\.gif">$/d'
50
51#djnews lame shit limits hits to 120 and has nonstandard format
52echo '' ; echo "=== Dejanews ==="
53doquery "/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:
62echo \
63"GET /cgi-bin/pursuit?query=${PLUSARG}&maxhits=300&terse=terse&matchmode=and&minscore=.5 HTTP/1.x" \
64 > $IFILE
65echo "User-agent: *FUCK OFF*" >> $IFILE
66echo "Why: go ask todd@pointcom.com (Todd Whitney)" >> $IFILE
67echo '' >> $IFILE
68echo '' ; echo "=== Lycos ==="
69nc -v -i 1 -w 30 twelve.srv.lycos.com 80 < $IFILE
70
71rm -f $IFILE
72exit 0
73
74# CURRENTLY BROKEN [?]
75# infoseek
76
77# some args need to be redone to ensure whatever "and" mode applies