home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume30 / log_tcp / part01 next >
Encoding:
Text File  |  1992-06-20  |  53.4 KB  |  1,555 lines

  1. Newsgroups: comp.sources.misc
  2. From: wietse@wzv.win.tue.nl (Wietse Venema)
  3. Subject:  v30i079:  log_tcp - TCP/IP daemon wrapper, Part01/02
  4. Message-ID: <csm-v30i079=log_tcp.232607@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 30da1f9309e734e8269a1d32ded82f24
  6. Date: Sun, 21 Jun 1992 04:26:31 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: wietse@wzv.win.tue.nl (Wietse Venema)
  10. Posting-number: Volume 30, Issue 79
  11. Archive-name: log_tcp/part01
  12. Environment: UNIX
  13. Supersedes: log_tcp: Volume 23, Issue 77
  14.  
  15. This package provides a couple of tiny programs that monitor incoming
  16. requests for IP services such as TFTP, EXEC, FTP, RSH, TELNET, RLOGIN,
  17. FINGER, SYSTAT, and many others.
  18.  
  19. Optional features are: access control based on pattern matching; remote
  20. username lookup using the RFC 931 protocol; protection against rsh and
  21. rlogin attacks from hosts that pretend to have someone elses name.
  22.  
  23. The programs can be installed without requiring any changes to existing
  24. software or configuration files. By default, they just log the remote
  25. host name and then invoke the real network daemon. No information is
  26. exchanged with the remote client process.
  27.  
  28. Enhancements over the previous release are: 
  29.  
  30.     1 - network daemons no longer have to live within a common directory
  31.     2 - the access control code now uses both the host address and name
  32.     3 - an access control pattern that supports netmasks
  33.     4 - additional protection against forged host names
  34.     5 - a pattern that matches hosts whose name or address lookup fails
  35.     6 - an operator that prevents hosts or services from being matched
  36.     7 - optional remote username lookup with the RFC 931 protocol
  37.     8 - an optional umask to prevent the creation of world-writable files
  38.     9 - hooks for access control language extensions
  39.    10 - last but not least, thoroughly revised documentation.
  40.  
  41. Except for the change described under (2) the present version should be
  42. backwards compatible with earlier ones.
  43.  
  44.     Wietse Venema (wietse@wzv.win.tue.nl),
  45.     Department of Mathematics and Computing Science,
  46.     Eindhoven University of Technology,
  47.     The Netherlands.
  48.  
  49. #! /bin/sh
  50. # This is a shell archive.  Remove anything before this line, then feed it
  51. # into a shell via "sh file" or similar.  To overwrite existing files,
  52. # type "sh file -c".
  53. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  54. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  55. # Contents:  README Makefile fromhost.c hosts_access.5 hosts_access.c
  56. #   options.c
  57. # Wrapped by kent@sparky on Sat Jun 20 23:22:23 1992
  58. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  59. echo If this archive is complete, you will see the following message:
  60. echo '          "shar: End of archive 1 (of 2)."'
  61. if test -f 'README' -a "${1}" != "-c" ; then 
  62.   echo shar: Will not clobber existing file \"'README'\"
  63. else
  64.   echo shar: Extracting \"'README'\" \(13298 characters\)
  65.   sed "s/^X//" >'README' <<'END_OF_FILE'
  66. X@(#) README 1.7 92/06/11 22:21:17
  67. X
  68. XGeneral description
  69. X-------------------
  70. X
  71. XWith this package you can monitor incoming connections to the SYSTAT,
  72. XFINGER, FTP, TELNET, RLOGIN, RSH, EXEC, TFTP, TALK, and other IP
  73. Xnetwork services.  Connections are reported through the syslog daemon.
  74. XRequirements are that network daemons are started by the inetd program
  75. Xor something similar, and the availability of a syslog(3) library.
  76. X
  77. XThe programs are tiny front ends. By default, they just report the name
  78. Xor address of the remote host and of the requested service, and then
  79. Xinvoke the real network daemon; no information is exchanged with the
  80. Xremote client process.
  81. X
  82. XOptional features are: access control that limits the number of hosts
  83. Xthat can connect to your network daemons, remote user name lookups with
  84. Xthe RFC 931 protocol, and protection against hosts that pretend to have
  85. Xsomeone elses host name.
  86. X
  87. XThe programs can be installed without any changes to existing software
  88. Xor to existing configuration files.  Just move the vendor-provided
  89. Xdaemons to another directory and install the front ends into their
  90. Xoriginal places.  Installation details are given below.
  91. X
  92. XEarly versions of the programs were tested with Ultrix >= 2.2, with
  93. XSunOS >= 3.4 and ISC 2.2. Later versions have been installed on a wide
  94. Xvariety of platforms such as SunOS 4.1.1, Ultrix 4.0 and 4.2, Apollo
  95. XSR10.3.5 and an unknown number of other ones. The software should run
  96. Xwithout modification on top of most BSD-style TCP/IP implementations.
  97. X
  98. XRestrictions
  99. X------------
  100. X
  101. XSome UDP (and RPC) daemons linger around for a while after they have
  102. Xserviced a request, just in case another request comes in.  In the
  103. Xinetd configuration file these daemons are registered with the `wait'
  104. Xoption. Only the request that started such a daemon will be handled by
  105. Xthe front ends.  This restriction does not apply to connection-oriented
  106. X(TCP) services.
  107. X
  108. XSome ConvexOS versions come with a broken recvfrom(2) implementation.
  109. XThis makes it impossible for the daemon front ends to look up the
  110. Xremote host address (and hence, the name) in case of UDP connections.
  111. X
  112. XAccess control
  113. X--------------
  114. X
  115. XWhen compiled with -DHOSTS_ACCESS, the front-end programs support a
  116. Xsimple form of access control that is based on pattern matching.  The
  117. Xaccess-control software provides hooks for the execution of shell
  118. Xcommands when a pattern fires; this feature may be useful to install
  119. X"booby traps" on specific network services.  For details, see the
  120. Xhosts_access(5) manual page, which is in `nroff -man' format.
  121. X
  122. XDetection of hosts that pretend to have someone elses host name
  123. X---------------------------------------------------------------
  124. X
  125. XAuthentication based on host names, such as used by RLOGIN and RSH,
  126. Xused to work quite reliably when all host name lookups were done from
  127. Xa _local_ hosts file.
  128. X
  129. XWith _distributed_ name services, authentication schemes that rely on
  130. Xhost names can be subverted by playing games with the address->name and
  131. Xname->address maps that are maintained by some far-away name servers.
  132. X
  133. XThe front-end programs verify the remote host name that is returned by
  134. Xthe DNS server responsible for the address->name mapping, by looking at
  135. Xthe name and address that are returned by the DNS server responsible
  136. Xfor the name->address mapping. If any discrepancies are found, the
  137. Xfront ends conclude that they are dealing with a host that pretends to
  138. Xhave someone elses host name.
  139. X
  140. XIf the sources are compiled with -DPARANOID, the front ends will drop
  141. Xthe connection in case of a host name/address mismatch. Otherwise, the
  142. Xfront ends pretend that the host name is unknown when logging the
  143. Xconnection and consulting the optional access control tables.
  144. X
  145. XRFC 931 support
  146. X---------------
  147. X
  148. XThe protocol described in RFC 931 provides a means to get the remote
  149. Xuser name from the client host.  The requirement is that the client
  150. Xhost runs an RFC 931-compliant daemon.
  151. X
  152. XUser name lookups are enabled if the source is compiled with -DRFC931.
  153. XThere are some limitations, though: the number of hosts that run an RFC
  154. X931 daemon is still small; user name lookups do not work for datagram
  155. X(UDP) connections. More seriously, remote user name loookups can cause
  156. Xnoticeable delays with connections from PCs.
  157. X
  158. XHooks for extending the access control language
  159. X-----------------------------------------------
  160. X
  161. XA skeleton is available for adding user-defined extensions to the
  162. Xaccess control language.  The options.c file implements examples that
  163. Xselectively (1) make a daemon front end switch to another user or group
  164. Xid, (2) perform remote user name lookups, and (3) run an alternate
  165. Xserver (for example, a bogus ftp daemon that mumbles some faked error
  166. Xmessage before hanging up).
  167. X
  168. XThe the language extension hook is not enabled by default because it
  169. Xintroduces a minor change to the access control language syntax.
  170. X
  171. XRelated software
  172. X----------------
  173. X
  174. XVersions of rshd and rlogind, hacked to report the remote user name in
  175. Xaddition to the remote host name, are available for anonymous ftp
  176. X(ftp.win.tue.nl:/pub/security/logdaemon.tar.Z).  These programs are
  177. Xderived from source code on the first 43BSD network source tape; they
  178. Xhave been tested only with SunOS >= 4.0 (the rshd appears to work with
  179. XUltrix 4.x, too).
  180. X
  181. XThe securelib shared library by William LeFebvre can be used to control
  182. Xaccess to network daemons that are not run under control of the inetd,
  183. Xsuch as the RPC daemons that are registered with the portmap daemon.
  184. XAvailable as eecs.nwu.edu:/pub/securelib.tar.
  185. X
  186. XAn alternative portmap daemon can also help to improve RPC security.
  187. Xftp.win.tue.nl:/pub/security/portmap.shar.Z was tested with SunOS
  188. X4.1.1, Ultrix 3.0 and Ultrix 4.x. The protection is less effective than
  189. Xthat of the securelib library because portmap's primary task is to
  190. Xmaintain the RPC daemon lookup table. SunOS 4.x users should install
  191. Xthe latest revision of the portmap and NIS software.
  192. X
  193. XAnother way to manage access to TCP/IP services is illustrated by the
  194. Xservers provided with the authutil package (comp.sources.unix volume
  195. X22) by Dan Bernstein. This one relies on RFC 931.
  196. X
  197. XSource for a reasonably fast and portable RFC 931 daemon by Peter
  198. XEriksson is available from ftp.lysator.liu.se:/pub/net/pauthd*.tar.Z.
  199. X
  200. XSome TCP/IP implementations come without syslog library. A replacement
  201. Xcan be found in ftp.win.tue.nl:/pub/security/surrogate-syslog.tar.Z.
  202. X
  203. XConfiguration and installation (the easy way)
  204. X---------------------------------------------
  205. X
  206. XAn advanced installation recipe is given later on. The "easy" recipe
  207. Xrequires no changes to existing software or configuration files.
  208. X
  209. XIf you don't run Ultrix, you don't need the miscd front-end program.
  210. XThe miscd daemon implements among others the SYSTAT service, which
  211. Xproduces the same output as the the WHO command.
  212. X
  213. XBy default, the front-end programs assume that the vendor-provided
  214. Xdaemons will be moved to the "/usr/etc/..." directory.  If you want
  215. Xsomething else, adjust the REAL_DAEMON_DIR macro in the file tcpd.c
  216. X(and the REAL_DAEMON macro in miscd.c).
  217. X
  218. XFollow the instructions at the beginning of the Makefile and compile
  219. Xthe programs. The result is two binaries (three in case of Ultrix). The
  220. X`try' program can be used to play with host access control tables and
  221. Xis described in a later section. 
  222. X
  223. XThe tcpd program can be used for monitoring requests for the telnet,
  224. Xfinger, ftp, exec, rsh, rlogin, tftp, talk, spray, rusers, comsat and
  225. Xother services that have a one-to-one mapping onto executable files.
  226. X
  227. XDecide which services you want to be monitored. Move the corresponding
  228. Xvendor-provided daemon programs to the location specified by the
  229. XREAL_DAEMON_DIR macro in the file tcpd.c, and copy the tcpd front end
  230. Xto the locations where the vendor-provided daemons used to be. That is,
  231. Xone copy of (or link to) the tcpd program for each service that you
  232. Xwant to monitor.
  233. X
  234. XUltrix only:  If you want to monitor and/or restrict access to the
  235. XSYSTAT service, move the vendor-provided miscd daemon to the location
  236. Xspecified by the REAL_DAEMON macro in the miscd.c file, and install the
  237. Xmiscd front end into the original miscd location.
  238. X
  239. XConfiguration and installation (the advanced way)
  240. X-------------------------------------------------
  241. X
  242. XInstead of moving the vendor-provided daemons to another directory,
  243. Xdefine the REAL_DAEMON_DIR macro in the file tcpd.c (and, if you run
  244. XUltrix, REAL_DAEMON in miscd.c) to reflect the present location of
  245. Xthose daemons. Then follow the instructions in the Makefile and do
  246. Xa "make".
  247. X
  248. XThe tcpd program can be used for monitoring requests for the telnet,
  249. Xfinger, ftp, exec, rsh, rlogin, tftp, talk, spray, rusers, comsat and
  250. Xother services that have a one-to-one mapping onto executable files.
  251. X
  252. XInstall the tcpd command in a suitable place. Apollo UNIX users will
  253. Xwant to install it under a different name because tcpd is the name of
  254. Xan already existing command. A suitable name for the front-end program
  255. Xwould be "frontd".  Then perform the following edits on the inetd
  256. Xconfiguration file (usually /etc/inetd.conf):
  257. X
  258. X    finger  stream  tcp     nowait  nobody  /usr/etc/in.fingerd     in.fingerd
  259. X
  260. Xbecomes:
  261. X
  262. X    finger  stream  tcp     nowait  nobody  /usr/etc/tcpd           in.fingerd
  263. X
  264. XThe example applies to SunOS 4.x; other UNIX implementations should not
  265. Xdiffer much. Similar changes will be needed for other services that are
  266. Xto be covered by the tcpd (or frontd) front-end program. Send a SIGHUP
  267. Xto the inetd process to make the changes effective.
  268. X
  269. XThe miscd daemon that comes with Ultrix implements several network
  270. Xservices. It decides what to do by looking at its process name. One of
  271. Xthe services is systat, which is a kind of limited finger service.  If
  272. Xyou want to monitor the systat service, install the miscd front end in
  273. Xa suitable place and update the inetd configuration file:
  274. X
  275. X    systat  stream  tcp     nowait  /front/ends/miscd           systatd
  276. X
  277. XThat's right, Ultrix still runs its daemons with root privileges.
  278. X
  279. XDaemons with arbitrary path names
  280. X---------------------------------
  281. X
  282. XThe above tcpd examples work fine with network daemons that live in a
  283. Xcommon directory, but sometimes that is not possible. You can cope with
  284. Xthese cases by specifying, in the inetd configuration file, an absolute
  285. Xpath name for the daemon process name.  For example,
  286. X
  287. X    ntalk   dgram   udp     wait    root    /usr/etc/tcpd /usr/local/lib/ntalkd
  288. X
  289. XTcpd ignores the REAL_DAEMON_DIR macro when the daemon process name is
  290. Xan absolute pathname;  logging and access control will be based on the
  291. Xlast component of the daemon process name.
  292. X
  293. XTesting the access control files
  294. X--------------------------------
  295. X
  296. XThe "try" command, provided with this package, can be used to test out
  297. Xthe access control files.  The command syntax is:
  298. X
  299. X    ./try process_name hostname    (e.g. ./try in.tftpd localhost)
  300. X
  301. X    ./try process_name address    (e.g. ./try in.tftpd 127.0.0.1)
  302. X
  303. XIn the first case, the program will use both the host name and
  304. Xaddress.  In the second case, the program will pretend that the host
  305. Xname is unknown, so that you can simulate what happens when hostname
  306. Xlookup fails.  If there are any serious errors they will be reported
  307. Xvia the syslog daemon.  Run a "tail -f" on the logfile while playing
  308. Xwith the "try" command.
  309. X
  310. XOther applications
  311. X------------------
  312. X
  313. XThe access control routines can easily be integrated with other
  314. Xprograms.  The hosts_access.3 manual page (`nroff -man' format)
  315. Xdescribes the external interface of the libwrap.a library.
  316. X
  317. XThe tcpd front end can even be used to control access to the smtp port.
  318. XIn that case, sendmail should not be run as a stand-alone daemon, but
  319. Xit should be registered in the inetd.conf file. For example:
  320. X
  321. X    smtp    stream  tcp     nowait  root    /usr/etc/tcpd /usr/lib/sendmail -bs
  322. X
  323. XYou will periodically want to run sendmail to process queued-up
  324. Xmessages. A crontab entry like:
  325. X
  326. X    0,15,30,45 * * * * /usr/lib/sendmail -q
  327. X
  328. Xshould take care of that.
  329. X
  330. XAcknowledgements
  331. X----------------
  332. X
  333. XThanks to Brendan Kehoe (brendan@cs.widener.edu), Heimir Sverrisson
  334. X(heimir@hafro.is) and Dan Bernstein (brnstnd@kramden.acf.nyu.edu) for
  335. Xfeedback on an early release of this product.  The host name/address
  336. Xcheck was suggested by John Kimball (jkimball@src.honeywell.com).
  337. XApollo's UNIX environment has some peculiar quirks: Willem-Jan Withagen
  338. X(wjw@eb.ele.tue.nl), Pieter Schoenmakers (tiggr@es.ele.tue.nl) and
  339. XCharles S. Fuller (fuller@wccs.psc.edu) provided assistance.  Hal R.
  340. XBrand (BRAND@addvax.llnl.gov) told me how to get the remote IP address
  341. Xin case of datagram-oriented services, and suggested the optional shell
  342. Xcommand feature.  Shabbir Safdar (shabby@mentor.cc.purdue.edu) provided
  343. Xa first version of a much-needed manual page.  Granville Boman Goza, IV
  344. X(gbg@sei.cmu.edu) suggested to use the remote IP address even when the
  345. Xhost name is available.  Casper H.S. Dik (casper@fwi.uva.nl) provided
  346. Xadditional insight into DNS spoofing techniques.  The bogus daemon
  347. Xfeature was inspired by code from Andrew Macpherson (BNR Europe Ltd).
  348. XI appreciate the code fragments that I received from Howard Chu
  349. X(hyc@hanauma.jpl.nasa.gov), John P. Rouillard (rouilj@cs.umb.edu) and
  350. Xothers. These saved me a lot of work.
  351. X
  352. X    Wietse Venema (wietse@wzv.win.tue.nl),
  353. X    Department of Mathematics and Computing Science,
  354. X    Eindhoven University of Technology,
  355. X    The Netherlands.
  356. END_OF_FILE
  357.   if test 13298 -ne `wc -c <'README'`; then
  358.     echo shar: \"'README'\" unpacked with wrong size!
  359.   fi
  360.   # end of 'README'
  361. fi
  362. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  363.   echo shar: Will not clobber existing file \"'Makefile'\"
  364. else
  365.   echo shar: Extracting \"'Makefile'\" \(5800 characters\)
  366.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  367. X# @(#) Makefile 1.5 92/06/11 22:21:35
  368. X
  369. X##############################
  370. X## Begin configuration options
  371. X
  372. X# By default, logfile entries are written to the same file as used for
  373. X# sendmail transaction logs. Change the definition of the following macro
  374. X# if you disagree. See `man 3 syslog' for examples. Some syslog versions
  375. X# do not provide this flexibility.
  376. X
  377. XFACILITY= LOG_MAIL
  378. X
  379. X# To disable host access control, comment out the following macro definition.
  380. X# Note: host access control requires the strtok() and strchr() routines.
  381. X# Host access control can also be turned off by providing no access control
  382. X# tables.
  383. X
  384. XACCESS    = -DHOSTS_ACCESS
  385. X
  386. X# Disable the following macro definition if you wish to talk to hosts that
  387. X# pretend to have someone elses host name. Doing so is a bad idea if you run
  388. X# services whose authentication relies on host names, such as rlogin or rsh.
  389. X
  390. XPARANOID= -DPARANOID
  391. X
  392. X# If your system supports NIS or YP-style netgroups, enable the following
  393. X# macro definition.
  394. X
  395. XNETGROUP= -DNETGROUP
  396. X
  397. X# Enable the following definition if the front ends should attempt to get
  398. X# the remote user name. This works only if the remote host runs a daemon
  399. X# that supports the RFC 931 protocol. Remote user name lookups will not
  400. X# work for UDP-based connections, and will cause noticeable delays with
  401. X# connections from PCs.
  402. X
  403. X#AUTH    = -DRFC931
  404. X
  405. X# On many systems, network daemons and other system processes are started
  406. X# with a zero umask value, so that world-writable files may be produced.
  407. X# It is a good idea to edit your /etc/rc* files so that they begin with
  408. X# an explicit umask setting.  On our site we use 022 because it does not
  409. X# break anything yet gives adequate protection against tampering.
  410. X# 
  411. X# The following macro specifies the default umask for daemons run under
  412. X# control of the daemon front ends. Comment it out only if you are sure
  413. X# that inetd and its children are started with a sane umask value.
  414. X
  415. XUMASK    = -DDAEMON_UMASK=022
  416. X
  417. X# Some versions of Apollo or SYSV.4 UNIX have a bug in the getpeername(2)
  418. X# routine.  You have this bug if the front end reports that all UDP
  419. X# connections come from address 0.0.0.0. Compile with -DGETPEERNAME_BUG
  420. X# for a workaround. The workaround does no harm on other systems. If in
  421. X# doubt, leave it in.
  422. X
  423. XBUGS    = -DGETPEERNAME_BUG
  424. X
  425. X# Apollo Domain/OS offers both bsd and sys5 environments, sometimes
  426. X# on the same machine.  If your Apollo is primarily sys5.3 and also
  427. X# has bsd4.3, enable the following to build under bsd and run under
  428. X# either environment.
  429. X
  430. X#SYSTYPE=  -A run,any -A sys,any
  431. X
  432. X# Some C compilers (Ultrix 4.x) insist that ranlib(1) be run on an object
  433. X# library; some don't care as long as the modules are in the right order;
  434. X# some systems don't even have a ranlib(1) command. Make your choice.
  435. X
  436. XRANLIB    = ranlib    # use ranlib
  437. X#RANLIB    = echo        # no ranlib
  438. X
  439. X# If your C library does not have memcmp(3), compile with -Dmemcmp=bcmp.
  440. X
  441. XCFLAGS    = -O -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
  442. X    $(BUGS) $(SYSTYPE) $(AUTH) $(UMASK)
  443. X
  444. X# Include the file strcasecmp.o if strcasecmp() is not provided by your C
  445. X# library.  The strcasecmp.c file provided with this package comes from
  446. X# 43BSD UNIX.  You may have to add -Du_char="unsigned char" to the CFLAGS
  447. X# macro above.
  448. X
  449. XAUX_OBJ    = # strcasecmp.o
  450. X
  451. X# Some System-V versions require that you explicitly specify the networking
  452. X# libraries (for example, -lnet or -linet).
  453. X
  454. XLIBS    = # -lnet -lsyslog -ldbm
  455. X
  456. X# Ultrix users may want to use the miscd front end, too. The Ultrix miscd
  457. X# implements among others the SYSTAT service which runs the WHO command,
  458. X# and thus provides a subset of the finger service. The very first front
  459. X# end application was to monitor the use of SYSTAT.
  460. X
  461. Xall:    tcpd try # miscd
  462. X
  463. X## End configuration options
  464. X############################
  465. X
  466. XLIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o hosts_info.o \
  467. X    hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ)
  468. X
  469. XKIT    = README miscd.c tcpd.c fromhost.c hosts_access.c shell_cmd.c \
  470. X    log_tcp.h try.c refuse.c Makefile hosts_access.5 strcasecmp.c BLURB \
  471. X    rfc931.c tcpd.8 hosts_info.c hosts_access.3 hosts_ctl.c percent_x.c \
  472. X    options.c clean_exit.c rfc931_option
  473. X
  474. XLIB    = libwrap.a
  475. X
  476. X$(LIB):    $(LIB_OBJ)
  477. X    rm -f $(LIB)
  478. X    ar rv $(LIB) $(LIB_OBJ)
  479. X    $(RANLIB) $(LIB)
  480. X
  481. Xtcpd:    tcpd.o fromhost.o $(LIB)
  482. X    $(CC) $(CFLAGS) -o $@ tcpd.o fromhost.o $(LIB)
  483. X
  484. Xmiscd:    miscd.o fromhost.o $(LIB)
  485. X    $(CC) $(CFLAGS) -o $@ miscd.o fromhost.o $(LIB)
  486. X
  487. Xtry:    try.o $(LIB)
  488. X    $(CC) $(CFLAGS) -o $@ try.o $(LIB)
  489. X
  490. Xfromhost: fromhost.c log_tcp.h Makefile $(LIB)
  491. X    $(CC) $(CFLAGS) -DTEST -o fromhost fromhost.c $(LIB)
  492. X    rm -f fromhost.o
  493. X
  494. Xshar:    
  495. X    @shar $(KIT)
  496. X
  497. Xkit:
  498. X    @makekit $(KIT)
  499. X
  500. Xarchive:
  501. X    $(ARCHIVE) $(KIT)
  502. X
  503. Xclean:
  504. X    rm -f tcpd miscd try fromhost *.[oa] core
  505. X
  506. X# Enable all bells and whistles for linting.
  507. X
  508. Xlint: tcpd_lint miscd_lint try_lint
  509. X
  510. Xtcpd_lint:
  511. X    lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DPARANOID -DNETGROUP \
  512. X    -DGETPEERNAME_BUG -DRFC931 -DDAEMON_UMASK=022 tcpd.c fromhost.c \
  513. X    hosts_access.c shell_cmd.c refuse.c rfc931.c hosts_info.c percent_x.c \
  514. X    clean_exit.c
  515. X
  516. Xmiscd_lint:
  517. X    lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DPARANOID -DNETGROUP \
  518. X    -DGETPEERNAME_BUG -DRFC931 -DDAEMON_UMASK=022 miscd.c fromhost.c \
  519. X    hosts_access.c shell_cmd.c refuse.c rfc931.c hosts_info.c percent_x.c \
  520. X    clean_exit.c
  521. X
  522. Xtry_lint:
  523. X    lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DNETGROUP try.c \
  524. X    hosts_ctl.c hosts_access.c hosts_info.c percent_x.c
  525. X
  526. X# Compilation dependencies.
  527. X
  528. Xclean_exit.o: log_tcp.h Makefile
  529. Xfromhost.o: log_tcp.h Makefile
  530. Xhosts_access.o: log_tcp.h Makefile
  531. Xhosts_ctl.o: log_tcp.h Makefile
  532. Xhosts_info.o: log_tcp.h Makefile
  533. Xmiscd.o: log_tcp.h Makefile
  534. Xoptions.o: log_tcp.h Makefile
  535. Xpercent_x.o: log_tcp.h Makefile
  536. Xrefuse.o: log_tcp.h Makefile
  537. Xrfc931.o: log_tcp.h Makefile
  538. Xshell_cmd.o: log_tcp.h Makefile
  539. Xtcpd.o: log_tcp.h Makefile
  540. Xtry.o: log_tcp.h Makefile
  541. END_OF_FILE
  542.   if test 5800 -ne `wc -c <'Makefile'`; then
  543.     echo shar: \"'Makefile'\" unpacked with wrong size!
  544.   fi
  545.   # end of 'Makefile'
  546. fi
  547. if test -f 'fromhost.c' -a "${1}" != "-c" ; then 
  548.   echo shar: Will not clobber existing file \"'fromhost.c'\"
  549. else
  550.   echo shar: Extracting \"'fromhost.c'\" \(6349 characters\)
  551.   sed "s/^X//" >'fromhost.c' <<'END_OF_FILE'
  552. X /*
  553. X  * fromhost() determines the type of connection (datagram, stream), the name
  554. X  * and address of the host at the other end of standard input, and the
  555. X  * remote user name (if RFC 931 lookups are enabled). A host name of "stdin"
  556. X  * is returned if the program is run from a tty. The value "unknown" is
  557. X  * returned as a placeholder for information that could not be looked up.
  558. X  * All results are in static memory.
  559. X  * 
  560. X  * The return status is (-1) if the remote host pretends to have someone elses
  561. X  * host name, otherwise a zero status is returned.
  562. X  * 
  563. X  * Diagnostics are reported through syslog(3).
  564. X  * 
  565. X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  566. X  */
  567. X
  568. X#ifndef lint
  569. Xstatic char sccsid[] = "@(#) fromhost.c 1.5 92/06/11 22:21:24";
  570. X#endif
  571. X
  572. X/* System libraries. */
  573. X
  574. X#include <sys/types.h>
  575. X#include <sys/param.h>
  576. X#include <sys/socket.h>
  577. X#include <netinet/in.h>
  578. X#include <netdb.h>
  579. X#include <stdio.h>
  580. X#include <syslog.h>
  581. X#include <errno.h>
  582. X
  583. Xextern char *inet_ntoa();
  584. Xextern char *strncpy();
  585. Xextern char *strcpy();
  586. X
  587. X/* Local stuff. */
  588. X
  589. X#include "log_tcp.h"
  590. X
  591. X/* Forward declarations. */
  592. X
  593. Xstatic int matchname();
  594. X
  595. X/* The following are to be used in assignment context, not in comparisons. */
  596. X
  597. X#define    GOOD    1
  598. X#define    BAD    0
  599. X
  600. X/* Initially, we know nothing about the origin of the connection. */
  601. X
  602. Xstatic struct from_host from_unknown = {
  603. X    0,                    /* connected/unconnected */
  604. X    FROM_UNKNOWN,            /* remote host name */
  605. X    FROM_UNKNOWN,            /* remote host address */
  606. X    FROM_UNKNOWN,            /* remote user name */
  607. X};
  608. X
  609. X /*
  610. X  * The Apollo SR10.3 and some SYSV4 getpeername(2) versions do not return an
  611. X  * error in case of a datagram-oriented socket. Instead, they claim that all
  612. X  * UDP requests come from address 0.0.0.0. The following code works around
  613. X  * the problem. It does no harm on "normal" systems.
  614. X  */
  615. X
  616. X#ifdef GETPEERNAME_BUG
  617. X
  618. Xstatic int fix_getpeername(sock, sa, len)
  619. Xint     sock;
  620. Xstruct sockaddr *sa;
  621. Xint    *len;
  622. X{
  623. X    int     ret;
  624. X    struct sockaddr_in *sin = (struct sockaddr_in *) sa;
  625. X
  626. X    if ((ret = getpeername(sock, sa, len)) >= 0
  627. X    && sa->sa_family == AF_INET
  628. X    && sin->sin_addr.s_addr == 0) {
  629. X    errno = ENOTCONN;
  630. X    return (-1);
  631. X    } else {
  632. X    return (ret);
  633. X    }
  634. X}
  635. X
  636. X#define    getpeername    fix_getpeername
  637. X#endif
  638. X
  639. X/* fromhost - find out what is at the other end of standard input */
  640. X
  641. Xint     fromhost(f)
  642. Xstruct from_host *f;
  643. X{
  644. X    struct sockaddr sa;
  645. X    struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
  646. X    struct hostent *hp;
  647. X    int     length = sizeof(sa);
  648. X    char    buf[BUFSIZ];
  649. X    static char addr_buf[FROM_ADDRLEN];
  650. X    static char name_buf[MAXHOSTNAMELEN];
  651. X
  652. X    /*
  653. X     * There are so many results and so many early returns that it seems
  654. X     * safest to first initialize all results to UNKNOWN.
  655. X     */
  656. X
  657. X    *f = from_unknown;
  658. X
  659. X    /*
  660. X     * Look up the remote host address. Hal R. Brand <BRAND@addvax.llnl.gov>
  661. X     * suggested how to get the remote host info in case of UDP connections:
  662. X     * peek at the first message without actually looking at its contents.
  663. X     */
  664. X
  665. X    if (getpeername(0, &sa, &length) >= 0) {    /* assume TCP request */
  666. X    f->sock_type = FROM_CONNECTED;
  667. X    } else {
  668. X    switch (errno) {
  669. X    case ENOTSOCK:                /* stdin is not a socket */
  670. X        if (isatty(0))
  671. X        f->name = "stdin";
  672. X        return (0);
  673. X    case ENOTCONN:                /* assume UDP request */
  674. X        length = sizeof(sa);
  675. X        if (recvfrom(0, buf, sizeof(buf), MSG_PEEK, &sa, &length) < 0) {
  676. X        syslog(LOG_ERR, "recvfrom: %m");
  677. X        return (0);
  678. X        }
  679. X#ifdef really_paranoid
  680. X        memset(buf, 0 sizeof(buf));
  681. X#endif
  682. X        f->sock_type = FROM_UNCONNECTED;
  683. X        break;
  684. X    default:                /* other, punt */
  685. X        syslog(LOG_ERR, "getpeername: %m");
  686. X        return (0);
  687. X    }
  688. X    }
  689. X    /* At present, we can only deal with the AF_INET address family. */
  690. X
  691. X    if (sa.sa_family != AF_INET) {
  692. X    syslog(LOG_ERR, "unexpected address family %ld", (long) sa.sa_family);
  693. X    return (0);
  694. X    }
  695. X    /* Save the host address. A later inet_ntoa() call may clobber it. */
  696. X
  697. X    f->addr = strcpy(addr_buf, inet_ntoa(sin->sin_addr));
  698. X
  699. X    /* Look up the remote user name. Does not work for UDP services. */
  700. X
  701. X#ifdef RFC931
  702. X    if (f->sock_type == FROM_CONNECTED)
  703. X    f->user = rfc931_name(sin);
  704. X#endif
  705. X
  706. X    /* Look up the remote host name. */
  707. X
  708. X    if ((hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
  709. X                sizeof(sin->sin_addr.s_addr),
  710. X                AF_INET)) == 0) {
  711. X    return (0);
  712. X    }
  713. X    /* Save the host name. A later gethostbyxxx() call may clobber it. */
  714. X
  715. X    f->name = strncpy(name_buf, hp->h_name, sizeof(name_buf) - 1);
  716. X    name_buf[sizeof(name_buf) - 1] = 0;
  717. X
  718. X    /*
  719. X     * Verify that the host name does not belong to someone else. If host
  720. X     * name verification fails, pretend that the host name lookup failed.
  721. X     */
  722. X
  723. X    if (matchname(f->name, sin->sin_addr)) {
  724. X    return (0);
  725. X    } else {
  726. X    f->name = FROM_UNKNOWN;
  727. X    return (-1);                /* verification failed */
  728. X    }
  729. X}
  730. X
  731. X/* matchname - determine if host name matches IP address */
  732. X
  733. Xstatic int matchname(remotehost, addr)
  734. Xchar   *remotehost;
  735. Xstruct in_addr addr;
  736. X{
  737. X    struct hostent *hp;
  738. X    int     i;
  739. X
  740. X    if ((hp = gethostbyname(remotehost)) == 0) {
  741. X
  742. X    /*
  743. X     * Unable to verify that the host name matches the address. This may
  744. X     * be a transient problem or a botched name server setup. We decide
  745. X     * to play safe.
  746. X     */
  747. X
  748. X    syslog(LOG_ERR, "gethostbyname(%s): lookup failure", remotehost);
  749. X    return (BAD);
  750. X
  751. X    } else {
  752. X
  753. X    if (strcasecmp(remotehost, hp->h_name)) {
  754. X        syslog(LOG_ERR, "host name/name mismatch: %s != %s",
  755. X           remotehost, hp->h_name);
  756. X        return (BAD);
  757. X    }
  758. X    /* Look up the host address in the address list we just got. */
  759. X
  760. X    for (i = 0; hp->h_addr_list[i]; i++) {
  761. X        if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
  762. X        return (GOOD);
  763. X    }
  764. X
  765. X    /*
  766. X     * The host name does not map to the original host address. Perhaps
  767. X     * someone has compromised a name server. More likely someone botched
  768. X     * it, but that could be dangerous, too.
  769. X     */
  770. X
  771. X    syslog(LOG_ERR, "host name/address mismatch: %s != %s",
  772. X           inet_ntoa(addr), hp->h_name);
  773. X    return (BAD);
  774. X    }
  775. X}
  776. X
  777. X#ifdef TEST
  778. X
  779. X/* Code for stand-alone testing. */
  780. X
  781. Xmain(argc, argv)
  782. Xint     argc;
  783. Xchar  **argv;
  784. X{
  785. X    struct from_host from;
  786. X
  787. X#ifdef LOG_MAIL
  788. X    (void) openlog(argv[0], LOG_PID, FACILITY);
  789. X#else
  790. X    (void) openlog(argv[0], LOG_PID);
  791. X#endif
  792. X    (void) fromhost(&from);
  793. X    printf("%s\n", hosts_info(&from));
  794. X    return (0);
  795. X}
  796. X
  797. X#endif
  798. END_OF_FILE
  799.   if test 6349 -ne `wc -c <'fromhost.c'`; then
  800.     echo shar: \"'fromhost.c'\" unpacked with wrong size!
  801.   fi
  802.   # end of 'fromhost.c'
  803. fi
  804. if test -f 'hosts_access.5' -a "${1}" != "-c" ; then 
  805.   echo shar: Will not clobber existing file \"'hosts_access.5'\"
  806. else
  807.   echo shar: Extracting \"'hosts_access.5'\" \(7619 characters\)
  808.   sed "s/^X//" >'hosts_access.5' <<'END_OF_FILE'
  809. X.TH HOSTS_ACCESS 5
  810. X.SH NAME
  811. Xhosts_access \- format of host access control files
  812. X.SH DESCRIPTION
  813. XThis manual page describes a simple access control language that is
  814. Xbased on host (or domain) names, netgroups, internet addresses (or
  815. Xnetwork numbers) and on network daemon process names. Examples are
  816. Xgiven at the end.
  817. X.PP
  818. XIn the following text, \fIdaemon\fR is the the process name (argv[0]
  819. Xvalue) of a network daemon process, and \fIclient\fR is the name and/or
  820. Xaddress of a remote host.
  821. X.SH ACCESS CONTROL FILES
  822. XThe access control software consults two files:
  823. X.IP o
  824. XAccess will be granted when a (daemon,client) pair matches an entry in
  825. Xthe \fI/etc/hosts.allow\fR file.
  826. X.IP o
  827. XOtherwise, access will be denied when a (daemon,client) pair matches an
  828. Xentry in the \fI/etc/hosts.deny\fR file.
  829. X.IP o
  830. XOtherwise, access will be granted.
  831. X.PP
  832. XA non-existing access control file is treated as if it were an empty
  833. Xfile. Thus, access control can be turned off by providing no access
  834. Xcontrol files.
  835. X.SH ACCESS CONTROL RULES
  836. XEach access control file consists of zero or more lines of text.  These
  837. Xlines are processed in order of apperance. The search terminates when a
  838. Xmatch is found.
  839. X.IP o
  840. XLines that begin with a `#\' character are ignored.
  841. X.IP o
  842. XAll other lines should satisfy the following format, things between []
  843. Xbeing optional:
  844. X.sp
  845. X.ti +3
  846. Xdaemon_list : client_list [ : shell_command ]
  847. X.PP
  848. X\fIdaemon_list\fR is a list of one or more daemon process names
  849. X(argv[0] values) or wildcards (see below).  
  850. X.PP
  851. X\fIclient_list\fR is a list
  852. Xof one or more host names, host addresses, patterns or wildcards (see
  853. Xbelow) that will be matched against the remote host name or address.
  854. X.PP
  855. XList elements should be separated by blanks and/or commas.  
  856. X.PP
  857. XWith the exception of netgroup lookups, all access control checks are
  858. Xcase insensitive.
  859. X.br
  860. X.ne 4
  861. X.SH PATTERNS
  862. XThe access control language implements the following patterns:
  863. X.IP o
  864. XA string that begins with a `.\' character.  A client name or address
  865. Xis matched if its last components match the specified pattern.  For
  866. Xexample, the pattern `.tue.nl\' matches the host name
  867. X`wzv.win.tue.nl\'.
  868. X.IP o
  869. XA string that ends with a `.\' character.  A client name or address is
  870. Xmatched if its first fields match the given string.  For example, the
  871. Xpattern `131.155.\' matches the address of (almost) every host on the
  872. XEind\%hoven University network (131.155.x.x).
  873. X.IP o
  874. XA string that begins with a `@\' character is treated as a netgroup
  875. Xname.  Netgroups are usually supported on systems with NIS (formerly
  876. XYP) data bases. A client host name is matched if it is a (host) member
  877. Xof the specified netgroup.
  878. X.IP o
  879. XAn expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
  880. X`net/mask\' pair. A client address is matched if `net\' is equal to the
  881. Xbitwise AND of the address and the `mask\'. For example, the net/mask
  882. Xpattern `131.155.72.0/255.255.254.0\' matches every address in the
  883. Xrange `131.155.72.0\' through `131.155.73.255\'.
  884. X.SH WILDCARDS
  885. XThe access control language supports explicit wildcards:
  886. X.IP ALL
  887. XIf this token appears in a daemon_list, it matches all network daemon
  888. Xprocess names.  If the ALL token appears in a client_list, it matches
  889. Xall client names and addresses.
  890. X.IP LOCAL
  891. XMatches any string that does not contain a dot character.
  892. XTypical use is in client_lists.
  893. X.IP UNKNOWN
  894. XMatches any host whose name and/or address lookup failed.  Should be
  895. Xused with care, because host names may also be unavailable due to
  896. Xtemporary name server problems.
  897. X.IP FAIL
  898. XLike the ALL wildcard, but causes the software to pretend that the scan
  899. Xof the current access control table fails. This is useful to avoid
  900. Xunwanted matches with later entries in the same access control table.
  901. X.br
  902. X.ne 6
  903. X.SH SHELL COMMANDS
  904. XIf the first-matched access control rule contains a shell command, that
  905. Xcommand is subjected to the following subsitutions:
  906. X.IP %a
  907. Xexpands to the remote host address.
  908. X.IP %c
  909. Xexpands to client information: user@host, user@address, a host name, or
  910. Xjust an address, depending on how much information is available.
  911. X.IP %h
  912. Xexpands to the remote host name (or address, if the host name is
  913. Xunavailable).
  914. X.IP %d
  915. Xexpands to the daemon process name (argv[0] value).
  916. X.IP %p
  917. Xexpands to the daemon process id.
  918. X.IP %u
  919. Xexpands to the remote user name.
  920. X.IP %%
  921. Xexpands to a single `%\' character.
  922. X.PP
  923. XThe result is executed by a \fI/bin/sh\fR child process with standard
  924. Xinput, output and error connected to \fI/dev/null\fR.  Specify an `&\'
  925. Xat the end of the command if you do not want to wait until it has
  926. Xcompleted.
  927. X.PP
  928. XShell commands should not rely on the PATH setting of the inetd.
  929. XInstead, they should use absolute path names, or they should begin with
  930. Xan explicit PATH=whatever statement.
  931. X.SH EXAMPLES
  932. XThe following example restricts services to hosts within the local
  933. Xdomain (no `.\' character in the host name), 
  934. Xall hosts below the \fI.some.domain\fR, and all hosts in the
  935. X\fIsome_netgroup\fR netgroup:
  936. X.PP
  937. X.ne 2
  938. X/etc/hosts.allow: 
  939. X.in +3
  940. XALL: LOCAL, .some.domain, @some_netgroup
  941. X.PP
  942. X.ne 2
  943. X/etc/hosts.deny: 
  944. X.in +3
  945. XALL: ALL
  946. X.PP
  947. X.ne 4
  948. XThe following fragment matches any host below .some.domain, with the
  949. Xexception of hosts below .sub.some.domain:
  950. X.PP
  951. X.ne 2
  952. X.in +3
  953. XFAIL: .sub.some.domain 
  954. X.br
  955. XALL: .some.domain
  956. X.PP
  957. X.ne 8
  958. XIn order to deny some hosts all services, except ftp:
  959. X.PP
  960. X/etc/hosts.allow: 
  961. X.in +3
  962. Xin.ftpd: ALL
  963. X.PP
  964. X/etc/hosts.deny: 
  965. X.in +3
  966. XALL: some.host.name, .some.domain
  967. X.PP
  968. XThe example can be improved a little by including address and/or
  969. Xnetwork/netmask information, so that there is no way to "sneak in" when
  970. Xhost names are temporarily unavailable.
  971. X.PP
  972. XThe last example performs a reverse finger whenever someone invokes
  973. Xthe tftp service from outside the local domain. The result is mailed
  974. Xto root:
  975. X.PP
  976. X.ne 2
  977. X/etc/hosts.allow:
  978. X.in +3
  979. X.nf
  980. Xin.tftpd: LOCAL, .my.domain
  981. X.PP
  982. X.ne 2
  983. X/etc/hosts.deny:
  984. X.in +3
  985. X.nf
  986. Xin.tftpd: ALL: /usr/ucb/finger -l @%h | /usr/ucb/mail -s %d-%h root &
  987. X.fi
  988. X.PP
  989. XOn network firewall systems this trick can be carried even further.
  990. XThe typical network firewall only provides a limited set of services to
  991. Xthe outer world. All other services can be "bugged" just like the above
  992. Xtftp example. The result is an excellent early-warning system.
  993. X.SH DIAGNOSTICS
  994. XAn error is reported when a syntax error is found in a host access
  995. Xcontrol rule; when the length of access control rule exceeds the STDIO
  996. Xbuffer size; when an access control rule is not terminated by a newline
  997. Xcharacter; when the result of %<character> expansion would overflow an
  998. Xinternal buffer; when a system call fails that shouldn\'t.  All
  999. Xproblems are reported via the syslog daemon.
  1000. X.SH FILES
  1001. X.na
  1002. X.nf
  1003. X/etc/hosts.allow, (daemon,client) pairs that are granted access.
  1004. X/etc/hosts.deny, (daemon,client) pairs that are denied access.
  1005. X.ad
  1006. X.fi
  1007. X.SH BUGS
  1008. XIf a name server lookup times out, the host name will not be available
  1009. Xto the access control software, even though the host is registered.
  1010. X.PP
  1011. XDomain name server lookups are case insensitive; NIS (formerly YP)
  1012. Xnetgroup lookups are case sensitive.
  1013. X.PP
  1014. XSome UDP (and RPC) daemons linger around for a while after they have
  1015. Xserviced a request, in case another request comes in. In the inetd
  1016. Xconfiguration file, these daemons are registered with the `wait\'
  1017. Xoption.  Access control will apply only to the request that started
  1018. Xsuch a daemon. This restriction does not apply to connection-oriented
  1019. X(TCP) services.
  1020. X.SH AUTHOR
  1021. X.na
  1022. X.nf
  1023. XWietse Venema (wietse@wzv.win.tue.nl)
  1024. XDepartment of Mathematics and Computing Science
  1025. XEindhoven University of Technology
  1026. XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1027. X\" @(#) hosts_access.5 1.9 92/06/11 22:21:37
  1028. END_OF_FILE
  1029.   if test 7619 -ne `wc -c <'hosts_access.5'`; then
  1030.     echo shar: \"'hosts_access.5'\" unpacked with wrong size!
  1031.   fi
  1032.   # end of 'hosts_access.5'
  1033. fi
  1034. if test -f 'hosts_access.c' -a "${1}" != "-c" ; then 
  1035.   echo shar: Will not clobber existing file \"'hosts_access.c'\"
  1036. else
  1037.   echo shar: Extracting \"'hosts_access.c'\" \(7329 characters\)
  1038.   sed "s/^X//" >'hosts_access.c' <<'END_OF_FILE'
  1039. X /*
  1040. X  * This module implements a simple access control language that is based on
  1041. X  * host (or domain) names, netgroup, internet addresses (or network numbers)
  1042. X  * and daemon process names. When a match is found an optional shell command
  1043. X  * is executed and the search is terminated.
  1044. X  * 
  1045. X  * Diagnostics are reported through syslog(3).
  1046. X  * 
  1047. X  * Compile with -DNETGROUP if your library provides support for netgroups.
  1048. X  * 
  1049. X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  1050. X  */
  1051. X
  1052. X#ifndef lint
  1053. Xstatic char sccsid[] = "@(#) hosts_access.c 1.8 92/06/12 15:55:52";
  1054. X#endif
  1055. X
  1056. X /* System libraries. */
  1057. X
  1058. X#include <sys/types.h>
  1059. X#include <sys/param.h>
  1060. X#include <netinet/in.h>
  1061. X#include <arpa/inet.h>
  1062. X#include <stdio.h>
  1063. X#include <syslog.h>
  1064. X#include <ctype.h>
  1065. X
  1066. Xextern char *fgets();
  1067. Xextern char *strchr();
  1068. Xextern char *strtok();
  1069. X
  1070. X#ifndef    INADDR_NONE
  1071. X#define    INADDR_NONE    (-1)        /* XXX should be 0xffffffff */
  1072. X#endif
  1073. X
  1074. X/* Local stuff. */
  1075. X
  1076. X#include "log_tcp.h"
  1077. X
  1078. X/* Delimiters for lists of daemons or clients. */
  1079. X
  1080. Xstatic char sep[] = ", \t";
  1081. X
  1082. X/* Constants to be used in assignments only, not in comparisons... */
  1083. X
  1084. X#define    YES        1
  1085. X#define    NO        0
  1086. X#define    FAIL        (-1)
  1087. X
  1088. X/* Forward declarations. */
  1089. X
  1090. Xstatic int table_match();
  1091. Xstatic int list_match();
  1092. Xstatic int masked_match();
  1093. Xstatic void list_split();
  1094. X
  1095. X/* hosts_access - host access control facility */
  1096. X
  1097. Xint     hosts_access(daemon, client)
  1098. Xchar   *daemon;
  1099. Xstruct from_host *client;        /* host or user name may be empty */
  1100. X{
  1101. X
  1102. X    /*
  1103. X     * If the (daemon, client) pair is matched by an entry in the file
  1104. X     * /etc/hosts.allow, access is granted. Otherwise, if the (daemon,
  1105. X     * client) pair is matched by an entry in the file /etc/hosts.deny,
  1106. X     * access is denied. Otherwise, access is granted. A non-existent
  1107. X     * access-control file is treated as an empty file.
  1108. X     */
  1109. X
  1110. X    if (table_match(HOSTS_ALLOW, daemon, client))
  1111. X    return (YES);
  1112. X    if (table_match(HOSTS_DENY, daemon, client))
  1113. X    return (NO);
  1114. X    return (YES);
  1115. X}
  1116. X
  1117. X/* table_match - match table entries with (daemon, client) pair */
  1118. X
  1119. Xstatic int table_match(table, daemon, client)
  1120. Xchar   *table;
  1121. Xchar   *daemon;
  1122. Xstruct from_host *client;        /* host or user name may be empty */
  1123. X{
  1124. X    FILE   *fp;
  1125. X    char    sv_list[BUFSIZ];        /* becomes list of daemons */
  1126. X    char   *cl_list;            /* becomes list of clients */
  1127. X    char   *argv[sizeof(sv_list) / 2 + 1];
  1128. X    char   *sh_cmd;            /* becomes optional shell command */
  1129. X    int     match;
  1130. X    int     end;
  1131. X
  1132. X    /* The following variables should always be tested together. */
  1133. X
  1134. X    int     sv_match = NO;        /* daemon matched */
  1135. X    int     cl_match = NO;        /* client matced */
  1136. X
  1137. X    /*
  1138. X     * Process the table one line at a time. Lines that begin with a '#'
  1139. X     * character are ignored. Non-comment lines are broken at the ':'
  1140. X     * character (we complain if there is none). The first field is matched
  1141. X     * against the daemon process name (argv[0]), the second field against
  1142. X     * the host name or address. A non-existing table is treated as if it
  1143. X     * were an empty table. When a match is found an optional shell command
  1144. X     * is executed.
  1145. X     * 
  1146. X     * Daemon and client lists are converted to arrays of character pointers
  1147. X     * because the client list may have to be processed twice: once to match
  1148. X     * the host name, and once for matching the address.
  1149. X     */
  1150. X
  1151. X    if (fp = fopen(table, "r")) {
  1152. X    while (!(sv_match && cl_match) && fgets(sv_list, sizeof(sv_list), fp)) {
  1153. X        if (sv_list[end = strlen(sv_list) - 1] != '\n') {
  1154. X        syslog(LOG_ERR, "%s: missing newline or line too long", table);
  1155. X        continue;
  1156. X        } else {
  1157. X        sv_list[end] = '\0';        /* strip trailing newline */
  1158. X        }
  1159. X        if (sv_list[0] == '#')        /* skip comments */
  1160. X        continue;
  1161. X        if ((cl_list = strchr(sv_list, ':')) == 0) {
  1162. X        syslog(LOG_ERR, "%s: malformed entry: \"%s\"", table, sv_list);
  1163. X        continue;
  1164. X        }
  1165. X        *cl_list++ = '\0';            /* split 1st and 2nd fields */
  1166. X        if ((sh_cmd = strchr(cl_list, ':')) != 0)
  1167. X        *sh_cmd++ = '\0';        /* split 2nd and 3rd fields */
  1168. X        list_split(sv_list, argv);
  1169. X        if ((sv_match = list_match(argv, daemon)) != 0) {
  1170. X        list_split(cl_list, argv);
  1171. X        if (client->name[0] == 0
  1172. X            || (cl_match = list_match(argv, client->name)) == 0)
  1173. X            cl_match = list_match(argv, client->addr);
  1174. X        }
  1175. X    }
  1176. X    (void) fclose(fp);
  1177. X    }
  1178. X    match = (sv_match == YES && cl_match == YES);
  1179. X    if (match && sh_cmd)
  1180. X    shell_cmd(sh_cmd, daemon, client);
  1181. X    return (match);
  1182. X}
  1183. X
  1184. X/* list_split - destructively convert string to array of character pointers */
  1185. X
  1186. Xstatic void list_split(string, argv)
  1187. Xregister char *string;
  1188. Xregister char **argv;
  1189. X{
  1190. X    for (*argv = strtok(string, sep); *argv; *++argv = strtok((char *) 0, sep))
  1191. X     /* void */ ;
  1192. X}
  1193. X
  1194. X/* list_match - match a string against a list of tokens */
  1195. X
  1196. Xstatic int list_match(list, string)
  1197. Xchar  **list;
  1198. Xchar   *string;
  1199. X{
  1200. X    char   *tok;
  1201. X    int     tok_len;
  1202. X    int     str_len;
  1203. X    char   *cut;
  1204. X
  1205. X    /*
  1206. X     * Process tokens one at a time. Return YES if a token has the magic
  1207. X     * value "ALL". Return FAIL if the token is "FAIL". If the token starts
  1208. X     * with a "." (domain name), return YES if it matches the last fields of
  1209. X     * the string. If the token has the magic value "LOCAL", return YES if
  1210. X     * the string does not contain a "." character. If the token ends on a
  1211. X     * "." (network number), return YES if it matches the first fields of the
  1212. X     * string. If the token begins with a "@" (netgroup name), return YES if
  1213. X     * the string is a (host) member of the netgroup. Return YES if the token
  1214. X     * fully matches the string. If the token is a netnumber/netmask pair,
  1215. X     * return YES if the address is a member of the specified subnet.
  1216. X     */
  1217. X
  1218. X    for (tok = *list; tok; tok = *++list) {
  1219. X    if (tok[0] == '.') {            /* domain: match last fields */
  1220. X        if ((str_len = strlen(string)) > (tok_len = strlen(tok))
  1221. X        && strcasecmp(tok, string + str_len - tok_len) == 0)
  1222. X        return (YES);
  1223. X#ifdef    NETGROUP
  1224. X    } else if (tok[0] == '@') {        /* netgroup: look it up */
  1225. X        if (!isdigit(string[0])
  1226. X        && innetgr(tok + 1, string, (char *) 0, (char *) 0))
  1227. X        return (YES);
  1228. X#endif
  1229. X    } else if (strcasecmp(tok, "ALL") == 0) {    /* all: match any */
  1230. X        return (YES);
  1231. X    } else if (strcasecmp(tok, "FAIL") == 0) {    /* fail: match any */
  1232. X        return (FAIL);
  1233. X    } else if (strcasecmp(tok, "LOCAL") == 0) {    /* local: no dots */
  1234. X        if (strchr(string, '.') == 0 && strcasecmp(string, "unknown") != 0)
  1235. X        return (YES);
  1236. X    } else if (!strcasecmp(tok, string)) {    /* match host name or address */
  1237. X        return (YES);
  1238. X    } else if (tok[(tok_len = strlen(tok)) - 1] == '.') {    /* network */
  1239. X        if (strncmp(tok, string, tok_len) == 0)
  1240. X        return (YES);
  1241. X    } else if ((cut = strchr(tok, '/')) != 0) {    /* netnumber/netmask */
  1242. X        if (isdigit(string[0]) && masked_match(tok, cut, string))
  1243. X        return (YES);
  1244. X    }
  1245. X    }
  1246. X    return (NO);
  1247. X}
  1248. X
  1249. X/* masked_match - match address against netnumber/netmask */
  1250. X
  1251. Xstatic int masked_match(tok, slash, string)
  1252. Xchar   *tok;
  1253. Xchar   *slash;
  1254. Xchar   *string;
  1255. X{
  1256. X    unsigned long net;
  1257. X    unsigned long mask;
  1258. X    unsigned long addr;
  1259. X
  1260. X    if ((addr = inet_addr(string)) == INADDR_NONE)
  1261. X    return (NO);
  1262. X    *slash = 0;
  1263. X    net = inet_addr(tok);
  1264. X    *slash = '/';
  1265. X    if (net == INADDR_NONE || (mask = inet_addr(slash + 1)) == INADDR_NONE) {
  1266. X    syslog(LOG_ERR, "bad net/mask access control: %s", tok);
  1267. X    return (NO);
  1268. X    }
  1269. X    return ((addr & mask) == net);
  1270. X}
  1271. END_OF_FILE
  1272.   if test 7329 -ne `wc -c <'hosts_access.c'`; then
  1273.     echo shar: \"'hosts_access.c'\" unpacked with wrong size!
  1274.   fi
  1275.   # end of 'hosts_access.c'
  1276. fi
  1277. if test -f 'options.c' -a "${1}" != "-c" ; then 
  1278.   echo shar: Will not clobber existing file \"'options.c'\"
  1279. else
  1280.   echo shar: Extracting \"'options.c'\" \(7510 characters\)
  1281.   sed "s/^X//" >'options.c' <<'END_OF_FILE'
  1282. X /*
  1283. X  * General skeleton for adding options to the access control language. This
  1284. X  * code can be enabled by replacing in hosts_access.c the shell_command()
  1285. X  * call by a call to process_options(), with the same argument list. Shell
  1286. X  * commands will still be available, be it with a slightly different syntax.
  1287. X  * 
  1288. X  * The code uses a slightly different format of access control rules. It
  1289. X  * assumes that an access control rule looks like this:
  1290. X  * 
  1291. X  * daemon_list : client_list : option : option ...
  1292. X  * 
  1293. X  * An option is of the form "keyword" or "keyword = value". Option fields are
  1294. X  * processed from left to right. Blanks around keywords, "="  and values are
  1295. X  * optional.
  1296. X  * 
  1297. X  * Diagnostics are reported through syslog(3).
  1298. X  * 
  1299. X  * Examples of options that are already implemented by the current skeleton:
  1300. X  * 
  1301. X  * user = nobody
  1302. X  * 
  1303. X  * Causes the process to switch its user id to that of "nobody". This normally
  1304. X  * requires root privilege.
  1305. X  * 
  1306. X  * group = tty
  1307. X  * 
  1308. X  * Causes the process to change its group id to that of the "tty" group. In
  1309. X  * order to switch both user and group ids you should normally switch the
  1310. X  * group id before switching the user id.
  1311. X  * 
  1312. X  * spawn = /usr/ucb/finger -l @%h | /usr/ucb/mail root
  1313. X  * 
  1314. X  * Executes (in a child process) the shell command "finger -l @%h | mail root"
  1315. X  * after doing the %<character> expansions described in the hosts_access(5)
  1316. X  * manual page. The command is executed with stdin, stdout and stderr
  1317. X  * connected to the null device. Because options are processed in order,
  1318. X  * multiple spawn comands can be specified within the same access control
  1319. X  * rule, though "spawn = command1; command2" would be more efficient.
  1320. X  * 
  1321. X  * in.ftpd : client_list : twist = /bin/echo 421 Some bogus error message
  1322. X  * 
  1323. X  * Sends some bogus error message to the remote client instead of running the
  1324. X  * real ftp daemon. The command is subjected to %<character> expansion and
  1325. X  * executed by /bin/sh. Stdin, stdout and stderr are not redirected. Some
  1326. X  * inetd's only pass stdin to their servers; in that case the command should
  1327. X  * write its output to stdin, as with: "command >&0". The twist'ed command
  1328. X  * overlays the current process; it makes no sense to specify other options
  1329. X  * on the same line after a "twist". The "twist" option was inspired by Dan
  1330. X  * Bernstein's shuctl daemon wrapper control language.
  1331. X  * 
  1332. X  * The decision to do RFC 931 lookups can be moved to this code, too. This can
  1333. X  * be accomplished by feeding the rfc931_option file to the "patch" command.
  1334. X  * In that case you get a fifth option:
  1335. X  * 
  1336. X  * rfc931
  1337. X  * 
  1338. X  * Causes the daemon front ends to look up the remote user name with the RFC
  1339. X  * 931 protocol.
  1340. X  * 
  1341. X  * Warnings:
  1342. X  * 
  1343. X  * This module uses the non-reentrant strtok() library routine. The options
  1344. X  * argument to process_options() is destroyed.
  1345. X  * 
  1346. X  * There cannot be a ":" character in keywords or values. Backslash sequences
  1347. X  * are not yet recognized.
  1348. X  * 
  1349. X  * In case of UDP connections, do not "twist" commands that use the standard
  1350. X  * I/O or read(2)/write(2) routines to communicate with the client process.
  1351. X  * 
  1352. X  * In case of errors, use clean_exit() instead of directly calling exit(), or
  1353. X  * your inetd may go into a loop.
  1354. X  */
  1355. X
  1356. X/* System libraries. */
  1357. X
  1358. X#include <sys/types.h>
  1359. X#include <sys/param.h>
  1360. X#include <sys/socket.h>
  1361. X#include <netinet/in.h>
  1362. X#include <netdb.h>
  1363. X#include <stdio.h>
  1364. X#include <syslog.h>
  1365. X#include <pwd.h>
  1366. X#include <ctype.h>
  1367. X
  1368. Xextern char *strtok();
  1369. Xextern char *strchr();
  1370. X
  1371. X/* Local stuff. */
  1372. X
  1373. X#include "log_tcp.h"
  1374. X
  1375. X/* List of functions that implement the options. Add yours here. */
  1376. X
  1377. Xstatic void user_option();        /* execute "user=name" option */
  1378. Xstatic void group_option();        /* execute "group=name" option */
  1379. Xstatic void twist_option();        /* execute "twist=command" option */
  1380. X#ifdef RFC931_OPTION
  1381. Xstatic void rfc931_option();        /* execute "rfc931" option */
  1382. X#endif
  1383. X
  1384. Xstatic char *chop_string();        /* strip leading and trailing blanks */
  1385. X
  1386. X/* Structure of the options table. */
  1387. X
  1388. Xstruct option {
  1389. X    char   *name;            /* keyword name, case does not matter */
  1390. X    int     need_value;            /* value required or not */
  1391. X    void    (*func) ();            /* function that does the real work */
  1392. X};
  1393. X
  1394. X/* List of known keywords. Add yours here. */
  1395. X
  1396. Xstatic struct option option_table[] = {
  1397. X    "user", 1, user_option,        /* switch user id */
  1398. X    "group", 1, group_option,        /* switch group id */
  1399. X    "spawn", 1, shell_cmd,        /* spawn shell command */
  1400. X    "twist", 1, twist_option,        /* replace current process */
  1401. X#ifdef RFC931_OPTION
  1402. X    "rfc931", 0, rfc931_option,        /* do RFC 931 lookup */
  1403. X#endif
  1404. X    0,
  1405. X};
  1406. X
  1407. X/* process_options - process optional access control information */
  1408. X
  1409. Xprocess_options(options, daemon, client)
  1410. Xchar   *options;
  1411. Xchar   *daemon;
  1412. Xstruct from_host *client;
  1413. X{
  1414. X    char   *key;
  1415. X    char   *value;
  1416. X    struct option *op;
  1417. X
  1418. X    /* Light-weight parser. We're not going to duplicate PERL. */
  1419. X
  1420. X    for (key = strtok(options, ":"); key; key = strtok((char *) 0, ":")) {
  1421. X    if (value = strchr(key, '=')) {        /* keyword=value */
  1422. X        *value++ = 0;
  1423. X        value = chop_string(value);        /* strip blanks around value */
  1424. X        if (*value == 0)
  1425. X        value = 0;
  1426. X    }
  1427. X    key = chop_string(key);            /* strip blanks around key */
  1428. X    for (op = option_table; op->name; op++)    /* find keyword */
  1429. X        if (strcasecmp(op->name, key) == 0)
  1430. X        break;
  1431. X    if (op->name == 0) {
  1432. X        syslog(LOG_ERR, "bad option or syntax: \"%s\"", key);
  1433. X    } else if (value == 0 && op->need_value) {
  1434. X        syslog(LOG_ERR, "option \"%s\" requires value", key);
  1435. X    } else if (value && op->need_value == 0) {
  1436. X        syslog(LOG_ERR, "option \"%s\" requires no value", key);
  1437. X    } else {
  1438. X        (*(op->func)) (value, daemon, client);
  1439. X    }
  1440. X    }
  1441. X}
  1442. X
  1443. X/* user_option - switch user id */
  1444. X
  1445. X/* ARGSUSED */
  1446. X
  1447. Xstatic void user_option(value, daemon, client)
  1448. Xchar   *value;
  1449. Xchar   *daemon;
  1450. Xstruct from_host *client;
  1451. X{
  1452. X    struct passwd *pwd;
  1453. X
  1454. X    if ((pwd = getpwnam(value)) == 0) {
  1455. X    syslog(LOG_ERR, "unknown user: \"%s\"", value);
  1456. X    clean_exit(client);
  1457. X    } else if (setuid(pwd->pw_uid)) {
  1458. X    syslog(LOG_ERR, "setuid(%s): %m", value);
  1459. X    clean_exit(client);
  1460. X    }
  1461. X}
  1462. X
  1463. X/* group_option - switch group id */
  1464. X
  1465. X/* ARGSUSED */
  1466. X
  1467. Xstatic void group_option(value, daemon, client)
  1468. Xchar   *value;
  1469. Xchar   *daemon;
  1470. Xstruct from_host *client;
  1471. X{
  1472. X    struct passwd *pwd;
  1473. X
  1474. X    if ((pwd = getpwnam(value)) == 0) {
  1475. X    syslog(LOG_ERR, "unknown group: \"%s\"", value);
  1476. X    clean_exit(client);
  1477. X    } else if (setgid(pwd->pw_gid)) {
  1478. X    syslog(LOG_ERR, "setgid(%s): %m", value);
  1479. X    clean_exit(client);
  1480. X    }
  1481. X}
  1482. X
  1483. X/* twist_option - replace process by shell command */
  1484. X
  1485. Xstatic void twist_option(value, daemon, client)
  1486. Xchar   *value;
  1487. Xchar   *daemon;
  1488. Xstruct from_host *client;
  1489. X{
  1490. X    char    buf[BUFSIZ];
  1491. X    int     pid = getpid();
  1492. X
  1493. X    percent_x(buf, sizeof(buf), value, daemon, client, pid);
  1494. X    (void) execl("/bin/sh", "sh", "-c", buf, (char *) 0);
  1495. X    syslog(LOG_ERR, "twist \"%s\": %m", buf);
  1496. X    clean_exit(client);
  1497. X}
  1498. X
  1499. X#ifdef RFC931_OPTION
  1500. X
  1501. X/* rfc931_option - look up remote user name */
  1502. X
  1503. X/* ARGSUSED */
  1504. X
  1505. Xstatic void rfc931_option(value, daemon, client)
  1506. Xchar   *value;
  1507. Xchar   *daemon;
  1508. Xstruct from_host *client;
  1509. X{
  1510. X    if (client->sin != 0 && client->sock_type == FROM_CONNECTED)
  1511. X    client->user = rfc931_name(client->sin);
  1512. X}
  1513. X
  1514. X#endif
  1515. X
  1516. X/* chop_string - strip leading and trailing blanks from string */
  1517. X
  1518. Xstatic char *chop_string(start)
  1519. Xregister char *start;
  1520. X{
  1521. X    register char *end;
  1522. X
  1523. X    while (*start && isspace(*start))
  1524. X    start++;
  1525. X
  1526. X    end = start + strlen(start) - 1;
  1527. X    while (end > start && isspace(*end))
  1528. X    *end-- = 0;
  1529. X
  1530. X    return (start);
  1531. X}
  1532. END_OF_FILE
  1533.   if test 7510 -ne `wc -c <'options.c'`; then
  1534.     echo shar: \"'options.c'\" unpacked with wrong size!
  1535.   fi
  1536.   # end of 'options.c'
  1537. fi
  1538. echo shar: End of archive 1 \(of 2\).
  1539. cp /dev/null ark1isdone
  1540. MISSING=""
  1541. for I in 1 2 ; do
  1542.     if test ! -f ark${I}isdone ; then
  1543.     MISSING="${MISSING} ${I}"
  1544.     fi
  1545. done
  1546. if test "${MISSING}" = "" ; then
  1547.     echo You have unpacked both archives.
  1548.     rm -f ark[1-9]isdone
  1549. else
  1550.     echo You still must unpack the following archives:
  1551.     echo "        " ${MISSING}
  1552. fi
  1553. exit 0
  1554. exit 0 # Just in case...
  1555.