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