*** /usr/local/src/cnews/ctl/newgroup	Wed Feb 26 14:45:44 1997
--- newgroup.pgp	Fri Mar 21 20:08:32 1997
***************
*** 3,11 ****
  #	subject to our sys file group pattern
  # 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), and fourth a set of
! # flags ("y" do it, "n" don't, "q" don't report at all, "v" include
! # entire control message in report) (default "yv").
  
  # =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  . ${NEWSCONFIG-/var/news/lib/bin/config}
--- 3,14 ----
  #	subject to our sys file group pattern
  # 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>@}>()=
  . ${NEWSCONFIG-/var/news/lib/bin/config}
***************
*** 35,40 ****
--- 38,58 ----
  '')	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
+ 
  # verify acceptable name syntax
  verdict="`echo \"$g\" | awk -f $NEWSBIN/namecheck.awk`"
  if test " $verdict" != " "
***************
*** 79,92 ****
  if test -r $perms
  then
  	newaction=`gngp -a -r "$g" $perms | awk '$3 ~ /n/' |
! 		awk '$2 == "any" || $2 == "'"$authorid"'" { print $4 }' |
  		sed -n 1p`
  	case "$newaction" in
  	?*)	action=$newaction	;;
  	esac
  fi
  case "$action" in
! *n*)	reject=${reject-'controlperm file denies permission'}	;;
  esac
  
  # check that my sys file allows this group
--- 97,128 ----
  if test -r $perms
  then
  	newaction=`gngp -a -r "$g" $perms | awk '$3 ~ /n/' |
! 		awk '$2 == "any" || $2 == "'"$authorid"'" { 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
  
  # check that my sys file allows this group
***************
*** 120,125 ****
--- 156,165 ----
  			esac
  			echo "Request was refused:"
  			echo "	$reject"
+ 			case "$signer" in
+ 			?*)	echo "But valid signature from '$signer' was given" ;;
+ 			'')	;;
+ 			esac
  			case "$action" in
  			*v*)	echo '==='
  				cat $posting
***************
*** 197,202 ****
--- 237,246 ----
  			*)	p=unmoderated	;;
  			esac
  			echo "set \`$g' to $p."	;;
+ 		esac
+ 		case "$signer" in
+ 		?*)	echo "A valid signature from '$signer' was given" ;;
+ 		'')	;;
  		esac
  		case "$fail" in
  		'')	echo "This was done."	;;
*** /usr/local/src/cnews/ctl/rmgroup	Wed Feb 26 14:45:49 1997
--- rmgroup	Fri Mar 21 20:22:48 1997
***************
*** 2,10 ****
  # rmgroup group - delete group
  # 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), and fourth a set of
! # flags ("y" do it, "n" don't, "q" don't report at all, "v" include
! # entire control message in report) (default "nv").
  
  # =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  . ${NEWSCONFIG-/var/news/lib/bin/config}
--- 2,13 ----
  # rmgroup group - delete group
  # 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>@}>()=
  . ${NEWSCONFIG-/var/news/lib/bin/config}
***************
*** 32,37 ****
--- 35,55 ----
  '')	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
+ 
  # do we have the group?
  getg="\$1 == \"$g\" { print }"
  got="`awk \"$getg\" $NEWSCTL/active`"
***************
*** 45,58 ****
  if test -r $perms
  then
  	newaction=`gngp -a -r "$g" $perms | awk '$3 ~ /r/' |
! 		awk '$2 == "any" || $2 == "'"$authorid"'" { print $4 }' |
  		sed -n 1p`
  	case "$newaction" in
  	?*)	action=$newaction	;;
  	esac
  fi
  case "$action" in
! *n*)	reject=${reject-'controlperm file denies permission'}	;;
  esac
  
  # the verdict
--- 63,108 ----
  if test -r $perms
  then
  	newaction=`gngp -a -r "$g" $perms | awk '$3 ~ /r/' |
! 		awk '$2 == "any" || $2 == "'"$authorid"'" { 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
! # X-PGP-Sig is not required, but if present had better be correct 
! n*)	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 rmgroup message"}
! 	   		signer='';;
! 	   esac ;;
!  	1)  ;; # Authentication not required
!  	2) reject=${reject-"unrecognized signature by '$signer' in rmgroup message"} ;;
!  	3) reject=${reject-'authentication failed'} ;;
!  	*) reject=${reject-'unknown pgpverify error'} ;;
!  	esac
!  	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 rmgroup message'}
! 	   		signer='';;
! 	   esac ;;
!  	1) reject=${reject-'rmgroup message not signed'} ;;
!  	2) reject=${reject-'unrecognized signature in rmgroup message'} ;;
!  	3) reject=${reject-'authentication failed'} ;;
!  	*) reject=${reject-'unknown pgpverify error'} ;;
!  	esac
!  	;;
  esac
  
  # the verdict
***************
*** 64,69 ****
--- 114,123 ----
  			echo "to remove newsgroup \`$g'."
  			echo "Request was refused:"
  			echo "	$reject"
+ 			case "$signer" in
+ 			?*)	echo "But valid signature from '$signer' was given" ;;
+ 			'')	;;
+ 			esac
  			echo "Use delgroup to do it by hand, if appropriate."
  			case "$action" in
  			*v*)	echo '==='
***************
*** 102,107 ****
--- 156,165 ----
  *)	(
  		echo "$author said to"
  		echo "remove \`$g'."
+ 		case "$signer" in
+ 		?*)	echo "A valid signature from '$signer' was given" ;;
+ 		'')	;;
+ 		esac
  		case "$fail" in
  		'')	echo "This was done."	;;
  		*)	echo "This failed:"
*** /usr/local/src/cnews/ctl/checkgroups	Wed Feb 26 14:45:36 1997
--- checkgroups	Fri Mar 21 21:21:51 1997
***************
*** 2,7 ****
--- 2,15 ----
  # 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>@}>()=
  . ${NEWSCONFIG-/var/news/lib/bin/config}
***************
*** 20,30 ****
  sameact=/tmp/cg$$sa
  samenew=/tmp/cg$$sn
  modchng=/tmp/cg$$mc
  
  umask $NEWSUMASK
  trap 'rm -f /tmp/cg$$* ; trap 0 ; exit' 0 1 2 15
  
! # behead stdin (checkgroups article) & ignore lines that don't fit the syntax
  # (should just be able to reject tabless lines, but Bitnet buggers that).
  # ignore signatures and initial !mod lines.
  ngalpha='-_+a-zA-Z0-9'
--- 28,73 ----
  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 lines that don't fit the syntax
  # (should just be able to reject tabless lines, but Bitnet buggers that).
  # ignore signatures and initial !mod lines.
  ngalpha='-_+a-zA-Z0-9'
***************
*** 31,41 ****
  sed -n -e '1,/^$/d' -e '1{/^!mod$/d;}' -e '/^-- $/,$d' \
  	-e "/^[$ngalpha][	 ][	 ]*/p" \
  	-e "/^[$ngalpha][$ngalpha.]*[$ngalpha][	 ][	 ]*/p" \
! 	>$desc
  
  # generate list of hierarchies affected
  sed 's/\..*//' $desc | sort -u >$hiers
  
  # backup newsgroups before updating it
  if test -r $NEWSCTL/newsgroups
  then
--- 74,147 ----
  sed -n -e '1,/^$/d' -e '1{/^!mod$/d;}' -e '/^-- $/,$d' \
  	-e "/^[$ngalpha][	 ][	 ]*/p" \
  	-e "/^[$ngalpha][$ngalpha.]*[$ngalpha][	 ][	 ]*/p" \
! 	$posting >$desc
  
  # 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" || $2 =="'"$authorid"'" { 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
***************
*** 44,51 ****
  	>$NEWSCTL/newsgroups.bac
  fi
  # toss out old newsgroups rubbish
- hierlist="`cat $hiers`"		# message is assumed authoritative for these
- hierpat="` echo $hierlist | tr ' ' , `"	# one more time, with commas
  (gngp -av "$hierpat" $NEWSCTL/newsgroups.bac
   # add new newsgroups rubbish
   cat $desc) >$NEWSCTL/newsgroups
--- 150,155 ----
***************
*** 93,98 ****
--- 197,206 ----
  
  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"
