Index: ossp-pkg/lmtp2nntp/lmtp2nntp.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v rcsdiff -q -kk '-r1.95' '-r1.96' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v' 2>/dev/null --- lmtp2nntp.c 2001/10/15 13:14:43 1.95 +++ lmtp2nntp.c 2001/10/15 14:22:12 1.96 @@ -151,6 +151,7 @@ int option_timeout_nntp_read; int option_timeout_nntp_write; char *option_mailfrom; + char *option_restrictheader; unsigned int option_levelmask; char *option_pidfile; int option_killflag; @@ -224,6 +225,7 @@ "[-m mailfrom] " "[-n nodename] " "[-o operationmode] " + "[-r restrictheader] " "[-s size] " "[-t name=sec[,name=sec[,...]] " "[-u uid] " @@ -442,6 +444,7 @@ ctx->option_timeout_nntp_read = 60; ctx->option_timeout_nntp_write = 60; ctx->option_mailfrom = NULL; + ctx->option_restrictheader = NULL; ctx->option_levelmask = L2_LEVEL_NONE; ctx->option_pidfile = NULL; ctx->option_killflag = FALSE; @@ -491,7 +494,7 @@ */ /* read in the arguments */ - while ((i = getopt(argc, argv, "C:DKP:Va:b:c:d:g:h:l:m:n:o:s:t:u:v")) != -1) { + while ((i = getopt(argc, argv, "C:DKP:Va:b:c:d:g:h:l:m:n:o:r:s:t:u:v")) != -1) { switch (i) { case 'C': /*POD [B<-C> I] */ ctx->option_childsmax = atoi(optarg); @@ -803,6 +806,22 @@ } } break; + case 'r': /*POD [B<-r> I] */ + ctx->option_restrictheader = strdup(optarg); + /* protect ourselfs from the substitution of backreferences. + * Missing varargs would cause segfaults. Rewrite capturing + * brackets to clustering syntax. Use poor man's s///g + * simulator as current str library doesn't support global + * substitution */ + while (str_parse(ctx->option_restrictheader, "s/(.*?)\\((?!\\?:)(.*)/$1(?:$2/", &cp) > 0) { + free(ctx->option_restrictheader); + ctx->option_restrictheader = cp; + } + if (str_parse("<>", ctx->option_restrictheader) == -1) { + fprintf(stderr, "%s:Error: illegal regex \"%s\" to option -r.\n", ctx->progname, ctx->option_restrictheader); + CU(ERR_EXECUTION); + } + break; case 's': /*POD [B<-s> I] */ ctx->option_maxmessagesize = atoi(optarg); if(ctx->option_maxmessagesize < 64) { @@ -1266,6 +1285,8 @@ sa_destroy(ctx->saAltio); if (ctx->saaAltio) sa_addr_destroy(ctx->saaAltio); + if (ctx->option_restrictheader != NULL) + free(ctx->option_restrictheader); if (ctx->azHeaderValuePairs != NULL) free(ctx->azHeaderValuePairs); if (ctx->option_pidfile != NULL) @@ -1873,6 +1894,9 @@ int i; int bSuccess; char *cp; + int bOk; + char *cpRestrictheader; + char *cpRestrictvalue; log1(ctx, INFO, "LMTP service executing DATA command < %s", req->msg); @@ -2032,8 +2056,45 @@ } } + /* RFC0821 4.2.1. REPLY CODES BY FUNCTION GROUPS 550 Requested action not taken: mailbox unavailable + * RFC1893 2. Status Codes 5.X.X Permanent Failure + * RFC1893 3.5 Network and Routing Status X.7.1 Delivery not authorized, message refused + */ + log0(ctx, TRACE, "checking if restricted header causes reject"); + if (ctx->option_restrictheader != NULL) { + bOk = FALSE; + cp = NULL; + while ((cp = argz_next(ctx->msg->azHeaders, ctx->msg->asHeaders, cp)) != NULL) { + cpRestrictheader = cp; + if ((cp = argz_next(ctx->msg->azHeaders, ctx->msg->asHeaders, cp)) == NULL) + break; + cpRestrictvalue = cp; + str_format(errorstring, sizeof(errorstring), "%s %s", cpRestrictheader, cpRestrictvalue); + if (str_parse(errorstring, ctx->option_restrictheader) <= 0) { + log2(ctx, TRACE, "\"%s\" matching against \"%s\" NO", errorstring, ctx->option_restrictheader); + } + else { + log2(ctx, TRACE, "\"%s\" matching against \"%s\": YES", errorstring, ctx->option_restrictheader); + bOk = TRUE; + break; + } + } + if (bOk) { + log0(ctx, TRACE, "restricted header found"); + rcpt = NULL; + while ((rcpt = argz_next(ctx->msg->azRcpt, ctx->msg->asRcpt, rcpt)) != NULL) { + res.statuscode = "550"; + res.dsncode = "5.7.1"; + res.statusmsg = "Restricted header matched, message rejected."; + lmtp_response(lmtp, &res); + } + return LMTP_OK; + } + } + /* Optionally add command line specified Header/Value Pairs */ + log0(ctx, TRACE, "adding header/value pairs"); if ((ctx->asHeaderValuePairs >= 1) && ((ctx->asHeaderValuePairs & 1) == 0)) { cp = NULL; while ((cp = argz_next(ctx->azHeaderValuePairs, ctx->asHeaderValuePairs, cp)) != NULL) { Index: ossp-pkg/lmtp2nntp/lmtp2nntp.pod RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp.pod,v rcsdiff -q -kk '-r1.32' '-r1.33' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp.pod,v' 2>/dev/null --- lmtp2nntp.pod 2001/10/15 10:13:50 1.32 +++ lmtp2nntp.pod 2001/10/15 14:22:12 1.33 @@ -48,6 +48,7 @@ [B<-m> I] [B<-n> I] [B<-o> I] +[B<-r> I] [B<-s> I] [B<-t> I=I[,I=I[,...]] [B<-u> I] @@ -197,6 +198,13 @@ B<-d> option. However, if B<-d> option is given the NNTP client tries to connect but it's return codes are ignored. +=item B<-r> I + +Restricted headers. Messages with a matching restrictheader are rejected. If +ommitted no restrictions apply. Matching is done before -h headers are +appended. Use a PCRE (Perl compatible reguar expression) for +I. + =item B<-s> I Size limitation on message in bytes. Default is 8388608 (8M). Values below 64 Index: ossp-pkg/lmtp2nntp/test.sh RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/test.sh,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/test.sh,v' 2>/dev/null --- test.sh 2001/10/15 10:13:50 1.6 +++ test.sh 2001/10/15 14:22:12 1.7 @@ -104,7 +104,7 @@ prolog newmsg ./lmtp2nntp -? >${STDOUT} 2>${STDERR} -RC=`cat ${STDERR} | egrep -- '-C.*-D.*-K.*-P.*-V.*-a.*-b.*-d.*-g.*-h.*-l.*-m.*-n.*-o.*-s.*-t.*-v.*newsgroup' | wc -l` +RC=`cat ${STDERR} | egrep -- '-C.*-D.*-K.*-P.*-V.*-a.*-b.*-d.*-g.*-h.*-l.*-m.*-n.*-o.*-r.*-s.*-t.*-v.*newsgroup' | wc -l` if [ ${RC} -ne 1 -o -s ${STDOUT} ]; then echo "NO (got ${RC})" exit 1;