diff options
author | deraadt <> | 1996-09-05 08:55:43 +0000 |
---|---|---|
committer | deraadt <> | 1996-09-05 08:55:43 +0000 |
commit | c7823c0917675fd1ab482937ee1bd01d837b081c (patch) | |
tree | de25439975bbe0baac0f70799dad301539b7be3b /src/usr.bin | |
parent | c215a9e8412ead0190b788622f09bcdbb08794fa (diff) | |
download | openbsd-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')
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 | |||
4 | CFLAGS+= -DTELNET | ||
5 | PROG= nc | ||
6 | SRCS= 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 @@ | |||
1 | Netcat 1.10 | ||
2 | =========== /\_/\ | ||
3 | / 0 0 \ | ||
4 | Netcat is a simple Unix utility which reads and writes data ====v==== | ||
5 | across network connections, using TCP or UDP protocol. \ W / | ||
6 | It is designed to be a reliable "back-end" tool that can | | _ | ||
7 | be used directly or easily driven by other programs and / ___ \ / | ||
8 | scripts. At the same time, it is a feature-rich network / / \ \ | | ||
9 | debugging and exploration tool, since it can create almost (((-----)))-' | ||
10 | any kind of connection you would need and has several / | ||
11 | interesting built-in capabilities. Netcat, or "nc" as the ( ___ | ||
12 | actual program is named, should have been supplied long ago \__.=|___E | ||
13 | as another one of those cryptic but standard Unix tools. / | ||
14 | |||
15 | In the simplest usage, "nc host port" creates a TCP connection to the given | ||
16 | port on the given target host. Your standard input is then sent to the host, | ||
17 | and anything that comes back across the connection is sent to your standard | ||
18 | output. This continues indefinitely, until the network side of the connection | ||
19 | shuts down. Note that this behavior is different from most other applications | ||
20 | which shut everything down and exit after an end-of-file on the standard input. | ||
21 | |||
22 | Netcat can also function as a server, by listening for inbound connections | ||
23 | on arbitrary ports and then doing the same reading and writing. With minor | ||
24 | limitations, netcat doesn't really care if it runs in "client" or "server" | ||
25 | mode -- it still shovels data back and forth until there isn't any more left. | ||
26 | In either mode, shutdown can be forced after a configurable time of inactivity | ||
27 | on the network side. | ||
28 | |||
29 | And it can do this via UDP too, so netcat is possibly the "udp telnet-like" | ||
30 | application you always wanted for testing your UDP-mode servers. UDP, as the | ||
31 | "U" implies, gives less reliable data transmission than TCP connections and | ||
32 | some systems may have trouble sending large amounts of data that way, but it's | ||
33 | still a useful capability to have. | ||
34 | |||
35 | You may be asking "why not just use telnet to connect to arbitrary ports?" | ||
36 | Valid question, and here are some reasons. Telnet has the "standard input | ||
37 | EOF" problem, so one must introduce calculated delays in driving scripts to | ||
38 | allow network output to finish. This is the main reason netcat stays running | ||
39 | until the *network* side closes. Telnet also will not transfer arbitrary | ||
40 | binary data, because certain characters are interpreted as telnet options and | ||
41 | are thus removed from the data stream. Telnet also emits some of its | ||
42 | diagnostic messages to standard output, where netcat keeps such things | ||
43 | religiously separated from its *output* and will never modify any of the real | ||
44 | data in transit unless you *really* want it to. And of course telnet is | ||
45 | incapable of listening for inbound connections, or using UDP instead. Netcat | ||
46 | doesn't have any of these limitations, is much smaller and faster than telnet, | ||
47 | and has many other advantages. | ||
48 | |||
49 | Some 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 | |||
63 | Efforts have been made to have netcat "do the right thing" in all its various | ||
64 | modes. If you believe that it is doing the wrong thing under whatever | ||
65 | circumstances, please notify me and tell me how you think it should behave. | ||
66 | If netcat is not able to do some task you think up, minor tweaks to the code | ||
67 | will probably fix that. It provides a basic and easily-modified template for | ||
68 | writing other network applications, and I certainly encourage people to make | ||
69 | custom mods and send in any improvements they make to it. This is the second | ||
70 | release; the overall differences from 1.00 are relatively minor and have mostly | ||
71 | to do with portability and bugfixes. Many people provided greatly appreciated | ||
72 | fixes and comments on the 1.00 release. Continued feedback from the Internet | ||
73 | community is always welcome! | ||
74 | |||
75 | Netcat is entirely my own creation, although plenty of other code was used as | ||
76 | examples. It is freely given away to the Internet community in the hope that | ||
77 | it will be useful, with no restrictions except giving credit where it is due. | ||
78 | No GPLs, Berkeley copyrights or any of that nonsense. The author assumes NO | ||
79 | responsibility for how anyone uses it. If netcat makes you rich somehow and | ||
80 | you're feeling generous, mail me a check. If you are affiliated in any way | ||
81 | with Microsoft Network, get a life. Always ski in control. Comments, | ||
82 | questions, and patches to hobbit@avian.org. | ||
83 | |||
84 | Building | ||
85 | ======== | ||
86 | |||
87 | Compiling is fairly straightforward. Examine the Makefile for a SYSTYPE that | ||
88 | matches yours, and do "make <systype>". The executable "nc" should appear. | ||
89 | If there is no relevant SYSTYPE section, try "generic". If you create new | ||
90 | sections for generic.h and Makefile to support another platform, please follow | ||
91 | the given format and mail back the diffs. | ||
92 | |||
93 | There are a couple of other settable #defines in netcat.c, which you can | ||
94 | include as DFLAGS="-DTHIS -DTHAT" to your "make" invocation without having to | ||
95 | edit the Makefile. See the following discussions for what they are and do. | ||
96 | |||
97 | If you want to link against the resolver library on SunOS [recommended] and | ||
98 | you have BIND 4.9.x, you may need to change XLIBS=-lresolv in the Makefile to | ||
99 | XLIBS="-lresolv -l44bsd". | ||
100 | |||
101 | Linux sys/time.h does not really support presetting of FD_SETSIZE; a harmless | ||
102 | warning is issued. | ||
103 | |||
104 | Some systems may warn about pointer types for signal(). No problem, though. | ||
105 | |||
106 | Exploration of features | ||
107 | ======================= | ||
108 | |||
109 | Where to begin? Netcat is at the same time so simple and versatile, it's like | ||
110 | trying to describe everything you can do with your Swiss Army knife. This will | ||
111 | go over the basics; you should also read the usage examples and notes later on | ||
112 | which may give you even more ideas about what this sort of tool is good for. | ||
113 | |||
114 | If no command arguments are given at all, netcat asks for them, reads a line | ||
115 | from standard input, and breaks it up into arguments internally. This can be | ||
116 | useful when driving netcat from certain types of scripts, with the side effect | ||
117 | of hiding your command line arguments from "ps" displays. | ||
118 | |||
119 | The host argument can be a name or IP address. If -n is specified, netcat | ||
120 | will 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 | ||
122 | name and address lookup for the host, and warn you about the all-too-common | ||
123 | problem of mismatched names in the DNS. This often takes a little longer for | ||
124 | connection setup, but is useful to know about. There are circumstances under | ||
125 | which this can *save* time, such as when you want to know the name for some IP | ||
126 | address and also connect there. Netcat will just tell you all about it, saving | ||
127 | the manual steps of looking up the hostname yourself. Normally mismatch- | ||
128 | checking is case-insensitive per the DNS spec, but you can define ANAL at | ||
129 | compile time to make it case-sensitive -- sometimes useful for uncovering minor | ||
130 | errors in your own DNS files while poking around your networks. | ||
131 | |||
132 | A port argument is required for outbound connections, and can be numeric or a | ||
133 | name as listed in /etc/services. If -n is specified, only numeric arguments | ||
134 | are valid. Special syntax and/or more than one port argument cause different | ||
135 | behavior -- see details below about port-scanning. | ||
136 | |||
137 | The -v switch controls the verbosity level of messages sent to standard error. | ||
138 | You will probably want to run netcat most of the time with -v turned on, so you | ||
139 | can see info about the connections it is trying to make. You will probably | ||
140 | also want to give a smallish -w argument, which limits the time spent trying to | ||
141 | make a connection. I usually alias "nc" to "nc -v -w 3", which makes it | ||
142 | function just about the same for things I would otherwise use telnet to do. | ||
143 | The timeout is easily changed by a subsequent -w argument which overrides the | ||
144 | earlier one. Specifying -v more than once makes diagnostic output MORE | ||
145 | verbose. If -v is not specified at all, netcat silently does its work unless | ||
146 | some error happens, whereupon it describes the error and exits with a nonzero | ||
147 | status. Refused network connections are generally NOT considered to be errors, | ||
148 | unless you only asked for a single TCP port and it was refused. | ||
149 | |||
150 | Note that -w also sets the network inactivity timeout. This does not have any | ||
151 | effect until standard input closes, but then if nothing further arrives from | ||
152 | the network in the next <timeout> seconds, netcat tries to read the net once | ||
153 | more for good measure, and then closes and exits. There are a lot of network | ||
154 | services now that accept a small amount of input and return a large amount of | ||
155 | output, such as Gopher and Web servers, which is the main reason netcat was | ||
156 | written to "block" on the network staying open rather than standard input. | ||
157 | Handling the timeout this way gives uniform behavior with network servers that | ||
158 | *don't* close by themselves until told to. | ||
159 | |||
160 | UDP connections are opened instead of TCP when -u is specified. These aren't | ||
161 | really "connections" per se since UDP is a connectionless protocol, although | ||
162 | netcat does internally use the "connected UDP socket" mechanism that most | ||
163 | kernels support. Although netcat claims that an outgoing UDP connection is | ||
164 | "open" immediately, no data is sent until something is read from standard | ||
165 | input. Only thereafter is it possible to determine whether there really is a | ||
166 | UDP server on the other end, and often you just can't tell. Most UDP protocols | ||
167 | use timeouts and retries to do their thing and in many cases won't bother | ||
168 | answering at all, so you should specify a timeout and hope for the best. You | ||
169 | will get more out of UDP connections if standard input is fed from a source | ||
170 | of data that looks like various kinds of server requests. | ||
171 | |||
172 | To obtain a hex dump file of the data sent either way, use "-o logfile". The | ||
173 | dump 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 | ||
175 | representations of the traffic. Capturing a hex dump naturally slows netcat | ||
176 | down a bit, so don't use it where speed is critical. | ||
177 | |||
178 | Netcat can bind to any local port, subject to privilege restrictions and ports | ||
179 | that are already in use. It is also possible to use a specific local network | ||
180 | source address if it is that of a network interface on your machine. [Note: | ||
181 | this does not work correctly on all platforms.] Use "-p portarg" to grab a | ||
182 | specific local port, and "-s ip-addr" or "-s name" to have that be your source | ||
183 | IP address. This is often referred to as "anchoring the socket". Root users | ||
184 | can grab any unused source port including the "reserved" ones less than 1024. | ||
185 | Absence of -p will bind to whatever unused port the system gives you, just like | ||
186 | any other normal client connection, unless you use -r [see below]. | ||
187 | |||
188 | Listen mode will cause netcat to wait for an inbound connection, and then the | ||
189 | same data transfer happens. Thus, you can do "nc -l -p 1234 < filename" and | ||
190 | when someone else connects to your port 1234, the file is sent to them whether | ||
191 | they wanted it or not. Listen mode is generally used along with a local port | ||
192 | argument -- this is required for UDP mode, while TCP mode can have the system | ||
193 | assign one and tell you what it is if -v is turned on. If you specify a target | ||
194 | host and optional port in listen mode, netcat will accept an inbound connection | ||
195 | only from that host and if you specify one, only from that foreign source port. | ||
196 | In verbose mode you'll be informed about the inbound connection, including what | ||
197 | address and port it came from, and since listening on "any" applies to several | ||
198 | possibilities, which address it came *to* on your end. If the system supports | ||
199 | IP socket options, netcat will attempt to retrieve any such options from an | ||
200 | inbound connection and print them out in hex. | ||
201 | |||
202 | If netcat is compiled with -DGAPING_SECURITY_HOLE, the -e argument specifies | ||
203 | a program to exec after making or receiving a successful connection. In the | ||
204 | listening mode, this works similarly to "inetd" but only for a single instance. | ||
205 | Use with GREAT CARE. This piece of the code is normally not enabled; if you | ||
206 | know what you're doing, have fun. This hack also works in UDP mode. Note that | ||
207 | you can only supply -e with the name of the program, but no arguments. If you | ||
208 | want to launch something with an argument list, write a two-line wrapper script | ||
209 | or just use inetd like always. | ||
210 | |||
211 | If netcat is compiled with -DTELNET, the -t argument enables it to respond | ||
212 | to telnet option negotiation [always in the negative, i.e. DONT or WONT]. | ||
213 | This allows it to connect to a telnetd and get past the initial negotiation | ||
214 | far enough to get a login prompt from the server. Since this feature has | ||
215 | the potential to modify the data stream, it is not enabled by default. You | ||
216 | have to understand why you might need this and turn on the #define yourself. | ||
217 | |||
218 | Data from the network connection is always delivered to standard output as | ||
219 | efficiently as possible, using large 8K reads and writes. Standard input is | ||
220 | normally sent to the net the same way, but the -i switch specifies an "interval | ||
221 | time" which slows this down considerably. Standard input is still read in | ||
222 | large batches, but netcat then tries to find where line breaks exist and sends | ||
223 | one line every interval time. Note that if standard input is a terminal, data | ||
224 | is already read line by line, so unless you make the -i interval rather long, | ||
225 | what you type will go out at a fairly normal rate. -i is really designed | ||
226 | for use when you want to "measure out" what is read from files or pipes. | ||
227 | |||
228 | Port-scanning is a popular method for exploring what's out there. Netcat | ||
229 | accepts its commands with options first, then the target host, and everything | ||
230 | thereafter is interpreted as port names or numbers, or ranges of ports in M-N | ||
231 | syntax. CAVEAT: some port names in /etc/services contain hyphens -- netcat | ||
232 | currently will not correctly parse those, so specify ranges using numbers if | ||
233 | you can. If more than one port is thus specified, netcat connects to *all* of | ||
234 | them, sending the same batch of data from standard input [up to 8K worth] to | ||
235 | each one that is successfully connected to. Specifying multiple ports also | ||
236 | suppresses diagnostic messages about refused connections, unless -v is | ||
237 | specified twice for "more verbosity". This way you normally get notified only | ||
238 | about genuinely open connections. Example: "nc -v -w 2 -z target 20-30" will | ||
239 | try connecting to every port between 20 and 30 [inclusive] at the target, and | ||
240 | will likely inform you about an FTP server, telnet server, and mailer along the | ||
241 | way. The -z switch prevents sending any data to a TCP connection and very | ||
242 | limited probe data to a UDP connection, and is thus useful as a fast scanning | ||
243 | mode just to see what ports the target is listening on. To limit scanning | ||
244 | speed if desired, -i will insert a delay between each port probe. There are | ||
245 | some pitfalls with regard to UDP scanning, described later, but in general it | ||
246 | works well. | ||
247 | |||
248 | For each range of ports specified, scanning is normally done downward within | ||
249 | that range. If the -r switch is used, scanning hops randomly around within | ||
250 | that range and reports open ports as it finds them. [If you want them listed | ||
251 | in order regardless, pipe standard error through "sort"...] In addition, if | ||
252 | random mode is in effect, the local source ports are also randomized. This | ||
253 | prevents netcat from exhibiting any kind of regular pattern in its scanning. | ||
254 | You can exert fairly fine control over your scan by judicious use of -r and | ||
255 | selected port ranges to cover. If you use -r for a single connection, the | ||
256 | source port will have a random value above 8192, rather than the next one the | ||
257 | kernel would have assigned you. Note that selecting a specific local port | ||
258 | with -p overrides any local-port randomization. | ||
259 | |||
260 | Many people are interested in testing network connectivity using IP source | ||
261 | routing, even if it's only to make sure their own firewalls are blocking | ||
262 | source-routed packets. On systems that support it, the -g switch can be used | ||
263 | multiple times [up to 8] to construct a loose-source-routed path for your | ||
264 | connection, and the -G argument positions the "hop pointer" within the list. | ||
265 | If your network allows source-routed traffic in and out, you can test | ||
266 | connectivity to your own services via remote points in the internet. Note that | ||
267 | although newer BSD-flavor telnets also have source-routing capability, it isn't | ||
268 | clearly documented and the command syntax is somewhat clumsy. Netcat's | ||
269 | handling of "-g" is modeled after "traceroute". | ||
270 | |||
271 | Netcat tries its best to behave just like "cat". It currently does nothing to | ||
272 | terminal input modes, and does no end-of-line conversion. Standard input from | ||
273 | a terminal is read line by line with normal editing characters in effect. You | ||
274 | can freely suspend out of an interactive connection and resume. ^C or whatever | ||
275 | your interrupt character is will make netcat close the network connection and | ||
276 | exit. A switch to place the terminal in raw mode has been considered, but so | ||
277 | far has not been necessary. You can send raw binary data by reading it out of | ||
278 | a file or piping from another program, so more meaningful effort would be spent | ||
279 | writing an appropriate front-end driver. | ||
280 | |||
281 | Netcat is not an "arbitrary packet generator", but the ability to talk to raw | ||
282 | sockets and/or nit/bpf/dlpi may appear at some point. Such things are clearly | ||
283 | useful; I refer you to Darren Reed's excellent ip_filter package, which now | ||
284 | includes a tool to construct and send raw packets with any contents you want. | ||
285 | |||
286 | Example uses -- the light side | ||
287 | ============================== | ||
288 | |||
289 | Again, this is a very partial list of possibilities, but it may get you to | ||
290 | think up more applications for netcat. Driving netcat with simple shell or | ||
291 | expect scripts is an easy and flexible way to do fairly complex tasks, | ||
292 | especially if you're not into coding network tools in C. My coding isn't | ||
293 | particularly strong either [although undoubtedly better after writing this | ||
294 | thing!], so I tend to construct bare-metal tools like this that I can trivially | ||
295 | plug into other applications. Netcat doubles as a teaching tool -- one can | ||
296 | learn a great deal about more complex network protocols by trying to simulate | ||
297 | them through raw connections! | ||
298 | |||
299 | An example of netcat as a backend for something else is the shell-script | ||
300 | Web 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 | ||
302 | with telnet, and had to use calculated sleep times and other stupidity to | ||
303 | kludge around telnet's limitations. Netcat guarantees that I get the whole | ||
304 | page, and since it transfers all the data unmodified, I can even pull down | ||
305 | binary image files and display them elsewhere later. Some folks may find the | ||
306 | idea of a shell-script web browser silly and strange, but it starts up and | ||
307 | gets me my info a hell of a lot faster than a GUI browser and doesn't hide | ||
308 | any contents of links and forms and such. This is included, as scripts/web, | ||
309 | along with several other web-related examples. | ||
310 | |||
311 | Netcat is an obvious replacement for telnet as a tool for talking to daemons. | ||
312 | For example, it is easier to type "nc host 25", talk to someone's mailer, and | ||
313 | just ^C out than having to type ^]c or QUIT as telnet would require you to do. | ||
314 | You can quickly catalog the services on your network by telling netcat to | ||
315 | connect to well-known services and collect greetings, or at least scan for open | ||
316 | ports. You'll probably want to collect netcat's diagnostic messages in your | ||
317 | output files, so be sure to include standard error in the output using | ||
318 | `>& file' in *csh or `> file 2>&1' in bourne shell. | ||
319 | |||
320 | A scanning example: "echo QUIT | nc -v -w 5 target 20-250 500-600 5990-7000" | ||
321 | will inform you about a target's various well-known TCP servers, including | ||
322 | r-services, X, IRC, and maybe a few you didn't expect. Sending in QUIT and | ||
323 | using the timeout will almost guarantee that you see some kind of greeting or | ||
324 | error 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 | ||
326 | collect host information, and indeed some of the ideas herein were taken from | ||
327 | the SATAN backend tools. If you script this up to try every host in your | ||
328 | subnet space and just let it run, you will not only see all the services, | ||
329 | you'll find out about hosts that aren't correctly listed in your DNS. Then you | ||
330 | can compare new snapshots against old snapshots to see changes. For going | ||
331 | after particular services, a more intrusive example is in scripts/probe. | ||
332 | |||
333 | Netcat can be used as a simple data transfer agent, and it doesn't really | ||
334 | matter which end is the listener and which end is the client -- input at one | ||
335 | side arrives at the other side as output. It is helpful to start the listener | ||
336 | at the receiving side with no timeout specified, and then give the sending side | ||
337 | a small timeout. That way the listener stays listening until you contact it, | ||
338 | and after data stops flowing the client will time out, shut down, and take the | ||
339 | listener with it. Unless the intervening network is fraught with problems, | ||
340 | this should be completely reliable, and you can always increase the timeout. A | ||
341 | typical example of something "rsh" is often used for: on one side, | ||
342 | |||
343 | nc -l -p 1234 | uncompress -c | tar xvfp - | ||
344 | |||
345 | and then on the other side | ||
346 | |||
347 | tar cfp - /some/dir | compress -c | nc -w 3 othermachine 1234 | ||
348 | |||
349 | will transfer the contents of a directory from one machine to another, without | ||
350 | having to worry about .rhosts files, user accounts, or inetd configurations | ||
351 | at 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 | ||
353 | could conceivably use a scheme like this for backups, by having cron-jobs fire | ||
354 | up listeners and backup handlers [which can be restricted to specific addresses | ||
355 | and ports between each other] and pipe "dump" or "tar" on one machine to "dd | ||
356 | of=/dev/tapedrive" on another as usual. Since netcat returns a nonzero exit | ||
357 | status for a denied listener connection, scripts to handle such tasks could | ||
358 | easily log and reject connect attempts from third parties, and then retry. | ||
359 | |||
360 | Another simple data-transfer example: shipping things to a PC that doesn't have | ||
361 | any network applications yet except a TCP stack and a web browser. Point the | ||
362 | browser at an arbitrary port on a Unix server by telling it to download | ||
363 | something like http://unixbox:4444/foo, and have a listener on the Unix side | ||
364 | ready to ship out a file when the connect comes in. The browser may pervert | ||
365 | binary data when told to save the URL, but you can dig the raw data out of | ||
366 | the on-disk cache. | ||
367 | |||
368 | If 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 | ||
370 | run under "inetd". A script or program will have its input and output hooked | ||
371 | to the network the same way, perhaps sans some fancier signal handling. Given | ||
372 | that most network services do not bind to a particular local address, whether | ||
373 | they are under "inetd" or not, it is possible for netcat avoid the "address | ||
374 | already in use" error by binding to a specific address. This lets you [as | ||
375 | root, for low ports] place netcat "in the way" of a standard service, since | ||
376 | inbound connections are generally sent to such specifically-bound listeners | ||
377 | first and fall back to the ones bound to "any". This allows for a one-off | ||
378 | experimental simulation of some service, without having to screw around with | ||
379 | inetd.conf. Running with -v turned on and collecting a connection log from | ||
380 | standard error is recommended. | ||
381 | |||
382 | Netcat as well can make an outbound connection and then run a program or script | ||
383 | on the originating end, with input and output connected to the same network | ||
384 | port. This "inverse inetd" capability could enhance the backup-server concept | ||
385 | described above or help facilitate things such as a "network dialback" concept. | ||
386 | The possibilities are many and varied here; if such things are intended as | ||
387 | security mechanisms, it may be best to modify netcat specifically for the | ||
388 | purpose instead of wrapping such functions in scripts. | ||
389 | |||
390 | Speaking of inetd, netcat will function perfectly well *under* inetd as a TCP | ||
391 | connection redirector for inbound services, like a "plug-gw" without the | ||
392 | authentication step. This is very useful for doing stuff like redirecting | ||
393 | traffic through your firewall out to other places like web servers and mail | ||
394 | hubs, while posing no risk to the firewall machine itself. Put netcat behind | ||
395 | inetd and tcp_wrappers, perhaps thusly: | ||
396 | |||
397 | www stream tcp nowait nobody /etc/tcpd /bin/nc -w 3 realwww 80 | ||
398 | |||
399 | and you have a simple and effective "application relay" with access control | ||
400 | and logging. Note use of the wait time as a "safety" in case realwww isn't | ||
401 | reachable or the calling user aborts the connection -- otherwise the relay may | ||
402 | hang there forever. | ||
403 | |||
404 | You can use netcat to generate huge amounts of useless network data for | ||
405 | various performance testing. For example, doing | ||
406 | |||
407 | yes AAAAAAAAAAAAAAAAAAAAAA | nc -v -v -l -p 2222 > /dev/null | ||
408 | |||
409 | on one side and then hitting it with | ||
410 | |||
411 | yes BBBBBBBBBBBBBBBBBBBBBB | nc othermachine 2222 > /dev/null | ||
412 | |||
413 | from another host will saturate your wires with A's and B's. The "very | ||
414 | verbose" switch usage will tell you how many of each were sent and received | ||
415 | after you interrupt either side. Using UDP mode produces tremendously MORE | ||
416 | trash per unit time in the form of fragmented 8 Kbyte mobygrams -- enough to | ||
417 | stress-test kernels and network interfaces. Firing random binary data into | ||
418 | various network servers may help expose bugs in their input handling, which | ||
419 | nowadays is a popular thing to explore. A simple example data-generator is | ||
420 | given in data/data.c included in this package, along with a small collection | ||
421 | of canned input files to generate various packet contents. This program is | ||
422 | documented in its beginning comments, but of interest here is using "%r" to | ||
423 | generate random bytes at well-chosen points in a data stream. If you can | ||
424 | crash your daemon, you likely have a security problem. | ||
425 | |||
426 | The hex dump feature may be useful for debugging odd network protocols, | ||
427 | especially if you don't have any network monitoring equipment handy or aren't | ||
428 | root where you'd need to run "tcpdump" or something. Bind a listening netcat | ||
429 | to a local port, and have it run a script which in turn runs another netcat | ||
430 | to the real service and captures the hex dump to a log file. This sets up a | ||
431 | transparent relay between your local port and wherever the real service is. | ||
432 | Be sure that the script-run netcat does *not* use -v, or the extra info it | ||
433 | sends to standard error may confuse the protocol. Note also that you cannot | ||
434 | have the "listen/exec" netcat do the data capture, since once the connection | ||
435 | arrives it is no longer netcat that is running. | ||
436 | |||
437 | Binding to an arbitrary local port allows you to simulate things like r-service | ||
438 | clients, 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 | ||
440 | pair] into a "rsh" or "rlogin" server, FROM your port 1023 for example, | ||
441 | duplicates 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 | ||
443 | your client machine. The program data/rservice.c can aid this process by | ||
444 | constructing the "rcmd" protocol bytes. Doing this also prevents "rshd" from | ||
445 | trying to create that separate standard-error socket and still gives you an | ||
446 | input path, as opposed to the usual action of "rsh -n". Using netcat for | ||
447 | things like this can be really useful sometimes, because rsh and rlogin | ||
448 | generally want a host *name* as an argument and won't accept IP addresses. If | ||
449 | your client-end DNS is hosed, as may be true when you're trying to extract | ||
450 | backup sets on to a dumb client, "netcat -n" wins where normal rsh/rlogin is | ||
451 | useless. | ||
452 | |||
453 | If you are unsure that a remote syslogger is working, test it with netcat. | ||
454 | Make a UDP connection to port 514 and type in "<0>message", which should | ||
455 | correspond to "kern.emerg" and cause syslogd to scream into every file it has | ||
456 | open [and possibly all over users' terminals]. You can tame this down by | ||
457 | using a different number and use netcat inside routine scripts to send syslog | ||
458 | messages 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 | ||
460 | on loggerhost. The exact number may vary; check against your syslog.h first. | ||
461 | |||
462 | Netcat provides several ways for you to test your own packet filters. If you | ||
463 | bind to a port normally protected against outside access and make a connection | ||
464 | to somewhere outside your own network, the return traffic will be coming to | ||
465 | your chosen port from the "outside" and should be blocked. TCP may get through | ||
466 | if your filter passes all "ack syn", but it shouldn't be even doing that to low | ||
467 | ports on your network. Remember to test with UDP traffic as well! If your | ||
468 | filter passes at least outbound source-routed IP packets, bouncing a connection | ||
469 | back to yourself via some gateway outside your network will create "incoming" | ||
470 | traffic with your source address, which should get dropped by a correctly | ||
471 | configured anti-spoofing filter. This is a "non-test" if you're also dropping | ||
472 | source-routing, but it's good to be able to test for that too. Any packet | ||
473 | filter worth its salt will be blocking source-routed packets in both | ||
474 | directions, but you never know what interesting quirks you might turn up by | ||
475 | playing around with source ports and addresses and watching the wires with a | ||
476 | network monitor. | ||
477 | |||
478 | You can use netcat to protect your own workstation's X server against outside | ||
479 | access. X is stupid enough to listen for connections on "any" and never tell | ||
480 | you when new connections arrive, which is one reason it is so vulnerable. Once | ||
481 | you have all your various X windows up and running you can use netcat to bind | ||
482 | just to your ethernet address and listen to port 6000. Any new connections | ||
483 | from outside the machine will hit netcat instead your X server, and you get a | ||
484 | log of who's trying. You can either tell netcat to drop the connection, or | ||
485 | perhaps 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 | ||
487 | possible to authorize your X terminal only for its boot server, and run a relay | ||
488 | netcat over on the server that will in turn talk to your X terminal. Since | ||
489 | netcat only handles one listening connection per run, make sure that whatever | ||
490 | way you rig it causes another one to run and listen on 6000 soon afterward, or | ||
491 | your real X server will be reachable once again. A very minimal script just | ||
492 | to protect yourself could be | ||
493 | |||
494 | while true ; do | ||
495 | nc -v -l -s <your-addr> -p 6000 localhost 2 | ||
496 | done | ||
497 | |||
498 | which causes netcat to accept and then close any inbound connection to your | ||
499 | workstation's normal ethernet address, and another copy is immediately run by | ||
500 | the script. Send standard error to a file for a log of connection attempts. | ||
501 | If your system can't do the "specific bind" thing all is not lost; run your | ||
502 | X server on display ":1" or port 6001, and netcat can still function as a probe | ||
503 | alarm by listening on 6000. | ||
504 | |||
505 | Does your shell-account provider allow personal Web pages, but not CGI scripts? | ||
506 | You can have netcat listen on a particular port to execute a program or script | ||
507 | of your choosing, and then just point to the port with a URL in your homepage. | ||
508 | The listener could even exist on a completely different machine, avoiding the | ||
509 | potential ire of the homepage-host administrators. Since the script will get | ||
510 | the raw browser query as input it won't look like a typical CGI script, and | ||
511 | since it's running under your UID you need to write it carefully. You may want | ||
512 | to write a netcat-based script as a wrapper that reads a query and sets up | ||
513 | environment variables for a regular CGI script. The possibilities for using | ||
514 | netcat and scripts to handle Web stuff are almost endless. Again, see the | ||
515 | examples under scripts/. | ||
516 | |||
517 | Example uses -- the dark side | ||
518 | ============================= | ||
519 | |||
520 | Equal time is deserved here, since a versatile tool like this can be useful | ||
521 | to any Shade of Hat. I could use my Victorinox to either fix your car or | ||
522 | disassemble it, right? You can clearly use something like netcat to attack | ||
523 | or defend -- I don't try to govern anyone's social outlook, I just build tools. | ||
524 | Regardless of your intentions, you should still be aware of these threats to | ||
525 | your own systems. | ||
526 | |||
527 | The first obvious thing is scanning someone *else's* network for vulnerable | ||
528 | services. Files containing preconstructed data, be it exploratory or | ||
529 | exploitive, can be fed in as standard input, including command-line arguments | ||
530 | to netcat itself to keep "ps" ignorant of your doings. The more random the | ||
531 | scanning, the less likelihood of detection by humans, scan-detectors, or | ||
532 | dynamic filtering, and with -i you'll wait longer but avoid loading down the | ||
533 | target's network. Some examples for crafting various standard UDP probes are | ||
534 | given in data/*.d. | ||
535 | |||
536 | Some configurations of packet filters attempt to solve the FTP-data problem by | ||
537 | just allowing such connections from the outside. These come FROM port 20, TO | ||
538 | high TCP ports inside -- if you locally bind to port 20, you may find yourself | ||
539 | able to bypass filtering in some cases. Maybe not to low ports "inside", but | ||
540 | perhaps to TCP NFS servers, X servers, Prospero, ciscos that listen on 200x | ||
541 | and 400x... Similar bypassing may be possible for UDP [and maybe TCP too] if a | ||
542 | connection comes from port 53; a filter may assume it's a nameserver response. | ||
543 | |||
544 | Using -e in conjunction with binding to a specific address can enable "server | ||
545 | takeover" by getting in ahead of the real ones, whereupon you can snarf data | ||
546 | sent in and feed your own back out. At the very least you can log a hex dump | ||
547 | of someone else's session. If you are root, you can certainly use -s and -e to | ||
548 | run various hacked daemons without having to touch inetd.conf or the real | ||
549 | daemons themselves. You may not always have the root access to deal with low | ||
550 | ports, but what if you are on a machine that also happens to be an NFS server? | ||
551 | You might be able to collect some interesting things from port 2049, including | ||
552 | local file handles. There are several other servers that run on high ports | ||
553 | that are likely candidates for takeover, including many of the RPC services on | ||
554 | some platforms [yppasswdd, anyone?]. Kerberos tickets, X cookies, and IRC | ||
555 | traffic also come to mind. RADIUS-based terminal servers connect incoming | ||
556 | users to shell-account machines on a high port, usually 1642 or thereabouts. | ||
557 | SOCKS servers run on 1080. Do "netstat -a" and get creative. | ||
558 | |||
559 | There are some daemons that are well-written enough to bind separately to all | ||
560 | the local interfaces, possibly with an eye toward heading off this sort of | ||
561 | problem. Named from recent BIND releases, and NTP, are two that come to mind. | ||
562 | Netstat will show these listening on address.53 instead of *.53. You won't | ||
563 | be able to get in front of these on any of the real interface addresses, which | ||
564 | of course is especially interesting in the case of named, but these servers | ||
565 | sometimes forget about things like "alias" interface addresses or interfaces | ||
566 | that appear later on such as dynamic PPP links. There are some hacked web | ||
567 | servers and versions of "inetd" floating around that specifically bind as well, | ||
568 | based on a configuration file -- these generally *are* bound to alias addresses | ||
569 | to offer several different address-based services from one machine. | ||
570 | |||
571 | Using -e to start a remote backdoor shell is another obvious sort of thing, | ||
572 | easier than constructing a file for inetd to listen on "ingreslock" or | ||
573 | something, and you can access-control it against other people by specifying a | ||
574 | client host and port. Experience with this truly demonstrates how fragile the | ||
575 | barrier between being "logged in" or not really is, and is further expressed by | ||
576 | scripts/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 | ||
578 | periodically try connecting to a known place and port, you can later listen | ||
579 | there until the inbound connection arrives, and there's your shell. Running | ||
580 | a 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 | ||
582 | connections and may not be quite as subtle as you wanted. Packets may also be | ||
583 | lost, so use TCP if you need reliable connections. But since UDP is | ||
584 | connectionless, a hookup of this sort will stick around almost forever, even if | ||
585 | you ^C out of netcat or do a reboot on your side, and you only need to remember | ||
586 | the ports you used on both ends to reestablish. And outbound UDP-plus-exec | ||
587 | connection creates the connected socket and starts the program immediately. On | ||
588 | a listening UDP connection, the socket is created once a first packet is | ||
589 | received. In either case, though, such a "connection" has the interesting side | ||
590 | effect that only your client-side IP address and [chosen?] source port will | ||
591 | thereafter be able to talk to it. Instant access control! A non-local third | ||
592 | party 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 | |||
599 | The companion program data/rservice.c is helpful in scripting up any sort of | ||
600 | r-service username or password guessing attack. The arguments to "rservice" | ||
601 | are simply the strings that get null-terminated and passed over an "rcmd"-style | ||
602 | connection, with the assumption that the client does not need a separate | ||
603 | standard-error port. Brute-force password banging is best done via "rexec" if | ||
604 | it 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 | ||
606 | the password is right, or "Permission denied." Plug in a dictionary and go to | ||
607 | town. If you're attacking rsh/rlogin, remember to be root and bind to a port | ||
608 | between 512 and 1023 on your end, and pipe in "rservice joe joe pwd" and such. | ||
609 | |||
610 | Netcat can prevent inadvertently sending extra information over a telnet | ||
611 | connection. Use "nc -t" in place of telnet, and daemons that try to ask for | ||
612 | things like USER and TERM environment variables will get no useful answers, as | ||
613 | they otherwise would from a more recent telnet program. Some telnetds actually | ||
614 | try to collect this stuff and then plug the USER variable into "login" so that | ||
615 | the caller is then just asked for a password! This mechanism could cause a | ||
616 | login attempt as YOUR real username to be logged over there if you use a | ||
617 | Borman-based telnet instead of "nc -t". | ||
618 | |||
619 | Got an unused network interface configured in your kernel [e.g. SLIP], or | ||
620 | support for alias addresses? Ifconfig one to be any address you like, and bind | ||
621 | to it with -s to enable all sorts of shenanigans with bogus source addresses. | ||
622 | The interface probably has to be UP before this works; some SLIP versions | ||
623 | need a far-end address before this is true. Hammering on UDP services is then | ||
624 | a no-brainer. What you can do to an unfiltered syslog daemon should be fairly | ||
625 | obvious; trimming the conf file can help protect against it. Many routers out | ||
626 | there still blindly believe what they receive via RIP and other routing | ||
627 | protocols. Although most UDP echo and chargen servers check if an incoming | ||
628 | packet was sent from *another* "internal" UDP server, there are many that still | ||
629 | do not, any two of which [or many, for that matter] could keep each other | ||
630 | entertained for hours at the expense of bandwidth. And you can always make | ||
631 | someone wonder why she's being probed by nsa.gov. | ||
632 | |||
633 | Your TCP spoofing possibilities are mostly limited to destinations you can | ||
634 | source-route to while locally bound to your phony address. Many sites block | ||
635 | source-routed packets these days for precisely this reason. If your kernel | ||
636 | does oddball things when sending source-routed packets, try moving the pointer | ||
637 | around with -G. You may also have to fiddle with the routing on your own | ||
638 | machine before you start receiving packets back. Warning: some machines still | ||
639 | send out traffic using the source address of the outbound interface, regardless | ||
640 | of your binding, especially in the case of localhost. Check first. If you can | ||
641 | open a connection but then get no data back from it, the target host is | ||
642 | probably killing the IP options on its end [this is an option inside TCP | ||
643 | wrappers and several other packages], which happens after the 3-way handshake | ||
644 | is completed. If you send some data and observe the "send-q" side of "netstat" | ||
645 | for that connection increasing but never getting sent, that's another symptom. | ||
646 | Beware: if Sendmail 8.7.x detects a source-routed SMTP connection, it extracts | ||
647 | the hop list and sticks it in the Received: header! | ||
648 | |||
649 | SYN bombing [sometimes called "hosing"] can disable many TCP servers, and if | ||
650 | you hit one often enough, you can keep it unreachable for days. As is true of | ||
651 | many other denial-of-service attacks, there is currently no defense against it | ||
652 | except maybe at the human level. Making kernel SOMAXCONN considerably larger | ||
653 | than the default and the half-open timeout smaller can help, and indeed some | ||
654 | people running large high-performance web servers have *had* to do that just to | ||
655 | handle normal traffic. Taking out mailers and web servers is sociopathic, but | ||
656 | on the other hand it is sometimes useful to be able to, say, disable a site's | ||
657 | identd daemon for a few minutes. If someone realizes what is going on, | ||
658 | backtracing will still be difficult since the packets have a phony source | ||
659 | address, but calls to enough ISP NOCs might eventually pinpoint the source. | ||
660 | It is also trivial for a clueful ISP to watch for or even block outgoing | ||
661 | packets with obviously fake source addresses, but as we know many of them are | ||
662 | not clueful or willing to get involved in such hassles. Besides, outbound | ||
663 | packets with an [otherwise unreachable] source address in one of their net | ||
664 | blocks would look fairly legitimate. | ||
665 | |||
666 | Notes | ||
667 | ===== | ||
668 | |||
669 | A discussion of various caveats, subtleties, and the design of the innards. | ||
670 | |||
671 | As of version 1.07 you can construct a single file containing command arguments | ||
672 | and then some data to transfer. Netcat is now smart enough to pick out the | ||
673 | first line and build the argument list, and send any remaining data across the | ||
674 | net to one or multiple ports. The first release of netcat had trouble with | ||
675 | this -- it called fgets() for the command line argument, which behind the | ||
676 | scenes does a large read() from standard input, perhaps 4096 bytes or so, and | ||
677 | feeds that out to the fgets() library routine. By the time netcat 1.00 started | ||
678 | directly read()ing stdin for more data, 4096 bytes of it were gone. It now | ||
679 | uses raw read() everywhere and does the right thing whether reading from files, | ||
680 | pipes, or ttys. If you use this for multiple-port connections, the single | ||
681 | block of data will now be a maximum of 8K minus the first line. Improvements | ||
682 | have been made to the logic in sending the saved chunk to each new port. Note | ||
683 | that any command-line arguments hidden using this mechanism could still be | ||
684 | extracted from a core dump. | ||
685 | |||
686 | When netcat receives an inbound UDP connection, it creates a "connected socket" | ||
687 | back to the source of the connection so that it can also send out data using | ||
688 | normal write(). Using this mechanism instead of recvfrom/sendto has several | ||
689 | advantages -- the read/write select loop is simplified, and ICMP errors can in | ||
690 | effect be received by non-root users. However, it has the subtle side effect | ||
691 | that if further UDP packets arrive from the caller but from different source | ||
692 | ports, the listener will not receive them. UDP listen mode on a multihomed | ||
693 | machine may have similar quirks unless you specifically bind to one of its | ||
694 | addresses. It is not clear that kernel support for UDP connected sockets | ||
695 | and/or my understanding of it is entirely complete here, so experiment... | ||
696 | |||
697 | You should be aware of some subtleties concerning UDP scanning. If -z is on, | ||
698 | netcat attempts to send a single null byte to the target port, twice, with a | ||
699 | small time in between. You can either use the -w timeout, or netcat will try | ||
700 | to make a "sideline" TCP connection to the target to introduce a small time | ||
701 | delay equal to the round-trip time between you and the target. Note that if | ||
702 | you have a -w timeout and -i timeout set, BOTH take effect and you wait twice | ||
703 | as long. The TCP connection is to a normally refused port to minimize traffic, | ||
704 | but if you notice a UDP fast-scan taking somewhat longer than it should, it | ||
705 | could be that the target is actually listening on the TCP port. Either way, | ||
706 | any ICMP port-unreachable messages from the target should have arrived in the | ||
707 | meantime. The second single-byte UDP probe is then sent. Under BSD kernels, | ||
708 | the ICMP error is delivered to the "connected socket" and the second write | ||
709 | returns an error, which tells netcat that there is NOT a UDP service there. | ||
710 | While Linux seems to be a fortunate exception, under many SYSV derived kernels | ||
711 | the 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 | ||
713 | socket" concept, and netcat in its current form will not work for UDP at all.] | ||
714 | If -z is specified and only one UDP port is probed, netcat's exit status | ||
715 | reflects whether the connection was "open" or "refused" as with TCP. | ||
716 | |||
717 | It may also be that UDP packets are being blocked by filters with no ICMP error | ||
718 | returns, in which case everything will time out and return "open". This all | ||
719 | sounds backwards, but that's how UDP works. If you're not sure, try "echo | ||
720 | w00gumz | nc -u -w 2 target 7" to see if you can reach its UDP echo port at | ||
721 | all. You should have no trouble using a BSD-flavor system to scan for UDP | ||
722 | around 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 | ||
725 | errors, as does SATAN's "udp_scan" backend, but then again there's no guarantee | ||
726 | that the ICMP gets back to you either. Udp_scan also does the zero-byte | ||
727 | probes but is excruciatingly careful to calculate its own round-trip timing | ||
728 | average and dynamically set its own response timeouts along with decoding any | ||
729 | ICMP received. Netcat uses a much sleazier method which is nonetheless quite | ||
730 | effective. Cisco routers are known to have a "dead time" in between ICMP | ||
731 | responses about unreachable UDP ports, so a fast scan of a cisco will show | ||
732 | almost everything "open". If you are looking for a specific UDP service, you | ||
733 | can construct a file containing the right bytes to trigger a response from the | ||
734 | other end and send that as standard input. Netcat will read up to 8K of the | ||
735 | file and send the same data to every UDP port given. Note that you must use a | ||
736 | timeout in this case [as would any other UDP client application] since the | ||
737 | two-write probe only happens if -z is specified. | ||
738 | |||
739 | Many telnet servers insist on a specific set of option negotiations before | ||
740 | presenting a login banner. On a raw connection you will see this as small | ||
741 | amount of binary gook. My attempts to create fixed input bytes to make a | ||
742 | telnetd happy worked some places but failed against newer BSD-flavor ones, | ||
743 | possibly due to timing problems, but there are a couple of much better | ||
744 | workarounds. First, compile with -DTELNET and use -t if you just want to get | ||
745 | past the option negotiation and talk to something on a telnet port. You will | ||
746 | still see the binary gook -- in fact you'll see a lot more of it as the options | ||
747 | are responded to behind the scenes. The telnet responder does NOT update the | ||
748 | total byte count, or show up in the hex dump -- it just responds negatively to | ||
749 | any options read from the incoming data stream. If you want to use a normal | ||
750 | full-blown telnet to get to something but also want some of netcat's features | ||
751 | involved like settable ports or timeouts, construct a tiny "foo" script: | ||
752 | |||
753 | #! /bin/sh | ||
754 | exec nc -otheroptions targethost 23 | ||
755 | |||
756 | and then do | ||
757 | |||
758 | nc -l -p someport -e foo localhost & | ||
759 | telnet localhost someport | ||
760 | |||
761 | and your telnet should connect transparently through the exec'ed netcat to | ||
762 | the target, using whatever options you supplied in the "foo" script. Don't | ||
763 | use -t inside the script, or you'll wind up sending *two* option responses. | ||
764 | |||
765 | I've observed inconsistent behavior under some Linuxes [perhaps just older | ||
766 | ones?] when binding in listen mode. Sometimes netcat binds only to "localhost" | ||
767 | if invoked with no address or port arguments, and sometimes it is unable to | ||
768 | bind to a specific address for listening if something else is already listening | ||
769 | on "any". The former problem can be worked around by specifying "-s 0.0.0.0", | ||
770 | which 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 | ||
772 | in the makefile for SOCKS. On the flip side, binding to localhost and sending | ||
773 | packets to some other machine doesn't work as you'd expect -- they go out with | ||
774 | the source address of the sending interface instead. The Linux kernel contains | ||
775 | a specific check to ensure that packets from 127.0.0.1 are never sent to the | ||
776 | wire; other kernels may contain similar code. Linux, of course, *still* | ||
777 | doesn't support source-routing, but they claim that it and many other network | ||
778 | improvements are at least breathing hard. | ||
779 | |||
780 | There are several possible errors associated with making TCP connections, but | ||
781 | to specifically see anything other than "refused", one must wait the full | ||
782 | kernel-defined timeout for a connection to fail. Netcat's mechanism of | ||
783 | wrapping an alarm timer around the connect prevents the *real* network error | ||
784 | from being returned -- "errno" at that point indicates "interrupted system | ||
785 | call" since the connect attempt was interrupted. Some old 4.3 BSD kernels | ||
786 | would actually return things like "host unreachable" immediately if that was | ||
787 | the case, but most newer kernels seem to wait the full timeout and *then* pass | ||
788 | back the real error. Go figure. In this case, I'd argue that the old way was | ||
789 | better, despite those same kernels generally being the ones that tear down | ||
790 | *established* TCP connections when ICMP-bombed. | ||
791 | |||
792 | Incoming socket options are passed to applications by the kernel in the | ||
793 | kernel's own internal format. The socket-options structure for source-routing | ||
794 | contains the "first-hop" IP address first, followed by the rest of the real | ||
795 | options list. The kernel uses this as is when sending reply packets -- the | ||
796 | structure is therefore designed to be more useful to the kernel than to humans, | ||
797 | but the hex dump of it that netcat produces is still useful to have. | ||
798 | |||
799 | Kernels treat source-routing options somewhat oddly, but it sort of makes sense | ||
800 | once one understands what's going on internally. The options list of addresses | ||
801 | must contain hop1, hop2, ..., destination. When a source-routed packet is sent | ||
802 | by the kernel [at least BSD], the actual destination address becomes irrelevant | ||
803 | because it is replaced with "hop1", "hop1" is removed from the options list, | ||
804 | and all the other addresses in the list are shifted up to fill the hole. Thus | ||
805 | the outbound packet is sent from your chosen source address to the first | ||
806 | *gateway*, and the options list now contains hop2, ..., destination. During | ||
807 | all this address shuffling, the kernel does NOT change the pointer value, which | ||
808 | is why it is useful to be able to set the pointer yourself -- you can construct | ||
809 | some really bizarre return paths, and send your traffic fairly directly to the | ||
810 | target but around some larger loop on the way back. Some Sun kernels seem to | ||
811 | never flip the source-route around if it contains less than three hops, never | ||
812 | reset the pointer anyway, and tries to send the packet [with options containing | ||
813 | a "completed" source route!!] directly back to the source. This is way broken, | ||
814 | of course. [Maybe ipforwarding has to be on? I haven't had an opportunity to | ||
815 | beat on it thoroughly yet.] | ||
816 | |||
817 | "Credits" section: The original idea for netcat fell out of a long-standing | ||
818 | desire and fruitless search for a tool resembling it and having the same | ||
819 | features. After reading some other network code and realizing just how many | ||
820 | cool things about sockets could be controlled by the calling user, I started | ||
821 | on the basics and the rest fell together pretty quickly. Some port-scanning | ||
822 | ideas were taken from Venema/Farmer's SATAN tool kit, and Pluvius' "pscan" | ||
823 | utility. Healthy amounts of BSD kernel source were perused in an attempt to | ||
824 | dope out socket options and source-route handling; additional help was obtained | ||
825 | from Dave Borman's telnet sources. The select loop is loosely based on fairly | ||
826 | well-known code from "rsh" and Richard Stevens' "sock" program [which itself is | ||
827 | sort of a "netcat" with more obscure features], with some more paranoid | ||
828 | sanity-checking thrown in to guard against the distinct likelihood that there | ||
829 | are subtleties about such things I still don't understand. I found the | ||
830 | argument-hiding method cleanly implemented in Barrett's "deslogin"; reading the | ||
831 | line as input allows greater versatility and is much less prone to cause | ||
832 | bizarre problems than the more common trick of overwriting the argv array. | ||
833 | After the first release, several people contributed portability fixes; they are | ||
834 | credited in generic.h and the Makefile. Lauren Burka inspired the ascii art | ||
835 | for this revised document. Dean Gaudet at Wired supplied a precursor to | ||
836 | the hex-dump code, and mudge@l0pht.com originally experimented with and | ||
837 | supplied code for the telnet-options responder. Outbound "-e <prog>" resulted | ||
838 | from a need to quietly bypass a firewall installation. Other suggestions and | ||
839 | patches have rolled in for which I am always grateful, but there are only 26 | ||
840 | hours per day and a discussion of feature creep near the end of this document. | ||
841 | |||
842 | Netcat was written with the Russian railroad in mind -- conservatively built | ||
843 | and 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 | ||
845 | characters, dammit] and put in plenty of comments as to why certain things | ||
846 | are done. Items I know to be questionable are clearly marked with "XXX". | ||
847 | Source code was made to be modified, but determining where to start is | ||
848 | difficult with some of the tangles of spaghetti code that are out there. | ||
849 | Here are some of the major points I feel are worth mentioning about netcat's | ||
850 | internal design, whether or not you agree with my approach. | ||
851 | |||
852 | Except for generic.h, which changes to adapt more platforms, netcat is a single | ||
853 | source file. This has the distinct advantage of only having to include headers | ||
854 | once and not having to re-declare all my functions in a billion different | ||
855 | places. I have attempted to contain all the gross who's-got-what-.h-file | ||
856 | things in one small dumping ground. Functions are placed "dependencies-first", | ||
857 | such that when the compiler runs into the calls later, it already knows the | ||
858 | type 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 | ||
860 | easy enough to check manually. Each function has a standard-format comment | ||
861 | ahead of it, which is easily found using the regexp " :$". I freely use gotos. | ||
862 | Loops and if-clauses are made as small and non-nested as possible, and the ends | ||
863 | of same *marked* for clarity [I wish everyone would do this!!]. | ||
864 | |||
865 | Large structures and buffers are all malloc()ed up on the fly, slightly larger | ||
866 | than the size asked for and zeroed out. This reduces the chances of damage | ||
867 | from those "end of the buffer" fencepost errors or runaway pointers escaping | ||
868 | off the end. These things are permanent per run, so nothing needs to be freed | ||
869 | until the program exits. | ||
870 | |||
871 | File descriptor zero is always expected to be standard input, even if it is | ||
872 | closed. If a new network descriptor winds up being zero, a different one is | ||
873 | asked for which will be nonzero, and fd zero is simply left kicking around | ||
874 | for the rest of the run. Why? Because everything else assumes that stdin is | ||
875 | always zero and "netfd" is always positive. This may seem silly, but it was a | ||
876 | lot easier to code. The new fd is obtained directly as a new socket, because | ||
877 | trying to simply dup() a new fd broke subsequent socket-style use of the new fd | ||
878 | under Solaris' stupid streams handling in the socket library. | ||
879 | |||
880 | The catch-all message and error handlers are implemented with an ample list of | ||
881 | phoney arguments to get around various problems with varargs. Varargs seems | ||
882 | like deliberate obfuscation in the first place, and using it would also | ||
883 | require use of vfprintf() which not all platforms support. The trailing | ||
884 | sleep in bail() is to allow output to flush, which is sometimes needed if | ||
885 | netcat is already on the other end of a network connection. | ||
886 | |||
887 | The reader may notice that the section that does DNS lookups seems much | ||
888 | gnarlier and more confusing than other parts. This is NOT MY FAULT. The | ||
889 | sockaddr and hostent abstractions are an abortion that forces the coder to | ||
890 | deal with it. Then again, a lot of BSD kernel code looks like similar | ||
891 | struct-pointer hell. I try to straighten it out somewhat by defining my own | ||
892 | HINF structure, containing names, ascii-format IP addresses, and binary IP | ||
893 | addresses. I fill this structure exactly once per host argument, and squirrel | ||
894 | everything safely away and handy for whatever wants to reference it later. | ||
895 | |||
896 | Where many other network apps use the FIONBIO ioctl to set non-blocking I/O | ||
897 | on network sockets, netcat uses straightforward blocking I/O everywhere. | ||
898 | This makes everything very lock-step, relying on the network and filesystem | ||
899 | layers to feed in data when needed. Data read in is completely written out | ||
900 | before any more is fetched. This may not be quite the right thing to do under | ||
901 | some OSes that don't do timed select() right, but this remains to be seen. | ||
902 | |||
903 | The hexdump routine is written to be as fast as possible, which is why it does | ||
904 | so much work itself instead of just sprintf()ing everything together. Each | ||
905 | dump line is built into a single buffer and atomically written out using the | ||
906 | lowest level I/O calls. Further improvements could undoubtedly be made by | ||
907 | using writev() and eliminating all sprintf()s, but it seems to fly right along | ||
908 | as is. If both exec-a-prog mode and a hexdump file is asked for, the hexdump | ||
909 | flag is deliberately turned off to avoid creating random zero-length files. | ||
910 | Files are opened in "truncate" mode; if you want "append" mode instead, change | ||
911 | the open flags in main(). | ||
912 | |||
913 | main() may look a bit hairy, but that's only because it has to go down the | ||
914 | argv list and handle multiple ports, random mode, and exit status. Efforts | ||
915 | have been made to place a minimum of code inside the getopt() loop. Any real | ||
916 | work is sent off to functions in what is hopefully a straightforward way. | ||
917 | |||
918 | Obligatory vendor-bash: If "nc" had become a standard utility years ago, | ||
919 | the 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 | ||
921 | will aid people in finding and fixing the no-brainer holes of this sort that | ||
922 | keep appearing, by allowing easier experimentation with the "bare metal" of | ||
923 | the network layer. | ||
924 | |||
925 | It could be argued that netcat already has too many features. I have tried | ||
926 | to avoid "feature creep" by limiting netcat's base functionality only to those | ||
927 | things which are truly relevant to making network connections and the everyday | ||
928 | associated DNS lossage we're used to. Option switches already have slightly | ||
929 | overloaded functionality. Random port mode is sort of pushing it. The | ||
930 | hex-dump feature went in later because it *is* genuinely useful. The | ||
931 | telnet-responder code *almost* verges on the gratuitous, especially since it | ||
932 | mucks with the data stream, and is left as an optional piece. Many people have | ||
933 | asked for example "how 'bout adding encryption?" and my response is that such | ||
934 | things should be separate entities that could pipe their data *through* netcat | ||
935 | instead of having their own networking code. I am therefore not completely | ||
936 | enthusiastic about adding any more features to this thing, although you are | ||
937 | still free to send along any mods you think are useful. | ||
938 | |||
939 | Nonetheless, at this point I think of netcat as my tcp/ip swiss army knife, | ||
940 | and the numerous companion programs and scripts to go with it as duct tape. | ||
941 | Duct tape of course has a light side and a dark side and binds the universe | ||
942 | together, and if I wrap enough of it around what I'm trying to accomplish, | ||
943 | it *will* work. Alternatively, if netcat is a large hammer, there are many | ||
944 | network 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 @@ | |||
1 | all: data rservice xor | ||
2 | |||
3 | data: data.c | ||
4 | cc -s -O -o data data.c | ||
5 | rservice: rservice.c | ||
6 | cc -s -O -o rservice rservice.c | ||
7 | xor: xor.c | ||
8 | cc -s -O -o xor xor.c | ||
9 | clean: | ||
10 | rm -f *.o data rservice xor | ||
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 @@ | |||
1 | For now, read the header comments inside each of these for documentation. | ||
2 | The programs are simple enough that they don't really need a Makefile any more | ||
3 | complex than the one given; ymmv. Data and xor may also be useful on DOS, | ||
4 | which is why there are hooks for it in the code. | ||
5 | |||
6 | data.c a primitive atob / btoa byte generator | ||
7 | *.d example input to "data -g" | ||
8 | rservice.c a utility for scripting up rsh/rexec attacks | ||
9 | xor.c generic xor handler | ||
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 | |||
27 | static char buf_in [128]; | ||
28 | static char buf_raw [8192]; | ||
29 | static char surveysez[] = "survey sez... XXX\n"; | ||
30 | |||
31 | /* fgetss : | ||
32 | wrapper for fgets, that yanks trailing newlines. Doing the work ourselves | ||
33 | instead of calling strchr/strlen/whatever */ | ||
34 | char * fgetss (buf, len, from) | ||
35 | char * buf; | ||
36 | size_t len; | ||
37 | FILE * from; | ||
38 | { | ||
39 | register int x; | ||
40 | register char * p, * q; | ||
41 | p = fgets (buf, len, from); /* returns ptr to buf */ | ||
42 | if (! p) | ||
43 | return (NULL); | ||
44 | q = p; | ||
45 | for (x = 0; x < len; x++) { | ||
46 | *p = (*p & 0x7f); /* rip parity, just in case */ | ||
47 | switch (*p) { | ||
48 | case '\n': | ||
49 | case '\r': | ||
50 | case '\0': | ||
51 | *p = '\0'; | ||
52 | return (q); | ||
53 | } /* switch */ | ||
54 | p++; | ||
55 | } /* for */ | ||
56 | } /* fgetss */ | ||
57 | |||
58 | /* randint: | ||
59 | swiped from rndb.c. Generates an INT, you have to mask down to char. */ | ||
60 | int randint() | ||
61 | { | ||
62 | register int q; | ||
63 | register int x; | ||
64 | |||
65 | #ifndef HAVE_RANDOM | ||
66 | q = rand(); | ||
67 | #else | ||
68 | q = random(); | ||
69 | #endif | ||
70 | x = ((q >> 8) & 0xff); /* perturb low byte using some higher bits */ | ||
71 | x = q ^ x; | ||
72 | return (x); | ||
73 | } | ||
74 | |||
75 | main (argc, argv) | ||
76 | int argc; | ||
77 | char ** argv; | ||
78 | { | ||
79 | register unsigned char * p; | ||
80 | register char * q; | ||
81 | register int x; | ||
82 | int bc = 0; | ||
83 | int limit = 0; /* num to gen, or 0 = infinite */ | ||
84 | register int xlimit; /* running limit */ | ||
85 | FILE * txt; /* line-by-line ascii file */ | ||
86 | int raw; /* raw bytes fd */ | ||
87 | int dumping = 0; /* cmd flags ... */ | ||
88 | int genning = 0; | ||
89 | int randing = 0; | ||
90 | |||
91 | memset (buf_in, 0, sizeof (buf_in)); | ||
92 | memset (buf_raw, 0, sizeof (buf_raw)); | ||
93 | |||
94 | xlimit = 1; /* doubles as "exit flag" */ | ||
95 | bc = 1; /* preload, assuming "dump" */ | ||
96 | x = getpid() + 687319; | ||
97 | /* if your library doesnt have srandom/random, use srand/rand. [from rnd.c] */ | ||
98 | #ifndef HAVE_RANDOM | ||
99 | srand (time(0) + x); | ||
100 | #else | ||
101 | srandom (time(0) + x); | ||
102 | #endif | ||
103 | |||
104 | #ifdef O_BINARY | ||
105 | /* DOS stupidity */ | ||
106 | /* Aha: *here's* where that setmode() lib call conflict in ?BSD came from */ | ||
107 | x = setmode (0, O_BINARY); /* make stdin raw */ | ||
108 | if (x < 0) { | ||
109 | fprintf (stderr, "stdin binary setmode oops: %d\n", x); | ||
110 | exit (1); | ||
111 | } | ||
112 | x = setmode (1, O_BINARY); /* make stdout raw */ | ||
113 | if (x < 0) { | ||
114 | fprintf (stderr, "stdout binary setmode oops: %d\n", x); | ||
115 | exit (1); | ||
116 | } | ||
117 | #endif /* O_BINARY */ | ||
118 | |||
119 | if (argv[1]) { | ||
120 | p = argv[1]; /* shit-simple single arg parser... */ | ||
121 | if (*p == '-') /* dash is optional, we'll deal */ | ||
122 | p++; | ||
123 | if (*p == 'd') | ||
124 | dumping++; | ||
125 | if (*p == 'g') | ||
126 | genning++; | ||
127 | if (*p == 'r') | ||
128 | randing++; | ||
129 | } /* if argv 1 */ | ||
130 | |||
131 | /* optional second argument: limit # of bytes shoveled either way */ | ||
132 | if (argv[2]) { | ||
133 | x = atoi (argv[2]); | ||
134 | if (x) | ||
135 | limit = x; | ||
136 | else | ||
137 | goto wrong; | ||
138 | xlimit = limit; | ||
139 | } | ||
140 | |||
141 | /* Since this prog would likely best be written in assmbler, I'm gonna | ||
142 | write it *like* assembler. So there. */ | ||
143 | |||
144 | if (randing) | ||
145 | goto do_rand; | ||
146 | |||
147 | nextbuf: /* loop sleaze */ | ||
148 | |||
149 | if (dumping) { /* switch off to wherever */ | ||
150 | if (genning) | ||
151 | goto wrong; | ||
152 | goto do_dump; | ||
153 | } | ||
154 | if (genning) | ||
155 | goto do_gen; | ||
156 | wrong: | ||
157 | fprintf (stderr, surveysez); /* if both or neither */ | ||
158 | exit (1); | ||
159 | |||
160 | do_gen: | ||
161 | /* here if genning -- original functionality */ | ||
162 | q = buf_raw; | ||
163 | bc = 0; | ||
164 | /* suck up lines until eof or buf_raw is full */ | ||
165 | while (1) { | ||
166 | p = fgetss (buf_in, 120, stdin); | ||
167 | if (! p) | ||
168 | break; /* EOF */ | ||
169 | /* super-primitive version first: one thingie per line */ | ||
170 | if (*p == '#') /* comment */ | ||
171 | continue; | ||
172 | if (*p == '\0') /* blank line */ | ||
173 | continue; | ||
174 | if (*p == '%') { /* escape char? */ | ||
175 | p++; | ||
176 | if (*p == 'r') { /* random byte */ | ||
177 | x = randint(); | ||
178 | goto stuff; | ||
179 | } /* %r */ | ||
180 | } /* if "%" escape */ | ||
181 | if (*p == '0') | ||
182 | if (*(p+1) == 'x') /* 0x?? */ | ||
183 | goto hex; | ||
184 | x = atoi (p); /* reg'lar decimal number */ | ||
185 | goto stuff; | ||
186 | |||
187 | hex: | ||
188 | /* A 65 a 97 */ | ||
189 | /* xxx: use a conversion table for this or something. Since we ripped the | ||
190 | parity bit, we only need a preset array of 128 with downconversion factors | ||
191 | loaded in *once*. maybe look at scanf... */ | ||
192 | p++; p++; /* point at hex-chars */ | ||
193 | x = 0; | ||
194 | if ((*p > 96) && (*p < 123)) /* a-z */ | ||
195 | *p = (*p - 32); /* this is massively clumsy */ | ||
196 | if ((*p > 64) && (*p < 71)) /* A-F */ | ||
197 | x = (*p - 55); | ||
198 | if ((*p > 47) && (*p < 58)) /* digits */ | ||
199 | x = (*p - 48); | ||
200 | p++; | ||
201 | if (*p) /* another digit? */ | ||
202 | x = (x << 4); /* shift to hi half */ | ||
203 | if ((*p > 96) && (*p < 123)) /* a-z */ | ||
204 | *p = (*p - 32); | ||
205 | if ((*p > 64) && (*p < 71)) /* A-F */ | ||
206 | x = (x | (*p - 55)); /* lo half */ | ||
207 | if ((*p > 47) && (*p < 58)) /* digits */ | ||
208 | x = (x | (*p - 48)); | ||
209 | |||
210 | /* fall thru */ | ||
211 | stuff: /* cvt to byte and add to buffer */ | ||
212 | *q = (x & 0xff); | ||
213 | q++; | ||
214 | bc++; | ||
215 | if (limit) { | ||
216 | xlimit--; | ||
217 | if (xlimit == 0) /* max num reached */ | ||
218 | break; | ||
219 | } /* limit */ | ||
220 | if (bc >= sizeof (buf_raw)) /* buffer full */ | ||
221 | break; | ||
222 | } /* while 1 */ | ||
223 | |||
224 | /* now in theory we have our buffer formed; shovel it out */ | ||
225 | x = write (1, buf_raw, bc); | ||
226 | if (x <= 0) { | ||
227 | fprintf (stderr, "write oops: %d\n", x); | ||
228 | exit (1); | ||
229 | } | ||
230 | if (xlimit && p) | ||
231 | goto nextbuf; /* go get some more */ | ||
232 | exit (0); | ||
233 | |||
234 | do_dump: | ||
235 | /* here if dumping raw stuff into an ascii file */ | ||
236 | /* gad, this is *so* much simpler! can we say "don't rewrite printf"? */ | ||
237 | x = read (0, buf_raw, 8192); | ||
238 | if (x <= 0) | ||
239 | exit (0); | ||
240 | q = buf_raw; | ||
241 | for ( ; x > 0; x--) { | ||
242 | p = q; | ||
243 | printf ("%-3.3d # 0x%-2.2x # ", *p, *p); | ||
244 | if ((*p > 31) && (*p < 127)) | ||
245 | printf ("%c %d\n", *p, bc); | ||
246 | else | ||
247 | printf (". %d\n", bc); | ||
248 | q++; | ||
249 | bc++; | ||
250 | if (limit) { | ||
251 | xlimit--; | ||
252 | if (xlimit == 0) { | ||
253 | fflush (stdout); | ||
254 | exit (0); | ||
255 | } | ||
256 | } /* limit */ | ||
257 | } /* for */ | ||
258 | goto nextbuf; | ||
259 | |||
260 | do_rand: | ||
261 | /* here if generating all-random bytes. Stays in this loop */ | ||
262 | p = buf_raw; | ||
263 | while (1) { | ||
264 | *p = (randint() & 0xff); | ||
265 | write (1, p, 1); /* makes very slow! */ | ||
266 | if (limit) { | ||
267 | xlimit--; | ||
268 | if (xlimit == 0) | ||
269 | break; | ||
270 | } | ||
271 | } /* while */ | ||
272 | exit (0); | ||
273 | |||
274 | } /* main */ | ||
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: | ||
8 | 0 # query id = 2 | ||
9 | 2 | ||
10 | |||
11 | 1 # flags/opcodes = query, dorecurse | ||
12 | 0 | ||
13 | |||
14 | 0 # qdcount, i.e. nqueries: 1 | ||
15 | 1 | ||
16 | |||
17 | 0 # ancount: answers, 0 | ||
18 | 0 | ||
19 | |||
20 | 0 # nscount: 0 | ||
21 | 0 | ||
22 | |||
23 | 0 # addl records: 0 | ||
24 | 0 | ||
25 | |||
26 | # end of fixed header | ||
27 | |||
28 | 0 # name-len: 0 for ".", lenbyte plus name-bytes otherwise | ||
29 | |||
30 | 0 # type: any, 255 | ||
31 | 0xff | ||
32 | |||
33 | 0 # class: IN | ||
34 | 1 | ||
35 | |||
36 | # i think that's it.. | ||
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 | |||
4 | 000 # XID: 4 trash bytes | ||
5 | 001 | ||
6 | 002 | ||
7 | 003 | ||
8 | |||
9 | 000 # CALL: 0 | ||
10 | 000 | ||
11 | 000 | ||
12 | 000 | ||
13 | |||
14 | 000 # RPC version: 2 | ||
15 | 000 | ||
16 | 000 | ||
17 | 002 | ||
18 | |||
19 | 000 # nfs: 100003 | ||
20 | 001 | ||
21 | 0x86 | ||
22 | 0xa3 | ||
23 | |||
24 | 000 # version: 1 | ||
25 | 000 | ||
26 | 000 | ||
27 | 001 | ||
28 | |||
29 | 000 # procedure number: 0 | ||
30 | 000 | ||
31 | 000 | ||
32 | 000 | ||
33 | |||
34 | 000 # port: junk | ||
35 | 000 | ||
36 | 000 | ||
37 | 000 | ||
38 | |||
39 | 000 # auth trash | ||
40 | 000 | ||
41 | 000 | ||
42 | 000 | ||
43 | |||
44 | 000 # auth trash | ||
45 | 000 | ||
46 | 000 | ||
47 | 000 | ||
48 | |||
49 | 000 # auth trash | ||
50 | 000 | ||
51 | 000 | ||
52 | 000 | ||
53 | |||
54 | 000 # extra auth trash? probably not needed | ||
55 | 000 | ||
56 | 000 | ||
57 | 000 | ||
58 | |||
59 | # that's it! | ||
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 | |||
7 | 255 # 0xff # . 1 | ||
8 | 243 # 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 | |||
5 | 001 # 0x01 # . # XID: 4 trash bytes | ||
6 | 002 # 0x02 # . | ||
7 | 003 # 0x03 # . | ||
8 | 004 # 0x04 # . | ||
9 | |||
10 | 000 # 0x00 # . # MSG: int 0=call, 1=reply | ||
11 | 000 # 0x00 # . | ||
12 | 000 # 0x00 # . | ||
13 | 000 # 0x00 # . | ||
14 | |||
15 | 000 # 0x00 # . # pmap call body: rpc version=2 | ||
16 | 000 # 0x00 # . | ||
17 | 000 # 0x00 # . | ||
18 | 002 # 0x02 # . | ||
19 | |||
20 | 000 # 0x00 # . # pmap call body: prog=PMAP, 100000 | ||
21 | 001 # 0x01 # . | ||
22 | 134 # 0x86 # . | ||
23 | 160 # 0xa0 # . | ||
24 | |||
25 | 000 # 0x00 # . # pmap call body: progversion=2 | ||
26 | 000 # 0x00 # . | ||
27 | 000 # 0x00 # . | ||
28 | 002 # 0x02 # . | ||
29 | |||
30 | 000 # 0x00 # . # pmap call body: proc=DUMP, 4 | ||
31 | 000 # 0x00 # . | ||
32 | 000 # 0x00 # . | ||
33 | 004 # 0x04 # . | ||
34 | |||
35 | # with AUTH_NONE, there are 4 zero integers [16 bytes] here | ||
36 | |||
37 | 000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0 | ||
38 | 000 # 0x00 # . | ||
39 | 000 # 0x00 # . | ||
40 | 000 # 0x00 # . | ||
41 | |||
42 | 000 # 0x00 # . # auth junk | ||
43 | 000 # 0x00 # . | ||
44 | 000 # 0x00 # . | ||
45 | 000 # 0x00 # . | ||
46 | |||
47 | 000 # 0x00 # . # auth junk | ||
48 | 000 # 0x00 # . | ||
49 | 000 # 0x00 # . | ||
50 | 000 # 0x00 # . | ||
51 | |||
52 | 000 # 0x00 # . # auth junk | ||
53 | 000 # 0x00 # . | ||
54 | 000 # 0x00 # . | ||
55 | 000 # 0x00 # . | ||
56 | |||
57 | # The reply you get back contains your XID, int 1 if "accepted", and | ||
58 | # a whole mess of gobbledygook containing program numbers, versions, | ||
59 | # and ports that rpcinfo knows how to decode. For the moment, you get | ||
60 | # to wade through it yourself... | ||
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 | |||
5 | 001 # 0x01 # . # XID: 4 trash bytes | ||
6 | 002 # 0x02 # . | ||
7 | 003 # 0x03 # . | ||
8 | 004 # 0x04 # . | ||
9 | |||
10 | 000 # 0x00 # . # MSG: int 0=call, 1=reply | ||
11 | 000 # 0x00 # . | ||
12 | 000 # 0x00 # . | ||
13 | 000 # 0x00 # . | ||
14 | |||
15 | 000 # 0x00 # . # pmap call body: rpc version=2 | ||
16 | 000 # 0x00 # . | ||
17 | 000 # 0x00 # . | ||
18 | 002 # 0x02 # . | ||
19 | |||
20 | 000 # 0x00 # . # pmap call body: prog=PMAP, 100000 | ||
21 | 001 # 0x01 # . | ||
22 | 134 # 0x86 # . | ||
23 | 160 # 0xa0 # . | ||
24 | |||
25 | 000 # 0x00 # . # pmap call body: progversion=2 | ||
26 | 000 # 0x00 # . | ||
27 | 000 # 0x00 # . | ||
28 | 002 # 0x02 # . | ||
29 | |||
30 | 000 # 0x00 # . # pmap call body: proc=GETPORT, 3 | ||
31 | 000 # 0x00 # . | ||
32 | 000 # 0x00 # . | ||
33 | 003 # 0x03 # . | ||
34 | |||
35 | # with AUTH_NONE, there are 4 zero integers [16 bytes] here | ||
36 | |||
37 | 000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0 | ||
38 | 000 # 0x00 # . | ||
39 | 000 # 0x00 # . | ||
40 | 000 # 0x00 # . | ||
41 | |||
42 | 000 # 0x00 # . # auth junk | ||
43 | 000 # 0x00 # . | ||
44 | 000 # 0x00 # . | ||
45 | 000 # 0x00 # . | ||
46 | |||
47 | 000 # 0x00 # . # auth junk | ||
48 | 000 # 0x00 # . | ||
49 | 000 # 0x00 # . | ||
50 | 000 # 0x00 # . | ||
51 | |||
52 | 000 # 0x00 # . # auth junk | ||
53 | 000 # 0x00 # . | ||
54 | 000 # 0x00 # . | ||
55 | 000 # 0x00 # . | ||
56 | |||
57 | 000 # 0x00 # . # prog=MOUNT, 100005 | ||
58 | 001 # 0x01 # . | ||
59 | 134 # 0x86 # . | ||
60 | 165 # 0xa5 # . | ||
61 | |||
62 | 000 # 0x00 # . # progversion=1 | ||
63 | 000 # 0x00 # . | ||
64 | 000 # 0x00 # . | ||
65 | 001 # 0x01 # . | ||
66 | |||
67 | 000 # 0x00 # . # protocol=udp, 17 | ||
68 | 000 # 0x00 # . | ||
69 | 000 # 0x00 # . | ||
70 | 017 # 0x11 # . | ||
71 | |||
72 | 000 # 0x00 # . # proc num = junk | ||
73 | 000 # 0x00 # . | ||
74 | 000 # 0x00 # . | ||
75 | 000 # 0x00 # . | ||
76 | |||
77 | # The reply you get back contains your XID, int 1 if "accepted", and | ||
78 | # mountd's port number at the end or 0 if not registered. | ||
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 | ||
24 | 2 # RIPCMD_RESPONSE | ||
25 | 1 # version | ||
26 | 0 # padding | ||
27 | 0 | ||
28 | |||
29 | # sockaddr-plus-metric structs begin, as many as necessary... | ||
30 | 0 # len | ||
31 | 2 # AF_INET | ||
32 | 0 # port | ||
33 | 0 | ||
34 | # addr bytes: | ||
35 | X | ||
36 | Y | ||
37 | Z | ||
38 | Q | ||
39 | 0 # filler, out to 16 bytes [sizeof (sockaddr)] ... | ||
40 | 0 | ||
41 | 0 | ||
42 | 0 | ||
43 | 0 | ||
44 | 0 | ||
45 | 0 | ||
46 | 0 | ||
47 | 0 # metric: net-order integer | ||
48 | 0 | ||
49 | 0 | ||
50 | 1 | ||
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 */ | ||
15 | static char cmd[] = "pwd"; | ||
16 | |||
17 | static char buf [256]; | ||
18 | |||
19 | main(argc, argv) | ||
20 | int argc; | ||
21 | char * argv[]; | ||
22 | { | ||
23 | register int x; | ||
24 | register int y; | ||
25 | char * p; | ||
26 | char * q; | ||
27 | |||
28 | p = buf; | ||
29 | memset (buf, 0, 256); | ||
30 | |||
31 | p++; /* first null */ | ||
32 | y = 1; | ||
33 | |||
34 | if (! argv[1]) | ||
35 | goto wrong; | ||
36 | x = strlen (argv[1]); | ||
37 | memcpy (p, argv[1], x); /* first arg plus another null */ | ||
38 | x++; | ||
39 | p += x; | ||
40 | y += x; | ||
41 | |||
42 | if (! argv[2]) | ||
43 | goto wrong; | ||
44 | x = strlen (argv[2]); | ||
45 | memcpy (p, argv[2], x); /* second arg plus null */ | ||
46 | x++; | ||
47 | p += x; | ||
48 | y += x; | ||
49 | |||
50 | q = cmd; | ||
51 | if (argv[3]) | ||
52 | q = argv[3]; | ||
53 | x = strlen (q); /* not checked -- bfd */ | ||
54 | memcpy (p, q, x); /* the command, plus final null */ | ||
55 | x++; | ||
56 | p += x; | ||
57 | y += x; | ||
58 | |||
59 | memcpy (p, "\n", 1); /* and a newline, so it goes */ | ||
60 | y++; | ||
61 | |||
62 | write (1, buf, y); /* zot! */ | ||
63 | exit (0); | ||
64 | |||
65 | wrong: | ||
66 | fprintf (stderr, "wrong! needs 2 or more args.\n"); | ||
67 | exit (1); | ||
68 | } | ||
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 | |||
8 | 000 # XID: 4 trash bytes | ||
9 | 001 | ||
10 | 002 | ||
11 | 003 | ||
12 | |||
13 | 000 # CALL: 0 | ||
14 | 000 | ||
15 | 000 | ||
16 | 000 | ||
17 | |||
18 | 000 # RPC version: 2 | ||
19 | 000 | ||
20 | 000 | ||
21 | 002 | ||
22 | |||
23 | 000 # mount: 100005 | ||
24 | 001 | ||
25 | 0x86 | ||
26 | 0xa5 | ||
27 | |||
28 | 000 # mount version: 1 | ||
29 | 000 | ||
30 | 000 | ||
31 | 001 | ||
32 | |||
33 | 000 # procedure number -- put what you need here: | ||
34 | 000 # 2 = dump [showmount -e] | ||
35 | 000 # 5 = exportlist [showmount -a] | ||
36 | xxx # "sed s/xxx/$1/ | data -g | nc ..." or some such... | ||
37 | |||
38 | 000 # port: junk | ||
39 | 000 | ||
40 | 000 | ||
41 | 000 | ||
42 | |||
43 | 000 # auth trash | ||
44 | 000 | ||
45 | 000 | ||
46 | 000 | ||
47 | |||
48 | 000 # auth trash | ||
49 | 000 | ||
50 | 000 | ||
51 | 000 | ||
52 | |||
53 | 000 # auth trash | ||
54 | 000 | ||
55 | 000 | ||
56 | 000 | ||
57 | |||
58 | 000 # extra auth trash? probably not needed | ||
59 | 000 | ||
60 | 000 | ||
61 | 000 | ||
62 | |||
63 | # that's it! | ||
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 | |||
19 | char buf[8192]; | ||
20 | char bytes[256]; | ||
21 | char * py; | ||
22 | |||
23 | /* do the xor, in place. Uses global ptr "py" to maintain "bytes" state */ | ||
24 | xorb (buf, len) | ||
25 | char * buf; | ||
26 | int len; | ||
27 | { | ||
28 | register int x; | ||
29 | register char * pb; | ||
30 | |||
31 | pb = buf; | ||
32 | x = len; | ||
33 | while (x > 0) { | ||
34 | *pb = (*pb ^ *py); | ||
35 | pb++; | ||
36 | py++; | ||
37 | if (! *py) | ||
38 | py = bytes; | ||
39 | x--; | ||
40 | } | ||
41 | } /* xorb */ | ||
42 | |||
43 | /* blah */ | ||
44 | main (argc, argv) | ||
45 | int argc; | ||
46 | char ** argv; | ||
47 | { | ||
48 | register int x = 0; | ||
49 | register int y; | ||
50 | |||
51 | /* manually preload; xor-with-0xFF is all too common */ | ||
52 | memset (bytes, 0, sizeof (bytes)); | ||
53 | bytes[0] = 0xff; | ||
54 | |||
55 | /* if file named in any arg, reload from that */ | ||
56 | #ifdef O_BINARY /* DOS shit... */ | ||
57 | x = setmode (0, O_BINARY); /* make stdin raw */ | ||
58 | if (x < 0) { | ||
59 | fprintf (stderr, "stdin binary setmode oops: %d\n", x); | ||
60 | exit (1); | ||
61 | } | ||
62 | x = setmode (1, O_BINARY); /* make stdout raw */ | ||
63 | if (x < 0) { | ||
64 | fprintf (stderr, "stdout binary setmode oops: %d\n", x); | ||
65 | exit (1); | ||
66 | } | ||
67 | #endif /* O_BINARY */ | ||
68 | |||
69 | if (argv[1]) | ||
70 | #ifdef O_BINARY | ||
71 | x = open (argv[1], O_RDONLY | O_BINARY); | ||
72 | #else | ||
73 | x = open (argv[1], O_RDONLY); | ||
74 | #endif | ||
75 | if (x > 0) { | ||
76 | read (x, bytes, 250); /* nothin' fancy here */ | ||
77 | close (x); | ||
78 | } | ||
79 | py = bytes; | ||
80 | x = 1; | ||
81 | while (x > 0) { | ||
82 | x = read (0, buf, sizeof (buf)); | ||
83 | if (x <= 0) | ||
84 | break; | ||
85 | xorb (buf, x); | ||
86 | y = write (1, buf, x); | ||
87 | if (y <= 0) | ||
88 | exit (1); | ||
89 | } | ||
90 | exit (0); | ||
91 | } | ||
92 | |||
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 | ||
117 | HAVE_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 | ||
138 | randomness 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 | ||
142 | randomness about machine/endian.h, machine/inline.h -- bsdi, net/2 | ||
143 | randomness 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?] | ||
150 | lseek: SEEK_SET vs L_SET and associated lossage [epi-notes, old 386Mach] | ||
151 | bsdi: ioctl_compat.h ? | ||
152 | --- takin' some ifdefs from CNS krb: | ||
153 | F_GETOWN/F_SETOWN | ||
154 | CRAY: long = 8 bytes, etc [class with alpha?] | ||
155 | CGETENT | ||
156 | SIGINFO | ||
157 | SIGTSTP SIGTTOU SIGWINCH | ||
158 | SPX? | ||
159 | SYSV_TERMIO -- covered elsewhere, I hope | ||
160 | TIOCEXT TIOCFLUSH TIOC[GS]WINSIZ | ||
161 | NEWINIT: something about init cleaning up dead login processes [telnet?] | ||
162 | PARENT_DOES_UTMP, too [telnet] | ||
163 | VDISCARD | ||
164 | VEOL/VEOL2/VLNEXT VREPRINT -- termios stuff?, and related... | ||
165 | STREAMSPTY/STREAMSPTYEM | ||
166 | AF_INET/AF_UNSPEC, PF_* | ||
167 | ECHOCTL/ECHOKE | ||
168 | F_ULOCK [?!] | ||
169 | setpgrp/getpgrp() ONEARG business.. | ||
170 | HAVE_ALLOCA | ||
171 | HAVE_GETUTENT | ||
172 | HAVE_SYS_SELECT_H [irix!] | ||
173 | HAVE_DIRENT [old 386mach has *direct.h*!] | ||
174 | HAVE_SIGSET | ||
175 | HAVE_VFORK_H and HAVE_VFORK | ||
176 | HAVE_VHANGUP | ||
177 | HAVE_VSPRINTF | ||
178 | HAVE_IPTOS_* | ||
179 | HAVE_STRCASECMP, STRNCASECMP | ||
180 | HAVE_SYS_FCNTL_H | ||
181 | HAVE_SYS_TIME_H | ||
182 | HAVE_UTIMES | ||
183 | NOTTYENT [?] | ||
184 | HAVE_FCHMOD | ||
185 | HAVE_GETUSERSHELL | ||
186 | HAVE_SIGCONTEXT [stack hair, very machine-specific] | ||
187 | YYLINENO? | ||
188 | POSIX_SIGNALS | ||
189 | POSIX_TERMIOS | ||
190 | SETPROCTITLE -- breaks some places, like fbsd sendmail | ||
191 | SIG* -- actual signal names? some are missing | ||
192 | SIOCGIFCONF | ||
193 | SO_BROADCAST | ||
194 | SHMEM [krb tickets] | ||
195 | VARARGS, or HAVE_VARARGS | ||
196 | CBAUD | ||
197 | ... and B300, B9600, etc etc | ||
198 | HAVE_BZERO vs memset/memcpy | ||
199 | HAVE_SETVBUF | ||
200 | HAVE_STRDUP | ||
201 | HAVE_GETENV | ||
202 | HAVE_STRSAVE | ||
203 | HAVE_STBLKSIZE [stat?] | ||
204 | HAVE_STREAM_H -- in sys/, ref sendmail 8.7 for IP_SRCROUTE | ||
205 | FCHMOD | ||
206 | INITGROUPS -- most machines seem to *have* | ||
207 | SETREUID | ||
208 | SNPRINTF | ||
209 | SETPGRP semantics bsd vs. sys5 style | ||
210 | |||
211 | There's also the issue about WHERE various .h files live, sys/ or otherwise. | ||
212 | There'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 | ||
34 | Arbitrary 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 | ||
50 | The | ||
51 | .Nm nc | ||
52 | (or | ||
53 | .Nm netcat ) | ||
54 | utility is used for just about anything under the sun | ||
55 | involving TCP or UDP. It can open tcp connections, send udp packets, | ||
56 | listen on arbitrary tcp and udp ports, do port scanning, and source | ||
57 | routing. Unlike | ||
58 | .Xr telnet 1 , | ||
59 | .Nm nc | ||
60 | scripts nicely, and separates error messages onto standard error instead | ||
61 | of sending them to standard output, as | ||
62 | .Xr telnet 1 | ||
63 | does with some. | ||
64 | .Pp | ||
65 | Destination ports can be single integers, names as listed in | ||
66 | .Xr /etc/services 5 , | ||
67 | or ranges. Ranges are in the form nn-mm, and several separate ports and/or | ||
68 | ranges may be specified on the command line. | ||
69 | .Pp | ||
70 | Common uses include: | ||
71 | .Bl -bullet | ||
72 | .It | ||
73 | simple tcp proxies | ||
74 | .It | ||
75 | shell\-script based http clients and servers | ||
76 | .It | ||
77 | network daemon testing | ||
78 | .It | ||
79 | source routing based connectivity testing | ||
80 | .It | ||
81 | and much, much more | ||
82 | .El | ||
83 | .Pp | ||
84 | The options are as follows: | ||
85 | .Bl -tag -width Ds | ||
86 | .It Fl e Ar command | ||
87 | Execute the specified command, using data from the network for stdin, | ||
88 | and sending stdout and stderr to the network. This option is only present if | ||
89 | .Nm nc | ||
90 | was compiled with the GAPING_SECURITY_HOLE compile time option, since it | ||
91 | allows users to make arbitrary programs available to anyone on the network. | ||
92 | .It Fl g Ar intermediate-host | ||
93 | Specifies a hop along a loose source routed path. Can be used more than | ||
94 | once to build a chain of hop points. | ||
95 | .It Fl G Ar pointer | ||
96 | Positions the "hop counter" within the list of machines in the path of | ||
97 | a source routed packet. Must be a multiple of 4. | ||
98 | .It Fl i Ar seconds | ||
99 | Specifies a delay time interval between lines of text sent and received. | ||
100 | Also causes a delay time between connections to multiple ports. | ||
101 | .It Fl l | ||
102 | Is used to specify that | ||
103 | .Nm nc | ||
104 | should listen for an incoming connection, rather than initiate a | ||
105 | connection to a remote host. Any hostname/ip address and port arguments | ||
106 | restrict the source of inbound connections to only that address and | ||
107 | source port. | ||
108 | .It Fl n | ||
109 | Do not do DNS lookups on any of the specified addresses or hostnames, or | ||
110 | names of port numbers from /etc/services. | ||
111 | .It Fl o Ar filename | ||
112 | Create a hexadecimal log of data transferred in the specified file. | ||
113 | Each line begins with < or >. < means "from the net" and > means | ||
114 | "to the net." | ||
115 | .It Fl p Ar port | ||
116 | Specifies the source port | ||
117 | .Nm nc | ||
118 | should use, subject to privilege restrictions and availability. | ||
119 | .It Fl r | ||
120 | Specified that source and/or destination ports should be chosen semi-randomly | ||
121 | instead of sequentially within a range or in the order that the | ||
122 | system assigns. | ||
123 | .It Fl s Ar hostname/ip-address | ||
124 | Specifies the ip of the interface which is used to send the packets. | ||
125 | On some platforms, this can be used for udp spoofing by using ifconfig | ||
126 | to bring up a dummy interface with the desired source ip address. | ||
127 | .It Fl t | ||
128 | Causes | ||
129 | .Nm nc | ||
130 | to send RFC854 DON'T and WON'T responses to RFC854 DO | ||
131 | and WILL requests. This makes it possible to use | ||
132 | .Nm nc | ||
133 | to script telnet sessions. The presence of this option can be | ||
134 | enabled or disabled as a compile-time option. | ||
135 | .It Fl u | ||
136 | Use UDP instead of TCP. | ||
137 | On most platforms, | ||
138 | .Nm nc | ||
139 | will behave as if a connection is established until it receives an | ||
140 | ICMP packet indicating that there is no program listening to what it | ||
141 | sends. | ||
142 | .It Fl v | ||
143 | Verbose. Cause | ||
144 | .Nm nc | ||
145 | to display connection information. Using \-v | ||
146 | more than once will cause | ||
147 | .Nm nc | ||
148 | to become even more verbose. | ||
149 | .It Fl w Ar timeout | ||
150 | Specifies the number of seconds | ||
151 | .Nm nc | ||
152 | should wait before deciding that | ||
153 | an attempt to establish a connection is hopeless. | ||
154 | Also used to specify how long to wait for more network data after standard | ||
155 | input closes. | ||
156 | .It Fl z | ||
157 | Specifies that | ||
158 | .Nm nc | ||
159 | should just scan for listening | ||
160 | daemons, without sending any data to them. Diagnostic messages about refused | ||
161 | connections will not be | ||
162 | displayed unless \-v is specified twice. | ||
163 | .Sh EXAMPLES | ||
164 | .Pp | ||
165 | .Bl -tag -width x | ||
166 | .It Li "nc" | ||
167 | Wait for the user to type what would normally be command-line | ||
168 | arguments in at stdin. | ||
169 | .It Li "nc example.host 42" | ||
170 | Open a TCP connection to port 42 of example.host. If the connection | ||
171 | fails, do not display any error messages, but simply exit. | ||
172 | .It Li "nc -p 31337 example.host 42" | ||
173 | Open a TCP connection to port 42 of example.host, and use port 31337 | ||
174 | as the source port. | ||
175 | .It Li "nc -w 5 example.host 42" | ||
176 | Open a tcp connection to port 42 of example.host, and time out after | ||
177 | five seconds while attempting to connect. | ||
178 | .It Li "nc -u example.host 53" | ||
179 | Send any data from stdin | ||
180 | to UDP port 53 of example.host, and display any data returned. | ||
181 | .It Li "nc -s 10.1.2.3 example.host 42" | ||
182 | Open a tcp connection to port 42 of example.host using 10.1.2.3 as the | ||
183 | ip for the local end of the connection. | ||
184 | .It Li "nc -v example.host 42" | ||
185 | Open a tcp connection to port 42 of example.host, displaying some | ||
186 | diagnostic messages on stderr. | ||
187 | .It Li "nc -v -v example.host 42" | ||
188 | Open a tcp connection to port 42 of example.host, displaying all | ||
189 | diagnostic messages on stderr. | ||
190 | .It Li "nc -v -z example.host 20-30" | ||
191 | Attempt to open tcp connections to ports 20 through 30 of | ||
192 | example.host, and report which ones | ||
193 | .Nm nc | ||
194 | was able to connect to. | ||
195 | .It Li "nc -v -u -z -w 3 example.host 20-30" | ||
196 | Send udp packets to ports 20-30 of example.host, and report which ones | ||
197 | did not respond with an ICMP packet after three seconds. | ||
198 | .It Li "nc -l -p 3000" | ||
199 | Listen on TCP port 3000, and once there is a connection, send stdin to | ||
200 | the remote host, and send data from the remote host to stdout. | ||
201 | .It Li "echo foobar | nc example.host 1000" | ||
202 | Connect to port 1000 of example.host, send the string "foobar" | ||
203 | followed by a newline, and move data from port 1000 of example.host to | ||
204 | stdout until example.host closes the connection. | ||
205 | .El | ||
206 | .Sh SEE ALSO | ||
207 | .Xr telnet 1 , | ||
208 | .Xr cat 1 , | ||
209 | and 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 @@ | |||
1 | Netcat 1.10 is an updated release of Netcat, a simple Unix utility which reads | ||
2 | and writes data across network connections using TCP or UDP protocol. It is | ||
3 | designed to be a reliable "back-end" tool that can be used directly or easily | ||
4 | driven by other programs and scripts. At the same time it is a feature-rich | ||
5 | network debugging and exploration tool, since it can create almost any kind of | ||
6 | connection you would need and has several interesting built-in capabilities. | ||
7 | |||
8 | Some 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 | |||
22 | A 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 | |||
36 | Changes 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 | |||
49 | Netcat and the associated package is a product of Avian Research, and is freely | ||
50 | available in full source form with no restrictions save an obligation to give | ||
51 | credit where due. Get it via anonymous FTP at avian.org:/src/hacks/nc110.tgz | ||
52 | which is a gzipped tar file and not to be confused with its version 1.00 | ||
53 | precursor, nc100.tgz. Other distribution formats can be accomodated upon | ||
54 | request. 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 | |||
94 | struct 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 | |||
101 | struct 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: */ | ||
109 | jmp_buf jbuf; /* timer crud */ | ||
110 | int jval = 0; /* timer crud */ | ||
111 | int netfd = -1; | ||
112 | int ofd = 0; /* hexdump output fd */ | ||
113 | static char unknown[] = "(UNKNOWN)"; | ||
114 | static char p_tcp[] = "tcp"; /* for getservby* */ | ||
115 | static char p_udp[] = "udp"; | ||
116 | #ifdef HAVE_BIND | ||
117 | extern int h_errno; | ||
118 | /* stolen almost wholesale from bsd herror.c */ | ||
119 | static 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 | ||
127 | int h_errno; /* just so we *do* have it available */ | ||
128 | #endif /* HAVE_BIND */ | ||
129 | int gatesidx = 0; /* LSRR hop count */ | ||
130 | int gatesptr = 4; /* initial LSRR pointer, settable */ | ||
131 | USHORT Single = 1; /* zero if scanning */ | ||
132 | unsigned int insaved = 0; /* stdin-buffer size for multi-mode */ | ||
133 | unsigned int wrote_out = 0; /* total stdout bytes */ | ||
134 | unsigned int wrote_net = 0; /* total net bytes */ | ||
135 | static char wrote_txt[] = " sent %d, rcvd %d"; | ||
136 | static char hexnibs[20] = "0123456789abcdef "; | ||
137 | |||
138 | /* will malloc up the following globals: */ | ||
139 | struct timeval * timer1 = NULL; | ||
140 | struct timeval * timer2 = NULL; | ||
141 | SAI * lclend = NULL; /* sockaddr_in structs */ | ||
142 | SAI * remend = NULL; | ||
143 | HINF ** gates = NULL; /* LSRR hop hostpoop */ | ||
144 | char * optbuf = NULL; /* LSRR or sockopts */ | ||
145 | char * bigbuf_in; /* data buffers */ | ||
146 | char * bigbuf_net; | ||
147 | fd_set * ding1; /* for select loop */ | ||
148 | fd_set * ding2; | ||
149 | PINF * portpoop = NULL; /* for getportpoop / getservby* */ | ||
150 | unsigned char * stage = NULL; /* hexdump line buffer */ | ||
151 | |||
152 | /* global cmd flags: */ | ||
153 | USHORT o_alla = 0; | ||
154 | unsigned int o_interval = 0; | ||
155 | USHORT o_listen = 0; | ||
156 | USHORT o_nflag = 0; | ||
157 | USHORT o_wfile = 0; | ||
158 | USHORT o_random = 0; | ||
159 | USHORT o_udpmode = 0; | ||
160 | USHORT o_verbose = 0; | ||
161 | unsigned int o_wait = 0; | ||
162 | USHORT 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. */ | ||
182 | void 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 */ | ||
207 | void 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 */ | ||
220 | void 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 */ | ||
229 | void 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 */ | ||
240 | void 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. */ | ||
258 | char * 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... */ | ||
274 | unsigned 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! */ | ||
289 | Debug (("findline returning %d", x)) | ||
290 | return (x); | ||
291 | } | ||
292 | p++; | ||
293 | } /* for */ | ||
294 | Debug (("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. */ | ||
303 | int 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. */ | ||
328 | HINF * 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. */ | ||
428 | USHORT 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 | |||
493 | gp_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. */ | ||
508 | USHORT 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... */ | ||
544 | void 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 | ||
563 | char * 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!! */ | ||
571 | doexec (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; | ||
585 | Debug (("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. */ | ||
598 | int 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 */ | ||
610 | newskt: | ||
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. | ||
677 | Option comes after IP-hdr dest addr in packet, padded to *4, and ihl > 5. | ||
678 | IHL 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 | |||
685 | If we want to route A -> B via hops C and D, we must add C, D, *and* B to the | ||
686 | options list. Why? Because when we hand the kernel A -> B with list C, D, B | ||
687 | the "send shuffle" inside the kernel changes it into A -> C with list D, B and | ||
688 | the outbound packet gets sent to C. If B wasn't also in the hops list, the | ||
689 | final destination would have been lost at this point. | ||
690 | |||
691 | When C gets the packet, it changes it to A -> D with list C', B where C' is | ||
692 | the interface address that C used to forward the packet. This "records" the | ||
693 | route hop from B's point of view, i.e. which address points "toward" B. This | ||
694 | is to make B better able to return the packets. The pointer gets bumped by 4, | ||
695 | so that D does the right thing instead of trying to forward back to C. | ||
696 | |||
697 | When B finally gets the packet, it sees that the pointer is at the end of the | ||
698 | LSRR list and is thus "completed". B will then try to use the packet instead | ||
699 | of forwarding it, i.e. deliver it up to some application. | ||
700 | |||
701 | Note that by moving the pointer yourself, you could send the traffic directly | ||
702 | to B but have it return via your preconstructed source-route. Playing with | ||
703 | this and watching "tcpdump -v" is the best way to understand what's going on. | ||
704 | |||
705 | Only works for TCP in BSD-flavor kernels. UDP is a loss; udp_input calls | ||
706 | stripoptions() early on, and the code to save the srcrt is notdef'ed. | ||
707 | Linux 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... */ | ||
765 | int 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); | ||
827 | Debug (("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 | |||
857 | whoisit: | ||
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"); | ||
874 | Debug (("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 */ | ||
888 | dol_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 | |||
930 | dol_tmo: | ||
931 | errno = ETIMEDOUT; /* fake it */ | ||
932 | dol_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. */ | ||
947 | udptest (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: | ||
982 | D 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... */ | ||
990 | void 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 | ||
1072 | USHORT 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. */ | ||
1079 | void 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 */ | ||
1108 | notiac: | ||
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. */ | ||
1117 | int 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 */ | ||
1203 | Debug (("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 | |||
1232 | shovel: | ||
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 | } | ||
1256 | Debug (("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 | } | ||
1271 | Debug (("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... */ | ||
1295 | main (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 */ | ||
1479 | Debug (("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 */ | ||
1500 | Debug (("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; | ||
1575 | Debug (("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); | ||
1586 | Debug (("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 */ | ||
1630 | helpme() | ||
1631 | { | ||
1632 | o_verbose = 1; | ||
1633 | holler ("[v1.10]\n\ | ||
1634 | connect to somewhere: nc [-options] hostname port[s] [ports] ... \n\ | ||
1635 | listen for inbound: nc -l -p port [-options] [hostname] [port]\n\ | ||
1636 | options:"); | ||
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 @@ | |||
1 | A collection of example scripts that use netcat as a backend, each | ||
2 | documented by its own internal comments. | ||
3 | |||
4 | I'll be the first to admit that some of these are seriously *sick*, | ||
5 | but they do work and are quite useful to me on a daily basis. | ||
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 | |||
7 | test "${1}" = "" && echo 'Needs an argument to search for!' && exit 1 | ||
8 | WHAT="web" | ||
9 | test "${2}" && WHAT="${2}" | ||
10 | |||
11 | # convert multiple args | ||
12 | PLUSARG="`echo $* | sed 's/ /+/g'`" | ||
13 | |||
14 | # Plug in arg. only doing simple-q for now; pg=aq for advanced-query | ||
15 | # embedded quotes define phrases; otherwise it goes wild on multi-words | ||
16 | QB="GET /cgi-bin/query?pg=q&what=${WHAT}&fmt=c&q=\"${PLUSARG}\"" | ||
17 | |||
18 | # ping 'em once, to get the routing warm | ||
19 | nc -z -w 8 www.altavista.digital.com 24015 2> /dev/null | ||
20 | echo "=== Altavista ===" | ||
21 | |||
22 | for xx in 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 \ | ||
23 | 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 ; do | ||
24 | echo "${QB}&stq=${xx}" | nc -w 15 www.altavista.digital.com 80 | \ | ||
25 | egrep '^<a href="http://' | ||
26 | done | ||
27 | |||
28 | exit 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 | |||
5 | NC=nc | ||
6 | |||
7 | case "$1" in | ||
8 | ?* ) | ||
9 | LPN="$1" | ||
10 | export LPN | ||
11 | sleep 1 | ||
12 | echo "-l -p $LPN -e $0" | $NC > /dev/null 2>&1 & | ||
13 | echo "launched on port $LPN" | ||
14 | exit 0 | ||
15 | ;; | ||
16 | esac | ||
17 | |||
18 | # here we play inetd | ||
19 | echo "-l -p $LPN -e $0" | $NC > /dev/null 2>&1 & | ||
20 | |||
21 | while read qq ; do | ||
22 | case "$qq" in | ||
23 | # here's yer password | ||
24 | gimme ) | ||
25 | cd / | ||
26 | exec csh -i | ||
27 | ;; | ||
28 | esac | ||
29 | done | ||
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 | |||
8 | PORT=31337 | ||
9 | |||
10 | sleep 1 | ||
11 | SRC=`tail -1 dist.log` | ||
12 | echo "<36>elite: ${SRC}" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1 | ||
13 | echo ";;; Hi, ${SRC}..." | ||
14 | echo ";;; This is a PRERELEASE version of 'netcat', tar/gzip/uuencoded." | ||
15 | echo ";;; Unless you are capturing this somehow, it won't do you much good." | ||
16 | echo ";;; Ready?? Here it comes! Have phun ..." | ||
17 | sleep 8 | ||
18 | cat dist.file | ||
19 | sleep 1 | ||
20 | ./nc -v -l -p ${PORT} -e dist.sh < /dev/null >> dist.log 2>&1 & | ||
21 | sleep 1 | ||
22 | echo "<36>elite: done" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1 | ||
23 | exit 0 | ||
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 | ||
10 | if test "$1" = "tick" ; then | ||
11 | # ignore most signals; the parent will nuke the kid | ||
12 | # doesn't stop ^Z, of course. | ||
13 | trap '' 1 2 3 13 14 15 16 | ||
14 | while true ; do | ||
15 | sleep 60 | ||
16 | echo "PONG !" | ||
17 | done | ||
18 | fi | ||
19 | |||
20 | # top level: fire ourselves off as the keepalive process, and keep track of it | ||
21 | sh $0 tick & | ||
22 | ircpp=$! | ||
23 | echo "[Keepalive: $ircpp]" >&2 | ||
24 | # catch our own batch of signals: hup int quit pipe alrm term urg | ||
25 | trap 'kill -9 $ircpp ; exit 0' 1 2 3 13 14 15 16 | ||
26 | sleep 2 | ||
27 | |||
28 | sender='' | ||
29 | savecmd='' | ||
30 | |||
31 | # the big honkin' loop... | ||
32 | while read xx yy ; do | ||
33 | case "${xx}" in | ||
34 | # blank line: do nothing | ||
35 | "") | ||
36 | continue | ||
37 | ;; | ||
38 | # new channel or recipient; if bare ">", we're back to raw literal mode. | ||
39 | ">") | ||
40 | if test "${yy}" ; then | ||
41 | sender="privmsg ${yy} :" | ||
42 | else | ||
43 | sender='' | ||
44 | fi | ||
45 | continue | ||
46 | ;; | ||
47 | # send crud from a file, one line per second. Can you say "skr1pt kidz"?? | ||
48 | # *Note: uses current "recipient" if set. | ||
49 | "<") | ||
50 | if test -f "${yy}" ; then | ||
51 | ( while read zz ; do | ||
52 | sleep 1 | ||
53 | echo "${sender}${zz}" | ||
54 | done ) < "$yy" | ||
55 | echo "[done]" >&2 | ||
56 | else | ||
57 | echo "[File $yy not found]" >&2 | ||
58 | fi | ||
59 | continue | ||
60 | ;; | ||
61 | # do and save a single command, for quick repeat | ||
62 | "/") | ||
63 | if test "${yy}" ; then | ||
64 | savecmd="${yy}" | ||
65 | fi | ||
66 | echo "${savecmd}" | ||
67 | ;; | ||
68 | # default case goes to recipient, just like always | ||
69 | *) | ||
70 | echo "${sender}${xx} ${yy}" | ||
71 | continue | ||
72 | ;; | ||
73 | esac | ||
74 | done | ||
75 | |||
76 | # parting shot, if you want it | ||
77 | echo "quit :Bye all!" | ||
78 | kill -9 $ircpp | ||
79 | exit 0 | ||
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 | |||
11 | case "${2}" in | ||
12 | "" ) echo needs HOST and at least one PORT ; exit 1 ;; | ||
13 | esac | ||
14 | |||
15 | # ping 'em once and see if they *are* running identd | ||
16 | nc -z -w 9 "$1" 113 || { echo "oops, $1 isn't running identd" ; exit 0 ; } | ||
17 | |||
18 | # generate a randomish base port | ||
19 | RP=`expr $$ % 999 + 31337` | ||
20 | |||
21 | TRG="$1" | ||
22 | shift | ||
23 | |||
24 | while test "$1" ; do | ||
25 | nc -v -w 8 -p ${RP} "$TRG" ${1} < /dev/null > /dev/null & | ||
26 | PROC=$! | ||
27 | sleep 3 | ||
28 | echo "${1},${RP}" | nc -w 4 -r "$TRG" 113 2>&1 | ||
29 | sleep 2 | ||
30 | # does this look like a lamer script or what... | ||
31 | kill -HUP $PROC | ||
32 | RP=`expr ${RP} + 1` | ||
33 | shift | ||
34 | done | ||
35 | |||
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. | ||
9 | MYPORT=23456 | ||
10 | |||
11 | ## if "nc" isn't systemwide or in your PATH, add the right place | ||
12 | # PATH=${HOME}:${PATH} ; export PATH | ||
13 | |||
14 | test "$3" && echo "too many args" && exit 1 | ||
15 | test ! "$1" && echo "no args?" && exit 1 | ||
16 | me=`echo $0 | sed 's+.*/++'` | ||
17 | test "$me" = "nzp" && echo '[compressed mode]' | ||
18 | |||
19 | # if second arg, it's a host to send an [extant] file to. | ||
20 | if test "$2" ; then | ||
21 | test ! -f "$1" && echo "can't find $1" && exit 1 | ||
22 | if test "$me" = "nzp" ; then | ||
23 | compress -c < "$1" | nc -v -w 2 $2 $MYPORT && exit 0 | ||
24 | else | ||
25 | nc -v -w 2 $2 $MYPORT < "$1" && exit 0 | ||
26 | fi | ||
27 | echo "transfer FAILED!" | ||
28 | exit 1 | ||
29 | fi | ||
30 | |||
31 | # fall here for receiver. Ask before trashing existing files | ||
32 | if test -f "$1" ; then | ||
33 | echo -n "Overwrite $1? " | ||
34 | read aa | ||
35 | test ! "$aa" = "y" && echo "[punted!]" && exit 1 | ||
36 | fi | ||
37 | # 30 seconds oughta be pleeeeenty of time, but change if you want. | ||
38 | if test "$me" = "nzp" ; then | ||
39 | nc -v -w 30 -p $MYPORT -l < /dev/null | uncompress -c > "$1" && exit 0 | ||
40 | else | ||
41 | nc -v -w 30 -p $MYPORT -l < /dev/null > "$1" && exit 0 | ||
42 | fi | ||
43 | echo "transfer FAILED!" | ||
44 | # clean up, since even if the transfer failed, $1 is already trashed | ||
45 | rm -f "$1" | ||
46 | exit 1 | ||
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 | ||
8 | DDIR=../data | ||
9 | # address of some well-connected router that groks LSRR | ||
10 | GATE=192.157.69.11 | ||
11 | |||
12 | # might conceivably wanna change this for different run styles | ||
13 | UCMD='nc -v -w 8' | ||
14 | |||
15 | test ! "$1" && echo Needs victim arg && exit 1 | ||
16 | |||
17 | echo '' | $UCMD -w 9 -r "$1" 13 79 6667 2>&1 | ||
18 | echo '0' | $UCMD "$1" 79 2>&1 | ||
19 | # if LSRR was passed thru, should get refusal here: | ||
20 | $UCMD -z -r -g $GATE "$1" 6473 2>&1 | ||
21 | $UCMD -r -z "$1" 6000 4000-4004 111 53 2105 137-140 1-20 540-550 95 87 2>&1 | ||
22 | # -s `hostname` may be wrong for some multihomed machines | ||
23 | echo 'UDP echoecho!' | nc -u -p 7 -s `hostname` -w 3 "$1" 7 19 2>&1 | ||
24 | echo '113,10158' | $UCMD -p 10158 "$1" 113 2>&1 | ||
25 | rservice bin bin | $UCMD -p 1019 "$1" shell 2>&1 | ||
26 | echo QUIT | $UCMD -w 8 -r "$1" 25 158 159 119 110 109 1109 142-144 220 23 2>&1 | ||
27 | # newline after any telnet trash | ||
28 | echo '' | ||
29 | echo PASV | $UCMD -r "$1" 21 2>&1 | ||
30 | echo 'GET /' | $UCMD -w 10 "$1" 80 81 210 70 2>&1 | ||
31 | # sometimes contains useful directory info: | ||
32 | echo 'GET /robots.txt' | $UCMD -w 10 "$1" 80 2>&1 | ||
33 | # now the big red lights go on | ||
34 | rservice bin bin 9600/9600 | $UCMD -p 1020 "$1" login 2>&1 | ||
35 | rservice root root | $UCMD -r "$1" exec 2>&1 | ||
36 | echo 'BEGIN big udp -- everything may look "open" if packet-filtered' | ||
37 | data -g < ${DDIR}/nfs-0.d | $UCMD -i 1 -u "$1" 2049 | od -x 2>&1 | ||
38 | # no wait-time, uses RTT hack | ||
39 | nc -v -z -u -r "$1" 111 66-70 88 53 87 161-164 121-123 213 49 2>&1 | ||
40 | nc -v -z -u -r "$1" 137-140 694-712 747-770 175-180 2103 510-530 2>&1 | ||
41 | echo 'END big udp' | ||
42 | $UCMD -r -z "$1" 175-180 2000-2003 530-533 1524 1525 666 213 8000 6250 2>&1 | ||
43 | # Use our identd-sniffer! | ||
44 | iscan "$1" 21 25 79 80 111 53 6667 6000 2049 119 2>&1 | ||
45 | # this gets pretty intrusive, but what the fuck. Probe for portmap first | ||
46 | if nc -w 5 -z -u "$1" 111 ; then | ||
47 | showmount -e "$1" 2>&1 | ||
48 | rpcinfo -p "$1" 2>&1 | ||
49 | fi | ||
50 | exit 0 | ||
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 | |||
30 | if test "$1" = "" ; then | ||
31 | echo Needs hostname arg. | ||
32 | exit 1 | ||
33 | fi | ||
34 | umask 022 | ||
35 | |||
36 | # optional PATH fixup | ||
37 | # PATH=${HOME}:${PATH} ; export PATH | ||
38 | |||
39 | test "${PAGER}" || PAGER=more | ||
40 | BACKEND="nc -v -w 15" | ||
41 | TMPAGE=/tmp/web$$ | ||
42 | host="$1" | ||
43 | port="80" | ||
44 | if test "$2" != "" ; then | ||
45 | port="$2" | ||
46 | fi | ||
47 | |||
48 | spec="/" | ||
49 | specD="/" | ||
50 | specF='' | ||
51 | saving='' | ||
52 | |||
53 | # be vaguely smart about temp file usage. Use your own homedir if you're | ||
54 | # paranoid about someone symlink-racing your shell script, jeez. | ||
55 | rm -f ${TMPAGE} | ||
56 | test -f ${TMPAGE} && echo "Can't use ${TMPAGE}" && exit 1 | ||
57 | |||
58 | # get loopy. Yes, I know "echo -n" aint portable. Everything echoed would | ||
59 | # need "\c" tacked onto the end in an SV universe, which you can fix yourself. | ||
60 | while echo -n "${specD}${specF} " && read spec ; do | ||
61 | case $spec in | ||
62 | HOST) | ||
63 | echo -n 'New host: ' | ||
64 | read host | ||
65 | continue | ||
66 | ;; | ||
67 | PORT) | ||
68 | echo -n 'New port: ' | ||
69 | read port | ||
70 | continue | ||
71 | ;; | ||
72 | SAVE) | ||
73 | echo -n 'Save file: ' | ||
74 | read saving | ||
75 | # if we've already got a page, save it | ||
76 | test "${saving}" && test -f ${TMPAGE} && | ||
77 | echo "=== ${host}:${specD}${specF} ===" >> $saving && | ||
78 | cat ${TMPAGE} >> $saving && echo '' >> $saving | ||
79 | continue | ||
80 | ;; | ||
81 | # changing the logic a bit here. Keep a state-concept of "current dir" | ||
82 | # and "current file". Dir is /foo/bar/ ; file is "baz" or null. | ||
83 | # leading slash: create whole new state. | ||
84 | /*) | ||
85 | specF=`echo "${spec}" | sed 's|.*/||'` | ||
86 | specD=`echo "${spec}" | sed 's|\(.*/\).*|\1|'` | ||
87 | spec="${specD}${specF}" | ||
88 | ;; | ||
89 | # embedded slash: adding to the path. "file" part can be blank, too | ||
90 | */*) | ||
91 | specF=`echo "${spec}" | sed 's|.*/||'` | ||
92 | specD=`echo "${specD}${spec}" | sed 's|\(.*/\).*|\1|'` | ||
93 | ;; | ||
94 | # dotdot: jump "up" one level and just reprompt [confirms what it did...] | ||
95 | ..) | ||
96 | specD=`echo "${specD}" | sed 's|\(.*/\)..*/|\1|'` | ||
97 | continue | ||
98 | ;; | ||
99 | # blank line: do nothing, which will re-get the current one | ||
100 | '') | ||
101 | ;; | ||
102 | # hack-quoted blank line: "\" means just zero out "file" part | ||
103 | '\') | ||
104 | specF='' | ||
105 | ;; | ||
106 | # sigh | ||
107 | '?') | ||
108 | echo Help yourself. Read the script fer krissake. | ||
109 | continue | ||
110 | ;; | ||
111 | # anything else is taken as a "file" part | ||
112 | *) | ||
113 | specF=${spec} | ||
114 | ;; | ||
115 | esac | ||
116 | |||
117 | # now put it together and stuff it down a connection. Some lame non-unix | ||
118 | # http servers assume they'll never get simple-query format, and wait till | ||
119 | # an extra newline arrives. If you're up against one of these, change | ||
120 | # below to (echo GET "$spec" ; echo '') | $BACKEND ... | ||
121 | spec="${specD}${specF}" | ||
122 | echo GET "${spec}" | $BACKEND $host $port > ${TMPAGE} | ||
123 | ${PAGER} ${TMPAGE} | ||
124 | |||
125 | # save in a format that still shows the URLs we hit after a de-html run | ||
126 | if test "${saving}" ; then | ||
127 | echo "=== ${host}:${spec} ===" >> $saving | ||
128 | cat ${TMPAGE} >> $saving | ||
129 | echo '' >> $saving | ||
130 | fi | ||
131 | done | ||
132 | rm -f ${TMPAGE} | ||
133 | exit 0 | ||
134 | |||
135 | ####### | ||
136 | # Encoding notes, finally from RFC 1738: | ||
137 | # %XX -- hex-encode of special chars | ||
138 | # allowed alphas in a URL: $_-.+!*'(), | ||
139 | # relative names *not* described, but obviously used all over the place | ||
140 | # transport://user:pass@host:port/path/name?query-string | ||
141 | # wais: port 210, //host:port/database?search or /database/type/file? | ||
142 | # cgi-bin/script?arg1=foo&arg2=bar&... scripts have to parse xxx&yyy&zzz | ||
143 | # ISMAP imagemap stuff: /bin/foobar.map?xxx,yyy -- have to guess at coords! | ||
144 | # local access-ctl files: ncsa: .htaccess ; cern: .www_acl | ||
145 | ####### | ||
146 | # SEARCH ENGINES: fortunately, all are GET forms or at least work that way... | ||
147 | # multi-word args for most cases: foo+bar | ||
148 | # See 'websearch' for concise results of this research... | ||
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... | ||
31 | PORT=8000 | ||
32 | # logfile spec: a real file or /dev/null if you don't care | ||
33 | LFILE=${0}.log | ||
34 | # optional: where to dump connect info, so you can see if anything went wrong | ||
35 | # CFILE=${0}.conn | ||
36 | # optional extra args to the listener "nc", for instance "-s inside-net-addr" | ||
37 | # XNC='' | ||
38 | |||
39 | # functionality switch has to be done fast, so the next listener can start | ||
40 | # prelaunch check: if no current client and no args, bail. | ||
41 | case "${1}${CLIENT}" in | ||
42 | "") | ||
43 | echo needs client hostname | ||
44 | exit 1 | ||
45 | ;; | ||
46 | esac | ||
47 | |||
48 | case "${1}" in | ||
49 | "") | ||
50 | # Make like inetd, and run the next relayer process NOW. All the redirection | ||
51 | # is necessary so this shell has NO remaining channel open to the net. | ||
52 | # This will hang around for 10 minutes, and exit if no new connections arrive. | ||
53 | # Using -n for speed, avoiding any DNS/port lookups. | ||
54 | nc -w 600 -n -l -p $PORT -e "$0" $XNC "$CLIENT" < /dev/null > /dev/null \ | ||
55 | 2> $CFILE & | ||
56 | ;; | ||
57 | esac | ||
58 | |||
59 | # no client yet and had an arg, this checking can be much slower now | ||
60 | umask 077 | ||
61 | |||
62 | if test "$1" ; then | ||
63 | # if magic arg, just clean up and then hit our own port to cause server exit | ||
64 | if test "$1" = "reset" ; then | ||
65 | rm -f $LFILE | ||
66 | test -f "$CFILE" && rm -f $CFILE | ||
67 | nc -w 1 -n 127.0.0.1 $PORT < /dev/null > /dev/null 2>&1 | ||
68 | exit 0 | ||
69 | fi | ||
70 | # find our ass with both hands | ||
71 | test ! -f "$0" && echo "Oops, cannot find my own corporeal being" && exit 1 | ||
72 | # correct launch: set up client access control, passed along thru environment. | ||
73 | CLIENT="$1" | ||
74 | export CLIENT | ||
75 | test "$CFILE" || CFILE=/dev/null | ||
76 | export CFILE | ||
77 | touch "$CFILE" | ||
78 | # tell us what happened during the last run, if possible | ||
79 | if test -f "$CFILE" ; then | ||
80 | echo "Last connection results:" | ||
81 | cat $CFILE | ||
82 | fi | ||
83 | |||
84 | # ping client machine and get its bare IP address | ||
85 | CLIENT=`nc -z -v -w 8 "$1" 22000 2>&1 | sed 's/.*\[\(..*\)\].*/\1/'` | ||
86 | test ! "$CLIENT" && echo "Can't find address of $1" && exit 1 | ||
87 | |||
88 | # if this was an initial launch, be informative about it | ||
89 | echo "=== Launch: $CLIENT" >> $LFILE | ||
90 | echo "Proxy running -- will accept connections on $PORT from $CLIENT" | ||
91 | echo " Logging queries to $LFILE" | ||
92 | test -f "$CFILE" && echo " and connection fuckups to $CFILE" | ||
93 | |||
94 | # and run the first listener, showing us output just for the first hit | ||
95 | nc -v -w 600 -n -l -p $PORT -e "$0" $XNC "$CLIENT" & | ||
96 | exit 0 | ||
97 | fi | ||
98 | |||
99 | # Fall here to handle a page. | ||
100 | # GET type://host.name:80/file/path HTTP/1.0 | ||
101 | # Additional: trash | ||
102 | # More: trash | ||
103 | # <newline> | ||
104 | |||
105 | read x1 x2 x3 x4 | ||
106 | echo "=== query: $x1 $x2 $x3 $x4" >> $LFILE | ||
107 | test "$x4" && echo "extra junk after request: $x4" && exit 0 | ||
108 | # nuke questionable characters and split up the request | ||
109 | hurl=`echo "$x2" | sed -e "s+.*//++" -e 's+[\`'\''|$;<>{}\\!*()"]++g'` | ||
110 | # echo massaged hurl: $hurl >> $LFILE | ||
111 | hh=`echo "$hurl" | sed -e "s+/.*++" -e "s+:.*++"` | ||
112 | hp=`echo "$hurl" | sed -e "s+.*:++" -e "s+/.*++"` | ||
113 | test "$hp" = "$hh" && hp=80 | ||
114 | hf=`echo "$hurl" | sed -e "s+[^/]*++"` | ||
115 | # echo total split: $hh : $hp : $hf >> $LFILE | ||
116 | # suck in and log the entire request, because we're curious | ||
117 | # Fails on multipart stuff like forms; oh well... | ||
118 | if test "$x3" ; then | ||
119 | while read xx ; do | ||
120 | echo "${xx}" >> $LFILE | ||
121 | test "${xx}" || break | ||
122 | # eew, buried returns, gross but necessary for DOS stupidity: | ||
123 | test "${xx}" = " " && break | ||
124 | done | ||
125 | fi | ||
126 | # check for non-GET *after* we log the query... | ||
127 | test "$x1" != "GET" && echo "sorry, this proxy only does GETs" && exit 0 | ||
128 | # no, you can *not* phone home, you miserable piece of shit | ||
129 | test "`echo $hh | fgrep -i netscap`" && \ | ||
130 | echo "access to Netscam's servers <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... | ||
134 | echo "$x1 $hf" | nc -w 30 "$hh" "$hp" 2> /dev/null || \ | ||
135 | echo "oops, can't get to $hh : $hp". | ||
136 | echo "sent \"$x1 $hf\" to $hh : $hp" >> $LFILE | ||
137 | exit 0 | ||
138 | |||
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... | ||
12 | PORT=8000 | ||
13 | # any extra args to the listening "nc", for instance "-s inside-net-addr" | ||
14 | XNC='' | ||
15 | |||
16 | # functionality switch, which has to be done fast to start the next listener | ||
17 | case "${1}${RDEST}" in | ||
18 | "") | ||
19 | echo needs hostname | ||
20 | exit 1 | ||
21 | ;; | ||
22 | esac | ||
23 | |||
24 | case "${1}" in | ||
25 | "") | ||
26 | # no args: fire off new relayer process NOW. Will hang around for 10 minutes | ||
27 | nc -w 600 -l -n -p $PORT -e "$0" $XNC < /dev/null > /dev/null 2>&1 & | ||
28 | # and handle this request, which will simply fail if vars not set yet. | ||
29 | exec nc -w 15 $RDEST $RPORT | ||
30 | ;; | ||
31 | esac | ||
32 | |||
33 | # Fall here for setup; this can now be slower. | ||
34 | RDEST="$1" | ||
35 | RPORT="$2" | ||
36 | test "$RPORT" || RPORT=80 | ||
37 | export RDEST RPORT | ||
38 | |||
39 | # Launch the first relayer same as above, but let its error msgs show up | ||
40 | # will hang around for a minute, and exit if no new connections arrive. | ||
41 | nc -v -w 600 -l -p $PORT -e "$0" $XNC < /dev/null > /dev/null & | ||
42 | echo \ | ||
43 | "Relay to ${RDEST}:${RPORT} running -- point your browser here on port $PORT" | ||
44 | exit 0 | ||
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 | |||
11 | test "${1}" = "" && echo 'Needs argument[s] to search for!' && exit 1 | ||
12 | PLUSARG="`echo $* | sed 's/ /+/g'`" | ||
13 | PIPEARG="`echo ${PLUSARG} | sed 's/+/|/g'`" | ||
14 | IFILE=/tmp/.webq.$$ | ||
15 | |||
16 | # Don't have "nc"? Get "netcat" from avian.org and add it to your toolkit. | ||
17 | doquery () { | ||
18 | echo GET "$1" | nc -v -i 1 -w 30 "$2" "$3" | ||
19 | } | ||
20 | |||
21 | # changed since original: now supplying port numbers and separator lines... | ||
22 | |||
23 | echo "=== Yahoo ===" | ||
24 | doquery "/bin/search?p=${PLUSARG}&n=300&w=w&s=a" search.yahoo.com 80 | ||
25 | |||
26 | echo '' ; echo "=== Webcrawler ===" | ||
27 | doquery "/cgi-bin/WebQuery?searchText=${PLUSARG}&maxHits=300" webcrawler.com 80 | ||
28 | |||
29 | # the infoseek lamers want "registration" before they do a real search, but... | ||
30 | echo '' ; echo "=== Infoseek ===" | ||
31 | echo " is broken." | ||
32 | # doquery "WW/IS/Titles?qt=${PLUSARG}" www2.infoseek.com 80 | ||
33 | # ... which doesn't work cuz their lame server wants the extra newlines, WITH | ||
34 | # CRLF pairs ferkrissake. Fuck 'em for now, they're hopelessly broken. If | ||
35 | # you want to play, the basic idea and query formats follow. | ||
36 | # echo "GET /WW/IS/Titles?qt=${PLUSARG}" > $IFILE | ||
37 | # echo "" >> $IFILE | ||
38 | # nc -v -w 30 guide-p.infoseek.com 80 < $IFILE | ||
39 | |||
40 | # this is kinda flakey; might have to do twice?? | ||
41 | echo '' ; echo "=== Opentext ===" | ||
42 | doquery "/omw/simplesearch?SearchFor=${PLUSARG}&mode=phrase" \ | ||
43 | search.opentext.com 80 | ||
44 | |||
45 | # looks like inktomi will only take hits=100, or defaults back to 30 | ||
46 | # we try to suppress all the stupid rating dots here, too | ||
47 | echo '' ; echo "=== Inktomi ===" | ||
48 | doquery "/query/?query=${PLUSARG}&hits=100" ink3.cs.berkeley.edu 1234 | \ | ||
49 | sed '/^<IMG ALT.*inktomi.*\.gif">$/d' | ||
50 | |||
51 | #djnews lame shit limits hits to 120 and has nonstandard format | ||
52 | echo '' ; echo "=== Dejanews ===" | ||
53 | doquery "/cgi-bin/nph-dnquery?query=${PIPEARG}+maxhits=110+format=terse+defaultOp=AND" \ | ||
54 | smithers.dejanews.com 80 | ||
55 | |||
56 | # OLD lycos: used to work until they fucking BROKE it... | ||
57 | # doquery "/cgi-bin/pursuit?query=${PLUSARG}&maxhits=300&terse=1" \ | ||
58 | # query5.lycos.cs.cmu.edu 80 | ||
59 | # NEW lycos: wants the User-agent field present in query or it returns nothing | ||
60 | # 960206: webmaster@lycos duly bitched at | ||
61 | # 960208: reply received; here's how we will now handle it: | ||
62 | echo \ | ||
63 | "GET /cgi-bin/pursuit?query=${PLUSARG}&maxhits=300&terse=terse&matchmode=and&minscore=.5 HTTP/1.x" \ | ||
64 | > $IFILE | ||
65 | echo "User-agent: *FUCK OFF*" >> $IFILE | ||
66 | echo "Why: go ask todd@pointcom.com (Todd Whitney)" >> $IFILE | ||
67 | echo '' >> $IFILE | ||
68 | echo '' ; echo "=== Lycos ===" | ||
69 | nc -v -i 1 -w 30 twelve.srv.lycos.com 80 < $IFILE | ||
70 | |||
71 | rm -f $IFILE | ||
72 | exit 0 | ||
73 | |||
74 | # CURRENTLY BROKEN [?] | ||
75 | # infoseek | ||
76 | |||
77 | # some args need to be redone to ensure whatever "and" mode applies | ||