Subject: INN poison and REMEMBER_TRASH patch
From: Russ Allbery <rra@stanford.edu>
Almost-A-Date: 1998/03/21
Newsgroups: net.config

I posted this here once before, but now it's been tested and I believe I
can recommend it as stable.  This is a merger of Panix's poison patch and
Odd Einar's REMEMBER_TRASH patch.  It adds the @pattern syntax for the
hosts.nntp file, so that you can reject U2 postings from unsound peers
with:

        peer.name::*,@net.*

entries in hosts.nntp.  Posts rejected due to @ or ! entries in hosts.nntp
do not get added to the history file even if REMEMBER_TRASH is set, so if
you later get the same article via a sound path, you'll accept it.

Note:  There have been reports that Panix's patch, on which this is based,
interprets the syntax:

        peer.name::@net.*

as rejecting all articles.  Be sure to include the initial * in there.

This is a patch against INN 1.7.2-insync-1.1d.

--- inn-1.7.2.orig/innd/art.c.orig	Tue Dec 16 21:33:16 1997
+++ inn-1.7.2/innd/art.c	Sun Jan  4 17:40:15 1998
@@ -1799,6 +1799,7 @@
     ARTDATA		Data;
     BOOL		Approved;
     BOOL		Accepted;
+    BOOL		DontRemember;
     BOOL		LikeNewgroup;
     BOOL		ToGroup;
     BOOL		GroupMissing;
@@ -1812,6 +1813,7 @@
     char		ControlWord[SMBUF];
     int			ControlHeader;
     int			oerrno;
+    int 		canpost;
 #if defined(DO_PERL)
     char		*perlrc;
 #endif /* DO_PERL */
@@ -2098,8 +2100,20 @@
     ngptr = GroupPointers;
     j = 0;
     for (GroupMissing = Accepted = FALSE; (p = *groups) != NULL; groups++) {
-	if (!RCcanpost(cp, p))
+        canpost = RCcanpost(cp, p);
+	if (!canpost) {
+	    DontRemember = TRUE;
 	    continue;
+	}
+	else if (canpost < 0) {
+	    (void)sprintf(buff, "%d Won't accept posts in \"%s\"",
+	        NNTP_REJECTIT_VAL, p);
+	    ARTlog(&Data, ART_REJECT, buff);
+	    if (distributions)
+		DISPOSE(distributions);
+	    ARTreject(buff, article);
+	    return buff;
+	}
 	if ((ngp = NGfind(p)) == NULL) {
 	    GroupMissing = TRUE;
 	    if (LikeNewgroup && Approved) {
@@ -2207,7 +2221,7 @@
 	    ARTlog(&Data, ART_REJECT, buff);
 #if	defined(DONT_WANT_TRASH)
 #if	defined(DO_REMEMBER_TRASH)
-	    if (Mode == OMrunning && !HISwrite(&Data, ""))
+	    if (!DontRemember && Mode == OMrunning && !HISwrite(&Data, ""))
 		syslog(L_ERROR, "%s cant write history %s %m",
                        LogName, Data.MessageID);
 #endif	/* defined(DO_REMEMBER_TRASH) */
@@ -2223,7 +2237,7 @@
 	     * you explicitly excluded in your active file. */
 	    if (!GroupMissing) {
 #if	defined(DO_REMEMBER_TRASH)
-                if (Mode == OMrunning && !HISwrite(&Data, ""))
+                if (!DontRemember && Mode == OMrunning && !HISwrite(&Data, ""))
                     syslog(L_ERROR, "%s cant write history %s %m",
                            LogName, Data.MessageID);
 #endif	/* defined(DO_REMEMBER_TRASH) */
--- inn-1.7.2.orig/innd/innd.h.orig	Fri Dec 12 09:26:10 1997
+++ inn-1.7.2/innd/innd.h	Sun Jan  4 17:36:12 1998
@@ -544,7 +544,7 @@
 
 extern BOOL		RCnolimit();
 extern BOOL		RCauthorized();
-extern BOOL		RCcanpost();
+extern int		RCcanpost();
 extern char		*RChostname();
 extern int		RCismaster();
 extern void		RCclose();
--- inn-1.7.2.orig/innd/rc.c.orig	Mon Dec  8 15:48:50 1997
+++ inn-1.7.2/innd/rc.c	Sun Jan  4 17:36:12 1998
@@ -787,14 +787,14 @@
 /*
 **  Is the remote site allowed to post to this group?
 */
-BOOL
+int
 RCcanpost(cp, group)
     register CHANNEL	*cp;
     register char	*group;
 {
     register REMOTEHOST	*rp;
-    register BOOL	match;
-    register BOOL	subvalue;
+    register char	match;
+    register char	subvalue;
     register char	**argv;
     register char	*pat;
     register int	i;
@@ -805,16 +805,20 @@
 	    continue;
 	if (rp->Patterns == NULL)
 	    break;
-	for (match = TRUE, argv = rp->Patterns; (pat = *argv++) != NULL; ) {
-	    subvalue = *pat != SUB_NEGATE;
-	    if (!subvalue)
+	for (match = 0, argv = rp->Patterns; (pat = *argv++) != NULL; ) {
+	    subvalue = (*pat != SUB_NEGATE) && (*pat != SUB_POISON) ?
+	      0 : *pat;
+	    if (subvalue)
 		pat++;
-	    if ((match != subvalue) && wildmat(group, pat))
+	    if ((match != subvalue) && wildmat(group, pat)) {
+		if (subvalue == SUB_POISON)
+		    return -1;
 		match = subvalue;
+	    }
 	}
-	return match;
+	return !match;
     }
-    return TRUE;
+    return 1;
 }
 
 
--- inn-1.7.2.orig/doc/hosts.nntp.5
+++ inn-1.7.2/doc/hosts.nntp.5
@@ -39,17 +39,20 @@
 the host may send articles.
 This list is parsed as a
 .IR newsfeeds (5)
-subscription list; groups not in the list are ignored.
+subscription list; groups not in the list are ignored. Posts crossposted
+in groups matched by a @group.* entry are dropped.
 .PP
 For example:
 .RS
 .nf
 ##  FOO has a password, UUNET and VIX dont.
 ##  UUNET cannot post to local groups.
+##  Example is not part of Usenet II.
 ##  These are comment lines.
 news.foo.com:magic
 uunet.uu.net::!foo.*
 data.ramona.vix.com:
+newspeer.example.com::*,@net.*
 .fi
 .RE
 .PP
