#! /bin/sh # checkgroups - check active file for missing or extra newsgroups or groups # with incorrect moderation status, and update the newsgroups file. # stdin must a checkgroups news article # also subject to $NEWSCTL/controlperm: four fields per line, first # a newsgroup pattern, second an author name (or "any"), third a set of # operations ("n" newgroup, "r" rmgroup, "c" checkgroups), and fourth a set of # flags ("p" do it iff poster's identity is pgpverified, # "y" do it, "n" don't, "q" don't report at all, "v" include # entire control message in report) (default "yv"); the "p" and "n" flags may # be followed by the ID of the person permitted to pgpverify; # the pgpverify program (not supplied) is presumed to be in $NEWSBIN # =()<. ${NEWSCONFIG-@@}>()= . ${NEWSCONFIG-/usr/local/libexec/cnews/config} PATH=$NEWSCTL/bin:$NEWSBIN:$NEWSPATH ; export PATH desc=/tmp/cg$$d hiers=/tmp/cg$$h canact=/tmp/cg$$a newact=/tmp/cg$$n diffs=/tmp/cg$$df actgrps=/tmp/cg$$ag newgrps=/tmp/cg$$ng samegrps=/tmp/cg$$sg addgrps=/tmp/cg$$ad remgrps=/tmp/cg$$rm sameact=/tmp/cg$$sa samenew=/tmp/cg$$sn modchng=/tmp/cg$$mc posting=/tmp/cg$$ps hdr=/tmp/cg$$hd umask $NEWSUMASK if [ "$1" = "-f" ] then force="force" fi # get the full article, and its header, into files for inspection trap 'rm -f /tmp/cg$$* ; trap 0 ; exit' 0 1 2 15 cat > $posting canonhdr $posting >$hdr # who sent it? author="`egrep '^From:' $hdr | sed 's/^[^:]*: *//' `" authorid="`echo \"$author\" | sed '/.*<\(.*\)>.*/s//\1/ /\([^ ][^ ]*\) *(.*).*/s//\1/'`" # was it approved? case "`egrep '^Approved:' $hdr`" in '') reject=${reject-'no Approved header'} ;; esac # was it pgpsigned? case "`egrep -i '^X-PGP-Sig: ' $hdr`" in ?*) if test -x $NEWSBIN/pgpverify then signer=`pgpverify < $posting` pgpresult=$? case "$pgpresult" in 0) ;; # Authentication succeeded 3) reject=${reject-'authentication failed'} ;; *) ;; esac else pgpresult=1 fi ;; *) pgpresult=1 ;; esac # Behead checkgroups article & ignore headers and initial lines that don't # fit the syntax (see son-of-1036). This is permissive insofar as introductory # text and signatures should not really occur in a checkgroups message. But # if they did and were allowed through severe corruption of the newsgroups # file could ensue. As a byproduct, tale's periodic "Checkgroups message # (with/without INET groups)" may be piped directly into this script. # Also, spaces rather than tabs after the newsgroup name are permitted, but # some white space is required. # ??? does this raise a problem with Bitnet ??? # "Invalidations" (e.g. !mod) are recognised but not acted upon. # There is no provision for "encoded words" (see son-of-1036). ngletgit='a-z_0-9' ngalpha='-_+a-z0-9' if test `awk " BEGIN {state = 1} /^![$ngletgit][$ngalpha]*(,[$ngletgit][$ngalpha]*)*$/ \ {if (state == 1) {state = 2; next} else {state = 3; exit} } /^[$ngletgit][$ngalpha]*(\.[$ngletgit][$ngalpha]*)+[ ]+[ -_a-~]*$/ \ {state = 2; print > \"$desc\"; next} /^$/ {next} /^-- $/ {exit} {if (state == 2) {state = 3; exit} } END {print state}" $posting ` \ -ne 2 then reject=${reject-'ill-formed checkgroups message - edit before resubmitting'} fi # generate list of hierarchies affected sed 's/\..*//' $desc | sort -u >$hiers hierlist="`cat $hiers`" # message is assumed authoritative for these hierpat="` echo $hierlist | tr ' ' , `" # one more time, with commas # consult control file, if present perms=$NEWSCTL/controlperm action=nv if test -r $perms then newaction=`gngp -ar $hierpat $perms | awk '$3 ~ /c/' | awk '$2 == "any" || "'"$authorid"'" ~ $2 { printf "%s %s\n",$4,$5 }' | sed -n 1p` case "$newaction" in ?*) action=$newaction ;; esac fi # $action is of the form "y|n|p[q|v] [authorized ID]" case "$action" in n*) reject=${reject-'controlperm file denies permission'} ;; # use $pgpresult computed earlier if controlperm file requires it p*) case "$pgpresult" in 0) authorized=`echo "$action" | awk '{print $2}'` case "$authorized" in "$signer") ;; # Authentication succeeded '') ;; # Authentication succeeded ?*) reject=${reject-"unauthorized signature by '$signer' in newgroup message"} signer='';; esac ;; 1) reject=${reject-'newgroup message not signed'} ;; 2) reject=${reject-'unrecognized signature in newgroup message'} ;; 3) reject=${reject-'authentication failed'} ;; *) reject=${reject-'unknown pgpverify error'} ;; esac ;; esac # the verdict case "$force$reject" in force*) ;; #allow it because it was forced ?*) case "$action" in *q*) ;; *) ( echo "checkgroups: \`$author' tried" echo "to checkgroups on $NEWSCTL/newsgroups." echo " $reject" case "$signer" in ?*) echo "But valid signature from '$signer' was given" ;; esac echo "Use $NEWSBIN/ctl/checkgroups -f" echo "to do it by hand, if appropriate." case "$action" in *v*) echo '===' cat $posting echo '===' ;; esac ) | report 'rejected checkgroups' ;; esac exit ;; esac # do the job # backup newsgroups before updating it if test -r $NEWSCTL/newsgroups then cp $NEWSCTL/newsgroups $NEWSCTL/newsgroups.bac || exit 1 else >$NEWSCTL/newsgroups.bac fi # toss out old newsgroups rubbish (gngp -av "$hierpat" $NEWSCTL/newsgroups.bac # add new newsgroups rubbish cat $desc) >$NEWSCTL/newsgroups # canonicalise active file & select interesting hierarchies awk '{ modstat = $4 if (modstat != "y" && modstat != "m") modstat = "y" print $1, modstat }' $NEWSCTL/active | gngp -a "$hierpat" | sort >$canact # canonicalise body into an active-file-like thing awk ' /Moderated/ { print $1, "m" } # TODO: " (Moderated)$"? as per B 2.11.19 !/Moderated/ { print $1, "y" } ' $desc | sort >$newact # what's different? first, what groups have vanished or appeared? sed 's/ .*//' $canact >$actgrps sed 's/ .*//' $newact >$newgrps comm -12 $actgrps $newgrps >$samegrps comm -23 $actgrps $newgrps >$remgrps comm -13 $actgrps $newgrps >$addgrps if test -s $remgrps; then echo echo 'obsolete groups:' cat $remgrps fi >$diffs if test -s $addgrps; then echo echo 'new groups:' join $addgrps $newact fi >>$diffs # next, what surviving groups have changed moderation status? join $samegrps $canact >$sameact join $samegrps $newact >$samenew comm -13 $sameact $samenew >$modchng if test -s $modchng; then echo echo 'groups needing moderation status changed to that shown:' cat $modchng fi >>$diffs if test -s $diffs; then (echo "Subject: possible active file problems"; echo; echo "$author issued a checkgroups control message." case "$signer" in ?*) echo "A valid signature from '$signer' was given." ;; esac echo "If you believe this checkgroups control message for hierarchies" echo "\`$hierpat', the following differences may reflect groups" echo "that should be added, deleted, or have their moderation" echo "status(es) changed:" cat $diffs) | report 'checkgroups output' fi exit 0 ## end of new one