#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 02/06/1992 09:19 UTC by zen@death
# Source directory /big/zen/COPS/test/extra_src
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1307 -rw------- Makefile
#   6411 -rw------- filecheck.c
#   4080 -rwx------ uucp.chk
#   3236 -rw------- uufiles.list
#
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
X
# %Z% %M% %I% %E% %U%
# Makefile for "filecheck" (generated by /local/bin/makemake version 1.00.10)
# Created by chip@chinacat on Tue Jun 25 17:52:12 CDT 1991
X
SHELL = /bin/sh
CC = cc
DEFS = 
COPTS = -O
LOPTS = 
LIBS = 
DEBUG = -g -DDEBUG
LINTFLAGS = -DLINT -DNO_PROTOTYPE
X
TARG = filecheck
OTHERS = 
X
SRCS = filecheck.c
X
OBJS = filecheck.o
X
# Any edits below this line will be lost if "makemake" is rerun!
# Commands may be inserted after the '#%custom' line at the end of this file.
X
CFLAGS = $(COPTS) $(DEFS) # $(DEBUG)
LDFLAGS = $(LOPTS) # $(DEBUG)
X
all:		$(TARG) $(OTHERS)
clean:			; rm -f $(TARG) $(OTHERS) *.o a.out core $(TARG).lint
lint:		$(TARG).lint
X
$(TARG):	$(OBJS)
X		$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
X
$(TARG).lint:	$(TARG)
X		lint $(LINTFLAGS) $(DEFS) $(SRCS) $(LIBS) > $@
X
filecheck.o: filecheck.c
X
make:		;
X		/local/bin/makemake -i -v1.00.10 -aMakefile \
X		    -DSHELL='$(SHELL)' -DCC='$(CC)' -DDEFS='$(DEFS)' \
X		    -DCOPTS='$(COPTS)' -DLOPTS='$(LOPTS)' -DLIBS='$(LIBS)' \
X		    -DDEBUG='$(DEBUG)' -DLINTFLAGS='$(LINTFLAGS)' \
X		    -DOTHERS='$(OTHERS)' $(TARG) $(SRCS)
X
#%custom - commands below this line will be maintained if 'makemake' is rerun
X
SHFILES = uucp.chk filecheck.c uufiles.list Makefile
SHAR = cops-uucp.sh
X
shar : $(SHAR)
X
$(SHAR) : $(SHFILES)
X	shar $(SHFILES) >$@
X
SHAR_EOF
chmod 0600 Makefile ||
echo 'restore of Makefile failed'
Wc_c="`wc -c < 'Makefile'`"
test 1307 -eq "$Wc_c" ||
	echo 'Makefile: original size 1307, current size' "$Wc_c"
fi
# ============= filecheck.c ==============
if test -f 'filecheck.c' -a X"$1" != X"-c"; then
	echo 'x - skipping filecheck.c (File already exists)'
else
echo 'x - extracting filecheck.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'filecheck.c' &&
/*
X * filecheck - check ownership/permissions of a set of files
X *
X * A list of file specifications is read, one specification per line, and
X * check given by the specification is performed.  If the check fails, a
X * message is printed to stdout.  If no failures occur, this program
X * terminates with a zero exit status, otherwize nonzero if any checks failed.
X *
X * A specification is in the following format:
X *
X *		pathname    [!]key-list    uid-list    gid-list    perms
X *
X * pathname		Full pathname of the file to check.
X *
X * key-list		A list of keys, seperated by colons, to which this spec
X *				applies.  The key is specified by the "-k" command line
X *				options, or "all" if none given.  If the given key is
X *				contained in the key-list, then this spec is checked.  If the
X *				given key does not match then this specification is ignored.
X *
X *				For example, if the specification contains a key-list of
X *				"xenix:usg" and we run "filecheck -k xenix", then the spec
X *				will be checked.  If we run "filecheck -k sun" then the spec
X *				will be ignored.
X *
X *				If the given key is "all" (or none is specified since this is
X *				the default), then all specifications are checked.  If the
X *				key-list for a specification contains "all", then it will be
X *				checked regardless of the key given on the command line.
X *
X *				If a "!" appears at the front of the key-list, then a
X *				complaint will be issued if the file specified by "pathname"
X *				does not exist.  Otherwise, if the file does not exist the
X *				specification is ignored.
X *
X * uid-list		A colon delimited list of user names.  If the file is not
X *				owned by a user in this list, then a complaint is generated.
X *				If the value of this field is "-" then the user ownership
X *				check is suppressed.
X *
X * gid-list		A colon delimited list of group names.  If the file is not
X *				owned by a group in this list, then a complaint is generated.
X *				If the value of this field is "-" then the group ownership
X *				check is suppressed.
X *
X * perms		A maximum set of permissions which this file should have.
X *				For example, if the specification says "755" and the
X *				file is actually "555" then it is OK.  However, if the
X *				file is actually "775" then a complaint will be issued
X *				because the group write privilge is enabled.  If the value
X *				of this field is "-" then the permissions check is suppressed.
X */
X
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
X
#define USAGE	"usage: [-k key] [file]\n"
X
#define TRUE	1
#define FALSE	0
X
int check_key();
int check_uid();
int check_gid();
int check_perms();
X
extern struct passwd *getpwnam(), *getpwuid();
extern struct group *getgrnam(), *getgrgid();
long strtol();
X
main(argc, argv)
int argc;
char *argv[];
{
X	char *f_pathname, *f_key, *f_uname, *f_gname, *f_perms;
X	char buf[512], *selkey;
X	int must_exist, status, lineno, i;
X	struct stat sbuf;
X	extern int optind;
X	extern char *optarg;
X
X	selkey = "all";
X	while ((i = getopt(argc, argv, "k:")) != EOF) {
X		switch (i) {
X		case 'k':
X			selkey = optarg;
X			break;
X		default:
X			fprintf(stderr, USAGE, argv[0]);
X			exit(1);
X		}
X	}
X
X	switch (argc-optind) {
X	case 0:
X		break;
X	case 1:
X		if (freopen(argv[optind], "r", stdin) == NULL) {
X			perror(argv[optind]);
X			exit(1);
X		}
X		break;
X	default:
X		fprintf(stderr, USAGE, argv[0]);
X		exit(1);
X	}
X
X	lineno = 0;
X	status = 0;
X	while (++lineno, fgets(buf, sizeof(buf), stdin) != NULL) {
X
X		/*
X		 * Break up the line.  Skip comments and blank lines.
X		 */
X		if ((f_pathname = strtok(buf, " \t\n")) == NULL || *f_pathname == '#' )
X			continue;
X		if (
X			(f_key = strtok((char *)NULL, " \t\n")) == NULL ||
X			(f_uname = strtok((char *)NULL, " \t\n")) == NULL ||
X			(f_gname = strtok((char *)NULL, " \t\n")) == NULL ||
X			(f_perms = strtok((char *)NULL, " \t\n")) == NULL ||
X			strtok((char *)NULL, " \t\n") != NULL
X		) {
X			printf("%s(%d): bad line ignored\n", f_pathname, lineno);
X			status = 1;
X			continue;
X		}
X
X		/*
X		 * See if we want to insist that this file exists.
X		 */
X		must_exist = (*f_key == '!');
X		if (must_exist)
X			++f_key;
X
X		/*
X		 * See if we want to do this entry.
X		 */
X		if (!check_key(selkey, f_key))
X			continue;
X
X		/*
X		 * Get info on this file.
X		 */
X		if (stat(f_pathname, &sbuf) != 0) {
X			if (must_exist) {
X				fprintf(stderr, "%s: could not access file\n", f_pathname);
X				status = 1;
X			}
X			continue;
X		}
X
X		/*
X		 * Perform checks.
X		 */
X		if (!check_uid(f_pathname, f_uname, &sbuf))
X			status = 1;
X		if (!check_gid(f_pathname, f_gname, &sbuf))
X			status = 1;
X		if (!check_perms(f_pathname, f_perms, &sbuf))
X			status = 1;
X
X	}
X
X	exit(status);
X	/*NOTREACHED*/
}
X
X
int check_key(key, klist)
char *key, *klist;
{
X	char *k;
X	if (key == NULL || klist == NULL || strcmp("all", key) == 0)
X		return TRUE;
X	while ((k = strtok(klist, ": \t\n")) != NULL) {
X		if (strcmp(k, key) == 0 || strcmp(k, "all") == 0)
X			return TRUE;
X		klist = NULL;
X	}
X	return FALSE;
}
X
X
int check_uid(fname, ulist, s)
char *fname;
char *ulist;
struct stat *s;
{
X	struct passwd *pw;
X	char buf[256];
X	char *up, *u;
X
X	if (strcmp(ulist, "-") == 0)
X		return TRUE;
X	up = strcpy(buf, ulist);
X	while ((u = strtok(up, ": \t\n")) != NULL) {
X		if ((pw = getpwnam(u)) != NULL && s->st_uid == pw->pw_uid)
X			return TRUE;
X		up = NULL;
X	}
X	pw = getpwuid(s->st_uid);
X	printf("%s: uid is %s(%d), expected %s\n",
X		fname, (pw == NULL ? "<unknown>" : pw->pw_name), s->st_uid, ulist);
X	return FALSE;
}
X
X
int check_gid(fname, glist, s)
char *fname;
char *glist;
struct stat *s;
{
X	struct group *gr;
X	char buf[256];
X	char *gp, *g;
X
X	if (strcmp(glist, "-") == 0)
X		return TRUE;
X	gp = strcpy(buf, glist);
X	while ((g = strtok(gp, ": \t\n")) != NULL) {
X		if ((gr = getgrnam(g)) != NULL && s->st_gid == gr->gr_gid)
X			return TRUE;
X		gp = NULL;
X	}
X	gr = getgrgid(s->st_gid);
X	printf("%s: gid is %s(%d), expected %s\n",
X		fname, (gr == NULL ? "<unknown>" : gr->gr_name), s->st_gid, glist);
X	return FALSE;
}
X
X
int check_perms(fname, perms, s)
char *fname;
char *perms;
struct stat *s;
{
X	int perms_want, perms_act;
X
X	if (strcmp(perms, "-") == 0)
X		return TRUE;
X	perms_want = (int) strtol(perms, (char *)NULL, 8);
X	perms_act = s->st_mode & 07777;
X	if ((perms_act & perms_want) == perms_act)
X		return TRUE;
X
X	printf("%s: permissions are %04o, should be at least %04o\n",
X		fname, perms_act, perms_want);
X	return FALSE;
}
X
SHAR_EOF
chmod 0600 filecheck.c ||
echo 'restore of filecheck.c failed'
Wc_c="`wc -c < 'filecheck.c'`"
test 6411 -eq "$Wc_c" ||
	echo 'filecheck.c: original size 6411, current size' "$Wc_c"
fi
# ============= uucp.chk ==============
if test -f 'uucp.chk' -a X"$1" != X"-c"; then
	echo 'x - skipping uucp.chk (File already exists)'
else
echo 'x - extracting uucp.chk (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'uucp.chk' &&
:
X
#
# site-specific customizations
#
# OK_DIRS	Colon-delimited list of directories uucp accounts are
#		allowed to access.
#
# OK_CMDS	Colon-delimited list of commands uucp accounts are allowed
#		to execute.
#
X
OK_DIRS="/tmp:/usr/tmp:/usr/spool/uucppublic"
OK_CMDS="rmail:rnews:lp:who:uucp:rsmtp:rcsmtp"
X
# if [ -f /usr/lib/uucp/Systems ] ; then
if [ -f /etc/uucp/Systems ] ; then
X	uutype=bnu
elif [ -f /usr/lib/uucp/L.sys ] ; then
X	uutype=v2
else
X	echo "$0: cannot figure out type of uucp system" 1>&2
X	exit 1
fi
X
#
# If "uucheck" is available then run it.
#
if [ -x /usr/lib/uucp/uucheck ] ; then
X	/usr/lib/uucp/uucheck
fi
X
#
# Check the file permissions.
#
./filecheck -k $uutype ./uufiles.list
X
#
# Various checks specific to BNU uucp.
#
if [ $uutype = bnu ] ; then
X
X	#
X	# "remote.unknown" must be executable to prevent unknown machines
X	# from logging in.
X	#
X	if [ ! -x /usr/lib/uucp/remote.unknown ] ; then
X		echo "warning - no executable 'remote.unknown' - unknown machine logins allowed"
X	fi
X
X	#
X	# ".Admin/foreign" must be writable for login attempts by unknown
X	# machines to be logged.
X	#
X	cd /usr/spool/uucp/.Admin
X	if [ -f foreign ] ; then
X		set X `ls -l foreign`
X		perms="$2"
X		owner="$4"
X		if [ "$owner" != "uucp" ] ; then
X			echo "warning - .Admin/foreign is not owned by uucp"
X		fi
X		case "$perms" in
X		-?w???????)
X			;;
X		*)
X			echo "warning - .Admin/foreign is not writable by uucp"
X			;;
X		esac
X		case "$perms" in
X		-??????r??)
X			echo "warning - .Admin/foreign is readable by world"
X			;;
X		esac
X	else
X		su uucp -c 'echo testing > foreign' 2>/dev/null
X		if [ -f foreign ] ; then
X			rm foreign
X		else
X			echo "warning - .Admin/foreign cannot be created by uucp"
X		fi
X	fi
fi
X
#
# Check access permissions granted (BNU).
#
if [ -f /usr/lib/uucp/Permissions ] ; then
X	awk '
X
X	$1 ~ /^#/ { rec = "" ; next }
X
X	{
X		for ( i = 1 ; i <= NF ; ++i ) {
X			if ( substr($i,1,8) == "MACHINE=" ) {
X				rec = rec " " $i
X				continue
X			}
X			if ( substr($i,1,8) == "LOGNAME=" ) {
X				rec = rec " " $i
X				continue
X			}
X			if ( substr($i,1,5) == "READ=" ) {
X				mode = "read"
X				n = split(substr($i,6,9999), x, ":")
X				n_ok = split(OK_DIRS, ok, ":")
X			} else if ( substr($i,1,6) == "WRITE=" ) {
X				mode = "write"
X				n = split(substr($i,7,9999), x, ":")
X				n_ok = split(OK_DIRS, ok, ":")
X			} else if ( substr($i,1,9) == "COMMANDS=" ) {
X				mode = "execute"
X				n = split(substr($i,10,9999), x, ":")
X				n_ok = split(OK_CMDS, ok, ":")
X			} else {
X				continue
X			}
X			for ( j = 1 ; j <= n ; ++j ) {
X				for ( k = 1 ; k <= n_ok && x[j] != ok[k] ; ++k )
X					;
X				if ( k > n_ok )
X					printf("warning - Permissions grants %s access to \"%s\" for%s\n", mode, x[j], rec)
X			}
X		}
X	}
X
X	$NF != "\\" { rec = "" }
X
X	' OK_DIRS="$OK_DIRS" OK_CMDS="$OK_CMDS" /usr/lib/uucp/Permissions
fi
X
#
# Check access permissions granted (V2).
#
#	Important note - there are so many freaking variants of how to
#	obtain default username/machine info from USERFILE, that I just
#	punted here.  Unfortunately, USERFILE is a gawdawful wretched
#	mess (the best reason for BNU existing IMHO), so one could argue
#	that these checks are the most important things this could do.
#
if [ -f /usr/lib/uucp/USERFILE ] ; then
X
X	awk '
X
X	BEGIN {
X		num_ok_dirs = split(OK_DIRS, ok_dir, ":")
X	}
X
X	$1 ~ /^#/ { rec = "" ; next }
X
X	{
X		if ( $2 == "c" )				# skip callback flag
X			j = 2
X		else
X			j = 1
X		while ( ++j <= NF ) {
X			for ( k = 1 ; k <= num_ok_dirs && ok_dir[k] != $j ; ++k )
X				;
X			if ( k > num_ok_dirs )
X				printf("warning - USERFILE grants access to \"%s\" for %s\n", $j, $1)
X		}
X	}
X
X	' OK_DIRS="$OK_DIRS" /usr/lib/uucp/USERFILE
X
fi
X
#
# Check execute permissions granted (V2).
#
cd /usr/lib/uucp
for file in L.cmds L-cmds uuxqtcmds ; do
X    if [ -f $file ] ; then
X	    awk '
X	    BEGIN { num_ok_cmds = split(OK_CMDS, ok_cmd, ":") }
X	    $1 ~ /^PATH=/ { next }
X	    {
X		for ( i = 1 ; i <= num_ok_cmds && ok_cmd[i] != $0 ; ++i )
X			;
X		if ( i > num_ok_cmds )
X		    printf("warning - %s grants execute access to \"%s\"\n", FILENAME, $0)
X	    }
X	    ' OK_CMDS="$OK_CMDS" $file
X    fi
done
X
Xexit 0
X
SHAR_EOF
chmod 0700 uucp.chk ||
echo 'restore of uucp.chk failed'
Wc_c="`wc -c < 'uucp.chk'`"
test 4080 -eq "$Wc_c" ||
	echo 'uucp.chk: original size 4080, current size' "$Wc_c"
fi
# ============= uufiles.list ==============
if test -f 'uufiles.list' -a X"$1" != X"-c"; then
	echo 'x - skipping uufiles.list (File already exists)'
else
echo 'x - extracting uufiles.list (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'uufiles.list' &&
X
#
# file				key	user	group		perms
#
X
/usr/bin/uucp			!all	uucp	uucp:daemon	4111
/usr/bin/cu			!all	uucp	uucp:daemon	4111
/usr/bin/uudecode		all	-	-		 755
/usr/bin/uuencode		all	-	-		 755
/usr/bin/uuname			!all	uucp	uucp:daemon	4111
/usr/bin/uusend			all	-	-		 755
/usr/bin/uustat			!all	uucp	uucp:daemon	4111
/usr/bin/uuto			all	-	-		 755
/usr/bin/uux			!all	uucp	uucp:daemon	4111
X
/usr/lib/uucp			!all	uucp	uucp:daemon	 755
/usr/lib/uucp/.XQTDIR		!v2	uucp	uucp:daemon	 555
/usr/lib/uucp/Devices		!bnu	uucp	uucp:daemon	 640
/usr/lib/uucp/Dialcodes		!bnu	uucp	uucp:daemon	 640
/usr/lib/uucp/Dialers		!bnu	uucp	uucp:daemon	 640
/usr/lib/uucp/FWDFILE		v2	uucp	uucp:daemon	 640
/usr/lib/uucp/L-cmds		v2	uucp	uucp:daemon	 640
/usr/lib/uucp/L-devices		!v2	uucp	uucp:daemon	 640
/usr/lib/uucp/L-dialcodes	!v2	uucp	uucp:daemon	 640
/usr/lib/uucp/L.cmds		v2	uucp	uucp:daemon	 640
/usr/lib/uucp/L.sys		!v2	uucp	uucp:daemon	 640
/usr/lib/uucp/L_stat		v2	uucp	uucp:daemon	 644
/usr/lib/uucp/L_sub		v2	uucp	uucp:daemon	 644
/usr/lib/uucp/Maxuuscheds	!bnu	uucp	uucp:daemon	 644
/usr/lib/uucp/Maxuuxqts		!bnu	uucp	uucp:daemon	 644
/usr/lib/uucp/ORIGFILE		v2	uucp	uucp:daemon	 640
/usr/lib/uucp/Permissions	!bnu	uucp	uucp:daemon	 640
/usr/lib/uucp/Poll		!bnu	uucp	uucp:daemon	 644
/usr/lib/uucp/SEQF		v2	uucp	uucp:daemon	 640
/usr/lib/uucp/SQFILE		v2	uucp	uucp:daemon	 640
/usr/lib/uucp/Systems		!bnu	uucp	uucp:daemon	 640
/usr/lib/uucp/USERFILE		!v2	uucp	uucp:daemon	 640
/usr/lib/uucp/remote.unknown	!bnu	uucp	uucp:daemon	 755
/usr/lib/uucp/uucheck		all	uucp	uucp:daemon	 110
/usr/lib/uucp/uucico		!all	uucp	uucp:daemon	4111
/usr/lib/uucp/uuclean		all	uucp	uucp:daemon	4110
/usr/lib/uucp/uucleanup		bnu	uucp	uucp:daemon	 110
/usr/lib/uucp/uudemon.admin	bnu	uucp	uucp:daemon	 555
/usr/lib/uucp/uudemon.clean	bnu	uucp	uucp:daemon	 555
/usr/lib/uucp/uudemon.day	bnu	uucp	uucp:daemon	 500
/usr/lib/uucp/uudemon.hour	bnu	uucp	uucp:daemon	 555
/usr/lib/uucp/uudemon.hr	v2	uucp	uucp:daemon	 500
/usr/lib/uucp/uudemon.poll	bnu	uucp	uucp:daemon	 555
/usr/lib/uucp/uudemon.wk	v2	uucp	uucp:daemon	 500
/usr/lib/uucp/uulog		all	uucp	uucp:daemon	 555
/usr/lib/uucp/uupick		all	uucp	uucp:daemon	 555
/usr/lib/uucp/uusched		!bnu	uucp	uucp:daemon	4111
/usr/lib/uucp/uusub		all	uucp	uucp:daemon	 755
/usr/lib/uucp/uuto		all	uucp	uucp:daemon	 555
/usr/lib/uucp/uutry		all	uucp	uucp:daemon	 755
/usr/lib/uucp/uuxqt		!all	uucp	uucp:daemon	4111
/usr/lib/uucp/uuxqtcmds		v2	uucp	uucp:daemon	 640
X
/usr/spool/uucp			!all	uucp	uucp:daemon	 775
/usr/spool/uucp/.Admin		!bnu	uucp	uucp:daemon	 775
/usr/spool/uucp/.Admin/audit	bnu	uucp	uucp:daemon	 660
/usr/spool/uucp/.Admin/errors	bnu	uucp	uucp:daemon	 660
/usr/spool/uucp/.Admin/foreign	bnu	uucp	uucp:daemon	 660
/usr/spool/uucp/.Corrupt	!bnu	uucp	uucp:daemon	 775
/usr/spool/uucp/.Log		!bnu	uucp	uucp:daemon	 775
/usr/spool/uucp/.Old		!bnu	uucp	uucp:daemon	 775
/usr/spool/uucp/.Sequence	!bnu	uucp	uucp:daemon	 775
/usr/spool/uucp/.Status		!bnu	uucp	uucp:daemon	 775
/usr/spool/uucp/.Workspace	!bnu	uucp	uucp:daemon	 775
/usr/spool/uucp/.Xqtdir		!bnu	uucp	uucp:daemon	 775
/usr/spool/uucp/ERRLOG		v2	uucp	uucp:daemon	 644
/usr/spool/uucp/LOGFILE		v2	uucp	uucp:daemon	 664
/usr/spool/uucp/SYSLOG		v2	uucp	uucp:daemon	 664
X
SHAR_EOF
chmod 0600 uufiles.list ||
echo 'restore of uufiles.list failed'
Wc_c="`wc -c < 'uufiles.list'`"
test 3236 -eq "$Wc_c" ||
	echo 'uufiles.list: original size 3236, current size' "$Wc_c"
fi
exit 0
