INN commit: branches/2.5 (8 files)

INN Commit rra at isc.org
Sun Nov 15 09:01:24 UTC 2009


    Date: Sunday, November 15, 2009 @ 01:01:24
  Author: iulius
Revision: 8743

* If the length of NNTP arguments is too long (> 497 bytes),
a 501 error is now returned.

* If a command is given less (or more) arguments than expected,
a 501 error is now returned.

* Improve the HELP output for innd, specifying expected arguments.

* HEAD answers 412 (not in a newsgroup) when requesting
an article number.  It was previously sending 501 (syntax error in
mesasge-ID).

Added:
  branches/2.5/lib/argparse.c
    (from rev 8667, trunk/lib/argparse.c)
Modified:
  branches/2.5/MANIFEST
  branches/2.5/include/inn/libinn.h
  branches/2.5/include/nntp.h
  branches/2.5/innd/nc.c
  branches/2.5/lib/Makefile
  branches/2.5/nnrpd/misc.c
  branches/2.5/nnrpd/nnrpd.h

----------------------+
 MANIFEST             |    1 
 include/inn/libinn.h |    3 
 include/nntp.h       |    1 
 innd/nc.c            |  170 ++++++++++++++++++++++++++++++++++---------------
 lib/Makefile         |    2 
 lib/argparse.c       |   76 +++++++++++++++++++++
 nnrpd/misc.c         |   65 ------------------
 nnrpd/nnrpd.h        |    2 
 8 files changed, 202 insertions(+), 118 deletions(-)

Modified: MANIFEST
===================================================================
--- MANIFEST	2009-11-15 09:00:35 UTC (rev 8742)
+++ MANIFEST	2009-11-15 09:01:24 UTC (rev 8743)
@@ -462,6 +462,7 @@
 lib                                   INN library routines (Directory)
 lib/Makefile                          Makefile for library
 lib/alloca.c                          alloca replacement
+lib/argparse.c                        Functions for parsing arguments
 lib/asprintf.c                        asprintf replacement
 lib/buffer.c                          Reusable counted buffer
 lib/cleanfrom.c                       Clean out a From line

Modified: include/inn/libinn.h
===================================================================
--- include/inn/libinn.h	2009-11-15 09:00:35 UTC (rev 8742)
+++ include/inn/libinn.h	2009-11-15 09:01:24 UTC (rev 8743)
@@ -92,12 +92,15 @@
 /*
 **  TIME AND DATE PARSING, GENERATION, AND HANDLING
 */
+extern int      Argify(char *line, char ***argvp);
+extern char *   Glom(char **av);
 extern bool     makedate(time_t, bool local, char *buff, size_t buflen);
 extern time_t   parsedate_nntp(const char *, const char *, bool local);
 extern time_t   parsedate_rfc2822(const char *);
 extern time_t   parsedate_rfc2822_lax(const char *);
 
 
+
 /*
 **  WILDMAT MATCHING
 */

Modified: include/nntp.h
===================================================================
--- include/nntp.h	2009-11-15 09:00:35 UTC (rev 8742)
+++ include/nntp.h	2009-11-15 09:01:24 UTC (rev 8743)
@@ -29,7 +29,6 @@
 #define NNTP_HAVEIT			"435 Duplicate"
 #define NNTP_HAVEIT_BADID		"435 Bad Message-ID"
 #define NNTP_LIST_FOLLOWS		"215"
-#define NNTP_HELP_FOLLOWS		"100 Legal commands"
 #define NNTP_ARTICLE_FOLLOWS		"220"
 #define NNTP_POSTOK			"200"
 #define NNTP_REJECTIT_EMPTY		"437 Empty article"

Modified: innd/nc.c
===================================================================
--- innd/nc.c	2009-11-15 09:00:35 UTC (rev 8742)
+++ innd/nc.c	2009-11-15 09:01:24 UTC (rev 8743)
@@ -22,6 +22,9 @@
     const char *        Name;
     innd_callback_func  Function;
     int                 Size;
+    int                 Minac;
+    int                 Maxac;
+    const char *        Help;
 } NCDISPATCH;
 
 /* The functions that implement the various commands. */
@@ -48,46 +51,60 @@
 static void NCwritedone(CHANNEL *cp);
 
 /* Set up the dispatch table for all of the commands. */
-#define COMMAND(name, func) { name, func, sizeof(name) - 1 }
+#define NC_any -1
+#define COMMAND(name, func, min, max, help) { name, func, sizeof(name) - 1, min, max, help }
+#define COMMAND_READER(name) { name, NC_reader, sizeof(name) - 1, 1, NC_any, NULL }
+#define COMMAND_UNIMP(name) { name, NC_unimp, sizeof(name) - 1, 1, NC_any, NULL }
 static NCDISPATCH NCcommands[] = {
-    COMMAND("authinfo",  NCauthinfo),
-    COMMAND("check",     NCcheck),
-    COMMAND("head",      NChead),
-    COMMAND("help",      NChelp),
-    COMMAND("ihave",     NCihave),
-    COMMAND("list",      NClist),
-    COMMAND("mode",      NCmode),
-    COMMAND("quit",      NCquit),
-    COMMAND("stat",      NCstat),
-    COMMAND("takethis",  NCtakethis),
-    COMMAND("xbatch",    NCxbatch),
+    COMMAND("AUTHINFO",  NCauthinfo,   3,  3,
+            "USER name|PASS password"),
+    COMMAND("CHECK",     NCcheck,      2,  2,
+            "message-ID"),
+    COMMAND("HEAD",      NChead,       1,  2,
+            "message-ID"),
+    COMMAND("HELP",      NChelp,       1,  1,
+            NULL),
+    COMMAND("IHAVE",     NCihave,      2,  2,
+            "message-ID"),
+    COMMAND("LIST",      NClist,       1,  3,
+            "[ACTIVE|ACTIVE.TIMES|NEWSGROUPS]"),
+    COMMAND("MODE",      NCmode,       2,  2,
+            "READER"),
+    COMMAND("QUIT",      NCquit,       1,  1,
+            NULL),
+    COMMAND("STAT",      NCstat,       1,  2,
+            "message-ID"),
+    COMMAND("TAKETHIS",  NCtakethis,   2,  2,
+            "message-ID"),
+    COMMAND("XBATCH",    NCxbatch,     2,  2,
+            "size"),
 
     /* Unimplemented reader commands which may become available after a MODE
        READER command. */
-    COMMAND("article",   NC_reader),
-    COMMAND("body",      NC_reader),
-    COMMAND("date",      NC_reader),
-    COMMAND("group",     NC_reader),
-    COMMAND("hdr",       NC_reader),
-    COMMAND("last",      NC_reader),
-    COMMAND("listgroup", NC_reader),
-    COMMAND("newgroups", NC_reader),
-    COMMAND("newnews",   NC_reader),
-    COMMAND("next",      NC_reader),
-    COMMAND("over",      NC_reader),
-    COMMAND("post",      NC_reader),
+    COMMAND_READER("ARTICLE"),
+    COMMAND_READER("BODY"),
+    COMMAND_READER("DATE"),
+    COMMAND_READER("GROUP"),
+    COMMAND_READER("HDR"),
+    COMMAND_READER("LAST"),
+    COMMAND_READER("LISTGROUP"),
+    COMMAND_READER("NEWGROUPS"),
+    COMMAND_READER("NEWNEWS"),
+    COMMAND_READER("NEXT"),
+    COMMAND_READER("OVER"),
+    COMMAND_READER("POST"),
 #ifdef HAVE_SSL
-    COMMAND("starttls",  NC_reader),
+    COMMAND_READER("STARTTLS"),
 #endif
-    COMMAND("xgtitle",   NC_reader),
-    COMMAND("xhdr",      NC_reader),
-    COMMAND("xover",     NC_reader),
-    COMMAND("xpat",      NC_reader),
+    COMMAND_READER("XGTITLE"),
+    COMMAND_READER("XHDR"),
+    COMMAND_READER("XOVER"),
+    COMMAND_READER("XPAT"),
 
     /* Other unimplemented standard commands.
        SLAVE (which was ill-defined in RFC 977) was removed from the NNTP
        protocol in RFC 3977. */
-    COMMAND("slave",     NC_unimp)
+    COMMAND_UNIMP("SLAVE")
 };
 #undef COMMAND
 
@@ -294,11 +311,19 @@
     ARTHANDLE		*art;
     char                *buff = NULL;
 
-    /* Snip off the Message-ID. */
+    /* Snip off the message-ID. */
     for (p = cp->In.data + cp->Start + strlen("HEAD"); ISWHITE(*p); p++)
 	continue;
     cp->Start = cp->Next;
 
+    /* No argument given. */
+    if (*p == '\0') {
+        xasprintf(&buff, "%d Not in a newsgroup", NNTP_FAIL_NO_GROUP);
+        NCwritereply(cp, buff);
+        free(buff);
+        return;
+    }
+
     if (!ARTidok(p)) {
         xasprintf(&buff, "%d Syntax error in message-ID", NNTP_ERR_SYNTAX);
         NCwritereply(cp, buff);
@@ -354,7 +379,7 @@
     ARTHANDLE		*art;
     char		*buff = NULL;
 
-    /* Snip off the Message-ID. */
+    /* Snip off the message-ID. */
     for (p = cp->In.data + cp->Start + strlen("STAT"); ISWHITE(*p); p++)
 	continue;
     cp->Start = cp->Next;
@@ -460,8 +485,8 @@
 }
 
 /*
-**  The "help" command.
-**  As MODE STREAM is recognized, we still display "mode" when
+**  The HELP command.
+**  As MODE STREAM is recognized, we still display MODE when
 **  noreader is set to true or the server is paused or throttled
 **  with readerswhenstopped set to false.
 */
@@ -470,16 +495,22 @@
 {
     static char		LINE1[] = "For more information, contact \"";
     static char		LINE2[] = "\" at this machine.";
+    char                *buff = NULL;
     NCDISPATCH		*dp;
 
-    WCHANappend(cp, NNTP_HELP_FOLLOWS, strlen(NNTP_HELP_FOLLOWS));
-    WCHANappend(cp, NCterm, strlen(NCterm));
+    xasprintf(&buff, "%d Legal commands%s", NNTP_INFO_HELP, NCterm);
+    WCHANappend(cp, buff, strlen(buff));
     for (dp = NCcommands; dp < ARRAY_END(NCcommands); dp++)
 	if (dp->Function != NC_unimp && dp->Function != NC_reader) {
+            /* Ignore the streaming commands if necessary. */
             if ((!StreamingOff && cp->Streaming) ||
                 (dp->Function != NCcheck && dp->Function != NCtakethis)) {
-                WCHANappend(cp, "\t", 1);
+                WCHANappend(cp, "  ", 2);
                 WCHANappend(cp, dp->Name, dp->Size);
+                if (dp->Help != NULL) {
+                    WCHANappend(cp, " ", 1);
+                    WCHANappend(cp, dp->Help, strlen(dp->Help));
+                }
                 WCHANappend(cp, NCterm, strlen(NCterm));
             }
 	}
@@ -489,10 +520,11 @@
     WCHANappend(cp, NCterm, strlen(NCterm));
     NCwritereply(cp, NCdot) ;
     cp->Start = cp->Next;
+    free(buff);
 }
 
 /*
-**  The "ihave" command.  Check the Message-ID, and see if we want the
+**  The IHAVE command.  Check the message-ID, and see if we want the
 **  article or not.  Set the state appropriately.
 */
 static void
@@ -506,7 +538,7 @@
 #endif /*defined(DO_PERL) || defined(DO_PYTHON) */
 
     cp->Ihave++;
-    /* Snip off the Message-ID. */
+    /* Snip off the message-ID. */
     for (p = cp->In.data + cp->Start + strlen("ihave"); ISWHITE(*p); p++)
 	continue;
     cp->Start = cp->Next;
@@ -846,6 +878,10 @@
   bool		readmore, movedata;
   ARTDATA	*data = &cp->Data;
   HDRCONTENT    *hc = data->HdrContent;
+  int           ac;
+  static char   **av;
+  char          **v;
+  bool          validcommandtoolong;
 
   readmore = movedata = false;
   if (Tracing || cp->Tracing)
@@ -944,7 +980,12 @@
 	cp->Start = cp->Next;
 	break;
       }
+
+      /* Guarantee null-termination. */
       p[-2] = '\0';
+      p = q;
+      ac = Argify(p, &av);
+
       if (Tracing || cp->Tracing)
 	syslog(L_TRACE, "%s < %s", CHANname(cp), q);
 
@@ -957,9 +998,8 @@
 
       /* If the line is too long, we have to make sure that
        * no recognized command has been sent. */
+      validcommandtoolong = false;
       if (i - cp->Start > NNTP_MAXLEN_COMMAND) {
-        bool validcommandtoolong = false;
-
         for (p = q, dp = NCcommands; dp < ARRAY_END(NCcommands); dp++) {
           if ((dp->Function != NC_unimp) &&
               (strncasecmp(p, dp->Name, dp->Size) == 0)) {
@@ -995,12 +1035,12 @@
 	  /* Ignore the streaming commands if necessary. */
 	  if (!StreamingOff || cp->Streaming ||
 	    (dp->Function != NCcheck && dp->Function != NCtakethis)) {
-	    (*dp->Function)(cp);
-	    cp->BadCommands = 0;
 	    break;
 	  }
 	}
       }
+
+      /* If no command has been recognized. */
       if (dp == ARRAY_END(NCcommands)) {
 	if (++(cp->BadCommands) >= BAD_COMMAND_COUNT) {
           cp->State = CSwritegoodbye;
@@ -1022,7 +1062,39 @@
 	if (p == NULL)
 	  syslog(L_NOTICE, "%s bad_command %s", CHANname(cp),
 	    MaxLength(q, q));
+        break;
       }
+
+      /* Check whether all arguments do not exceed their allowed size. */
+      if (ac > 1) {
+          validcommandtoolong = false;
+          for (v = av; *v; v++)
+              if (strlen(*v) > NNTP_MAXLEN_ARG) {
+                  validcommandtoolong = true;
+                  snprintf(buff, sizeof(buff), "%d Argument too long",
+                           NNTP_ERR_SYNTAX);
+                  NCwritereply(cp, buff);
+                  break;
+              }
+          if (validcommandtoolong) {
+              cp->Start = cp->Next;
+              break;
+          }
+      }
+
+      /* Check usage. */
+      if ((dp->Minac != NC_any && ac < dp->Minac)
+          || (dp->Maxac != NC_any && ac > dp->Maxac)) {
+          snprintf(buff, sizeof(buff), "%d Syntax is:  %s %s",
+                   NNTP_ERR_SYNTAX, dp->Name, dp->Help ? dp->Help : "(no argument allowed)");
+          NCwritereply(cp, buff);
+          cp->Start = cp->Next;
+          break;
+      }
+
+      (*dp->Function)(cp);
+      cp->BadCommands = 0;
+
       break;
 
     case CSgetheader:
@@ -1304,7 +1376,6 @@
 }
 
 
-
 /*
 **  Set up the NNTP channel state.
 */
@@ -1406,12 +1477,13 @@
 
 
 
-/* These modules support the streaming option to tranfer articles
-** faster.
+/*
+**  These modules support the streaming option to tranfer articles
+**  faster.
 */
 
 /*
-**  The "check" command.  Check the Message-ID, and see if we want the
+**  The CHECK command.  Check the message-ID, and see if we want the
 **  article or not.  Stay in command state.
 */
 static void
@@ -1425,7 +1497,7 @@
 #endif /* DO_PERL || DO_PYTHON */
 
     cp->Check++;
-    /* Snip off the Message-ID. */
+    /* Snip off the message-ID. */
     for (p = cp->In.data + cp->Start; *p && !ISWHITE(*p); p++)
 	continue;
     cp->Start = cp->Next;
@@ -1529,7 +1601,7 @@
     WIP                 *wp;
 
     cp->Takethis++;
-    /* Snip off the Message-ID. */
+    /* Snip off the message-ID. */
     for (p = cp->In.data + cp->Start + strlen("takethis"); ISWHITE(*p); p++)
 	continue;
     cp->Start = cp->Next;

Modified: lib/Makefile
===================================================================
--- lib/Makefile	2009-11-15 09:00:35 UTC (rev 8742)
+++ lib/Makefile	2009-11-15 09:01:24 UTC (rev 8743)
@@ -6,7 +6,7 @@
 CFLAGS  = $(GCFLAGS)
 
 # The base library files that are always compiled and included.
-SOURCES       = buffer.c cleanfrom.c clientactive.c clientlib.c commands.c concat.c \
+SOURCES       = argparse.c buffer.c cleanfrom.c clientactive.c clientlib.c commands.c concat.c \
 		conffile.c confparse.c daemonize.c date.c dbz.c defdist.c \
 		dispatch.c fdflags.c fdlimit.c getfqdn.c \
 		getmodaddr.c hash.c hashtab.c headers.c hex.c innconf.c inndcomm.c \

Copied: branches/2.5/lib/argparse.c (from rev 8667, trunk/lib/argparse.c)
===================================================================
--- lib/argparse.c	                        (rev 0)
+++ lib/argparse.c	2009-11-15 09:01:24 UTC (rev 8743)
@@ -0,0 +1,76 @@
+/*  $Id$
+**
+**  Routines for parsing arguments.
+*/
+
+#include "config.h"
+#include "clibrary.h"
+#include <ctype.h>
+#include <time.h>
+
+#include "inn/innconf.h"
+#include "inn/libinn.h"
+
+/*
+**  Parse a string into a NULL-terminated array of words; return number
+**  of words.  If argvp isn't NULL, it and what it points to will be freed.
+*/
+int
+Argify(char *line, char ***argvp)
+{
+    char        **argv;
+    char        *p;
+
+    if (*argvp != NULL) {
+        free(*argvp[0]);
+        free(*argvp);
+    }
+
+    /* Copy the line, which we will split up. */
+    while (ISWHITE(*line))
+        line++;
+    p = xstrdup(line);
+
+    /* Allocate worst-case amount of space. */
+    for (*argvp = argv = xmalloc((strlen(p) + 2) * sizeof(char *)); *p; ) {
+        /* Mark start of this word, find its end. */
+        for (*argv++ = p; *p && !ISWHITE(*p); )
+            p++;
+        if (*p == '\0')
+            break;
+
+        /* Nip off word, skip whitespace. */
+        for (*p++ = '\0'; ISWHITE(*p); )
+            p++;
+    }
+    *argv = NULL;
+    return argv - *argvp;
+}
+
+
+/*
+**  Take a vector which Argify made and glue it back together with
+**  spaces between each element.  Returns a pointer to dynamic space.
+*/
+char *
+Glom(char **av)
+{
+    char        **v;
+    int i;
+    char                *save;
+
+    /* Get space. */
+    for (i = 0, v = av; *v; v++)
+        i += strlen(*v) + 1;
+    i++;
+
+    save = xmalloc(i);
+    save[0] = '\0';
+    for (v = av; *v; v++) {
+        if (v > av)
+            strlcat(save, " ", i);
+        strlcat(save, *v, i);
+    }
+
+    return save;
+}

Modified: nnrpd/misc.c
===================================================================
--- nnrpd/misc.c	2009-11-15 09:00:35 UTC (rev 8742)
+++ nnrpd/misc.c	2009-11-15 09:01:24 UTC (rev 8743)
@@ -27,71 +27,6 @@
 
 
 /*
-**  Parse a string into a NULL-terminated array of words; return number
-**  of words.  If argvp isn't NULL, it and what it points to will be freed.
-*/
-int
-Argify(char *line, char ***argvp)
-{
-    char	**argv;
-    char	*p;
-
-    if (*argvp != NULL) {
-	free(*argvp[0]);
-	free(*argvp);
-    }
-
-    /* Copy the line, which we will split up. */
-    while (ISWHITE(*line))
-	line++;
-    p = xstrdup(line);
-
-    /* Allocate worst-case amount of space. */
-    for (*argvp = argv = xmalloc((strlen(p) + 2) * sizeof(char *)); *p; ) {
-	/* Mark start of this word, find its end. */
-	for (*argv++ = p; *p && !ISWHITE(*p); )
-	    p++;
-	if (*p == '\0')
-	    break;
-
-	/* Nip off word, skip whitespace. */
-	for (*p++ = '\0'; ISWHITE(*p); )
-	    p++;
-    }
-    *argv = NULL;
-    return argv - *argvp;
-}
-
-
-/*
-**  Take a vector which Argify made and glue it back together with
-**  spaces between each element.  Returns a pointer to dynamic space.
-*/
-char *
-Glom(char **av)
-{
-    char	**v;
-    int	i;
-    char		*save;
-
-    /* Get space. */
-    for (i = 0, v = av; *v; v++)
-	i += strlen(*v) + 1;
-    i++;
-
-    save = xmalloc(i);
-    save[0] = '\0';
-    for (v = av; *v; v++) {
-	if (v > av)
-            strlcat(save, " ", i);
-        strlcat(save, *v, i);
-    }
-
-    return save;
-}
-
-
-/*
 **  Match a list of newsgroup specifiers against a list of newsgroups.
 **  func is called to see if there is a match.
 */

Modified: nnrpd/nnrpd.h
===================================================================
--- nnrpd/nnrpd.h	2009-11-15 09:00:35 UTC (rev 8742)
+++ nnrpd/nnrpd.h	2009-11-15 09:01:24 UTC (rev 8743)
@@ -212,8 +212,6 @@
 				 bool *permanent);
 extern void		ARTclose(void);
 extern int		TrimSpaces(char *line);
-extern char		*Glom(char **av);
-extern int		Argify(char *line, char ***argvp);
 extern void		InitBackoffConstants(void);
 extern char		*PostRecFilename(char *ip, char *user);
 extern int		LockPostRec(char *path);




More information about the inn-committers mailing list