[alt.sources] package to monitor your internet connections

wswietse@win.tue.nl (Wietse Venema) (11/30/90)

This package provides a couple of tiny front end programs that log all
incoming requests to connection-oriented internet services (examples:
finger, systat, telnet, ftp, rlogin, rsh, exec).  Connections are
reported through the syslog facility. Each report contains the remote
host name, a time stamp and the name of the service requested. Such
information can be useful to detect break-in attempts or other
suspicious activities.

The programs do not require any changes to existing software or 
configuration files. 

The stuff was tested with SunOS >= 3.4, Ultrix >= 2.2 and some obscure
port of System V Release 2. 

This is a beta release of software that has been in use for over half
a year at Eindhoven University of Technology. Any feedback is welcome.
When the rough edges have been taken care of, I wil post the stuff to
one of the official source groups.

Versions of rshd and rlogind, hacked to report the remote user name as
well, are available for anon ftp (ftp.win.tue.nl:/pub/logdaemon.tar.Z).
Those programs have only been tested with SunOS 4.1.

	Wietse Venema
	Eindhoven University of Technology
	Eindhoven, The Netherlands

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  miscd.c tcpd.c hosts_deny.c makefile README
# Wrapped by wswietse@svin02 on Fri Nov 30 11:24:03 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f miscd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"miscd.c\"
else
echo shar: Extracting \"miscd.c\" \(2195 characters\)
sed "s/^X//" >miscd.c <<'END_OF_miscd.c'
X /*
X  * Wrapper around the ULTRIX miscd daemon. This program logs all connections
X  * and invokes the real daemon. For example, install as "/usr/etc/miscd",
X  * after saving the real daemon as "/usr/etc/.../miscd". miscd implements
X  * the systat service, which pipes the output from who(1) to stdout. This
X  * information is potentially useful to systems crackers.
X  * 
X  * Optionally refuses connections from hosts or domains specified in an
X  * external file.
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#define	REAL_DAEMON	"/usr/etc/.../miscd"
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <syslog.h>
X#include <netinet/in.h>
X#include <netdb.h>
X
X#ifndef	MAXHOSTNAMELEN
X#define	MAXHOSTNAMELEN	BUFSIZ
X#endif
X
Xmain(argc, argv)
Xint     argc;
Xchar  **argv;
X{
X    int     sockt;
X    int     length;
X    struct sockaddr sa;
X    struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
X    char    host_name[MAXHOSTNAMELEN];
X    struct hostent *hp;
X    char   *strcpy();
X    char   *inet_ntoa();
X    void    exit();
X    void    syslog();
X
X    sockt = fileno(stdin);
X    length = sizeof(sa);
X
X#ifdef	LOG_MAIL
X    (void) openlog(argv[0], LOG_PID, LOG_MAIL);
X#else
X    (void) openlog(argv[0], LOG_PID);
X#endif
X
X    if (getpeername(sockt, &sa, &length) < 0) {
X	if (isatty(sockt)) {
X	    (void) strcpy(host_name, "stdin");
X	} else {
X	    syslog(LOG_ERR, "getpeername: %m");
X	    (void) strcpy(host_name, "unknown");
X	}
X    } else {
X	switch (sa.sa_family) {
X	case AF_INET:
X	    hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
X			       sizeof(sin->sin_addr.s_addr), AF_INET);
X	    if (hp != NULL)
X		(void) strcpy(host_name, hp->h_name);
X	    else
X		(void) strcpy(host_name, inet_ntoa(sin->sin_addr));
X	    break;
X
X	default:
X	    syslog(LOG_ERR, "unknown address family %ld", sa.sa_family);
X	    (void) strcpy(host_name, "unknown");
X	}
X    }
X
X    syslog(LOG_INFO, "connect from %s", host_name);
X
X#ifdef	HOSTS_DENY
X
X    /* Deny access if host or domain is listed in hosts.deny file. */
X
X    hosts_deny(host_name);
X
X#endif
X
X    (void) execv(REAL_DAEMON, argv);
X    syslog(LOG_ERR, "%s: %m", REAL_DAEMON);
X}
END_OF_miscd.c
if test 2195 -ne `wc -c <miscd.c`; then
    echo shar: \"miscd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f tcpd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"tcpd.c\"
else
echo shar: Extracting \"tcpd.c\" \(2223 characters\)
sed "s/^X//" >tcpd.c <<'END_OF_tcpd.c'
X /*
X  * Wrapper around connection-oriented services. This program logs all
X  * connections and invokes the real daemon. For example, install as
X  * /usr/etc/{fingerd,telnetd,ftpd,rlogind,rshd,rexecd}, after saving the
X  * real daemons in the directory "/usr/etc/...".
X  * 
X  * Optionally refuses connections from hosts or domains specified in an
X  * external file.
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#define	REAL_DAEMON_DIR	"/usr/etc/..."
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <syslog.h>
X#include <netinet/in.h>
X#include <netdb.h>
X
X#ifndef	MAXHOSTNAMELEN
X#define	MAXHOSTNAMELEN	BUFSIZ
X#endif
X
Xmain(argc, argv)
Xint     argc;
Xchar  **argv;
X{
X    int     sockt;
X    int     length;
X    struct sockaddr sa;
X    struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
X    char    host_name[MAXHOSTNAMELEN];
X    struct hostent *hp;
X    char   *strcpy();
X    char   *inet_ntoa();
X    void    exit();
X    void    syslog();
X    char    path[BUFSIZ];
X
X    sockt = fileno(stdin);
X    length = sizeof(sa);
X
X#ifdef	LOG_MAIL
X    (void) openlog(argv[0], LOG_PID, LOG_MAIL);
X#else
X    (void) openlog(argv[0], LOG_PID);
X#endif
X
X    if (getpeername(sockt, &sa, &length) < 0) {
X	if (isatty(sockt)) {
X	    (void) strcpy(host_name, "stdin");
X	} else {
X	    syslog(LOG_ERR, "getpeername: %m");
X	    (void) strcpy(host_name, "unknown");
X	}
X    } else {
X	switch (sa.sa_family) {
X	case AF_INET:
X	    hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
X			       sizeof(sin->sin_addr.s_addr), AF_INET);
X	    if (hp != NULL)
X		(void) strcpy(host_name, hp->h_name);
X	    else
X		(void) strcpy(host_name, inet_ntoa(sin->sin_addr));
X	    break;
X
X	default:
X	    syslog(LOG_ERR, "unknown address family %ld", sa.sa_family);
X	    (void) strcpy(host_name, "unknown");
X	}
X    }
X
X    syslog(LOG_INFO, "connect from %s", host_name);
X
X#ifdef	HOSTS_DENY
X
X    /* Deny access if host or domain is listed in hosts.deny file. */
X
X    hosts_deny(host_name);
X
X#endif
X
X    /* Construct path to real daemon and invoke it */
X
X    (void) sprintf(path, "%s/%s", REAL_DAEMON_DIR, argv[0]);
X    (void) execv(path, argv);
X    syslog(LOG_ERR, "%s: %m", path);
X}
END_OF_tcpd.c
if test 2223 -ne `wc -c <tcpd.c`; then
    echo shar: \"tcpd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_deny.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hosts_deny.c\"
else
echo shar: Extracting \"hosts_deny.c\" \(1696 characters\)
sed "s/^X//" >hosts_deny.c <<'END_OF_hosts_deny.c'
X#ifdef	HOSTS_DENY
X
X /*
X  * This code refuses connections from hosts or domains listed in a file.
X  * Format is: one host name or domain name per line. The name comparison
X  * algorithm is case insensitive.
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <stdio.h>
X#include <syslog.h>
X#include <ctype.h>
X
X#ifndef	MAXHOSTNAMELEN
X#define	MAXHOSTNAMELEN	BUFSIZ
X#endif
X
X/* hosts_deny - deny access if host or domain is listed in hosts.deny file */
X
Xhosts_deny(name)
Xchar   *name;
X{
X    FILE   *fp;
X    char    buf[MAXHOSTNAMELEN + 2];
X
X    /*
X     * If the connection is refused, just log the event but do not notify the
X     * client.
X     */
X
X    if (fp = fopen(HOSTS_DENY, "r")) {
X	while (fgets(buf, sizeof(buf), fp)) {
X	    buf[strlen(buf) - 1] = '\0';
X	    if (istail(buf, name)) {
X		syslog(LOG_INFO, "refused connect from %s", name);
X		exit(0);
X	    }
X	}
X	(void) fclose(fp);
X    }
X}
X
X/* istail - is tail a trailing substring of string? */
X
Xint     istail(tail, string)
Xchar   *tail;
Xchar   *string;
X{
X    int     sl = strlen(string);
X    int     tl = strlen(tail);
X    char   *sp;
X    register int t;
X    register int s;
X
X    /* If the string is shorter than the tail it obviously cannot match. */
X
X    if (sl - tl < 0)
X	return (0);
X
X    /*
X     * Do case-insensitive match of the trailing substring of string with the
X     * same length as tail.
X     */
X
X    for (sp = string + sl - tl; *sp; tail++, sp++) {
X	s = *sp;
X	if (isascii(s) && isupper(s))
X	    s = tolower(s);
X	t = *tail;
X	if (isascii(t) && isupper(t))
X	    t = tolower(t);
X	if (s != t)
X	    return (0);
X    }
X    return (1);
X}
X
X#endif
END_OF_hosts_deny.c
if test 1696 -ne `wc -c <hosts_deny.c`; then
    echo shar: \"hosts_deny.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"makefile\"
else
echo shar: Extracting \"makefile\" \(585 characters\)
sed "s/^X//" >makefile <<'END_OF_makefile'
X# If you want to refuse connections from hosts or domains listed in an external
X# file, define the HOSTS_DENY macro to be a valid path name, for example:
X#
X# CFLAGS = -O -DHOSTS_DENY=\"/etc/hosts.deny\"
X#
X# The format of the file is: one host or domain per line; case does not matter.
X
XCFLAGS = -O -DHOSTS_DENY=\"/etc/hosts.deny\"
X
Xall:	tcpd miscd
X
Xtcpd:	tcpd.o hosts_deny.o
X	$(CC) $(CFLAGS) -o $@ tcpd.o hosts_deny.o
X
Xmiscd:	miscd.o hosts_deny.o
X	$(CC) $(CFLAGS) -o $@ miscd.o hosts_deny.o
X
Xshar:	
X	@shar miscd.c tcpd.c hosts_deny.c makefile README
X
Xclean:
X	rm -f tcpd miscd *.o core
END_OF_makefile
if test 585 -ne `wc -c <makefile`; then
    echo shar: \"makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(1041 characters\)
sed "s/^X//" >README <<'END_OF_README'
XWith the following two programs you log can all requests for the SYSTAT,
XFINGER, FTP, TELNET, RLOGIN, RSH and EXEC network services. Connections
Xare logged via the syslog(3) facility.
X
XThis may help you to detect if some cracker tries to get into your system
Xvia internet.
X
XThe programs are tiny front ends that report the remote host name and
Xthen invoke the real network daemon.  Thus, you will not need to change
Xsystems software or configuration files.  Just move the real daemons to
Xanother subdirectory and install the front ends in their original
Xplaces. See the source for details.
X
XThese programs were tested with Ultrix >= 2.2, with SunOS >= 3.4 and
Xsome obscure System V Release 2 port.
X
XThere is a little-tested facility to refuse connections from hosts or
Xdomains listed in an external text file. The format of that file is:
Xone host name or domain name per line; no blanks or empty lines. See
Xthe Makefile for details.
X
X	Wietse Venema,
X	Mathematics and Computing Science,
X	Eindhoven University of Technology,
X	The Netherlands.
END_OF_README
if test 1041 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0