#!/bin/sh
# @(#)pmapp 1.19 (PGP Moose) 99/01/27
# Authorisation script for PGP Moose
# Written by Greg Rose, RoSecure Software, Copyright C 1995.
# Debugging
# On most shells the following statements redirect a log of what
# is happening, AND ALL ERROR MESSAGES, to /tmp/pmdebug. Some shells
# (notably /bin/sh on Ultrix systems) do not do the redirection.
#exec 2>/tmp/pmdebug
#set -x
# Configuration Stuff:
# Default user / newsgroup. If not set, an argument is mandatory.
DEFAULT_NEWSGROUP=qc.test.moderated
# If an Approved: line is to be added, this is what it will say.
# Can be set in the environment.
if [ "x$APP" = "x" ]; then
APP="Authorising user <auth@moderator.site.com>"
fi
# If a From: line is to be added, this is what it will say.
# Can be set in the environment.
if [ "x$FROM" = "x" ]; then
if [ "x$LOGNAME" = "x" ]; then
LOGNAME=`whoami`
fi
FROM="`grep \^$LOGNAME: /etc/passwd |
awk -F: '{print \$5}'` <$LOGNAME@`hostname`>"
fi
# The PGP user and (optional) password. The password will be read
# from the controlling terminal if not specified. If the newsgroup/user
# argument is an email address, it is used instead of the configured
# PMUSER. The following line provides a default password if it is unset.
# This password will NOT be used if an email address is presented as an
# argument.
# Can be set in the environment.
if [ "x$PMUSER" = "x" ]; then
PMUSER=pgpmoose
DEFAULT_PASSWORD=t
fi
# In the case of a user posting, the name desired on the X-Auth
# line might not be the one used by PGP to look up the key.
# In this case, set this variable or import it. By default, though,
# leave it empty and $PMUSER will be used.
# Can be set in the environment.
if [ "x$PGPUSER" = "x" ]; then
PGPUSER=
fi
# Whether or not to fold long lines.
# Can be set in the environment.
if [ "x$FOLDLINES" = "x" ]; then
FOLDLINES=false # allowed values are 'true' or 'false'
fi
# Name of the posting host. Must be fully qualified host.domain.
# Unless your hostname is not fuly qualified, or you want to use
# an alias, you may as well just keep it as it is.
HOSTNAME=`hostname`
# A place to put temp files. These can add up to about twice the
# size of the article being posted.
TMP=/tmp
# If a Message-ID is being generated, this will appear in it.
DATESTAMP=`date +%Y\%m\%d\%H\%M` # NO WHITESPACE OR METACHARACTERS
# Where the active file is on this system, for checking crosspostings
# to multiple moderated groups. The check will be disabled if this is
# left empty (and Approved: lines will be added if needed).
ACTIVE=/usr/local/news/active
# If the article is crossposted to other moderated groups, a warning
# tells you to reorder the newsgroups and submit the article. A copy
# of the article is deposited in this file for you to edit.
SAVED_ARTICLE=$TMP/article
# End of configuration stuff.
# Be neat and tidy.
TF=$TMP/pgpmt$$
trap "stty echo </dev/tty >/dev/tty 2>/dev/null; rm -f $TF.?; exit 1" 1 2 3 15
# Check usage, set arguments
USAGE='echo >&2 "Usage: $0 [newsgroup|user] [article]"; exit 1'
case $# in
1)
if [ ! -r "$1" ]; then
cat >$TF.f
FILE=$TF.f
FILENAME="on standard input"
NEWSGROUP="$1"
elif [ ! "$DEFAULT_NEWSGROUP" ]; then
echo >&2 "$0: No default user or newsgroup set."
eval "$USAGE"
else
FILE="$1"
FILENAME="$1"
NEWSGROUP="$DEFAULT_NEWSGROUP"
PMPASSWORD="$DEFAULT_PASSWORD"
fi
;;
2)
if [ ! -r $2 ]; then
echo >&2 "$0: Can't read $2"
eval "$USAGE"
fi
FILE="$2"
FILENAME="$2"
NEWSGROUP="$1"
;;
0)
if [ ! "$DEFAULT_NEWSGROUP" ]; then
echo >&2 "$0: No default user or newsgroup set."
eval "$USAGE"
fi
cat >$TF.f
FILE=$TF.f
FILENAME="on standard input"
NEWSGROUP="$DEFAULT_NEWSGROUP"
PMPASSWORD="$DEFAULT_PASSWORD"
;;
*)
eval "$USAGE"
;;
esac
case "$NEWSGROUP" in
*@*)
USERFLAG=true
PMUSER=$NEWSGROUP
# PMPASSWORD is left either as imported or null in this case.
;;
*)
USERFLAG=false
PMPASSWORD="${PMPASSWORD-$DEFAULT_PASSWORD}"
;;
esac
# Set the user ID to be given to PGP to look up the key.
if [ "x$PGPUSER" = "x" ]; then
PGPUSER=$PMUSER
fi
# Split the file into headers and body.
# Note long lines in the body may be folded.
sed -n -e '/^ *$/q' -e 'p' $FILE >$TF.h
{ echo ""; sed -e '1,/^ *$/d' $FILE; } >$TF.b
if $FOLDLINES; then
d='..........'
if grep -s "$d$d$d$d$d$d$d$d" $TF.b >/dev/null; then
echo >&2 "$0: warning: lines exceed 80 characters, being folded."
sed -e '/.\{80\}/s/.\{79\}/&\
/g' $TF.b >$TF.l
mv $TF.l $TF.b
fi
fi
if [ ! -s $TF.h ]; then
echo "$0: problem with article $FILENAME; header section empty." >&2
exit 1
fi
# If no From: line, add one.
grep -i -s '^From:' $TF.h >/dev/null ||
echo "From: $FROM" >>$TF.h
# If no Message-ID: line, add one.
grep -i -s '^Message-ID:' $TF.h >/dev/null ||
echo "Message-ID: <pgpmoose.$DATESTAMP.$$@$HOSTNAME>" >>$TF.h
# Check for or Provide a Newsgroups: line if none there,
grep -i -s '^Newsgroups:' $TF.h >/dev/null || \
if $USERFLAG; then
# that is fine
:
else
echo "Newsgroups: $NEWSGROUP" >>$TF.h
fi
# Get the list of newsgroups and check that we are in it!
pmnewsgroups $TF.h >$TF.n
$USERFLAG || grep -i -s "^$NEWSGROUP\$" $TF.n >/dev/null || {
echo >&2 "$0: Newsgroup $NEWSGROUP not present in article $FILENAME"
exit 1
}
# Read a password if none is configured.
if [ ! "$PMPASSWORD" ]; then
stty -echo </dev/tty >/dev/tty 2>/dev/null
echo "Enter PGP passphrase for $PGPUSER:" >/dev/tty
PMPASSWORD=`head -1 </dev/tty`
stty echo </dev/tty >/dev/tty 2>/dev/null
fi
# Compute a signature for the important information.
PGPPASSFD=0
export PGPPASSFD
{
echo "$PMPASSWORD"
cat $TF.h $TF.b | pmcanon
} | pgp -sabf +BATCHMODE=on +SECRING=${SECRING:-secring.pgp} \
-u "$PGPUSER" >$TF.s 2>$TF.e || {
echo >&2 "$0: PGP signing failed. PGP output:"
cat >&2 $TF.e
exit 1
}
# Add an appropriate X-Auth: header
{
echo "X-Auth: PGPMoose V1.1 PGP $NEWSGROUP"
sed -e '1,/^$/d' -e '/END PGP MESSAGE/d' -e 's/^/ /' $TF.s
} >>$TF.h
# Now one of the hardest parts. If there is no Approved: line,
# check for moderated groups that don't have an X-Auth: line
# or an X-Approved-For-Group: line or an X-Approved: line
# [using X-Approved is discouraged -- use X-Approved-For-Group
# instead!] and do something sensible.
$USERFLAG || grep -i -s '^Approved:' $TF.h >/dev/null || {
if [ "$ACTIVE" ]; then
# Cut it down to a list of un-X-Auth:ed groups
egrep -i '^X-(Auth.*|Approved|Approved-For-Group):' $TF.h \
| sed -n -e 's/^.* //p' \
| sort \
| comm -23 $TF.n - \
>$TF.u
# Check if any of these are moderated
if [ -s $TF.u ]; then
badgroup=
for i in `cat $TF.u`; do
qi=`echo "$i" | sed -e 's/\./\\./g' -e 's/\+/\\+/g' `
if grep -i -s "^$qi[ ].*[ ]m$" $ACTIVE >/dev/null; then
echo >&2 "$0: Newsgroup $i is moderated."
badgroup=$i
fi
done
if [ "x$badgroup" != x ]; then
cat >&2 <<END
$0: Other moderated groups appear in newsgroup list.
The Authenticated article is saved in $SAVED_ARTICLE.
The newsgroups line has been reordered
to have it sent to the next moderator in the chain.
In future, you can manually add an Approved: line
before running this approval script if
you are absolutely sure that this is all right.
END
cat >>$TF.h <<END
X-WARNING-TO-MODERATORS: This article has been processed and
accepted using a cryptographic program by the moderator
of $NEWSGROUP. Its content must not be changed or it
will be automatically cancelled. If you don't like the
article or its crossposting, return it to the submitter.
(You can delete this message if you are the last
moderator to see it.)
X-Approved-For-Group: $APP $NEWSGROUP
END
{
# Make a new set of headers. Most of them are all right.
# Regrettable that this takes so much work, but it
# doesn't happen often, right?
# First pass through all but the Newsgroups:.
sed -n -e '/^[Nn][Ee][Ww][Ss][Gg][Rr][Oo][Uu][Pp][Ss]:/q' \
-e 'p' $TF.h
sed -e '1,/^[Nn][Ee][Ww][Ss][Gg][Rr][Oo][Uu][Pp][Ss]:/d' \
$TF.h \
| sed -n -e '/^[^ ]/,$p'
# Add a new Newsgroups: header
othergroups=`fgrep -v $badgroup $TF.n`
othergroupslist=`echo $othergroups | sed 's/ /,/g'`
echo "Newsgroups: $badgroup,$othergroupslist"
cat $TF.b
}
rm -f $TF.?
exit 0
fi
fi
fi
# If not rejected above, we can insert an Approved: header and go for it
echo "Approved: $APP" >>$TF.h
}
# recreate the article on standard output.
cat $TF.h $TF.b
rm -f $TF.?
exit 0
syntax highlighted by Code2HTML, v. 0.9.1