INN commit: branches/2.5 (7 files)

INN Commit rra at isc.org
Sun Nov 15 09:26:49 UTC 2009


    Date: Sunday, November 15, 2009 @ 01:26:49
  Author: iulius
Revision: 8786

Fix a bug introduced by commit 8437.  If the Message-ID:
or the Supersedes: headers contains trailing white spaces,
the article is stored corrupted (we have a '\r' inside
the header).

Introduce more intelligence in the parsing (see a wish
explained in commit 6921) and retain the removed character
to properly put it again after the parsing.

Modified:
  branches/2.5/include/inn/libinn.h
  branches/2.5/innd/art.c
  branches/2.5/innd/innd.h
  branches/2.5/innd/nc.c
  branches/2.5/lib/messageid.c
  branches/2.5/nnrpd/article.c
  branches/2.5/nnrpd/commands.c

----------------------+
 include/inn/libinn.h |    2 +-
 innd/art.c           |   35 +++++++++++++++++++++++------------
 innd/innd.h          |   21 ++++++++++++---------
 innd/nc.c            |   11 ++++++-----
 lib/messageid.c      |   17 ++++++++++++++---
 nnrpd/article.c      |    6 +++---
 nnrpd/commands.c     |    2 +-
 7 files changed, 60 insertions(+), 34 deletions(-)

Modified: include/inn/libinn.h
===================================================================
--- include/inn/libinn.h	2009-11-15 09:26:37 UTC (rev 8785)
+++ include/inn/libinn.h	2009-11-15 09:26:49 UTC (rev 8786)
@@ -152,7 +152,7 @@
 /* Headers. */
 extern char *           GenerateMessageID(char *domain);
 extern void             InitializeMessageIDcclass(void);
-extern bool             IsValidMessageID(const char *string);
+extern bool             IsValidMessageID(const char *string, bool stripspaces);
 extern bool             IsValidHeaderName(const char *string);
 extern void             HeaderCleanFrom(char *from);
 extern struct _DDHANDLE * DDstart(FILE *FromServer, FILE *ToServer);

Modified: innd/art.c
===================================================================
--- innd/art.c	2009-11-15 09:26:37 UTC (rev 8785)
+++ innd/art.c	2009-11-15 09:26:49 UTC (rev 8786)
@@ -386,8 +386,10 @@
     char **hops;
 
     /* We may still haven't received the message-ID of the rejected article. */
-    if (HDR_FOUND(HDR__MESSAGE_ID))
+    if (HDR_FOUND(HDR__MESSAGE_ID)) {
+        HDR_LASTCHAR_SAVE(HDR__MESSAGE_ID);
         HDR_PARSE_START(HDR__MESSAGE_ID);
+    }
 
     /* Set up the headers that we want to use.  We only need to parse the path
        on rejections if logipaddr is false or we can't find a good host. */
@@ -399,6 +401,7 @@
         }
     } else {
         if (HDR_FOUND(HDR__PATH)) {
+            HDR_LASTCHAR_SAVE(HDR__PATH);
             HDR_PARSE_START(HDR__PATH);
             hopcount =
                 ARTparsepath(HDR(HDR__PATH), HDR_LEN(HDR__PATH), &data->Path);
@@ -689,7 +692,8 @@
     hc->Length = -1;
   } else {
     /* We need to remove leading and trailing spaces for
-     * message-IDs; otherwise, ARTidok() will fail. */
+     * message-IDs; otherwise, history hashes may not be
+     * correctly computed. */
     if (i == HDR__MESSAGE_ID || i == HDR__SUPERSEDES) {
       for (p = colon + 1 ; (p < header + size - 2) &&
            (ISWHITE(*p)) ; p++);
@@ -721,6 +725,7 @@
   for (i = 0 ; i < MAX_ARTHEADER ; i++, hc++) {
     hc->Value = NULL;
     hc->Length = 0;
+    hc->LastChar = '\r';
   }
   data->Lines = data->HeaderLines = data->CRwithoutLF = data->LFwithoutCR = 0;
   data->DotStuffedLines = 0;
@@ -778,12 +783,14 @@
 
 	/* Write a local cancel entry so nobody else gives it to us. */
 	if (HDR_FOUND(HDR__MESSAGE_ID)) {
+            HDR_LASTCHAR_SAVE(HDR__MESSAGE_ID);
             HDR_PARSE_START(HDR__MESSAGE_ID);
             msgid = HDR(HDR__MESSAGE_ID);
             /* The article posting time has not been parsed.  We cannot
              * give it to InndHisRemember. */
             if (!HIScheck(History, msgid) && !InndHisRemember(msgid, 0))
                 warn("SERVER cant write %s", msgid);
+            HDR_PARSE_END(HDR__MESSAGE_ID);
 	}
     }
 }
@@ -976,8 +983,10 @@
   /* replace trailing '\r\n' with '\0\n' of all system header to be handled
      easily by str*() functions */
   for (i = 0 ; i < MAX_ARTHEADER ; i++) {
-    if (HDR_FOUND(i))
+    if (HDR_FOUND(i)) {
+      HDR_LASTCHAR_SAVE(i);
       HDR_PARSE_START(i);
+    }
   }
 
   /* Make sure all the headers we need are there */
@@ -985,7 +994,7 @@
     if (hp[i].Type == HTreq) {
       if (HDR_FOUND(i))
         continue;
-      if (hc[i].Length < 0) {
+      if (HDR_LEN(i) < 0) {
         sprintf(buff, "%d Duplicate \"%s\" header",
                 ihave ? NNTP_FAIL_IHAVE_REJECT : NNTP_FAIL_TAKETHIS_REJECT,
                 hp[i].Name);
@@ -1000,7 +1009,7 @@
   }
 
   /* Assumes the Message-ID: header is a required header. */
-  if (!IsValidMessageID(HDR(HDR__MESSAGE_ID))) {
+  if (!IsValidMessageID(HDR(HDR__MESSAGE_ID), true)) {
     HDR_LEN(HDR__MESSAGE_ID) = 0;
     sprintf(buff, "%d Bad \"Message-ID\" header",
             ihave ? NNTP_FAIL_IHAVE_REJECT : NNTP_FAIL_TAKETHIS_REJECT);
@@ -1208,9 +1217,9 @@
     return;
   }
 
-  if (!IsValidMessageID(MessageID)) {
+  if (!IsValidMessageID(MessageID, true)) {
     syslog(L_NOTICE, "%s bad cancel Message-ID %s", data->Feedsite,
-      MaxLength(MessageID, MessageID));
+           MaxLength(MessageID, MessageID));
     TMRstop(TMR_ARTCNCL);
     return;
   }
@@ -1243,7 +1252,7 @@
     OVcancel(token);
   if (!SMcancel(token) && SMerrno != SMERR_NOENT && SMerrno != SMERR_UNINIT)
     syslog(L_ERROR, "%s cant cancel %s (SMerrno %d)", LogName,
-	TokenToText(token), SMerrno);
+           TokenToText(token), SMerrno);
   if (innconf->immediatecancel && !SMflushcacheddata(SM_CANCELLEDART))
     syslog(L_ERROR, "%s cant cancel cached %s", LogName, TokenToText(token));
   snprintf(buff, sizeof(buff), "Cancelling %s",
@@ -1267,7 +1276,7 @@
   if (c == 'c' && strncmp(Control, "cancel", 6) == 0) {
     for (p = &Control[6]; ISWHITE(*p); p++)
       continue;
-    if (*p && IsValidMessageID(p))
+    if (*p && IsValidMessageID(p, true))
       ARTcancel(data, p, false);
     return;
   }
@@ -2426,10 +2435,12 @@
     ngp->PostCount = 0;
 
   token = ARTstore(cp);
-  /* change trailing '\r\n' to '\0\n' of all system header */
+  /* Change trailing '\r\n' to '\0\n' of all system header. */
   for (i = 0 ; i < MAX_ARTHEADER ; i++) {
-    if (HDR_FOUND(i))
+    if (HDR_FOUND(i)) {
+      HDR_LASTCHAR_SAVE(i);
       HDR_PARSE_START(i);
+    }
   }
   if (token.type == TOKEN_EMPTY) {
     syslog(L_ERROR, "%s cant store article: %s", LogName, SMerrorstr);
@@ -2538,7 +2549,7 @@
       ARTcontrol(data, HDR(HDR__CONTROL), cp);
     }
     if (DoCancels && HDR_FOUND(HDR__SUPERSEDES)) {
-      if (IsValidMessageID(HDR(HDR__SUPERSEDES)))
+      if (IsValidMessageID(HDR(HDR__SUPERSEDES), true))
 	ARTcancel(data, HDR(HDR__SUPERSEDES), false);
     }
   }

Modified: innd/innd.h
===================================================================
--- innd/innd.h	2009-11-15 09:26:37 UTC (rev 8785)
+++ innd/innd.h	2009-11-15 09:26:49 UTC (rev 8786)
@@ -116,24 +116,27 @@
 
 
 /*
-**  Header content
+**  Header content.
 */
 typedef struct _HDRCONTENT {
-  char  *  Value;   /* don't copy, shows where it begins */
-  int	   Length;  /* Length of Value(tailing CRLF is not
-			   included.  -1 if duplicated */
+  char  *  Value;     /* Don't copy, shows where it begins. */
+  int      Length;    /* Length of Value(tailing CRLF is not
+                         included.  -1 if duplicated. */
+  char     LastChar;  /* Saved char when the last one is cut during parsing.
+                         Usually '\r' but it may be another char. */
 } HDRCONTENT;
 
 
 /*
 **  A way to index into the header table.
 */
-#define HDR_FOUND(_x)		(hc[(_x)].Length > 0)
-#define HDR_PARSE_START(_x)	hc[(_x)].Value[hc[_x].Length] = '\0'
-#define HDR(_x)			(hc[(_x)].Value)
+#define HDR_FOUND(_x)           (hc[(_x)].Length > 0)
+#define HDR_LASTCHAR_SAVE(_x)   hc[(_x)].LastChar = hc[(_x)].Value[hc[_x].Length]
+#define HDR_PARSE_START(_x)     hc[(_x)].Value[hc[_x].Length] = '\0'
+#define HDR(_x)                 (hc[(_x)].Value)
 /* HDR_LEN does not includes trailing "\r\n" */
-#define HDR_LEN(_x)		(hc[(_x)].Length)
-#define HDR_PARSE_END(_x)	hc[(_x)].Value[hc[_x].Length] = '\r'
+#define HDR_LEN(_x)             (hc[(_x)].Length)
+#define HDR_PARSE_END(_x)       hc[(_x)].Value[hc[_x].Length] = hc[(_x)].LastChar
 
 
 #define HDR__APPROVED		0

Modified: innd/nc.c
===================================================================
--- innd/nc.c	2009-11-15 09:26:37 UTC (rev 8785)
+++ innd/nc.c	2009-11-15 09:26:49 UTC (rev 8786)
@@ -322,7 +322,7 @@
         return;
     }
 
-    if (!IsValidMessageID(cp->av[1])) {
+    if (!IsValidMessageID(cp->av[1], true)) {
         xasprintf(&buff, "%d Syntax error in message-ID", NNTP_ERR_SYNTAX);
         NCwritereply(cp, buff);
         free(buff);
@@ -388,7 +388,7 @@
         return;
     }
 
-    if (!IsValidMessageID(cp->av[1])) {
+    if (!IsValidMessageID(cp->av[1], true)) {
         xasprintf(&buff, "%d Syntax error in message-ID", NNTP_ERR_SYNTAX);
         NCwritereply(cp, buff);
         free(buff);
@@ -605,7 +605,7 @@
     cp->Ihave++;
     cp->Start = cp->Next;
 
-    if (!IsValidMessageID(cp->av[1])) {
+    if (!IsValidMessageID(cp->av[1], false)) {
         /* Return 435 here instead of 501 for compatibility reasons. */
         xasprintf(&buff, "%d Syntax error in message-ID", NNTP_FAIL_IHAVE_REFUSE);
         NCwritereply(cp, buff);
@@ -1312,6 +1312,7 @@
       if (*cp->Error != '\0') {
         if (innconf->remembertrash && (Mode == OMrunning)
             && HDR_FOUND(HDR__MESSAGE_ID)) {
+            HDR_LASTCHAR_SAVE(HDR__MESSAGE_ID);
             HDR_PARSE_START(HDR__MESSAGE_ID);
             /* The article posting time has not been parsed.  We cannot
              * give it to InndHisRemember. */
@@ -1705,7 +1706,7 @@
             cp->Sendid.size = MAXHEADERSIZE;
         cp->Sendid.data = xmalloc(cp->Sendid.size);
     }
-    if (!IsValidMessageID(cp->av[1])) {
+    if (!IsValidMessageID(cp->av[1], false)) {
 	snprintf(cp->Sendid.data, cp->Sendid.size, "%d %s",
                  NNTP_FAIL_CHECK_REFUSE, cp->av[1]);
 	NCwritereply(cp, cp->Sendid.data);
@@ -1797,7 +1798,7 @@
     cp->Takethis++;
     cp->Start = cp->Next;
 
-    if (!IsValidMessageID(cp->av[1])) {
+    if (!IsValidMessageID(cp->av[1], false)) {
 	syslog(L_NOTICE, "%s bad_messageid %s", CHANname(cp),
                MaxLength(cp->av[1], cp->av[1]));
     }

Modified: lib/messageid.c
===================================================================
--- lib/messageid.c	2009-11-15 09:26:37 UTC (rev 8785)
+++ lib/messageid.c	2009-11-15 09:26:49 UTC (rev 8786)
@@ -100,7 +100,7 @@
 **  Updated to RFC 5536 by Julien Elie.
 */
 bool
-IsValidMessageID(const char *MessageID)
+IsValidMessageID(const char *MessageID, bool stripspaces)
 {
     int c;
     const unsigned char *p;
@@ -111,6 +111,10 @@
 
     p = (const unsigned char *) MessageID;
 
+    if (stripspaces) {
+        for (; ISWHITE(*p); p++);
+    }
+
     /* Scan local-part:  "< dot-atom-text". */
     if (*p++ != '<')
         return false;
@@ -154,6 +158,13 @@
         if (*p != '.')
             break;
     }
-    
-    return *p == '>' && *++p == '\0';
+
+    if (*p++ != '>')
+        return false;
+
+    if (stripspaces) {
+        for (; ISWHITE(*p); p++);
+    }
+
+    return (*p == '\0');
 }

Modified: nnrpd/article.c
===================================================================
--- nnrpd/article.c	2009-11-15 09:26:37 UTC (rev 8785)
+++ nnrpd/article.c	2009-11-15 09:26:49 UTC (rev 8786)
@@ -596,7 +596,7 @@
     ARTNUM		tart;
     bool                final = false;
 
-    mid = (ac > 1 && IsValidMessageID(av[1]));
+    mid = (ac > 1 && IsValidMessageID(av[1], true));
 
     /* Check the syntax of the arguments first. */
     if (ac > 1 && !IsValidArticleNumber(av[1])) {
@@ -887,7 +887,7 @@
     bool                xover, mid;
 
     xover = (strcasecmp(av[0], "XOVER") == 0);
-    mid = (ac > 1 && IsValidMessageID(av[1]));
+    mid = (ac > 1 && IsValidMessageID(av[1], true));
 
     if (mid && !xover) {
         /* FIXME:  We still do not support OVER MSGID, sorry! */
@@ -1106,7 +1106,7 @@
     bool                hdr, mid;
 
     hdr = (strcasecmp(av[0], "HDR") == 0);
-    mid = (ac > 2 && IsValidMessageID(av[2]));
+    mid = (ac > 2 && IsValidMessageID(av[2], true));
 
     /* Check the syntax of the arguments first. */
     if (ac > 2 && !IsValidRange(av[2])) {

Modified: nnrpd/commands.c
===================================================================
--- nnrpd/commands.c	2009-11-15 09:26:37 UTC (rev 8785)
+++ nnrpd/commands.c	2009-11-15 09:26:49 UTC (rev 8786)
@@ -602,7 +602,7 @@
     ihave = (strcasecmp(av[0], "IHAVE") == 0);
 
     /* Check whether the message-ID is valid for IHAVE. */
-    if (ihave && ac == 2 && !IsValidMessageID(av[1])) {
+    if (ihave && ac == 2 && !IsValidMessageID(av[1], true)) {
         Reply("%d Syntax error in message-ID\r\n", NNTP_ERR_SYNTAX);
         return;
     }




More information about the inn-committers mailing list