diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-01-14 03:21:42 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-01-14 03:21:42 +0000 |
commit | 329cc2cc87730afac9b71e587a23dd70c8b53901 (patch) | |
tree | 82a4eac04f293758bda7297055a7c8e1236b4b76 /gnu/usr.sbin/sendmail/libmilter | |
parent | 67e6877326ec09684a9203da8452b23c01cd134c (diff) |
update to sendmail-8.12.2
Diffstat (limited to 'gnu/usr.sbin/sendmail/libmilter')
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/Makefile | 7 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/README | 20 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/comm.c | 9 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/docs/xxfi_body.html | 8 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/docs/xxfi_connect.html | 7 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/engine.c | 26 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/handler.c | 4 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/libmilter.h | 11 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/listener.c | 48 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/main.c | 10 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/signal.c | 20 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/smfi.c | 146 |
12 files changed, 256 insertions, 60 deletions
diff --git a/gnu/usr.sbin/sendmail/libmilter/Makefile b/gnu/usr.sbin/sendmail/libmilter/Makefile index 3e5a650668c..759b2b45e89 100644 --- a/gnu/usr.sbin/sendmail/libmilter/Makefile +++ b/gnu/usr.sbin/sendmail/libmilter/Makefile @@ -1,9 +1,10 @@ -# $OpenBSD: Makefile,v 1.3 2001/09/11 19:02:49 millert Exp $ +# $OpenBSD: Makefile,v 1.4 2002/01/14 03:21:40 millert Exp $ LIB= milter SRCS= main.c engine.c listener.c handler.c comm.c smfi.c signal.c \ - sm_gethost.c -CPPFLAGS+= -pthread + sm_gethost.c errstring.c strl.c +CPPFLAGS+= -pthread -Dsm_snprintf=snprintf +.PATH: ${.CURDIR}/../libsm # This is not a library that gets installed so only build the .a version # In the future we may wish to install it to ease the use of external filters. diff --git a/gnu/usr.sbin/sendmail/libmilter/README b/gnu/usr.sbin/sendmail/libmilter/README index fed06305d78..39049a4c0fe 100644 --- a/gnu/usr.sbin/sendmail/libmilter/README +++ b/gnu/usr.sbin/sendmail/libmilter/README @@ -15,6 +15,22 @@ your devtools/Site/site.config.m4 file: APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER') ++----------------+ +| SECURITY HINTS | ++----------------+ + +Note: we strongly recommend not to run any milter as root. Libmilter +does not need root access to communicate with sendmail. It is a +good security practice to run a program only with root privileges +if really necessary. A milter should probably check first whether +it runs as root and refuse to start in that case. There is a +compile time option _FFR_MILTER_ROOT_UNSAFE which keeps libmilter +from unlinking a socket when running as root. It is recommended +to turn on this option: + + APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER_ROOT_UNSAFE ') + + +-------------------+ | BUILDING A FILTER | +-------------------+ @@ -71,7 +87,7 @@ IPv4 socket on port 3333 of localhost. The current flags (F=) are: T Temporary fail connection if filter unavailable If neither F=R nor F=T is specified, the message is passed through sendmail -as if the filter were not present. +in case of filter errors as if the failing filters were not present. Finally, you can override the default timeouts used by sendmail when talking to the filters using the T= equate. There are four fields inside @@ -441,4 +457,4 @@ main(argc, argv) /* eof */ -$Revision: 1.8 $, Last updated $Date: 2001/09/11 19:02:49 $ +$Revision: 1.9 $, Last updated $Date: 2002/01/14 03:21:40 $ diff --git a/gnu/usr.sbin/sendmail/libmilter/comm.c b/gnu/usr.sbin/sendmail/libmilter/comm.c index 7f7c3e91e97..48818b13ca6 100644 --- a/gnu/usr.sbin/sendmail/libmilter/comm.c +++ b/gnu/usr.sbin/sendmail/libmilter/comm.c @@ -9,7 +9,7 @@ */ #include <sm/gen.h> -SM_RCSID("@(#)$Sendmail: comm.c,v 8.46 2001/09/11 04:04:44 gshapiro Exp $") +SM_RCSID("@(#)$Sendmail: comm.c,v 8.48 2001/11/07 17:43:04 ca Exp $") #include "libmilter.h" #include <sm/errstring.h> @@ -72,7 +72,9 @@ mi_rd_cmd(sd, timeout, cmd, rlen, name) *cmd = SMFIC_SELECT; return NULL; } - if ((len = MI_SOCK_READ(sd, data + i, sizeof data - i)) < 0) + + len = MI_SOCK_READ(sd, data + i, sizeof data - i); + if (MI_SOCK_READ_FAIL(len)) { smi_log(SMI_LOG_ERR, "%s, mi_rd_cmd: read returned %d: %s", @@ -136,7 +138,8 @@ mi_rd_cmd(sd, timeout, cmd, rlen, name) free(buf); return NULL; } - if ((len = MI_SOCK_READ(sd, buf + i, expl - i)) < 0) + len = MI_SOCK_READ(sd, buf + i, expl - i); + if (MI_SOCK_READ_FAIL(len)) { smi_log(SMI_LOG_ERR, "%s: mi_rd_cmd: read returned %d: %s", diff --git a/gnu/usr.sbin/sendmail/libmilter/docs/xxfi_body.html b/gnu/usr.sbin/sendmail/libmilter/docs/xxfi_body.html index abb8c81303b..b19e0d4913d 100644 --- a/gnu/usr.sbin/sendmail/libmilter/docs/xxfi_body.html +++ b/gnu/usr.sbin/sendmail/libmilter/docs/xxfi_body.html @@ -51,6 +51,12 @@ Handle a piece of a message's body. <th valign="top" align=left>NOTES</th> <td> <ul> +<li>bodyp points to a sequence of bytes. +It is <em>not</em> a C string (a sequence of characters that is terminated by '\0'). +Therefore, do not use the usual C string functions like strlen() on this byte block. +Moreover, the byte sequence may contain '\0' characters inside the block. +Hence even if a trailing '\0' is added, C string functions may still fail +to work as expected. <li>Since message bodies can be very large, defining xxfi_body can significantly impact filter performance. <li>End-of-lines are represented as received from SMTP (normally CR/LF). @@ -64,7 +70,7 @@ significantly impact filter performance. <hr size="1"> <font size="-1"> -Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. +Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. All rights reserved. <br> By using this file, you agree to the terms and conditions set diff --git a/gnu/usr.sbin/sendmail/libmilter/docs/xxfi_connect.html b/gnu/usr.sbin/sendmail/libmilter/docs/xxfi_connect.html index a174bf64f65..17102856ba2 100644 --- a/gnu/usr.sbin/sendmail/libmilter/docs/xxfi_connect.html +++ b/gnu/usr.sbin/sendmail/libmilter/docs/xxfi_connect.html @@ -49,7 +49,10 @@ is passed to smfi_register(). address enclosed in square brackets (e.g. `[a.b.c.d]'). </td></tr> <tr><td>hostaddr</td> - <td>the host address, as determined by a getpeername() call on the SMTP socket. NULL if the type is not supported in the current version.</td></tr> + <td>the host address, as determined by a getpeername() call on the SMTP socket. + NULL if the type is not supported in the current version or if + the SMTP connection is made via stdin. + </td></tr> </table> </td></tr> <!----------- Return values ----------> @@ -77,7 +80,7 @@ routine, this filter's xxfi_connect() will not be called.</td> <hr size="1"> <font size="-1"> -Copyright (c) 2000 Sendmail, Inc. and its suppliers. +Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. All rights reserved. <br> By using this file, you agree to the terms and conditions set diff --git a/gnu/usr.sbin/sendmail/libmilter/engine.c b/gnu/usr.sbin/sendmail/libmilter/engine.c index 7393b2a25d7..e12f84788f1 100644 --- a/gnu/usr.sbin/sendmail/libmilter/engine.c +++ b/gnu/usr.sbin/sendmail/libmilter/engine.c @@ -9,7 +9,7 @@ */ #include <sm/gen.h> -SM_RCSID("@(#)$Sendmail: engine.c,v 8.97 2001/09/11 04:04:44 gshapiro Exp $") +SM_RCSID("@(#)$Sendmail: engine.c,v 8.102 2001/12/13 17:10:00 ca Exp $") #include "libmilter.h" @@ -172,6 +172,7 @@ static cmdfct cmds[] = #define _SMFIS_OPTIONS 22 #define _SMFIS_NOREPLY 23 #define _SMFIS_FAIL (-1) +#define _SMFIS_NONE (-2) /* ** MI_ENGINE -- receive commands and process them @@ -208,6 +209,7 @@ mi_engine(ctx) fi_abort = ctx->ctx_smfi->xxfi_abort; mi_clr_macros(ctx, 0); fix_stm(ctx); + r = _SMFIS_NONE; do { /* call abort only if in a mail transaction */ @@ -222,6 +224,18 @@ mi_engine(ctx) ret = MI_FAILURE; break; } + + /* + ** Notice: buf is allocated by mi_rd_cmd() and it will + ** usually be free()d after it has been used in f(). + ** However, if the function returns _SMFIS_KEEP then buf + ** contains macros and will not be free()d. + ** Hence r must be set to _SMFIS_NONE if a new buf is + ** allocated to avoid problem with housekeeping, esp. + ** if the code "break"s out of the loop. + */ + + r = _SMFIS_NONE; if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len, ctx->ctx_smfi->xxfi_name)) == NULL && cmd < SMFIC_VALIDCMD) @@ -293,7 +307,11 @@ mi_engine(ctx) curstate = ST_HELO; if (!trans_ok(curstate, newstate)) + { + free(buf); + buf = NULL; continue; + } } arg.a_len = len; arg.a_buf = buf; @@ -354,7 +372,7 @@ mi_engine(ctx) /* close must always be called */ if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) (void) (*fi_close)(ctx); - if (buf != NULL) + if (r != _SMFIS_KEEP && buf != NULL) free(buf); mi_clr_macros(ctx, 0); return ret; @@ -1116,7 +1134,11 @@ mi_sendok(ctx, flag) { if (ctx == NULL || ctx->ctx_smfi == NULL) return false; + + /* did the milter request this operation? */ if (flag != 0 && !bitset(flag, ctx->ctx_smfi->xxfi_flags)) return false; + + /* are we in the correct state? It must be "End of Message". */ return ctx->ctx_state == ST_ENDM; } diff --git a/gnu/usr.sbin/sendmail/libmilter/handler.c b/gnu/usr.sbin/sendmail/libmilter/handler.c index 9fcf3c587b1..ab5c4f110ad 100644 --- a/gnu/usr.sbin/sendmail/libmilter/handler.c +++ b/gnu/usr.sbin/sendmail/libmilter/handler.c @@ -9,7 +9,7 @@ */ #include <sm/gen.h> -SM_RCSID("@(#)$Sendmail: handler.c,v 8.26 2001/09/11 04:04:45 gshapiro Exp $") +SM_RCSID("@(#)$Sendmail: handler.c,v 8.29 2001/11/15 00:17:15 msk Exp $") #include "libmilter.h" @@ -43,7 +43,7 @@ mi_handle_session(ctx) ret = mi_engine(ctx); if (ValidSocket(ctx->ctx_sd)) { - (void) close(ctx->ctx_sd); + (void) closesocket(ctx->ctx_sd); ctx->ctx_sd = INVALID_SOCKET; } if (ctx->ctx_reply != NULL) diff --git a/gnu/usr.sbin/sendmail/libmilter/libmilter.h b/gnu/usr.sbin/sendmail/libmilter/libmilter.h index f68d3d32021..207ae1f876d 100644 --- a/gnu/usr.sbin/sendmail/libmilter/libmilter.h +++ b/gnu/usr.sbin/sendmail/libmilter/libmilter.h @@ -19,7 +19,7 @@ #ifdef _DEFINE # define EXTERN # define INIT(x) = x -SM_IDSTR(MilterlId, "@(#)$Sendmail: libmilter.h,v 8.28 2001/09/11 04:04:45 gshapiro Exp $") +SM_IDSTR(MilterlId, "@(#)$Sendmail: libmilter.h,v 8.32 2001/11/29 02:21:02 ca Exp $") #else /* _DEFINE */ # define EXTERN extern # define INIT(x) @@ -33,9 +33,11 @@ SM_IDSTR(MilterlId, "@(#)$Sendmail: libmilter.h,v 8.28 2001/09/11 04:04:45 gshap #include "libmilter/milter.h" # define ValidSocket(sd) ((sd) >= 0) -# define INVALID_SOCKET -1 -# define MI_SOCK_READ(s, b, l) (read(s, b, l)) -# define MI_SOCK_WRITE(s, b, l) (write(s, b, l)) +# define INVALID_SOCKET (-1) +# define closesocket close +# define MI_SOCK_READ(s, b, l) read(s, b, l) +# define MI_SOCK_READ_FAIL(x) ((x) < 0) +# define MI_SOCK_WRITE(s, b, l) write(s, b, l) # define thread_create(ptid,wr,arg) pthread_create(ptid, NULL, wr, arg) # define sthread_get_id() pthread_self() @@ -114,4 +116,5 @@ extern char *mi_rd_cmd __P((socket_t, struct timeval *, char *, size_t *, char * extern int mi_wr_cmd __P((socket_t, struct timeval *, int, char *, size_t)); extern bool mi_sendok __P((SMFICTX_PTR, int)); + #endif /* !_LIBMILTER_H */ diff --git a/gnu/usr.sbin/sendmail/libmilter/listener.c b/gnu/usr.sbin/sendmail/libmilter/listener.c index f573c8e65d1..c81ebbaafa7 100644 --- a/gnu/usr.sbin/sendmail/libmilter/listener.c +++ b/gnu/usr.sbin/sendmail/libmilter/listener.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,7 +9,7 @@ */ #include <sm/gen.h> -SM_RCSID("@(#)$Sendmail: listener.c,v 8.75 2001/09/11 04:04:45 gshapiro Exp $") +SM_RCSID("@(#)$Sendmail: listener.c,v 8.81 2002/01/08 23:14:23 ca Exp $") /* ** listener.c -- threaded network listener @@ -56,7 +56,7 @@ mi_milteropen(conn, backlog, socksize, family, name) { socket_t sock; int sockopt = 1; - size_t len = -1; + size_t len = 0; char *p; char *colon; char *at; @@ -386,7 +386,7 @@ mi_milteropen(conn, backlog, socksize, family, name) smi_log(SMI_LOG_ERR, "%s: Unable to setsockopt: %s", name, sm_errstring(errno)); - (void) close(sock); + (void) closesocket(sock); return INVALID_SOCKET; } @@ -395,7 +395,7 @@ mi_milteropen(conn, backlog, socksize, family, name) smi_log(SMI_LOG_ERR, "%s: Unable to bind to port %s: %s", name, conn, sm_errstring(errno)); - (void) close(sock); + (void) closesocket(sock); return INVALID_SOCKET; } @@ -404,7 +404,7 @@ mi_milteropen(conn, backlog, socksize, family, name) smi_log(SMI_LOG_ERR, "%s: listen call failed: %s", name, sm_errstring(errno)); - (void) close(sock); + (void) closesocket(sock); return INVALID_SOCKET; } @@ -415,6 +415,7 @@ mi_milteropen(conn, backlog, socksize, family, name) ** Set global variable sockpath so the UNIX socket can be ** unlink()ed at exit. */ + sockpath = (char *) malloc(len); if (sockpath != NULL) (void) sm_strlcpy(sockpath, colon, len); @@ -423,7 +424,7 @@ mi_milteropen(conn, backlog, socksize, family, name) smi_log(SMI_LOG_ERR, "%s: can't malloc(%d) for sockpath: %s", name, len, sm_errstring(errno)); - (void) close(sock); + (void) closesocket(sock); return INVALID_SOCKET; } } @@ -470,21 +471,23 @@ mi_closener() if (ValidSocket(listenfd)) { #if NETUNIX - bool removable = false; + bool removable; struct stat sockinfo; struct stat fileinfo; - if (sockpath != NULL && - fstat(listenfd, &sockinfo) == 0 && - (S_ISFIFO(sockinfo.st_mode) + removable = sockpath != NULL && +#if _FFR_MILTER_ROOT_UNSAFE + geteuid() != 0 && +#endif /* _FFR_MILTER_ROOT_UNSAFE */ + fstat(listenfd, &sockinfo) == 0 && + (S_ISFIFO(sockinfo.st_mode) # ifdef S_ISSOCK - || !S_ISSOCK(sockinfo.st_mode) + || S_ISSOCK(sockinfo.st_mode) # endif /* S_ISSOCK */ - )) - removable = true; + ); #endif /* NETUNIX */ - (void) close(listenfd); + (void) closesocket(listenfd); listenfd = INVALID_SOCKET; #if NETUNIX @@ -493,8 +496,13 @@ mi_closener() { if (removable && stat(sockpath, &fileinfo) == 0 && - fileinfo.st_dev == sockinfo.st_dev && - fileinfo.st_ino == sockinfo.st_ino && + ((fileinfo.st_dev == sockinfo.st_dev && + fileinfo.st_ino == sockinfo.st_ino) +# ifdef S_ISSOCK + || S_ISSOCK(fileinfo.st_mode) +# endif /* S_ISSOCK */ + ) + && (S_ISFIFO(fileinfo.st_mode) # ifdef S_ISSOCK || S_ISSOCK(fileinfo.st_mode) @@ -692,7 +700,7 @@ mi_listener(conn, dbg, smfi, timeout, backlog) # endif /* BSD4_4_SOCKADDR */ cliaddr.sa.sa_family != family)) { - (void) close(connfd); + (void) closesocket(connfd); connfd = INVALID_SOCKET; save_errno = EINVAL; } @@ -725,7 +733,7 @@ mi_listener(conn, dbg, smfi, timeout, backlog) } if ((ctx = (SMFICTX_PTR) malloc(sizeof *ctx)) == NULL) { - (void) close(connfd); + (void) closesocket(connfd); mcnt++; smi_log(SMI_LOG_ERR, "%s: malloc(ctx) failed (%s), %s", smfi->xxfi_name, sm_errstring(save_errno), @@ -775,7 +783,7 @@ mi_listener(conn, dbg, smfi, timeout, backlog) smfi->xxfi_name, r, tcnt >= MAX_FAILS_T ? "abort" : "try again"); MI_SLEEP(tcnt); - (void) close(connfd); + (void) closesocket(connfd); free(ctx); if (tcnt >= MAX_FAILS_T) { diff --git a/gnu/usr.sbin/sendmail/libmilter/main.c b/gnu/usr.sbin/sendmail/libmilter/main.c index 2a7f665cb81..042d1a35bad 100644 --- a/gnu/usr.sbin/sendmail/libmilter/main.c +++ b/gnu/usr.sbin/sendmail/libmilter/main.c @@ -9,7 +9,7 @@ */ #include <sm/gen.h> -SM_RCSID("@(#)$Sendmail: main.c,v 8.52 2001/09/11 04:04:45 gshapiro Exp $") +SM_RCSID("@(#)$Sendmail: main.c,v 8.53 2001/11/29 02:21:02 ca Exp $") #define _DEFINE 1 #include "libmilter.h" @@ -177,6 +177,7 @@ smfi_setbacklog(obacklog) return MI_SUCCESS; } + /* ** SMFI_MAIN -- setup milter connnection and start listener. ** @@ -190,6 +191,8 @@ smfi_setbacklog(obacklog) int smfi_main() { + int r; + (void) signal(SIGPIPE, SIG_IGN); if (conn == NULL) { @@ -206,10 +209,11 @@ smfi_main() smfi->xxfi_name); return MI_FAILURE; } + r = MI_SUCCESS; /* Startup the listener */ if (mi_listener(conn, dbg, smfi, timeout, backlog) != MI_SUCCESS) - return MI_FAILURE; + r = MI_FAILURE; - return MI_SUCCESS; + return r; } diff --git a/gnu/usr.sbin/sendmail/libmilter/signal.c b/gnu/usr.sbin/sendmail/libmilter/signal.c index 113f7c9a96a..5a2c49bd5ec 100644 --- a/gnu/usr.sbin/sendmail/libmilter/signal.c +++ b/gnu/usr.sbin/sendmail/libmilter/signal.c @@ -9,7 +9,7 @@ */ #include <sm/gen.h> -SM_RCSID("@(#)$Sendmail: signal.c,v 8.27 2001/09/11 04:04:45 gshapiro Exp $") +SM_RCSID("@(#)$Sendmail: signal.c,v 8.35 2002/01/10 01:34:55 ca Exp $") #include "libmilter.h" @@ -101,15 +101,15 @@ mi_signal_thread(name) while (true) { sig = 0; -#ifdef SOLARIS +#if defined(SOLARIS) || defined(__svr5__) if ((sig = sigwait(&set)) < 0) -#else /* SOLARIS */ +#else /* defined(SOLARIS) || defined(__svr5__) */ if (sigwait(&set, &sig) != 0) -#endif /* SOLARIS */ +#endif /* defined(SOLARIS) || defined(__svr5__) */ { smi_log(SMI_LOG_ERR, - "%s: sigwait returned error: %s", - (char *)name, strerror(errno)); + "%s: sigwait returned error: %d", + (char *)name, errno); if (++errs > MAX_FAILS_T) { mi_stop_milters(MILTER_ABRT); @@ -151,6 +151,7 @@ mi_spawn_signal_thread(name) char *name; { sthread_t tid; + int r; sigset_t set; /* Mask HUP and KILL signals */ @@ -165,11 +166,12 @@ mi_spawn_signal_thread(name) "%s: Couldn't mask HUP and KILL signals", name); return MI_FAILURE; } - if (thread_create(&tid, mi_signal_thread, - (void *)name) != MI_SUCCESS) + r = thread_create(&tid, mi_signal_thread, (void *)name); + if (r != 0) { smi_log(SMI_LOG_ERR, - "%s: Couldn't start signal thread", name); + "%s: Couldn't start signal thread: %d", + name, r); return MI_FAILURE; } return MI_SUCCESS; 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 ** |