diff options
Diffstat (limited to 'gnu/usr.sbin/sendmail/libmilter/smfi.c')
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/smfi.c | 146 |
1 files changed, 137 insertions, 9 deletions
diff --git a/gnu/usr.sbin/sendmail/libmilter/smfi.c b/gnu/usr.sbin/sendmail/libmilter/smfi.c index 3fd3d5ce321..4a4132f083e 100644 --- a/gnu/usr.sbin/sendmail/libmilter/smfi.c +++ b/gnu/usr.sbin/sendmail/libmilter/smfi.c @@ -9,10 +9,14 @@ */ #include <sm/gen.h> -SM_RCSID("@(#)$Sendmail: smfi.c,v 8.46 2001/09/11 04:04:45 gshapiro Exp $") - +SM_RCSID("@(#)$Sendmail: smfi.c,v 8.57 2001/11/20 18:47:49 ca Exp $") +#include <sm/varargs.h> #include "libmilter.h" +/* for smfi_set{ml}reply, let's be generous. 256/16 should be sufficient */ +#define MAXREPLYLEN 980 /* max. length of a reply string */ +#define MAXREPLIES 32 /* max. number of reply strings */ + /* ** SMFI_ADDHEADER -- send a new header to the MTA ** @@ -234,11 +238,11 @@ smfi_quarantine(ctx, reason) return MI_FAILURE; timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; - len = strlen(reason); + len = strlen(reason) + 1; buf = malloc(len); if (buf == NULL) return MI_FAILURE; - (void) memcpy(buf, reason, len + 1); + (void) memcpy(buf, reason, len); r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_QUARANTINE, buf, len); free(buf); return r; @@ -284,6 +288,7 @@ myisenhsc(s, delim) return 0; return l + h; } + /* ** SMFI_SETREPLY -- set the reply code for the next reply to the MTA ** @@ -319,20 +324,30 @@ smfi_setreply(ctx, rcode, xcode, message) !isascii(rcode[2]) || !isdigit(rcode[2])) return MI_FAILURE; if (xcode != NULL) + { + if (!myisenhsc(xcode, '\0')) + return MI_FAILURE; len += strlen(xcode) + 1; + } if (message != NULL) - len += strlen(message) + 1; + { + size_t ml; + + /* XXX check also for unprintable chars? */ + if (strpbrk(message, "\r\n") != NULL) + return MI_FAILURE; + ml = strlen(message); + if (ml > MAXREPLYLEN) + return MI_FAILURE; + len += ml + 1; + } buf = malloc(len); if (buf == NULL) return MI_FAILURE; /* oops */ (void) sm_strlcpy(buf, rcode, len); (void) sm_strlcat(buf, " ", len); if (xcode != NULL) - { - if (!myisenhsc(xcode, '\0')) - return MI_FAILURE; (void) sm_strlcat(buf, xcode, len); - } if (message != NULL) { if (xcode != NULL) @@ -344,6 +359,119 @@ smfi_setreply(ctx, rcode, xcode, message) ctx->ctx_reply = buf; return MI_SUCCESS; } + +#if _FFR_MULTILINE +/* +** SMFI_SETMLREPLY -- set multiline reply code for the next reply to the MTA +** +** Parameters: +** ctx -- Opaque context structure +** rcode -- The three-digit (RFC 821) SMTP reply code. +** xcode -- The extended (RFC 2034) reply code. +** txt, ... -- The text part of the SMTP reply, +** MUST be terminated with NULL. +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +#if SM_VA_STD +smfi_setmlreply(SMFICTX *ctx, const char *rcode, const char *xcode, ...) +#else /* SM_VA_STD */ +smfi_setmlreply(ctx, rcode, xcode, va_alist) + SMFICTX *ctx; + const char *rcode; + const char *xcode; + va_dcl +#endif /* SM_VA_STD */ +{ + size_t len; + size_t rlen; + int args; + char *buf, *txt; + const char *xc; + char repl[16]; + SM_VA_LOCAL_DECL + + if (rcode == NULL || ctx == NULL) + return MI_FAILURE; + + /* ### <sp> */ + len = strlen(rcode) + 1; + if (len != 4) + return MI_FAILURE; + if ((rcode[0] != '4' && rcode[0] != '5') || + !isascii(rcode[1]) || !isdigit(rcode[1]) || + !isascii(rcode[2]) || !isdigit(rcode[2])) + return MI_FAILURE; + if (xcode != NULL) + { + if (!myisenhsc(xcode, '\0')) + return MI_FAILURE; + xc = xcode; + } + else + { + if (rcode[0] == '4') + xc = "4.0.0"; + else + xc = "5.0.0"; + } + + /* add trailing space */ + len += strlen(xc) + 1; + rlen = len; + args = 0; + SM_VA_START(ap, xcode); + while ((txt = SM_VA_ARG(ap, char *)) != NULL) + { + size_t tl; + + tl = strlen(txt); + if (tl > MAXREPLYLEN) + return MI_FAILURE; + + /* this text, reply codes, \r\n */ + len += tl + 2 + rlen; + if (++args > MAXREPLIES) + return MI_FAILURE; + + /* XXX check also for unprintable chars? */ + if (strpbrk(txt, "\r\n") != NULL) + return MI_FAILURE; + } + SM_VA_END(ap); + + /* trailing '\0' */ + ++len; + buf = malloc(len); + if (buf == NULL) + return MI_FAILURE; /* oops */ + (void) sm_strlcpyn(buf, len, 3, rcode, args == 1 ? " " : "-", xc); + (void) sm_strlcpyn(repl, sizeof repl, 4, rcode, args == 1 ? " " : "-", + xc, " "); + SM_VA_START(ap, xcode); + txt = SM_VA_ARG(ap, char *); + if (txt != NULL) + { + (void) sm_strlcat2(buf, " ", txt, len); + while ((txt = SM_VA_ARG(ap, char *)) != NULL) + { + if (--args <= 1) + repl[3] = ' '; + (void) sm_strlcat2(buf, "\r\n", repl, len); + (void) sm_strlcat(buf, txt, len); + } + } + if (ctx->ctx_reply != NULL) + free(ctx->ctx_reply); + ctx->ctx_reply = buf; + SM_VA_END(ap); + return MI_SUCCESS; +} +#endif /* _FFR_MULTILINE */ + /* ** SMFI_SETPRIV -- set private data ** |