1 /*
2    Shared secret TwoFish Encryption added 9/20/00  -JoJo
3    Extra -k Option added to set Shared secret key 9/25/00 -Xram_LraK
4    wrap user-supplied string to farm9crypt_init with memcpy() and ...
5    #ifdef resolv.h for broken linux distros 2/9/2001 -Jeff Nathan
6 
7 */
8 
9 /* Netcat 1.10 RELEASE 960320
10 
11    A damn useful little "backend" utility begun 950915 or thereabouts,
12    as *Hobbit*'s first real stab at some sockets programming.  Something that
13    should have and indeed may have existed ten years ago, but never became a
14    standard Unix utility.  IMHO, "nc" could take its place right next to cat,
15    cp, rm, mv, dd, ls, and all those other cryptic and Unix-like things.
16 
17    Read the README for the whole story, doc, applications, etc.
18 
19    Layout:
20 	conditional includes:
21 	includes:
22 	handy defines:
23 	globals:
24 	malloced globals:
25 	cmd-flag globals:
26 	support routines:
27 	readwrite select loop:
28 	main:
29 
30   bluesky:
31 	parse ranges of IP address as well as ports, perhaps
32 	RAW mode!
33 	backend progs to grab a pty and look like a real telnetd?!
34 	backend progs to do various encryption modes??!?!
35 */
36 
37 #include "generic.h"		/* same as with L5, skey, etc */
38 
39 /* conditional includes -- a very messy section which you may have to dink
40    for your own architecture [and please send diffs...]: */
41 /* #undef _POSIX_SOURCE		/* might need this for something? */
42 #define HAVE_BIND		/* ASSUMPTION -- seems to work everywhere! */
43 #define HAVE_HELP		/* undefine if you dont want the help text */
44 /* #define ANAL			/* if you want case-sensitive DNS matching */
45 
46 #ifdef HAVE_STDLIB_H
47 #include <stdlib.h>
48 #else
49 #include <malloc.h>
50 #endif
51 
52 /* have to do this *before* including types.h. xxx: Linux still has it wrong */
53 #ifdef FD_SETSIZE		/* should be in types.h, butcha never know. */
54 #undef FD_SETSIZE		/* if we ever need more than 16 active */
55 #endif				/* fd's, something is horribly wrong! */
56 #define FD_SETSIZE 16		/* <-- this'll give us a long anyways, wtf */
57 #include <sys/types.h>		/* *now* do it.  Sigh, this is broken */
58 #ifdef __FreeBSD__
59 #include <inttypes.h>
60 #endif
61 #ifdef HAVE_SELECT_H           /* random SV variants need this */
62 #include <sys/select.h>
63 #endif
64 
65 #ifdef HAVE_RANDOM		/* aficionados of ?rand48() should realize */
66 #define SRAND srandom		/* that this doesn't need *strong* random */
67 #define RAND random		/* numbers just to mix up port numbers!! */
68 #else
69 #define SRAND srand
70 #define RAND rand
71 #endif /* HAVE_RANDOM */
72 
73 /* includes: */
74 #include <sys/time.h>		/* timeval, time_t */
75 #include <setjmp.h>		/* jmp_buf et al */
76 #include <sys/socket.h>		/* basics, SO_ and AF_ defs, sockaddr, ... */
77 #include <netinet/in.h>		/* sockaddr_in, htons, in_addr */
78 #include <netinet/in_systm.h>	/* misc crud that netinet/ip.h references */
79 #include <netinet/ip.h>		/* IPOPT_LSRR, header stuff */
80 #include <netdb.h>		/* hostent, gethostby*, getservby* */
81 #include <arpa/inet.h>		/* inet_ntoa */
82 #include <stdio.h>
83 #include <string.h>		/* strcpy, strchr, yadda yadda */
84 #include <errno.h>
85 #include <signal.h>
86 #include <fcntl.h>		/* O_WRONLY et al */
87 #include <unistd.h>		/* clost() alarm() sleep() getopt() et al */
88 
89 #ifdef LINUX
90 #include <resolv.h>
91 #endif
92 
93 /* handy stuff: */
94 #define SA struct sockaddr	/* socket overgeneralization braindeath */
95 #define SAI struct sockaddr_in	/* ... whoever came up with this model */
96 #define IA struct in_addr	/* ... should be taken out and shot, */
97 				/* ... not that TLI is any better.  sigh.. */
98 #define SLEAZE_PORT 31337	/* for UDP-scan RTT trick, change if ya want */
99 #define USHORT unsigned short	/* use these for options an' stuff */
100 #define BIGSIZ 8192		/* big buffers */
101 
102 #ifndef INADDR_NONE
103 #define INADDR_NONE 0xffffffff
104 #endif
105 #ifdef MAXHOSTNAMELEN
106 #undef MAXHOSTNAMELEN		/* might be too small on aix, so fix it */
107 #endif
108 #define MAXHOSTNAMELEN 256
109 
110 #define MAXKEYSIZE 32
111 
112 struct host_poop {
113   char name[MAXHOSTNAMELEN];	/* dns name */
114   char addrs[8][24];		/* ascii-format IP addresses */
115   struct in_addr iaddrs[8];	/* real addresses: in_addr.s_addr: ulong */
116 };
117 #define HINF struct host_poop
118 
119 struct port_poop {
120   char name [64];		/* name in /etc/services */
121   char anum [8];		/* ascii-format number */
122   USHORT num;			/* real host-order number */
123 };
124 #define PINF struct port_poop
125 
126 /* globals: */
127 jmp_buf jbuf;			/* timer crud */
128 int jval = 0;			/* timer crud */
129 int netfd = -1;
130 int ofd = 0;			/* hexdump output fd */
131 static char unknown[] = "(UNKNOWN)";
132 static char p_tcp[] = "tcp";	/* for getservby* */
133 static char p_udp[] = "udp";
134 #ifdef HAVE_BIND
135 extern int h_errno;
136 /* stolen almost wholesale from bsd herror.c */
137 static char * h_errs[] = {
138   "Error 0",				/* but we *don't* use this */
139   "Unknown host",			/* 1 HOST_NOT_FOUND */
140   "Host name lookup failure",		/* 2 TRY_AGAIN */
141   "Unknown server error",		/* 3 NO_RECOVERY */
142   "No address associated with name",	/* 4 NO_ADDRESS */
143 };
144 #else
145 int h_errno;			/* just so we *do* have it available */
146 #endif /* HAVE_BIND */
147 int gatesidx = 0;		/* LSRR hop count */
148 int gatesptr = 4;		/* initial LSRR pointer, settable */
149 USHORT Single = 1;		/* zero if scanning */
150 unsigned int insaved = 0;	/* stdin-buffer size for multi-mode */
151 unsigned int wrote_out = 0;	/* total stdout bytes */
152 unsigned int wrote_net = 0;	/* total net bytes */
153 static char wrote_txt[] = " sent %d, rcvd %d";
154 static char hexnibs[20] = "0123456789abcdef  ";
155 
156 /* will malloc up the following globals: */
157 struct timeval * timer1 = NULL;
158 struct timeval * timer2 = NULL;
159 SAI * lclend = NULL;		/* sockaddr_in structs */
160 SAI * remend = NULL;
161 HINF ** gates = NULL;		/* LSRR hop hostpoop */
162 char * optbuf = NULL;		/* LSRR or sockopts */
163 char * bigbuf_in;		/* data buffers */
164 char * bigbuf_net;
165 fd_set * ding1;			/* for select loop */
166 fd_set * ding2;
167 PINF * portpoop = NULL;		/* for getportpoop / getservby* */
168 unsigned char * stage = NULL;	/* hexdump line buffer */
169 
170 /* global cmd flags: */
171 USHORT o_alla = 0;
172 unsigned int o_interval = 0;
173 USHORT o_listen = 0;
174 USHORT o_nflag = 0;
175 USHORT o_wfile = 0;
176 USHORT o_random = 0;
177 USHORT o_udpmode = 0;
178 USHORT o_verbose = 0;
179 unsigned int o_wait = 0;
180 USHORT o_zero = 0;
181 /* o_tn in optional section */
182 
183 /* Debug macro: squirt whatever message and sleep a bit so we can see it go
184    by.  need to call like Debug ((stuff)) [with no ; ] so macro args match!
185    Beware: writes to stdOUT... */
186 #ifdef DEBUG
187 #define Debug(x) printf x; printf ("\n"); fflush (stdout); sleep (1);
188 #else
189 #define Debug(x)	/* nil... */
190 #endif
191 
192 
193 /* support routines -- the bulk of this thing.  Placed in such an order that
194    we don't have to forward-declare anything: */
195 
196 /* holler :
197    fake varargs -- need to do this way because we wind up calling through
198    more levels of indirection than vanilla varargs can handle, and not all
199    machines have vfprintf/vsyslog/whatever!  6 params oughta be enough. */
holler(str,p1,p2,p3,p4,p5,p6)200 void holler (str, p1, p2, p3, p4, p5, p6)
201   char * str;
202   char * p1, * p2, * p3, * p4, * p5, * p6;
203 {
204   if (o_verbose) {
205     fprintf (stderr, str, p1, p2, p3, p4, p5, p6);
206 #ifdef HAVE_BIND
207     if (h_errno) {		/* if host-lookup variety of error ... */
208       if (h_errno > 4)		/* oh no you don't, either */
209 	fprintf (stderr, "preposterous h_errno: %d", h_errno);
210       else
211 	fprintf (stderr, h_errs[h_errno]);	/* handle it here */
212       h_errno = 0;				/* and reset for next call */
213     }
214 #endif
215     if (errno) {		/* this gives funny-looking messages, but */
216       perror (" ");		/* it's more portable than sys_errlist[]... */
217     } else			/* xxx: do something better?  */
218       fprintf (stderr, "\n");
219     fflush (stderr);
220   }
221 } /* holler */
222 
223 /* bail :
224    error-exit handler, callable from anywhere */
bail(str,p1,p2,p3,p4,p5,p6)225 void bail (str, p1, p2, p3, p4, p5, p6)
226   char * str;
227   char * p1, * p2, * p3, * p4, * p5, * p6;
228 {
229   o_verbose = 1;
230   holler (str, p1, p2, p3, p4, p5, p6);
231   close (netfd);
232   sleep (1);
233   exit (1);
234 } /* bail */
235 
236 /* catch :
237    no-brainer interrupt handler */
catch()238 void catch ()
239 {
240   errno = 0;
241   if (o_verbose > 1)		/* normally we don't care */
242     bail (wrote_txt, wrote_net, wrote_out);
243   bail (" punt!");
244 }
245 
246 /* timeout and other signal handling cruft */
tmtravel()247 void tmtravel ()
248 {
249   signal (SIGALRM, SIG_IGN);
250   alarm (0);
251   if (jval == 0)
252     bail ("spurious timer interrupt!");
253   longjmp (jbuf, jval);
254 }
255 
256 /* arm :
257    set the timer.  Zero secs arg means unarm */
arm(num,secs)258 void arm (num, secs)
259   unsigned int num;
260   unsigned int secs;
261 {
262   if (secs == 0) {			/* reset */
263     signal (SIGALRM, SIG_IGN);
264     alarm (0);
265     jval = 0;
266   } else {				/* set */
267     signal (SIGALRM, tmtravel);
268     alarm (secs);
269     jval = num;
270   } /* if secs */
271 } /* arm */
272 
273 /* Hmalloc :
274    malloc up what I want, rounded up to *4, and pre-zeroed.  Either succeeds
275    or bails out on its own, so that callers don't have to worry about it. */
Hmalloc(size)276 char * Hmalloc (size)
277   unsigned int size;
278 {
279   unsigned int s = (size + 4) & 0xfffffffc;	/* 4GB?! */
280   char * p = malloc (s);
281   if (p != NULL)
282     memset (p, 0, s);
283   else
284     bail ("Hmalloc %d failed", s);
285   return (p);
286 } /* Hmalloc */
287 
288 /* findline :
289    find the next newline in a buffer; return inclusive size of that "line",
290    or the entire buffer size, so the caller knows how much to then write().
291    Not distinguishing \n vs \r\n for the nonce; it just works as is... */
findline(buf,siz)292 unsigned int findline (buf, siz)
293   char * buf;
294   unsigned int siz;
295 {
296   register char * p;
297   register int x;
298   if (! buf)			/* various sanity checks... */
299     return (0);
300   if (siz > BIGSIZ)
301     return (0);
302   x = siz;
303   for (p = buf; x > 0; x--) {
304     if (*p == '\n') {
305       x = (int) (p - buf);
306       x++;			/* 'sokay if it points just past the end! */
307 Debug (("findline returning %d", x))
308       return (x);
309     }
310     p++;
311   } /* for */
312 Debug (("findline returning whole thing: %d", siz))
313   return (siz);
314 } /* findline */
315 
316 /* comparehosts :
317    cross-check the host_poop we have so far against new gethostby*() info,
318    and holler about mismatches.  Perhaps gratuitous, but it can't hurt to
319    point out when someone's DNS is fukt.  Returns 1 if mismatch, in case
320    someone else wants to do something about it. */
comparehosts(poop,hp)321 int comparehosts (poop, hp)
322   HINF * poop;
323   struct hostent * hp;
324 {
325   errno = 0;
326   h_errno = 0;
327 /* The DNS spec is officially case-insensitive, but for those times when you
328    *really* wanna see any and all discrepancies, by all means define this. */
329 #ifdef ANAL
330   if (strcmp (poop->name, hp->h_name) != 0) {		/* case-sensitive */
331 #else
332   if (strcasecmp (poop->name, hp->h_name) != 0) {	/* normal */
333 #endif
334     holler ("DNS fwd/rev mismatch: %s != %s", poop->name, hp->h_name);
335     return (1);
336   }
337   return (0);
338 /* ... do we need to do anything over and above that?? */
339 } /* comparehosts */
340 
341 /* gethostpoop :
342    resolve a host 8 ways from sunday; return a new host_poop struct with its
343    info.  The argument can be a name or [ascii] IP address; it will try its
344    damndest to deal with it.  "numeric" governs whether we do any DNS at all,
345    and we also check o_verbose for what's appropriate work to do. */
gethostpoop(name,numeric)346 HINF * gethostpoop (name, numeric)
347   char * name;
348   USHORT numeric;
349 {
350   struct hostent * hostent;
351   struct in_addr iaddr;
352   register HINF * poop = NULL;
353   register int x;
354 
355 /* I really want to strangle the twit who dreamed up all these sockaddr and
356    hostent abstractions, and then forced them all to be incompatible with
357    each other so you *HAVE* to do all this ridiculous casting back and forth.
358    If that wasn't bad enough, all the doc insists on referring to local ports
359    and addresses as "names", which makes NO sense down at the bare metal.
360 
361    What an absolutely horrid paradigm, and to think of all the people who
362    have been wasting significant amounts of time fighting with this stupid
363    deliberate obfuscation over the last 10 years... then again, I like
364    languages wherein a pointer is a pointer, what you put there is your own
365    business, the compiler stays out of your face, and sheep are nervous.
366    Maybe that's why my C code reads like assembler half the time... */
367 
368 /* If we want to see all the DNS stuff, do the following hair --
369    if inet_addr, do reverse and forward with any warnings; otherwise try
370    to do forward and reverse with any warnings.  In other words, as long
371    as we're here, do a complete DNS check on these clowns.  Yes, it slows
372    things down a bit for a first run, but once it's cached, who cares? */
373 
374   errno = 0;
375   h_errno = 0;
376   if (name)
377     poop = (HINF *) Hmalloc (sizeof (HINF));
378   if (! poop)
379     bail ("gethostpoop fuxored");
380   strcpy (poop->name, unknown);		/* preload it */
381 /* see wzv:workarounds.c for dg/ux return-a-struct inet_addr lossage */
382   iaddr.s_addr = inet_addr (name);
383 
384   if (iaddr.s_addr == INADDR_NONE) {	/* here's the great split: names... */
385     if (numeric)
386       bail ("Can't parse %s as an IP address", name);
387     hostent = gethostbyname (name);
388     if (! hostent)
389 /* failure to look up a name is fatal, since we can't do anything with it */
390       bail ("%s: forward host lookup failed: ", name);
391     strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
392     for (x = 0; hostent->h_addr_list[x] && (x < 8); x++) {
393       memcpy (&poop->iaddrs[x], hostent->h_addr_list[x], sizeof (IA));
394       strncpy (poop->addrs[x], inet_ntoa (poop->iaddrs[x]),
395 	sizeof (poop->addrs[0]));
396     } /* for x -> addrs, part A */
397     if (! o_verbose)			/* if we didn't want to see the */
398       return (poop);			/* inverse stuff, we're done. */
399 /* do inverse lookups in separate loop based on our collected forward addrs,
400    since gethostby* tends to crap into the same buffer over and over */
401     for (x = 0; poop->iaddrs[x].s_addr && (x < 8); x++) {
402       hostent = gethostbyaddr ((char *)&poop->iaddrs[x],
403 				sizeof (IA), AF_INET);
404       if ((! hostent) || (! hostent-> h_name))
405 	holler ("Warning: inverse host lookup failed for %s: ",
406 	  poop->addrs[x]);
407       else
408 	(void) comparehosts (poop, hostent);
409     } /* for x -> addrs, part B */
410 
411   } else {  /* not INADDR_NONE: numeric addresses... */
412     memcpy (poop->iaddrs, &iaddr, sizeof (IA));
413     strncpy (poop->addrs[0], inet_ntoa (iaddr), sizeof (poop->addrs));
414     if (numeric)			/* if numeric-only, we're done */
415       return (poop);
416     if (! o_verbose)			/* likewise if we don't want */
417       return (poop);			/* the full DNS hair */
418     hostent = gethostbyaddr ((char *) &iaddr, sizeof (IA), AF_INET);
419 /* numeric or not, failure to look up a PTR is *not* considered fatal */
420     if (! hostent)
421 	holler ("%s: inverse host lookup failed: ", name);
422     else {
423 	strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
424 	hostent = gethostbyname (poop->name);
425 	if ((! hostent) || (! hostent->h_addr_list[0]))
426 	  holler ("Warning: forward host lookup failed for %s: ",
427 		poop->name);
428 	else
429 	  (void) comparehosts (poop, hostent);
430     } /* if hostent */
431   } /* INADDR_NONE Great Split */
432 
433 /* whatever-all went down previously, we should now have a host_poop struct
434    with at least one IP address in it. */
435   h_errno = 0;
436   return (poop);
437 } /* gethostpoop */
438 
439 /* getportpoop :
440    Same general idea as gethostpoop -- look up a port in /etc/services, fill
441    in global port_poop, but return the actual port *number*.  Pass ONE of:
442 	pstring to resolve stuff like "23" or "exec";
443 	pnum to reverse-resolve something that's already a number.
444    If o_nflag is on, fill in what we can but skip the getservby??? stuff.
445    Might as well have consistent behavior here, and it *is* faster. */
getportpoop(pstring,pnum)446 USHORT getportpoop (pstring, pnum)
447   char * pstring;
448   unsigned int pnum;
449 {
450   struct servent * servent;
451   register int x;
452   register int y;
453   char * whichp = p_tcp;
454   if (o_udpmode)
455     whichp = p_udp;
456   portpoop->name[0] = '?';		/* fast preload */
457   portpoop->name[1] = '\0';
458 
459 /* case 1: reverse-lookup of a number; placed first since this case is much
460    more frequent if we're scanning */
461   if (pnum) {
462     if (pstring)			/* one or the other, pleeze */
463       return (0);
464     x = pnum;
465     if (o_nflag)			/* go faster, skip getservbyblah */
466       goto gp_finish;
467     y = htons (x);			/* gotta do this -- see Fig.1 below */
468     servent = getservbyport (y, whichp);
469     if (servent) {
470       y = ntohs (servent->s_port);
471       if (x != y)			/* "never happen" */
472 	holler ("Warning: port-bynum mismatch, %d != %d", x, y);
473       strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name));
474     } /* if servent */
475     goto gp_finish;
476   } /* if pnum */
477 
478 /* case 2: resolve a string, but we still give preference to numbers instead
479    of trying to resolve conflicts.  None of the entries in *my* extensive
480    /etc/services begins with a digit, so this should "always work" unless
481    you're at 3com and have some company-internal services defined... */
482   if (pstring) {
483     if (pnum)				/* one or the other, pleeze */
484       return (0);
485     x = atoi (pstring);
486     if (x)
487       return (getportpoop (NULL, x));	/* recurse for numeric-string-arg */
488     if (o_nflag)			/* can't use names! */
489       return (0);
490     servent = getservbyname (pstring, whichp);
491     if (servent) {
492       strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name));
493       x = ntohs (servent->s_port);
494       goto gp_finish;
495     } /* if servent */
496   } /* if pstring */
497 
498   return (0);				/* catches any problems so far */
499 
500 /* Obligatory netdb.h-inspired rant: servent.s_port is supposed to be an int.
501    Despite this, we still have to treat it as a short when copying it around.
502    Not only that, but we have to convert it *back* into net order for
503    getservbyport to work.  Manpages generally aren't clear on all this, but
504    there are plenty of examples in which it is just quietly done.  More BSD
505    lossage... since everything getserv* ever deals with is local to our own
506    host, why bother with all this network-order/host-order crap at all?!
507    That should be saved for when we want to actually plug the port[s] into
508    some real network calls -- and guess what, we have to *re*-convert at that
509    point as well.  Fuckheads. */
510 
511 gp_finish:
512 /* Fall here whether or not we have a valid servent at this point, with
513    x containing our [host-order and therefore useful, dammit] port number */
514   sprintf (portpoop->anum, "%d", x);	/* always load any numeric specs! */
515   portpoop->num = (x & 0xffff);		/* ushort, remember... */
516   return (portpoop->num);
517 } /* getportpoop */
518 
519 /* nextport :
520    Come up with the next port to try, be it random or whatever.  "block" is
521    a ptr to randports array, whose bytes [so far] carry these meanings:
522 	0	ignore
523 	1	to be tested
524 	2	tested [which is set as we find them here]
525    returns a USHORT random port, or 0 if all the t-b-t ones are used up. */
nextport(block)526 USHORT nextport (block)
527   char * block;
528 {
529   register unsigned int x;
530   register unsigned int y;
531 
532   y = 70000;			/* high safety count for rnd-tries */
533   while (y > 0) {
534     x = (RAND() & 0xffff);
535     if (block[x] == 1) {	/* try to find a not-done one... */
536       block[x] = 2;
537       break;
538     }
539     x = 0;			/* bummer. */
540     y--;
541   } /* while y */
542   if (x)
543     return (x);
544 
545   y = 65535;			/* no random one, try linear downsearch */
546   while (y > 0) {		/* if they're all used, we *must* be sure! */
547     if (block[y] == 1) {
548       block[y] = 2;
549       break;
550     }
551     y--;
552   } /* while y */
553   if (y)
554     return (y);			/* at least one left */
555 
556   return (0);			/* no more left! */
557 } /* nextport */
558 
559 /* loadports :
560    set "to be tested" indications in BLOCK, from LO to HI.  Almost too small
561    to be a separate routine, but makes main() a little cleaner... */
loadports(block,lo,hi)562 void loadports (block, lo, hi)
563   char * block;
564   USHORT lo;
565   USHORT hi;
566 {
567   USHORT x;
568 
569   if (! block)
570     bail ("loadports: no block?!");
571   if ((! lo) || (! hi))
572     bail ("loadports: bogus values %d, %d", lo, hi);
573   x = hi;
574   while (lo <= x) {
575     block[x] = 1;
576     x--;
577   }
578 } /* loadports */
579 
580 #ifdef GAPING_SECURITY_HOLE
581 char * pr00gie = NULL;			/* global ptr to -e arg */
582 
583 /* doexec :
584    fiddle all the file descriptors around, and hand off to another prog.  Sort
585    of like a one-off "poor man's inetd".  This is the only section of code
586    that would be security-critical, which is why it's ifdefed out by default.
587    Use at your own hairy risk; if you leave shells lying around behind open
588    listening ports you deserve to lose!! */
doexec(fd)589 doexec (fd)
590   int fd;
591 {
592   register char * p;
593 
594   dup2 (fd, 0);				/* the precise order of fiddlage */
595   close (fd);				/* is apparently crucial; this is */
596   dup2 (0, 1);				/* swiped directly out of "inetd". */
597   dup2 (0, 2);
598   p = strrchr (pr00gie, '/');		/* shorter argv[0] */
599   if (p)
600     p++;
601   else
602     p = pr00gie;
603 Debug (("gonna exec %s as %s...", pr00gie, p))
604   execl (pr00gie, p, NULL);
605   bail ("exec %s failed", pr00gie);	/* this gets sent out.  Hmm... */
606 } /* doexec */
607 #endif /* GAPING_SECURITY_HOLE */
608 
609 /* doconnect :
610    do all the socket stuff, and return an fd for one of
611 	an open outbound TCP connection
612 	a UDP stub-socket thingie
613    with appropriate socket options set up if we wanted source-routing, or
614 	an unconnected TCP or UDP socket to listen on.
615    Examines various global o_blah flags to figure out what-all to do. */
doconnect(rad,rp,lad,lp)616 int doconnect (rad, rp, lad, lp)
617   IA * rad;
618   USHORT rp;
619   IA * lad;
620   USHORT lp;
621 {
622   register int nnetfd;
623   register int rr;
624   int x, y;
625   errno = 0;
626 
627 /* grab a socket; set opts */
628 newskt:
629   if (o_udpmode)
630     nnetfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
631   else
632     nnetfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
633   if (nnetfd < 0)
634     bail ("Can't get socket");
635   if (nnetfd == 0)		/* if stdin was closed this might *be* 0, */
636     goto newskt;		/* so grab another.  See text for why... */
637   x = 1;
638   rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x));
639   if (rr == -1)
640     holler ("nnetfd reuseaddr failed");		/* ??? */
641 #ifdef SO_REUSEPORT	/* doesnt exist everywhere... */
642   rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
643   if (rr == -1)
644     holler ("nnetfd reuseport failed");		/* ??? */
645 #endif
646 #if 0
647 /* If you want to screw with RCVBUF/SNDBUF, do it here.  Liudvikas Bukys at
648    Rochester sent this example, which would involve YET MORE options and is
649    just archived here in case you want to mess with it.  o_xxxbuf are global
650    integers set in main() getopt loop, and check for rr == 0 afterward. */
651   rr = setsockopt(nnetfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf);
652   rr = setsockopt(nnetfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf);
653 #endif
654 
655   /* fill in all the right sockaddr crud */
656     lclend->sin_family = AF_INET;
657 
658 /* fill in all the right sockaddr crud */
659   lclend->sin_family = AF_INET;
660   remend->sin_family = AF_INET;
661 
662 /* if lad/lp, do appropriate binding */
663   if (lad)
664     memcpy (&lclend->sin_addr.s_addr, lad, sizeof (IA));
665   if (lp)
666     lclend->sin_port = htons (lp);
667   rr = 0;
668   if (lad || lp) {
669     x = (int) lp;
670 /* try a few times for the local bind, a la ftp-data-port... */
671     for (y = 4; y > 0; y--) {
672       rr = bind (nnetfd, (SA *)lclend, sizeof (SA));
673       if (rr == 0)
674 	break;
675       if (errno != EADDRINUSE)
676 	break;
677       else {
678 	holler ("retrying local %s:%d", inet_ntoa (lclend->sin_addr), lp);
679 	sleep (2);
680 	errno = 0;			/* clear from sleep */
681       } /* if EADDRINUSE */
682     } /* for y counter */
683   } /* if lad or lp */
684   if (rr)
685     bail ("Can't grab %s:%d with bind",
686 	inet_ntoa(lclend->sin_addr), lp);
687 
688   if (o_listen)
689     return (nnetfd);			/* thanks, that's all for today */
690 
691   memcpy (&remend->sin_addr.s_addr, rad, sizeof (IA));
692   remend->sin_port = htons (rp);
693 
694 /* rough format of LSRR option and explanation of weirdness.
695 Option comes after IP-hdr dest addr in packet, padded to *4, and ihl > 5.
696 IHL is multiples of 4, i.e. real len = ip_hl << 2.
697 	type 131	1	; 0x83: copied, option class 0, number 3
698 	len		1	; of *whole* option!
699 	pointer		1	; nxt-hop-addr; 1-relative, not 0-relative
700 	addrlist...	var	; 4 bytes per hop-addr
701 	pad-to-32	var	; ones, i.e. "NOP"
702 
703 If we want to route A -> B via hops C and D, we must add C, D, *and* B to the
704 options list.  Why?  Because when we hand the kernel A -> B with list C, D, B
705 the "send shuffle" inside the kernel changes it into A -> C with list D, B and
706 the outbound packet gets sent to C.  If B wasn't also in the hops list, the
707 final destination would have been lost at this point.
708 
709 When C gets the packet, it changes it to A -> D with list C', B where C' is
710 the interface address that C used to forward the packet.  This "records" the
711 route hop from B's point of view, i.e. which address points "toward" B.  This
712 is to make B better able to return the packets.  The pointer gets bumped by 4,
713 so that D does the right thing instead of trying to forward back to C.
714 
715 When B finally gets the packet, it sees that the pointer is at the end of the
716 LSRR list and is thus "completed".  B will then try to use the packet instead
717 of forwarding it, i.e. deliver it up to some application.
718 
719 Note that by moving the pointer yourself, you could send the traffic directly
720 to B but have it return via your preconstructed source-route.  Playing with
721 this and watching "tcpdump -v" is the best way to understand what's going on.
722 
723 Only works for TCP in BSD-flavor kernels.  UDP is a loss; udp_input calls
724 stripoptions() early on, and the code to save the srcrt is notdef'ed.
725 Linux is also still a loss at 1.3.x it looks like; the lsrr code is { }...
726 */
727 
728 /* if any -g arguments were given, set up source-routing.  We hit this after
729    the gates are all looked up and ready to rock, any -G pointer is set,
730    and gatesidx is now the *number* of hops */
731   if (gatesidx) {		/* if we wanted any srcrt hops ... */
732 /* don't even bother compiling if we can't do IP options here! */
733 #ifdef IP_OPTIONS
734     if (! optbuf) {		/* and don't already *have* a srcrt set */
735       char * opp;		/* then do all this setup hair */
736       optbuf = Hmalloc (48);
737       opp = optbuf;
738       *opp++ = IPOPT_LSRR;					/* option */
739       *opp++ = (char)
740 	(((gatesidx + 1) * sizeof (IA)) + 3) & 0xff;		/* length */
741       *opp++ = gatesptr;					/* pointer */
742 /* opp now points at first hop addr -- insert the intermediate gateways */
743       for ( x = 0; x < gatesidx; x++) {
744 	memcpy (opp, gates[x]->iaddrs, sizeof (IA));
745 	opp += sizeof (IA);
746       }
747 /* and tack the final destination on the end [needed!] */
748       memcpy (opp, rad, sizeof (IA));
749       opp += sizeof (IA);
750       *opp = IPOPT_NOP;			/* alignment filler */
751     } /* if empty optbuf */
752 /* calculate length of whole option mess, which is (3 + [hops] + [final] + 1),
753    and apply it [have to do this every time through, of course] */
754     x = ((gatesidx + 1) * sizeof (IA)) + 4;
755     rr = setsockopt (nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, x);
756     if (rr == -1)
757       bail ("srcrt setsockopt fuxored");
758 #else /* IP_OPTIONS */
759     holler ("Warning: source routing unavailable on this machine, ignoring");
760 #endif /* IP_OPTIONS*/
761   } /* if gatesidx */
762 
763 /* wrap connect inside a timer, and hit it */
764   arm (1, o_wait);
765   if (setjmp (jbuf) == 0) {
766     rr = connect (nnetfd, (SA *)remend, sizeof (SA));
767   } else {				/* setjmp: connect failed... */
768     rr = -1;
769     errno = ETIMEDOUT;			/* fake it */
770   }
771   arm (0, 0);
772   if (rr == 0)
773     return (nnetfd);
774   close (nnetfd);			/* clean up junked socket FD!! */
775   return (-1);
776 } /* doconnect */
777 
778 /* dolisten :
779    just like doconnect, and in fact calls a hunk of doconnect, but listens for
780    incoming and returns an open connection *from* someplace.  If we were
781    given host/port args, any connections from elsewhere are rejected.  This
782    in conjunction with local-address binding should limit things nicely... */
dolisten(rad,rp,lad,lp)783 int dolisten (rad, rp, lad, lp)
784   IA * rad;
785   USHORT rp;
786   IA * lad;
787   USHORT lp;
788 {
789   register int nnetfd;
790   register int rr;
791   HINF * whozis = NULL;
792   int x;
793   char * cp;
794   USHORT z;
795   errno = 0;
796 
797 /* Pass everything off to doconnect, who in o_listen mode just gets a socket */
798   nnetfd = doconnect (rad, rp, lad, lp);
799   if (nnetfd <= 0)
800     return (-1);
801   if (o_udpmode) {			/* apparently UDP can listen ON */
802     if (! lp)				/* "port 0",  but that's not useful */
803       bail ("UDP listen needs -p arg");
804   } else {
805     rr = listen (nnetfd, 1);		/* gotta listen() before we can get */
806     if (rr < 0)				/* our local random port.  sheesh. */
807       bail ("local listen fuxored");
808   }
809 
810 /* Various things that follow temporarily trash bigbuf_net, which might contain
811    a copy of any recvfrom()ed packet, but we'll read() another copy later. */
812 
813 /* I can't believe I have to do all this to get my own goddamn bound address
814    and port number.  It should just get filled in during bind() or something.
815    All this is only useful if we didn't say -p for listening, since if we
816    said -p we *know* what port we're listening on.  At any rate we won't bother
817    with it all unless we wanted to see it, although listening quietly on a
818    random unknown port is probably not very useful without "netstat". */
819   if (o_verbose) {
820     x = sizeof (SA);		/* how 'bout getsockNUM instead, pinheads?! */
821     rr = getsockname (nnetfd, (SA *) lclend, &x);
822     if (rr < 0)
823       holler ("local getsockname failed");
824     strcpy (bigbuf_net, "listening on [");	/* buffer reuse... */
825     if (lclend->sin_addr.s_addr)
826       strcat (bigbuf_net, inet_ntoa (lclend->sin_addr));
827     else
828       strcat (bigbuf_net, "any");
829     strcat (bigbuf_net, "] %d ...");
830     z = ntohs (lclend->sin_port);
831     holler (bigbuf_net, z);
832   } /* verbose -- whew!! */
833 
834 /* UDP is a speeeeecial case -- we have to do I/O *and* get the calling
835    party's particulars all at once, listen() and accept() don't apply.
836    At least in the BSD universe, however, recvfrom/PEEK is enough to tell
837    us something came in, and we can set things up so straight read/write
838    actually does work after all.  Yow.  YMMV on strange platforms!  */
839   if (o_udpmode) {
840     x = sizeof (SA);		/* retval for recvfrom */
841     arm (2, o_wait);		/* might as well timeout this, too */
842     if (setjmp (jbuf) == 0) {	/* do timeout for initial connect */
843       rr = recvfrom		/* and here we block... */
844 	(nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (SA *) remend, &x);
845 Debug (("dolisten/recvfrom ding, rr = %d, netbuf %s ", rr, bigbuf_net))
846     } else
847       goto dol_tmo;		/* timeout */
848     arm (0, 0);
849 /* I'm not completely clear on how this works -- BSD seems to make UDP
850    just magically work in a connect()ed context, but we'll undoubtedly run
851    into systems this deal doesn't work on.  For now, we apparently have to
852    issue a connect() on our just-tickled socket so we can write() back.
853    Again, why the fuck doesn't it just get filled in and taken care of?!
854    This hack is anything but optimal.  Basically, if you want your listener
855    to also be able to send data back, you need this connect() line, which
856    also has the side effect that now anything from a different source or even a
857    different port on the other end won't show up and will cause ICMP errors.
858    I guess that's what they meant by "connect".
859    Let's try to remember what the "U" is *really* for, eh? */
860     rr = connect (nnetfd, (SA *)remend, sizeof (SA));
861     goto whoisit;
862   } /* o_udpmode */
863 
864 /* fall here for TCP */
865   x = sizeof (SA);		/* retval for accept */
866   arm (2, o_wait);		/* wrap this in a timer, too; 0 = forever */
867   if (setjmp (jbuf) == 0) {
868     rr = accept (nnetfd, (SA *)remend, &x);
869   } else
870     goto dol_tmo;		/* timeout */
871   arm (0, 0);
872   close (nnetfd);		/* dump the old socket */
873   nnetfd = rr;			/* here's our new one */
874 
875 whoisit:
876   if (rr < 0)
877     goto dol_err;		/* bail out if any errors so far */
878 
879 /* If we can, look for any IP options.  Useful for testing the receiving end of
880    such things, and is a good exercise in dealing with it.  We do this before
881    the connect message, to ensure that the connect msg is uniformly the LAST
882    thing to emerge after all the intervening crud.  Doesn't work for UDP on
883    any machines I've tested, but feel free to surprise me. */
884 #ifdef IP_OPTIONS
885   if (! o_verbose)			/* if we wont see it, we dont care */
886     goto dol_noop;
887   optbuf = Hmalloc (40);
888   x = 40;
889   rr = getsockopt (nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x);
890   if (rr < 0)
891     holler ("getsockopt failed");
892 Debug (("ipoptions ret len %d", x))
893   if (x) {				/* we've got options, lessee em... */
894     unsigned char * q = (unsigned char *) optbuf;
895     char * p = bigbuf_net;		/* local variables, yuk! */
896     char * pp = &bigbuf_net[128];	/* get random space farther out... */
897     memset (bigbuf_net, 0, 256);	/* clear it all first */
898     while (x > 0) {
899 	sprintf (pp, "%2.2x ", *q);	/* clumsy, but works: turn into hex */
900 	strcat (p, pp);			/* and build the final string */
901 	q++; p++;
902 	x--;
903     }
904     holler ("IP options: %s", bigbuf_net);
905   } /* if x, i.e. any options */
906 dol_noop:
907 #endif /* IP_OPTIONS */
908 
909 /* find out what address the connection was *to* on our end, in case we're
910    doing a listen-on-any on a multihomed machine.  This allows one to
911    offer different services via different alias addresses, such as the
912    "virtual web site" hack. */
913   memset (bigbuf_net, 0, 64);
914   cp = &bigbuf_net[32];
915   x = sizeof (SA);
916   rr = getsockname (nnetfd, (SA *) lclend, &x);
917   if (rr < 0)
918     holler ("post-rcv getsockname failed");
919   strcpy (cp, inet_ntoa (lclend->sin_addr));
920 
921 /* now check out who it is.  We don't care about mismatched DNS names here,
922    but any ADDR and PORT we specified had better fucking well match the caller.
923    Converting from addr to inet_ntoa and back again is a bit of a kludge, but
924    gethostpoop wants a string and there's much gnarlier code out there already,
925    so I don't feel bad.
926    The *real* question is why BFD sockets wasn't designed to allow listens for
927    connections *from* specific hosts/ports, instead of requiring the caller to
928    accept the connection and then reject undesireable ones by closing.  In
929    other words, we need a TCP MSG_PEEK. */
930   z = ntohs (remend->sin_port);
931   strcpy (bigbuf_net, inet_ntoa (remend->sin_addr));
932   whozis = gethostpoop (bigbuf_net, o_nflag);
933   errno = 0;
934   x = 0;				/* use as a flag... */
935   if (rad)	/* xxx: fix to go down the *list* if we have one? */
936     if (memcmp (rad, whozis->iaddrs, sizeof (SA)))
937       x = 1;
938   if (rp)
939     if (z != rp)
940       x = 1;
941   if (x)					/* guilty! */
942     bail ("invalid connection to [%s] from %s [%s] %d",
943 	cp, whozis->name, whozis->addrs[0], z);
944   holler ("connect to [%s] from %s [%s] %d",		/* oh, you're okay.. */
945 	cp, whozis->name, whozis->addrs[0], z);
946   return (nnetfd);				/* open! */
947 
948 dol_tmo:
949   errno = ETIMEDOUT;			/* fake it */
950 dol_err:
951   close (nnetfd);
952   return (-1);
953 } /* dolisten */
954 
955 /* udptest :
956    fire a couple of packets at a UDP target port, just to see if it's really
957    there.  On BSD kernels, ICMP host/port-unreachable errors get delivered to
958    our socket as ECONNREFUSED write errors.  On SV kernels, we lose; we'll have
959    to collect and analyze raw ICMP ourselves a la satan's probe_udp_ports
960    backend.  Guess where one could swipe the appropriate code from...
961 
962    Use the time delay between writes if given, otherwise use the "tcp ping"
963    trick for getting the RTT.  [I got that idea from pluvius, and warped it.]
964    Return either the original fd, or clean up and return -1. */
udptest(fd,where)965 udptest (fd, where)
966   int fd;
967   IA * where;
968 {
969   register int rr;
970 
971   rr = write (fd, bigbuf_in, 1);
972   if (rr != 1)
973     holler ("udptest first write failed?! errno %d", errno);
974   if (o_wait)
975     sleep (o_wait);
976   else {
977 /* use the tcp-ping trick: try connecting to a normally refused port, which
978    causes us to block for the time that SYN gets there and RST gets back.
979    Not completely reliable, but it *does* mostly work. */
980     o_udpmode = 0;			/* so doconnect does TCP this time */
981 /* Set a temporary connect timeout, so packet filtration doesnt cause
982    us to hang forever, and hit it */
983     o_wait = 5;				/* enough that we'll notice?? */
984     rr = doconnect (where, SLEAZE_PORT, 0, 0);
985     if (rr > 0)
986       close (rr);			/* in case it *did* open */
987     o_wait = 0;				/* reset it */
988     o_udpmode++;			/* we *are* still doing UDP, right? */
989   } /* if o_wait */
990   errno = 0;				/* clear from sleep */
991   rr = write (fd, bigbuf_in, 1);
992   if (rr == 1)				/* if write error, no UDP listener */
993     return (fd);
994   close (fd);				/* use it or lose it! */
995   return (-1);
996 } /* udptest */
997 
998 /* oprint :
999    Hexdump bytes shoveled either way to a running logfile, in the format:
1000 D offset       -  - - - --- 16 bytes --- - - -  -     # .... ascii .....
1001    where "which" sets the direction indicator, D:
1002 	0 -- sent to network, or ">"
1003 	1 -- rcvd and printed to stdout, or "<"
1004    and "buf" and "n" are data-block and length.  If the current block generates
1005    a partial line, so be it; we *want* that lockstep indication of who sent
1006    what when.  Adapted from dgaudet's original example -- but must be ripping
1007    *fast*, since we don't want to be too disk-bound... */
oprint(which,buf,n)1008 void oprint (which, buf, n)
1009   int which;
1010   char * buf;
1011   int n;
1012 {
1013   int bc;			/* in buffer count */
1014   int obc;			/* current "global" offset */
1015   int soc;			/* stage write count */
1016   register unsigned char * p;	/* main buf ptr; m.b. unsigned here */
1017   register unsigned char * op;	/* out hexdump ptr */
1018   register unsigned char * a;	/* out asc-dump ptr */
1019   register int x;
1020   register unsigned int y;
1021 
1022   if (! ofd)
1023     bail ("oprint called with no open fd?!");
1024   if (n == 0)
1025     return;
1026 
1027   op = stage;
1028   if (which) {
1029     *op = '<';
1030     obc = wrote_out;		/* use the globals! */
1031   } else {
1032     *op = '>';
1033     obc = wrote_net;
1034   }
1035   op++;				/* preload "direction" */
1036   *op = ' ';
1037   p = (unsigned char *) buf;
1038   bc = n;
1039   stage[59] = '#';		/* preload separator */
1040   stage[60] = ' ';
1041 
1042   while (bc) {			/* for chunk-o-data ... */
1043     x = 16;
1044     soc = 78;			/* len of whole formatted line */
1045     if (bc < x) {
1046       soc = soc - 16 + bc;	/* fiddle for however much is left */
1047       x = (bc * 3) + 11;	/* 2 digits + space per, after D & offset */
1048       op = &stage[x];
1049       x = 16 - bc;
1050       while (x) {
1051 	*op++ = ' ';		/* preload filler spaces */
1052 	*op++ = ' ';
1053 	*op++ = ' ';
1054 	x--;
1055       }
1056       x = bc;			/* re-fix current linecount */
1057     } /* if bc < x */
1058 
1059     bc -= x;			/* fix wrt current line size */
1060     sprintf (&stage[2], "%8.8x ", obc);		/* xxx: still slow? */
1061     obc += x;			/* fix current offset */
1062     op = &stage[11];		/* where hex starts */
1063     a = &stage[61];		/* where ascii starts */
1064 
1065     while (x) {			/* for line of dump, however long ... */
1066       y = (int)(*p >> 4);	/* hi half */
1067       *op = hexnibs[y];
1068       op++;
1069       y = (int)(*p & 0x0f);	/* lo half */
1070       *op = hexnibs[y];
1071       op++;
1072       *op = ' ';
1073       op++;
1074       if ((*p > 31) && (*p < 127))
1075 	*a = *p;		/* printing */
1076       else
1077 	*a = '.';		/* nonprinting, loose def */
1078       a++;
1079       p++;
1080       x--;
1081     } /* while x */
1082     *a = '\n';			/* finish the line */
1083     x = write (ofd, stage, soc);
1084     if (x < 0)
1085       bail ("ofd write err");
1086   } /* while bc */
1087 } /* oprint */
1088 
1089 #ifdef TELNET
1090 USHORT o_tn = 0;		/* global -t option */
1091 
1092 /* atelnet :
1093    Answer anything that looks like telnet negotiation with don't/won't.
1094    This doesn't modify any data buffers, update the global output count,
1095    or show up in a hexdump -- it just shits into the outgoing stream.
1096    Idea and codebase from Mudge@l0pht.com. */
atelnet(buf,size)1097 void atelnet (buf, size)
1098   unsigned char * buf;		/* has to be unsigned here! */
1099   unsigned int size;
1100 {
1101   static unsigned char obuf [4];  /* tiny thing to build responses into */
1102   register int x;
1103   register unsigned char y;
1104   register unsigned char * p;
1105 
1106   y = 0;
1107   p = buf;
1108   x = size;
1109   while (x > 0) {
1110     if (*p != 255)			/* IAC? */
1111       goto notiac;
1112     obuf[0] = 255;
1113     p++; x--;
1114     if ((*p == 251) || (*p == 252))	/* WILL or WONT */
1115       y = 254;				/* -> DONT */
1116     if ((*p == 253) || (*p == 254))	/* DO or DONT */
1117       y = 252;				/* -> WONT */
1118     if (y) {
1119       obuf[1] = y;
1120       p++; x--;
1121       obuf[2] = *p;			/* copy actual option byte */
1122       (void) write (netfd, obuf, 3);
1123 /* if one wanted to bump wrote_net or do a hexdump line, here's the place */
1124       y = 0;
1125     } /* if y */
1126 notiac:
1127     p++; x--;
1128   } /* while x */
1129 } /* atelnet */
1130 #endif /* TELNET */
1131 
1132 /* readwrite :
1133    handle stdin/stdout/network I/O.  Bwahaha!! -- the select loop from hell.
1134    In this instance, return what might become our exit status. */
readwrite(fd)1135 int readwrite (fd)
1136   int fd;
1137 {
1138   register int rr;
1139   register char * zp;		/* stdin buf ptr */
1140   register char * np;		/* net-in buf ptr */
1141   unsigned int rzleft;
1142   unsigned int rnleft;
1143   USHORT netretry;		/* net-read retry counter */
1144   USHORT wretry;		/* net-write sanity counter */
1145   USHORT wfirst;		/* one-shot flag to skip first net read */
1146 
1147 /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to
1148    either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */
1149   if (fd > FD_SETSIZE) {
1150     holler ("Preposterous fd value %d", fd);
1151     return (1);
1152   }
1153   FD_SET (fd, ding1);		/* global: the net is open */
1154   netretry = 2;
1155   wfirst = 0;
1156   rzleft = rnleft = 0;
1157   if (insaved) {
1158     rzleft = insaved;		/* preload multi-mode fakeouts */
1159     zp = bigbuf_in;
1160     wfirst = 1;
1161     if (Single)			/* if not scanning, this is a one-off first */
1162       insaved = 0;		/* buffer left over from argv construction, */
1163     else {
1164       FD_CLR (0, ding1);	/* OR we've already got our repeat chunk, */
1165       close (0);		/* so we won't need any more stdin */
1166     } /* Single */
1167   } /* insaved */
1168   if (o_interval)
1169     sleep (o_interval);		/* pause *before* sending stuff, too */
1170   errno = 0;			/* clear from sleep, close, whatever */
1171 
1172 /* and now the big ol' select shoveling loop ... */
1173   while (FD_ISSET (fd, ding1)) {	/* i.e. till the *net* closes! */
1174     wretry = 8200;			/* more than we'll ever hafta write */
1175     if (wfirst) {			/* any saved stdin buffer? */
1176       wfirst = 0;			/* clear flag for the duration */
1177       goto shovel;			/* and go handle it first */
1178     }
1179     *ding2 = *ding1;			/* FD_COPY ain't portable... */
1180 /* some systems, notably linux, crap into their select timers on return, so
1181    we create a expendable copy and give *that* to select.  *Fuck* me ... */
1182     if (timer1)
1183       memcpy (timer2, timer1, sizeof (struct timeval));
1184     rr = select (16, ding2, 0, 0, timer2);	/* here it is, kiddies */
1185     if (rr < 0) {
1186 	if (errno != EINTR) {		/* might have gotten ^Zed, etc ?*/
1187 	  holler ("select fuxored");
1188 	  close (fd);
1189 	  return (1);
1190 	}
1191     } /* select fuckup */
1192 /* if we have a timeout AND stdin is closed AND we haven't heard anything
1193    from the net during that time, assume it's dead and close it too. */
1194     if (rr == 0) {
1195 	if (! FD_ISSET (0, ding1))
1196 	  netretry--;			/* we actually try a coupla times. */
1197 	if (! netretry) {
1198 	  if (o_verbose > 1)		/* normally we don't care */
1199 	    holler ("net timeout");
1200 	  close (fd);
1201 	  return (0);			/* not an error! */
1202 	}
1203     } /* select timeout */
1204 /* xxx: should we check the exception fds too?  The read fds seem to give
1205    us the right info, and none of the examples I found bothered. */
1206 
1207 /* Ding!!  Something arrived, go check all the incoming hoppers, net first */
1208     if (FD_ISSET (fd, ding2)) {		/* net: ding! */
1209 	/*rr = read (fd, bigbuf_net, BIGSIZ);*/
1210 	rr = farm9crypt_read (fd, bigbuf_net, BIGSIZ);
1211 	if (rr <= 0) {
1212 	  FD_CLR (fd, ding1);		/* net closed, we'll finish up... */
1213 	  rzleft = 0;			/* can't write anymore: broken pipe */
1214 	} else {
1215 	  rnleft = rr;
1216 	  np = bigbuf_net;
1217 #ifdef TELNET
1218 	  if (o_tn)
1219 	    atelnet (np, rr);		/* fake out telnet stuff */
1220 #endif /* TELNET */
1221 	} /* if rr */
1222 Debug (("got %d from the net, errno %d", rr, errno))
1223     } /* net:ding */
1224 
1225 /* if we're in "slowly" mode there's probably still stuff in the stdin
1226    buffer, so don't read unless we really need MORE INPUT!  MORE INPUT! */
1227     if (rzleft)
1228 	goto shovel;
1229 
1230 /* okay, suck more stdin */
1231     if (FD_ISSET (0, ding2)) {		/* stdin: ding! */
1232 	rr = read (0, bigbuf_in, BIGSIZ);
1233 /* Considered making reads here smaller for UDP mode, but 8192-byte
1234    mobygrams are kinda fun and exercise the reassembler. */
1235 	if (rr <= 0) {			/* at end, or fukt, or ... */
1236 	  FD_CLR (0, ding1);		/* disable and close stdin */
1237 	  close (0);
1238 	} else {
1239 	  rzleft = rr;
1240 	  zp = bigbuf_in;
1241 /* special case for multi-mode -- we'll want to send this one buffer to every
1242    open TCP port or every UDP attempt, so save its size and clean up stdin */
1243 	  if (! Single) {		/* we might be scanning... */
1244 	    insaved = rr;		/* save len */
1245 	    FD_CLR (0, ding1);		/* disable further junk from stdin */
1246 	    close (0);			/* really, I mean it */
1247 	  } /* Single */
1248 	} /* if rr/read */
1249     } /* stdin:ding */
1250 
1251 shovel:
1252 /* now that we've dingdonged all our thingdings, send off the results.
1253    Geez, why does this look an awful lot like the big loop in "rsh"? ...
1254    not sure if the order of this matters, but write net -> stdout first. */
1255 
1256 /* sanity check.  Works because they're both unsigned... */
1257     if ((rzleft > 8200) || (rnleft > 8200)) {
1258 	holler ("Bogus buffers: %d, %d", rzleft, rnleft);
1259 	rzleft = rnleft = 0;
1260     }
1261 /* net write retries sometimes happen on UDP connections */
1262     if (! wretry) {			/* is something hung? */
1263 	holler ("too many output retries");
1264 	return (1);
1265     }
1266     if (rnleft) {
1267 	rr = write (1, np, rnleft);
1268 	if (rr > 0) {
1269 	  if (o_wfile)
1270 	    oprint (1, np, rr);		/* log the stdout */
1271 	  np += rr;			/* fix up ptrs and whatnot */
1272 	  rnleft -= rr;			/* will get sanity-checked above */
1273 	  wrote_out += rr;		/* global count */
1274 	}
1275 Debug (("wrote %d to stdout, errno %d", rr, errno))
1276     } /* rnleft */
1277     if (rzleft) {
1278 	if (o_interval)			/* in "slowly" mode ?? */
1279 	  rr = findline (zp, rzleft);
1280 	else
1281 	  rr = rzleft;
1282 	/*rr = write (fd, zp, rr);*/	/* one line, or the whole buffer */
1283 	rr = farm9crypt_write (fd, zp, rr);	/* one line, or the whole buffer */
1284 
1285 	if (rr > 0) {
1286 	  if (o_wfile)
1287 	    oprint (0, zp, rr);		/* log what got sent */
1288 	  zp += rr;
1289 	  rzleft -= rr;
1290 	  wrote_net += rr;		/* global count */
1291 	}
1292 Debug (("wrote %d to net, errno %d", rr, errno))
1293     } /* rzleft */
1294     if (o_interval) {			/* cycle between slow lines, or ... */
1295 	sleep (o_interval);
1296 	errno = 0;			/* clear from sleep */
1297 	continue;			/* ...with hairy select loop... */
1298     }
1299     if ((rzleft) || (rnleft)) {		/* shovel that shit till they ain't */
1300 	wretry--;			/* none left, and get another load */
1301 	goto shovel;
1302     }
1303   } /* while ding1:netfd is open */
1304 
1305 /* XXX: maybe want a more graceful shutdown() here, or screw around with
1306    linger times??  I suspect that I don't need to since I'm always doing
1307    blocking reads and writes and my own manual "last ditch" efforts to read
1308    the net again after a timeout.  I haven't seen any screwups yet, but it's
1309    not like my test network is particularly busy... */
1310   close (fd);
1311   return (0);
1312 } /* readwrite */
1313 
1314 /* main :
1315    now we pull it all together... */
main(argc,argv)1316 main (argc, argv)
1317   int argc;
1318   char ** argv;
1319 {
1320 #ifndef HAVE_GETOPT
1321   extern char * optarg;
1322   extern int optind, optopt;
1323 #endif
1324   register int x;
1325   register char *cp;
1326   HINF * gp;
1327   HINF * whereto = NULL;
1328   HINF * wherefrom = NULL;
1329   IA * ouraddr = NULL;
1330   IA * themaddr = NULL;
1331   USHORT o_lport = 0;
1332   USHORT ourport = 0;
1333   USHORT loport = 0;		/* for scanning stuff */
1334   USHORT hiport = 0;
1335   USHORT curport = 0;
1336   char * randports = NULL;
1337   char * crypt_key_f9 = "metallica";
1338   char keystr[32];
1339 
1340 /*  if(farm9crypt_initialized() == 0) {
1341     farm9crypt_init(crypt_key_f9);
1342   }
1343 */
1344 
1345 #ifdef HAVE_BIND
1346 /* can *you* say "cc -yaddayadda netcat.c -lresolv -l44bsd" on SunLOSs? */
1347   res_init();
1348 #endif
1349 /* I was in this barbershop quartet in Skokie IL ... */
1350 /* round up the usual suspects, i.e. malloc up all the stuff we need */
1351   lclend = (SAI *) Hmalloc (sizeof (SA));
1352   remend = (SAI *) Hmalloc (sizeof (SA));
1353   bigbuf_in = Hmalloc (BIGSIZ);
1354   bigbuf_net = Hmalloc (BIGSIZ);
1355   ding1 = (fd_set *) Hmalloc (sizeof (fd_set));
1356   ding2 = (fd_set *) Hmalloc (sizeof (fd_set));
1357   portpoop = (PINF *) Hmalloc (sizeof (PINF));
1358 
1359   errno = 0;
1360   gatesptr = 4;
1361   h_errno = 0;
1362 
1363 /* catch a signal or two for cleanup */
1364   signal (SIGINT, catch);
1365   signal (SIGQUIT, catch);
1366   signal (SIGTERM, catch);
1367 /* and suppress others... */
1368 #ifdef SIGURG
1369   signal (SIGURG, SIG_IGN);
1370 #endif
1371 #ifdef SIGPIPE
1372   signal (SIGPIPE, SIG_IGN);		/* important! */
1373 #endif
1374 
1375 /* if no args given at all, get 'em from stdin, construct an argv, and hand
1376    anything left over to readwrite(). */
1377   if (argc == 1) {
1378     cp = argv[0];
1379     argv = (char **) Hmalloc (128 * sizeof (char *));	/* XXX: 128? */
1380     argv[0] = cp;			/* leave old prog name intact */
1381     cp = Hmalloc (BIGSIZ);
1382     argv[1] = cp;			/* head of new arg block */
1383     if (farm9crypt_initialized() == 0) {
1384       farm9crypt_init(crypt_key_f9);
1385     }
1386     fprintf (stderr, "Cmd line: ");
1387     fflush (stderr);		/* I dont care if it's unbuffered or not! */
1388     insaved = read (0, cp, BIGSIZ);	/* we're gonna fake fgets() here */
1389     if (insaved <= 0)
1390       bail ("wrong");
1391     x = findline (cp, insaved);
1392     if (x)
1393       insaved -= x;		/* remaining chunk size to be sent */
1394     if (insaved)		/* which might be zero... */
1395       memcpy (bigbuf_in, &cp[x], insaved);
1396     cp = strchr (argv[1], '\n');
1397     if (cp)
1398       *cp = '\0';
1399     cp = strchr (argv[1], '\r');	/* look for ^M too */
1400     if (cp)
1401       *cp = '\0';
1402 
1403 /* find and stash pointers to remaining new "args" */
1404     cp = argv[1];
1405     cp++;				/* skip past first char */
1406     x = 2;				/* we know argv 0 and 1 already */
1407     for (; *cp != '\0'; cp++) {
1408       if (*cp == ' ') {
1409 	*cp = '\0';			/* smash all spaces */
1410 	continue;
1411       } else {
1412 	if (*(cp-1) == '\0') {
1413 	  argv[x] = cp;
1414 	  x++;
1415 	}
1416       } /* if space */
1417     } /* for cp */
1418     argc = x;
1419   } /* if no args given */
1420 
1421 /* If your shitbox doesn't have getopt, step into the nineties already. */
1422 /* optarg, optind = next-argv-component [i.e. flag arg]; optopt = last-char */
1423   while ((x = getopt (argc, argv, "ae:g:G:hi:k:lno:p:rs:tuvw:z")) != EOF) {
1424 /* Debug (("in go: x now %c, optarg %x optind %d", x, optarg, optind)) */
1425     switch (x) {
1426       case 'a':
1427 	bail ("all-A-records NIY");
1428 	o_alla++; break;
1429 #ifdef GAPING_SECURITY_HOLE
1430       case 'e':				/* prog to exec */
1431 	pr00gie = optarg;
1432 	break;
1433 #endif
1434       case 'k':
1435 	farm9crypt_init(memcpy(keystr, optarg, MAXKEYSIZE));
1436 	break;
1437       case 'G':				/* srcrt gateways pointer val */
1438 	x = atoi (optarg);
1439 	if ((x) && (x == (x & 0x1c)))	/* mask off bits of fukt values */
1440 	  gatesptr = x;
1441 	else
1442 	  bail ("invalid hop pointer %d, must be multiple of 4 <= 28", x);
1443 	break;
1444       case 'g':				/* srcroute hop[s] */
1445 	if (gatesidx > 8)
1446 	  bail ("too many -g hops");
1447 	if (gates == NULL)		/* eat this, Billy-boy */
1448 	  gates = (HINF **) Hmalloc (sizeof (HINF *) * 10);
1449 	gp = gethostpoop (optarg, o_nflag);
1450 	if (gp)
1451 	  gates[gatesidx] = gp;
1452 	gatesidx++;
1453 	break;
1454       case 'h':
1455 	errno = 0;
1456 #ifdef HAVE_HELP
1457 	helpme();			/* exits by itself */
1458 #else
1459 	bail ("no help available, dork -- RTFS");
1460 #endif
1461       case 'i':				/* line-interval time */
1462 	o_interval = atoi (optarg) & 0xffff;
1463 	if (! o_interval)
1464 	  bail ("invalid interval time %s", optarg);
1465 	break;
1466       case 'l':				/* listen mode */
1467 	o_listen++; break;
1468       case 'n':				/* numeric-only, no DNS lookups */
1469 	o_nflag++; break;
1470       case 'o':				/* hexdump log */
1471 	stage = (unsigned char *) optarg;
1472 	o_wfile++; break;
1473       case 'p':				/* local source port */
1474 	o_lport = getportpoop (optarg, 0);
1475 	if (o_lport == 0)
1476 	  bail ("invalid local port %s", optarg);
1477 	break;
1478       case 'r':				/* randomize various things */
1479 	o_random++; break;
1480       case 's':				/* local source address */
1481 /* do a full lookup [since everything else goes through the same mill],
1482    unless -n was previously specified.  In fact, careful placement of -n can
1483    be useful, so we'll still pass o_nflag here instead of forcing numeric.  */
1484 	wherefrom = gethostpoop (optarg, o_nflag);
1485 	ouraddr = &wherefrom->iaddrs[0];
1486 	break;
1487 #ifdef TELNET
1488       case 't':				/* do telnet fakeout */
1489 	o_tn++; break;
1490 #endif /* TELNET */
1491       case 'u':				/* use UDP */
1492 	o_udpmode++; break;
1493       case 'v':				/* verbose */
1494 	o_verbose++; break;
1495       case 'w':				/* wait time */
1496 	o_wait = atoi (optarg);
1497 	if (o_wait <= 0)
1498 	  bail ("invalid wait-time %s", optarg);
1499 	timer1 = (struct timeval *) Hmalloc (sizeof (struct timeval));
1500 	timer2 = (struct timeval *) Hmalloc (sizeof (struct timeval));
1501 	timer1->tv_sec = o_wait;	/* we need two.  see readwrite()... */
1502 	break;
1503       case 'z':				/* little or no data xfer */
1504 	o_zero++;
1505 	break;
1506       default:
1507 	errno = 0;
1508 	bail ("nc -h for help");
1509     } /* switch x */
1510   } /* while getopt */
1511 
1512 /* other misc initialization */
1513 if (farm9crypt_initialized() == 0) {
1514 	farm9crypt_init(crypt_key_f9);
1515 }
1516 
1517 Debug (("fd_set size %d", sizeof (*ding1)))	/* how big *is* it? */
1518   FD_SET (0, ding1);			/* stdin *is* initially open */
1519   if (o_random) {
1520     SRAND (time (0));
1521     randports = Hmalloc (65536);	/* big flag array for ports */
1522   }
1523 #ifdef GAPING_SECURITY_HOLE
1524   if (pr00gie) {
1525     close (0);				/* won't need stdin */
1526     o_wfile = 0;			/* -o with -e is meaningless! */
1527     ofd = 0;
1528   }
1529 #endif /* G_S_H */
1530   if (o_wfile) {
1531     ofd = open (stage, O_WRONLY | O_CREAT | O_TRUNC, 0664);
1532     if (ofd <= 0)			/* must be > extant 0/1/2 */
1533       bail ("can't open %s", stage);
1534     stage = (unsigned char *) Hmalloc (100);
1535   }
1536 
1537 /* optind is now index of first non -x arg */
1538 Debug (("after go: x now %c, optarg %x optind %d", x, optarg, optind))
1539 /* Debug (("optind up to %d at host-arg %s", optind, argv[optind])) */
1540 /* gonna only use first addr of host-list, like our IQ was normal; if you wanna
1541    get fancy with addresses, look up the list yourself and plug 'em in for now.
1542    unless we finally implement -a, that is. */
1543   if (argv[optind])
1544     whereto = gethostpoop (argv[optind], o_nflag);
1545   if (whereto && whereto->iaddrs)
1546     themaddr = &whereto->iaddrs[0];
1547   if (themaddr)
1548     optind++;				/* skip past valid host lookup */
1549   errno = 0;
1550   h_errno = 0;
1551 
1552 /* Handle listen mode here, and exit afterward.  Only does one connect;
1553    this is arguably the right thing to do.  A "persistent listen-and-fork"
1554    mode a la inetd has been thought about, but not implemented.  A tiny
1555    wrapper script can handle such things... */
1556   if (o_listen) {
1557     curport = 0;			/* rem port *can* be zero here... */
1558     if (argv[optind]) {			/* any rem-port-arg? */
1559       curport = getportpoop (argv[optind], 0);
1560       if (curport == 0)			/* if given, demand correctness */
1561 	bail ("invalid port %s", argv[optind]);
1562     } /* if port-arg */
1563     netfd = dolisten (themaddr, curport, ouraddr, o_lport);
1564 /* dolisten does its own connect reporting, so we don't holler anything here */
1565     if (netfd > 0) {
1566 #ifdef GAPING_SECURITY_HOLE
1567       if (pr00gie)			/* -e given? */
1568 	doexec (netfd);
1569 #endif /* GAPING_SECURITY_HOLE */
1570       x = readwrite (netfd);		/* it even works with UDP! */
1571       if (o_verbose > 1)		/* normally we don't care */
1572 	holler (wrote_txt, wrote_net, wrote_out);
1573       exit (x);				/* "pack out yer trash" */
1574     } else /* if no netfd */
1575       bail ("no connection");
1576   } /* o_listen */
1577 
1578 /* fall thru to outbound connects.  Now we're more picky about args... */
1579   if (! themaddr)
1580     bail ("no destination");
1581   if (argv[optind] == NULL)
1582     bail ("no port[s] to connect to");
1583   if (argv[optind + 1])		/* look ahead: any more port args given? */
1584     Single = 0;				/* multi-mode, case A */
1585   ourport = o_lport;			/* which can be 0 */
1586 
1587 /* everything from here down is treated as as ports and/or ranges thereof, so
1588    it's all enclosed in this big ol' argv-parsin' loop.  Any randomization is
1589    done within each given *range*, but in separate chunks per each succeeding
1590    argument, so we can control the pattern somewhat. */
1591   while (argv[optind]) {
1592     hiport = loport = 0;
1593     cp = strchr (argv[optind], '-');	/* nn-mm range? */
1594     if (cp) {
1595       *cp = '\0';
1596       cp++;
1597       hiport = getportpoop (cp, 0);
1598       if (hiport == 0)
1599 	bail ("invalid port %s", cp);
1600     } /* if found a dash */
1601     loport = getportpoop (argv[optind], 0);
1602     if (loport == 0)
1603       bail ("invalid port %s", argv[optind]);
1604     if (hiport > loport) {		/* was it genuinely a range? */
1605       Single = 0;			/* multi-mode, case B */
1606       curport = hiport;			/* start high by default */
1607       if (o_random) {			/* maybe populate the random array */
1608 	loadports (randports, loport, hiport);
1609 	curport = nextport (randports);
1610       }
1611     } else			/* not a range, including args like "25-25" */
1612       curport = loport;
1613 Debug (("Single %d, curport %d", Single, curport))
1614 
1615 /* Now start connecting to these things.  curport is already preloaded. */
1616     while (loport <= curport) {
1617       if ((! o_lport) && (o_random)) {	/* -p overrides random local-port */
1618 	ourport = (RAND() & 0xffff);	/* random local-bind -- well above */
1619 	if (ourport < 8192)		/* resv and any likely listeners??? */
1620 	  ourport += 8192;		/* if it *still* conflicts, use -s. */
1621       }
1622       curport = getportpoop (NULL, curport);
1623       netfd = doconnect (themaddr, curport, ouraddr, ourport);
1624 Debug (("netfd %d from port %d to port %d", netfd, ourport, curport))
1625       if (netfd > 0)
1626 	if (o_zero && o_udpmode)	/* if UDP scanning... */
1627 	  netfd = udptest (netfd, themaddr);
1628       if (netfd > 0) {			/* Yow, are we OPEN YET?! */
1629 	x = 0;				/* pre-exit status */
1630 	holler ("%s [%s] %d (%s) open",
1631 	  whereto->name, whereto->addrs[0], curport, portpoop->name);
1632 #ifdef GAPING_SECURITY_HOLE
1633 	if (pr00gie)			/* exec is valid for outbound, too */
1634 	  doexec (netfd);
1635 #endif /* GAPING_SECURITY_HOLE */
1636 	if (! o_zero)
1637 	  x = readwrite (netfd);	/* go shovel shit */
1638       } else { /* no netfd... */
1639 	x = 1;				/* preload exit status for later */
1640 /* if we're scanning at a "one -v" verbosity level, don't print refusals.
1641    Give it another -v if you want to see everything. */
1642 	if ((Single || (o_verbose > 1)) || (errno != ECONNREFUSED))
1643 	  holler ("%s [%s] %d (%s)",
1644 	    whereto->name, whereto->addrs[0], curport, portpoop->name);
1645       } /* if netfd */
1646       close (netfd);			/* just in case we didn't already */
1647       if (o_interval)
1648 	sleep (o_interval);		/* if -i, delay between ports too */
1649       if (o_random)
1650 	curport = nextport (randports);
1651       else
1652 	curport--;			/* just decrement... */
1653     } /* while curport within current range */
1654     optind++;
1655   } /* while remaining port-args -- end of big argv-ports loop*/
1656 
1657   errno = 0;
1658   if (o_verbose > 1)		/* normally we don't care */
1659     holler (wrote_txt, wrote_net, wrote_out);
1660   if (Single)
1661     exit (x);			/* give us status on one connection */
1662   exit (0);			/* otherwise, we're just done */
1663 } /* main */
1664 
1665 #ifdef HAVE_HELP		/* unless we wanna be *really* cryptic */
1666 /* helpme :
1667    the obvious */
helpme()1668 helpme()
1669 {
1670   o_verbose = 1;
1671   holler ("[v1.10]\n\
1672 connect to somewhere:	nc [-options] hostname port[s] [ports] ... \n\
1673 listen for inbound:	nc -l -p port [-options] [hostname] [port]\n\
1674 options:");
1675 /* sigh, this necessarily gets messy.  And the trailing \ characters may be
1676    interpreted oddly by some compilers, generating or not generating extra
1677    newlines as they bloody please.  u-fix... */
1678 #ifdef GAPING_SECURITY_HOLE	/* needs to be separate holler() */
1679   holler ("\
1680 	-e prog			program to exec after connect [dangerous!!]");
1681 #endif
1682   holler ("\
1683 	-g gateway		source-routing hop point[s], up to 8\n\
1684 	-G num			source-routing pointer: 4, 8, 12, ...\n\
1685 	-h			this cruft\n\
1686 	-k secret		set the shared secret\n\
1687 	-i secs			delay interval for lines sent, ports scanned\n\
1688 	-l			listen mode, for inbound connects\n\
1689 	-n			numeric-only IP addresses, no DNS\n\
1690 	-o file			hex dump of traffic\n\
1691 	-p port			local port number\n\
1692 	-r			randomize local and remote ports\n\
1693 	-s addr			local source address");
1694 #ifdef TELNET
1695   holler ("\
1696 	-t			answer TELNET negotiation");
1697 #endif
1698   holler ("\
1699 	-u			UDP mode\n\
1700 	-v			verbose [use twice to be more verbose]\n\
1701 	-w secs			timeout for connects and final net reads\n\
1702 	-z			zero-I/O mode [used for scanning]");
1703   bail ("port numbers can be individual or ranges: lo-hi [inclusive]");
1704 } /* helpme */
1705 #endif /* HAVE_HELP */
1706 
1707 /* None genuine without this seal!  _H*/
1708