summaryrefslogtreecommitdiff
path: root/gnu/usr.sbin/sendmail/libmilter
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2002-01-14 03:21:42 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2002-01-14 03:21:42 +0000
commit329cc2cc87730afac9b71e587a23dd70c8b53901 (patch)
tree82a4eac04f293758bda7297055a7c8e1236b4b76 /gnu/usr.sbin/sendmail/libmilter
parent67e6877326ec09684a9203da8452b23c01cd134c (diff)
update to sendmail-8.12.2
Diffstat (limited to 'gnu/usr.sbin/sendmail/libmilter')
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/Makefile7
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/README20
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/comm.c9
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/docs/xxfi_body.html8
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/docs/xxfi_connect.html7
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/engine.c26
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/handler.c4
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/libmilter.h11
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/listener.c48
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/main.c10
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/signal.c20
-rw-r--r--gnu/usr.sbin/sendmail/libmilter/smfi.c146
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
**