diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2001-01-15 21:09:13 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2001-01-15 21:09:13 +0000 |
commit | 5062bcecfa81a7e0dd07894d6e93655a97239964 (patch) | |
tree | fd0e0dd2a71271dbe81c195cd9fbdd57fb7c20fb /gnu/usr.sbin/sendmail/libmilter | |
parent | 91deaea81040227b9ba537ff047f1f863f75fc31 (diff) |
sendmail 8.11.2 with BSD Makefiles
Diffstat (limited to 'gnu/usr.sbin/sendmail/libmilter')
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/README | 63 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/comm.c | 62 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/engine.c | 160 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/handler.c | 17 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/libmilter.h | 40 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/listener.c | 150 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/main.c | 55 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/signal.c | 43 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/sm_gethost.c | 22 | ||||
-rw-r--r-- | gnu/usr.sbin/sendmail/libmilter/smfi.c | 95 |
10 files changed, 496 insertions, 211 deletions
diff --git a/gnu/usr.sbin/sendmail/libmilter/README b/gnu/usr.sbin/sendmail/libmilter/README index 621219fb044..59d8beca9e1 100644 --- a/gnu/usr.sbin/sendmail/libmilter/README +++ b/gnu/usr.sbin/sendmail/libmilter/README @@ -18,6 +18,9 @@ adding the following to your devtools/Site/site.config.m4 file: APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_MILTER=1') APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER=1') +You will also need to define _FFR_MILTER when building your .cf file using +m4. + +-------------------+ | BUILDING A FILTER | +-------------------+ @@ -32,7 +35,8 @@ It is recommended that you build your filters in a location outside of the sendmail source tree. Modify the compiler include references (-I) and the library locations accordingly. Also, some operating systems may require additional libraries. For example, SunOS 5.X requires '-lresolv --lsocket -lnsl'. +-lsocket -lnsl'. Depending on your OS you may need a library instead +of the option -pthread, e.g., -lpthread. Filters must be thread-safe! Many operating systems now provide support for POSIX threads in the standard C libraries. The compiler flag to link with @@ -49,14 +53,14 @@ Filters are specified with a key letter ``X'' (for ``eXternal''). For example: - Xfilter1, S=unix:/var/run/f1.sock, F=R + Xfilter1, S=local:/var/run/f1.sock, F=R Xfilter2, S=inet6:999@localhost, F=T, T=S:1s;R:1s;E:5m Xfilter3, S=inet:3333@localhost specifies three filters. Filters can be specified in your .mc file using the following: - INPUT_MAIL_FILTER(`filter1', `S=unix:/var/run/f1.sock, F=R') + INPUT_MAIL_FILTER(`filter1', `S=local:/var/run/f1.sock, F=R') INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T, T=S:1s;R:1s;E:5m') INPUT_MAIL_FILTER(`filter3', `S=inet:3333@localhost') @@ -67,6 +71,9 @@ IPv4 socket on port 3333 of localhost. The current flags (F=) are: R Reject connection if filter unavailable 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. + Finally, you can override the default timeouts used by sendmail when talking to the filters using the T= equate. There are three fields inside of the T= equate: @@ -84,13 +91,17 @@ T=S:10s;R:10s;E:5m where 's' is seconds and 'm' is minutes. -Actual sequencing is handled by the InputMailFilters option which is set -automatically according to the order of the INPUT_MAIL_FILTER commands -in your .mc file. Alternatively, you can reset it's value by setting -confINPUT_MAIL_FILTERS in your .mc file. This options causes the three -filters to be called in the same order they were specified. It allows -for possible future filtering on output (although this is not intended -for this release). +Which filters are invoked and their sequencing is handled by the +InputMailFilters option. + + O InputMailFilters=filter1, filter2, filter3 + +This is is set automatically according to the order of the +INPUT_MAIL_FILTER commands in your .mc file. Alternatively, you can +reset its value by setting confINPUT_MAIL_FILTERS in your .mc file. +This options causes the three filters to be called in the same order +they were specified. It allows for possible future filtering on output +(although this is not intended for this release). Also note that a filter can be defined without adding it to the input filter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER() in your @@ -99,7 +110,7 @@ filter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER() in your To test sendmail with the sample filter, the following might be added (in the appropriate locations) to your .mc file: - INPUT_MAIL_FILTER(`sample', `S=unix:/var/run/f1.sock') + INPUT_MAIL_FILTER(`sample', `S=local:/var/run/f1.sock') +------------------+ @@ -115,7 +126,7 @@ on which to create a listening socket for the filter. Maintaining consistency with the suggested options for sendmail.cf, this would be the UNIX domain socket located in /var/run/f1.sock. - % ./sample -p unix:/var/run/f1.sock + % ./sample -p local:/var/run/f1.sock If the sample filter returns immediately to a command line, there was either an error with your command or a problem creating the specified socket. @@ -130,7 +141,7 @@ connected via one of these options, the session can be continued through the use of standard SMTP commands. % sendmail -bs -220 test.sendmail.com ESMTP Sendmail 8.10.0.Beta8/8.10.0.Beta8; Mon, 6 Dec 1999 19:34:23 -0800 (PST) +220 test.sendmail.com ESMTP Sendmail 8.11.0/8.11.0; Tue, 10 Nov 1970 13:05:23 -0500 (EST) HELO localhost 250 test.sendmail.com Hello testy@localhost, pleased to meet you MAIL From:<testy> @@ -167,10 +178,30 @@ See the sendmail(8) manual page for more information. | SOURCE FOR SAMPLE FILTER | +--------------------------+ +Note that the filter below may not be thread safe on some operating +systems. You should check your system man pages for the functions used +below to verify the functions are thread safe. + /* A trivial filter that logs all email to a file. */ +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> +#include <unistd.h> + #include "libmilter/mfapi.h" +typedef int bool; + +#ifndef FALSE +# define FALSE 0 +#endif /* ! FALSE*/ +#ifndef TRUE +# define TRUE 1 +#endif /* ! TRUE*/ + struct mlfiPriv { char *mlfi_fname; @@ -336,7 +367,7 @@ struct smfiDesc smfilter = { "SampleFilter", /* filter name */ SMFI_VERSION, /* version code -- do not change */ - SMFIF_MODHDRS, /* flags */ + SMFIF_ADDHDRS, /* flags */ NULL, /* connection info filter */ NULL, /* SMTP HELO command filter */ mlfi_envfrom, /* envelope sender filter */ @@ -355,7 +386,7 @@ main(argc, argv) int argc; char *argv[]; { - char c; + int c; const char *args = "p:"; /* Process command line options */ @@ -385,4 +416,4 @@ main(argc, argv) /* eof */ -$Revision: 1.3 $, Last updated $Date: 2000/04/07 19:20:34 $ +$Revision: 1.4 $, Last updated $Date: 2001/01/15 21:09:02 $ diff --git a/gnu/usr.sbin/sendmail/libmilter/comm.c b/gnu/usr.sbin/sendmail/libmilter/comm.c index 9e8702807ba..692ec2e84a4 100644 --- a/gnu/usr.sbin/sendmail/libmilter/comm.c +++ b/gnu/usr.sbin/sendmail/libmilter/comm.c @@ -9,24 +9,24 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: comm.c,v 8.30 2000/02/11 00:12:29 ca Exp $"; +static char id[] = "@(#)$Sendmail: comm.c,v 8.30.4.6 2000/10/05 22:44:01 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER #include "libmilter.h" #define FD_Z FD_ZERO(&readset); \ - FD_SET(fd, &readset); \ + FD_SET((u_int) sd, &readset); \ FD_ZERO(&excset); \ - FD_SET(fd, &excset) + FD_SET((u_int) sd, &excset) /* ** MI_RD_CMD -- read a command ** ** Parameters: -** fd -- file descriptor +** sd -- socket descriptor ** timeout -- maximum time to wait -** cmd -- single character command read from fd +** cmd -- single character command read from sd ** rlen -- pointer to length of result ** name -- name of milter ** @@ -37,8 +37,8 @@ static char id[] = "@(#)$Sendmail: comm.c,v 8.30 2000/02/11 00:12:29 ca Exp $"; */ char * -mi_rd_cmd(fd, timeout, cmd, rlen, name) - int fd; +mi_rd_cmd(sd, timeout, cmd, rlen, name) + socket_t sd; struct timeval *timeout; char *cmd; size_t *rlen; @@ -55,23 +55,25 @@ mi_rd_cmd(fd, timeout, cmd, rlen, name) *cmd = '\0'; *rlen = 0; - if (fd >= FD_SETSIZE) + + if (sd >= FD_SETSIZE) { smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d", - name, fd, FD_SETSIZE); + name, sd, FD_SETSIZE); *cmd = SMFIC_SELECT; return NULL; } + FD_Z; i = 0; - while ((ret = select(fd + 1, &readset, NULL, &excset, timeout)) >= 1) + while ((ret = select(sd + 1, &readset, NULL, &excset, timeout)) >= 1) { - if (FD_ISSET(fd, &excset)) + if (FD_ISSET(sd, &excset)) { *cmd = SMFIC_SELECT; return NULL; } - if ((len = read(fd, data + i, sizeof data - i)) < 0) + if ((len = MI_SOCK_READ(sd, data + i, sizeof data - i)) < 0) { smi_log(SMI_LOG_ERR, "%s, mi_rd_cmd: read returned %d: %s", @@ -84,7 +86,7 @@ mi_rd_cmd(fd, timeout, cmd, rlen, name) *cmd = SMFIC_EOF; return NULL; } - if (len >= sizeof data - i) + if (len >= (ssize_t) sizeof data - i) break; i += len; FD_Z; @@ -123,15 +125,15 @@ mi_rd_cmd(fd, timeout, cmd, rlen, name) i = 0; FD_Z; - while ((ret = select(fd + 1, &readset, NULL, &excset, timeout)) == 1) + while ((ret = select(sd + 1, &readset, NULL, &excset, timeout)) == 1) { - if (FD_ISSET(fd, &excset)) + if (FD_ISSET(sd, &excset)) { *cmd = SMFIC_SELECT; free(buf); return NULL; } - if ((len = read(fd, buf + i, expl - i)) < 0) + if ((len = MI_SOCK_READ(sd, buf + i, expl - i)) < 0) { smi_log(SMI_LOG_ERR, "%s: mi_rd_cmd: read returned %d: %s", @@ -181,10 +183,10 @@ mi_rd_cmd(fd, timeout, cmd, rlen, name) return NULL; } /* -** MI_WR_CMD -- write a cmd to fd +** MI_WR_CMD -- write a cmd to sd ** ** Parameters: -** fd -- file descriptor +** sd -- socket descriptor ** timeout -- maximum time to wait (currently unused) ** cmd -- single character command to write ** buf -- buffer with further data @@ -195,8 +197,8 @@ mi_rd_cmd(fd, timeout, cmd, rlen, name) */ int -mi_wr_cmd(fd, timeout, cmd, buf, len) - int fd; +mi_wr_cmd(sd, timeout, cmd, buf, len) + socket_t sd; struct timeval *timeout; int cmd; char *buf; @@ -217,17 +219,19 @@ mi_wr_cmd(fd, timeout, cmd, buf, len) i = 0; sl = MILTER_LEN_BYTES + 1; - do { + do + { FD_ZERO(&wrtset); - FD_SET(fd, &wrtset); - if ((ret = select(fd + 1, NULL, &wrtset, NULL, timeout)) == 0) + FD_SET((u_int) sd, &wrtset); + if ((ret = select(sd + 1, NULL, &wrtset, NULL, timeout)) == 0) return MI_FAILURE; } while (ret < 0 && errno == EINTR); if (ret < 0) return MI_FAILURE; /* use writev() instead to send the whole stuff at once? */ - while ((l = write(fd, (void *) (data + i), sl - i)) < sl) + while ((l = MI_SOCK_WRITE(sd, (void *) (data + i), + sl - i)) < (ssize_t) sl) { if (l < 0) return MI_FAILURE; @@ -241,15 +245,17 @@ mi_wr_cmd(fd, timeout, cmd, buf, len) return MI_SUCCESS; i = 0; sl = len; - do { + do + { FD_ZERO(&wrtset); - FD_SET(fd, &wrtset); - if ((ret = select(fd + 1, NULL, &wrtset, NULL, timeout)) == 0) + FD_SET((u_int) sd, &wrtset); + if ((ret = select(sd + 1, NULL, &wrtset, NULL, timeout)) == 0) return MI_FAILURE; } while (ret < 0 && errno == EINTR); if (ret < 0) return MI_FAILURE; - while ((l = write(fd, (void *) (buf + i), sl - i)) < sl) + while ((l = MI_SOCK_WRITE(sd, (void *) (buf + i), + sl - i)) < (ssize_t) sl) { if (l < 0) return MI_FAILURE; diff --git a/gnu/usr.sbin/sendmail/libmilter/engine.c b/gnu/usr.sbin/sendmail/libmilter/engine.c index e0f4b378270..6da335ef550 100644 --- a/gnu/usr.sbin/sendmail/libmilter/engine.c +++ b/gnu/usr.sbin/sendmail/libmilter/engine.c @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: engine.c,v 8.67 2000/03/27 05:04:16 ca Exp $"; +static char id[] = "@(#)$Sendmail: engine.c,v 8.67.4.15 2000/12/29 19:43:10 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -20,9 +20,6 @@ static char id[] = "@(#)$Sendmail: engine.c,v 8.67 2000/03/27 05:04:16 ca Exp $" # include <arpa/inet.h> #endif /* NETINET || NETINET6 */ -/* length of options: two 32bit integers */ -#define MILTER_OPTLEN 8 - /* generic argument for functions in the command table */ struct arg_struct { @@ -87,7 +84,7 @@ static int st_sender __P((genarg *)); static int st_rcpt __P((genarg *)); static int st_eoh __P((genarg *)); static int st_quit __P((genarg *)); -static int sendreply __P((sfsistat, int, struct timeval *, SMFICTX_PTR)); +static int sendreply __P((sfsistat, socket_t, struct timeval *, SMFICTX_PTR)); static void fix_stm __P((SMFICTX_PTR)); static bool trans_ok __P((int, int)); static char **dec_argv __P((char *, size_t)); @@ -110,6 +107,9 @@ static int dec_arg2 __P((char *, size_t, char **, char **)); #define ST_LAST ST_ABRT #define ST_SKIP 15 /* not a state but required for the state table */ +/* in a mail transaction? must be before eom according to spec. */ +#define ST_IN_MAIL(st) ((st) >= ST_MAIL && (st) < ST_ENDM) + /* ** set of next states ** each state (ST_*) corresponds to bit in an int value (1 << state) @@ -187,11 +187,13 @@ mi_engine(ctx) SMFICTX_PTR ctx; { size_t len; - int i, fd; + int i; + socket_t sd; int ret = MI_SUCCESS; int ncmds = sizeof(cmds) / sizeof(cmdfct); int curstate = ST_INIT; int newstate; + bool call_abort; sfsistat r; char cmd; char *buf = NULL; @@ -199,13 +201,17 @@ mi_engine(ctx) struct timeval timeout; int (*f) __P((genarg *)); sfsistat (*fi_abort) __P((SMFICTX *)); + sfsistat (*fi_close) __P((SMFICTX *)); arg.a_ctx = ctx; - fd = ctx->ctx_fd; + sd = ctx->ctx_sd; fi_abort = ctx->ctx_smfi->xxfi_abort; mi_clr_macros(ctx, 0); fix_stm(ctx); - do { + do + { + /* call abort only if in a mail transaction */ + call_abort = ST_IN_MAIL(curstate); timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; if (mi_stop() == MILTER_ABRT) @@ -216,12 +222,12 @@ mi_engine(ctx) ret = MI_FAILURE; break; } - if ((buf = mi_rd_cmd(fd, &timeout, &cmd, &len, + if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len, ctx->ctx_smfi->xxfi_name)) == NULL && cmd < SMFIC_VALIDCMD) { if (ctx->ctx_dbg > 5) - dprintf("[%d] error (%x)\n", + dprintf("[%d] mi_engine: mi_rd_cmd error (%x)\n", (int) ctx->ctx_id, (int) cmd); /* @@ -275,7 +281,9 @@ mi_engine(ctx) curstate, MASK(curstate), newstate, MASK(newstate), next_states[curstate]); - if (fi_abort != NULL) + + /* call abort only if in a mail transaction */ + if (fi_abort != NULL && call_abort) (void) (*fi_abort)(ctx); /* @@ -303,12 +311,13 @@ mi_engine(ctx) free(buf); buf = NULL; } - if (sendreply(r, fd, &timeout, ctx) != MI_SUCCESS) + if (sendreply(r, sd, &timeout, ctx) != MI_SUCCESS) { ret = MI_FAILURE; break; } + call_abort = ST_IN_MAIL(curstate); if (r == SMFIS_ACCEPT) { /* accept mail, no further actions taken */ @@ -337,16 +346,14 @@ mi_engine(ctx) if (ret != MI_SUCCESS) { - if (fi_abort != NULL) + /* call abort only if in a mail transaction */ + if (fi_abort != NULL && call_abort) (void) (*fi_abort)(ctx); } - else - { - sfsistat (*fi_close) __P((SMFICTX *)); - if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) - (void) (*fi_close)(ctx); - } + /* close must always be called */ + if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) + (void) (*fi_close)(ctx); if (buf != NULL) free(buf); mi_clr_macros(ctx, 0); @@ -357,7 +364,7 @@ mi_engine(ctx) ** ** Parameters: ** r -- reply code -** fd -- file descriptor +** sd -- socket descriptor ** timeout_ptr -- (ptr to) timeout to use for sending ** ctx -- context structure ** @@ -366,24 +373,24 @@ mi_engine(ctx) */ static int -sendreply(r, fd, timeout_ptr, ctx) +sendreply(r, sd, timeout_ptr, ctx) sfsistat r; - int fd; + socket_t sd; struct timeval *timeout_ptr; SMFICTX_PTR ctx; { int ret = MI_SUCCESS; - switch(r) + switch (r) { case SMFIS_CONTINUE: - ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_CONTINUE, NULL, 0); + ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 0); break; case SMFIS_TEMPFAIL: case SMFIS_REJECT: if (ctx->ctx_reply != NULL) { - ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_REPLYCODE, + ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_REPLYCODE, ctx->ctx_reply, strlen(ctx->ctx_reply) + 1); free(ctx->ctx_reply); @@ -391,15 +398,15 @@ sendreply(r, fd, timeout_ptr, ctx) } else { - ret = mi_wr_cmd(fd, timeout_ptr, r == SMFIS_REJECT ? + ret = mi_wr_cmd(sd, timeout_ptr, r == SMFIS_REJECT ? SMFIR_REJECT : SMFIR_TEMPFAIL, NULL, 0); } break; case SMFIS_DISCARD: - ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_DISCARD, NULL, 0); + ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_DISCARD, NULL, 0); break; case SMFIS_ACCEPT: - ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_ACCEPT, NULL, 0); + ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_ACCEPT, NULL, 0); break; case _SMFIS_OPTIONS: { @@ -411,7 +418,10 @@ sendreply(r, fd, timeout_ptr, ctx) v = htonl(ctx->ctx_smfi->xxfi_flags); (void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v, MILTER_LEN_BYTES); - ret = mi_wr_cmd(fd, timeout_ptr, SMFIC_OPTNEG, buf, + v = htonl(ctx->ctx_pflags); + (void) memcpy(&(buf[MILTER_LEN_BYTES * 2]), (void *) &v, + MILTER_LEN_BYTES); + ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG, buf, MILTER_OPTLEN); } break; @@ -466,15 +476,17 @@ static int st_optionneg(g) genarg *g; { - mi_int32 i, version; + mi_int32 i, v; if (g == NULL || g->a_ctx->ctx_smfi == NULL) return SMFIS_CONTINUE; mi_clr_macros(g->a_ctx, g->a_idx + 1); - if (g->a_len != MILTER_OPTLEN) + + /* check for minimum length */ + if (g->a_len < MILTER_OPTLEN) { smi_log(SMI_LOG_ERR, - "%s: st_optionneg[%d]: len mismatch %d != %d", + "%s: st_optionneg[%d]: len too short %d < %d", g->a_ctx->ctx_smfi->xxfi_name, (int) g->a_ctx->ctx_id, g->a_len, MILTER_OPTLEN); @@ -483,23 +495,51 @@ st_optionneg(g) (void) memcpy((void *) &i, (void *) &(g->a_buf[0]), MILTER_LEN_BYTES); - version = ntohl(i); - if (version != g->a_ctx->ctx_smfi->xxfi_version) + v = ntohl(i); + if (v < g->a_ctx->ctx_smfi->xxfi_version) { + /* hard failure for now! */ smi_log(SMI_LOG_ERR, - "%s: st_optionneg[%d]: version mismatch %d != %d", + "%s: st_optionneg[%d]: version mismatch MTA: %d < milter: %d", g->a_ctx->ctx_smfi->xxfi_name, - (int) g->a_ctx->ctx_id, (int) version, + (int) g->a_ctx->ctx_id, (int) v, g->a_ctx->ctx_smfi->xxfi_version); return _SMFIS_ABORT; } -#if 0 - /* flags are currently ignored */ (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]), MILTER_LEN_BYTES); - flags = ntohl(i); -#endif /* 0 */ + v = ntohl(i); + + /* no flags? set to default value for V1 actions */ + if (v == 0) + v = SMFI_V1_ACTS; + i = g->a_ctx->ctx_smfi->xxfi_flags; + if ((v & i) != i) + { + smi_log(SMI_LOG_ERR, + "%s: st_optionneg[%d]: 0x%x does not fulfill action requirements 0x%x", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id, v, i); + return _SMFIS_ABORT; + } + + (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES * 2]), + MILTER_LEN_BYTES); + v = ntohl(i); + + /* no flags? set to default value for V1 protocol */ + if (v == 0) + v = SMFI_V1_PROT; + i = g->a_ctx->ctx_pflags; + if ((v & i) != i) + { + smi_log(SMI_LOG_ERR, + "%s: st_optionneg[%d]: 0x%x does not fulfill protocol requirements 0x%x", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id, v, i); + return _SMFIS_ABORT; + } return _SMFIS_OPTIONS; } @@ -518,9 +558,9 @@ st_connectinfo(g) genarg *g; { size_t l; - int i; + size_t i; char *s, family; - u_short port; + u_short port = 0; _SOCK_ADDR sockaddr; sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *)); @@ -569,6 +609,8 @@ st_connectinfo(g) return _SMFIS_ABORT; } sockaddr.sa.sa_family = AF_INET; + if (port > 0) + sockaddr.sin.sin_port = port; } else # endif /* NETINET */ @@ -585,6 +627,8 @@ st_connectinfo(g) return _SMFIS_ABORT; } sockaddr.sa.sa_family = AF_INET6; + if (port > 0) + sockaddr.sin6.sin6_port = port; } else # endif /* NETINET6 */ @@ -763,7 +807,7 @@ st_macros(g) return _SMFIS_FAIL; if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL) return _SMFIS_FAIL; - switch(g->a_buf[0]) + switch (g->a_buf[0]) { case SMFIC_CONNECT: i = CI_CONN; @@ -857,15 +901,15 @@ st_bodyend(g) if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL && g->a_len > 0) { - int fd; + socket_t sd; struct timeval timeout; timeout.tv_sec = g->a_ctx->ctx_timeout; timeout.tv_usec = 0; - fd = g->a_ctx->ctx_fd; + sd = g->a_ctx->ctx_sd; r = (*fi_body)(g->a_ctx, (u_char *)g->a_buf, g->a_len); if (r != SMFIS_CONTINUE && - sendreply(r, fd, &timeout, g->a_ctx) != MI_SUCCESS) + sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS) return _SMFIS_ABORT; } } @@ -915,7 +959,8 @@ trans_ok(old, new) int s, n; s = old; - do { + do + { /* is this state transition allowed? */ if ((MASK(new) & next_states[s]) != 0) return TRUE; @@ -960,21 +1005,20 @@ fix_stm(ctx) if (ctx == NULL || ctx->ctx_smfi == NULL) return; - fl = ctx->ctx_smfi->xxfi_flags; - if (bitset(SMFIF_NOCONNECT, fl)) + fl = ctx->ctx_pflags; + if (bitset(SMFIP_NOCONNECT, fl)) next_states[ST_CONN] |= NX_SKIP; - if (bitset(SMFIF_NOHELO, fl)) + if (bitset(SMFIP_NOHELO, fl)) next_states[ST_HELO] |= NX_SKIP; - if (bitset(SMFIF_NOMAIL, fl)) + if (bitset(SMFIP_NOMAIL, fl)) next_states[ST_MAIL] |= NX_SKIP; - if (bitset(SMFIF_NORCPT, fl)) + if (bitset(SMFIP_NORCPT, fl)) next_states[ST_RCPT] |= NX_SKIP; - if (bitset(SMFIF_NOHDRS, fl)) - { + if (bitset(SMFIP_NOHDRS, fl)) next_states[ST_HDRS] |= NX_SKIP; + if (bitset(SMFIP_NOEOH, fl)) next_states[ST_EOHS] |= NX_SKIP; - } - if (bitset(SMFIF_NOBODY, fl)) + if (bitset(SMFIP_NOBODY, fl)) next_states[ST_BODY] |= NX_SKIP; } /* @@ -1019,7 +1063,7 @@ dec_argv(buf, len) /* overwrite last entry */ s[elem] = NULL; - return (s); + return s; } /* ** DEC_ARG2 -- split a buffer into two strings @@ -1040,7 +1084,7 @@ dec_arg2(buf, len, s1, s2) char **s1; char **s2; { - int i; + size_t i; *s1 = buf; for (i = 1; i < len && buf[i] != '\0'; i++) diff --git a/gnu/usr.sbin/sendmail/libmilter/handler.c b/gnu/usr.sbin/sendmail/libmilter/handler.c index 0a805b75752..3b5102fe031 100644 --- a/gnu/usr.sbin/sendmail/libmilter/handler.c +++ b/gnu/usr.sbin/sendmail/libmilter/handler.c @@ -9,14 +9,15 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: handler.c,v 8.19 2000/02/11 00:12:29 ca Exp $"; +static char id[] = "@(#)$Sendmail: handler.c,v 8.19.4.3 2000/12/29 19:45:39 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER #include "libmilter.h" + /* -** HANDLE_SESSION -- Handle a connected session in it's own context +** HANDLE_SESSION -- Handle a connected session in its own context ** ** Parameters: ** ctx -- context structure @@ -33,7 +34,7 @@ mi_handle_session(ctx) if (ctx == NULL) return MI_FAILURE; - ctx->ctx_id = pthread_self(); + ctx->ctx_id = (sthread_t) sthread_get_id(); /* ** detach so resources are free when the thread returns @@ -42,10 +43,16 @@ mi_handle_session(ctx) if (pthread_detach(ctx->ctx_id) != 0) return MI_FAILURE; ret = mi_engine(ctx); - if (ctx->ctx_fd >= 0) - (void) close(ctx->ctx_fd); + if (ValidSocket(ctx->ctx_sd)) + { + (void) close(ctx->ctx_sd); + ctx->ctx_sd = INVALID_SOCKET; + } if (ctx->ctx_reply != NULL) + { free(ctx->ctx_reply); + ctx->ctx_reply = NULL; + } if (ctx->ctx_privdata != NULL) { smi_log(SMI_LOG_WARN, diff --git a/gnu/usr.sbin/sendmail/libmilter/libmilter.h b/gnu/usr.sbin/sendmail/libmilter/libmilter.h index eaf581d760a..898edfc38bd 100644 --- a/gnu/usr.sbin/sendmail/libmilter/libmilter.h +++ b/gnu/usr.sbin/sendmail/libmilter/libmilter.h @@ -8,7 +8,7 @@ */ /* -** MILTER.H -- include file for mail filter library functions +** LIBMILTER.H -- include file for mail filter library functions */ #ifndef _LIBMILTER_H @@ -17,21 +17,40 @@ # define EXTERN # define INIT(x) = x # ifndef lint -static char MilterlId[] = "@(#)$Sendmail: libmilter.h,v 8.3 2000/02/26 01:32:13 gshapiro Exp $"; +static char MilterlId[] = "@(#)$Sendmail: libmilter.h,v 8.3.6.10 2000/11/20 21:15:36 ca Exp $"; # endif /* ! lint */ #else /* _DEFINE */ # define EXTERN extern # define INIT(x) #endif /* _DEFINE */ + +#define NOT_SENDMAIL 1 +#define _SOCK_ADDR union bigsockaddr +#include "sendmail.h" + #include "libmilter/milter.h" -#include "libmilter/mfapi.h" #ifndef __P # include "sendmail/cdefs.h" #endif /* ! __P */ #include "sendmail/useful.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 thread_create(ptid,wr,arg) pthread_create(ptid, NULL, wr, arg) +# define sthread_get_id() pthread_self() + +typedef pthread_mutex_t smutex_t; +# define smutex_init(mp) (pthread_mutex_init(mp, NULL) == 0) +# define smutex_destroy(mp) (pthread_mutex_destroy(mp) == 0) +# define smutex_lock(mp) (pthread_mutex_lock(mp) == 0) +# define smutex_unlock(mp) (pthread_mutex_unlock(mp) == 0) +# define smutex_trylock(mp) (pthread_mutex_trylock(mp) == 0) + #include <sys/time.h> /* version info */ @@ -42,6 +61,12 @@ static char MilterlId[] = "@(#)$Sendmail: libmilter.h,v 8.3 2000/02/26 01:32:13 #define MI_TIMEOUT 1800 /* default timeout for read/write */ #define MI_CHK_TIME 5 /* checking whether to terminate */ +#if SOMAXCONN > 20 +# define MI_SOMAXCONN SOMAXCONN +#else /* SOMAXCONN */ +# define MI_SOMAXCONN 20 +#endif /* SOMAXCONN */ + /* maximum number of repeated failures in mi_listener() */ #define MAX_FAILS_M 16 /* malloc() */ #define MAX_FAILS_T 16 /* thread creation */ @@ -65,8 +90,6 @@ static char MilterlId[] = "@(#)$Sendmail: libmilter.h,v 8.3 2000/02/26 01:32:13 #define SMI_LOG_INFO LOG_INFO #define SMI_LOG_DEBUG LOG_DEBUG -#define MI_INVALID_SOCKET (-1) - /* stop? */ #define MILTER_CONT 0 #define MILTER_STOP 1 @@ -75,17 +98,18 @@ static char MilterlId[] = "@(#)$Sendmail: libmilter.h,v 8.3 2000/02/26 01:32:13 /* functions */ extern int mi_handle_session __P((SMFICTX_PTR)); extern int mi_engine __P((SMFICTX_PTR)); -extern int mi_listener __P((char *, int, smfiDesc_ptr, time_t)); +extern int mi_listener __P((char *, int, smfiDesc_ptr, time_t, int)); extern void mi_clr_macros __P((SMFICTX_PTR, int)); extern int mi_stop __P((void)); extern int mi_control_startup __P((char *)); extern void mi_stop_milters __P((int)); extern void mi_clean_signals __P((void)); extern struct hostent *mi_gethostbyname __P((char *, int)); +extern void mi_closener __P((void)); /* communication functions */ -extern char *mi_rd_cmd __P((int, struct timeval *, char *, size_t *, char *)); -extern int mi_wr_cmd __P((int, struct timeval *, int, char *, size_t)); +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 3ee18045a40..43a00e60a69 100644 --- a/gnu/usr.sbin/sendmail/libmilter/listener.c +++ b/gnu/usr.sbin/sendmail/libmilter/listener.c @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: listener.c,v 8.38 2000/02/11 00:12:30 ca Exp $"; +static char id[] = "@(#)$Sendmail: listener.c,v 8.38.2.1.2.18 2000/12/29 19:44:28 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -19,10 +19,10 @@ static char id[] = "@(#)$Sendmail: listener.c,v 8.38 2000/02/11 00:12:30 ca Exp #include "libmilter.h" -#if NETINET || NETINET6 -# include <arpa/inet.h> -#endif /* NETINET || NETINET6 */ +# if NETINET || NETINET6 +# include <arpa/inet.h> +# endif /* NETINET || NETINET6 */ /* ** MI_MILTEROPEN -- setup socket to listen on ** @@ -35,26 +35,25 @@ static char id[] = "@(#)$Sendmail: listener.c,v 8.38 2000/02/11 00:12:30 ca Exp ** socket upon success, error code otherwise. */ -static int +static socket_t mi_milteropen(conn, backlog, socksize, name) char *conn; int backlog; SOCKADDR_LEN_T *socksize; char *name; { - int sock = 0; + socket_t sock; int sockopt = 1; char *p; char *colon; char *at; - struct hostent *hp = NULL; SOCKADDR addr; if (conn == NULL || conn[0] == '\0') { smi_log(SMI_LOG_ERR, "%s: empty or missing socket information", name); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } (void) memset(&addr, '\0', sizeof addr); @@ -86,7 +85,7 @@ mi_milteropen(conn, backlog, socksize, name) smi_log(SMI_LOG_ERR, "%s: no valid socket protocols available", name); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; # endif /* NETINET6 */ # endif /* NETINET */ #endif /* NETUNIX */ @@ -117,7 +116,7 @@ mi_milteropen(conn, backlog, socksize, name) { smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", name, p); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } *colon++ = ':'; } @@ -141,7 +140,7 @@ mi_milteropen(conn, backlog, socksize, name) # else /* NETINET6 */ smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", name, p); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; # endif /* NETINET6 */ # endif /* NETINET */ #endif /* NETUNIX */ @@ -162,7 +161,7 @@ mi_milteropen(conn, backlog, socksize, name) errno = EINVAL; smi_log(SMI_LOG_ERR, "%s: UNIX socket name %s too long", name, colon); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } # if 0 errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, @@ -174,7 +173,7 @@ mi_milteropen(conn, backlog, socksize, name) smi_log(SMI_LOG_ERR, "%s: UNIX socket name %s unsafe", name, colon); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } # endif /* 0 */ @@ -219,13 +218,13 @@ mi_milteropen(conn, backlog, socksize, name) *at = '\0'; if (isascii(*colon) && isdigit(*colon)) - port = htons(atoi(colon)); + port = htons((u_short) atoi(colon)); else { # ifdef NO_GETSERVBYNAME smi_log(SMI_LOG_ERR, "%s: invalid port number %s", name, colon); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; # else /* NO_GETSERVBYNAME */ register struct servent *sp; @@ -235,7 +234,7 @@ mi_milteropen(conn, backlog, socksize, name) smi_log(SMI_LOG_ERR, "%s: unknown port name %s", name, colon); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } port = sp->s_port; # endif /* NO_GETSERVBYNAME */ @@ -286,7 +285,7 @@ mi_milteropen(conn, backlog, socksize, name) smi_log(SMI_LOG_ERR, "%s: Invalid numeric domain spec \"%s\"", name, at); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } } else @@ -294,18 +293,20 @@ mi_milteropen(conn, backlog, socksize, name) smi_log(SMI_LOG_ERR, "%s: Invalid numeric domain spec \"%s\"", name, at); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } } else { + struct hostent *hp = NULL; + hp = mi_gethostbyname(at, addr.sa.sa_family); if (hp == NULL) { smi_log(SMI_LOG_ERR, "%s: Unknown host name %s", name, at); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } addr.sa.sa_family = hp->h_addrtype; switch (hp->h_addrtype) @@ -332,8 +333,11 @@ mi_milteropen(conn, backlog, socksize, name) smi_log(SMI_LOG_ERR, "%s: Unknown protocol for %s (%d)", name, at, hp->h_addrtype); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } +# if _FFR_FREEHOSTENT && NETINET6 + freehostent(hp); +# endif /* _FFR_FREEHOSTENT && NETINET6 */ } } else @@ -356,12 +360,12 @@ mi_milteropen(conn, backlog, socksize, name) #endif /* NETINET || NETINET6 */ sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); - if (sock < 0) + if (!ValidSocket(sock)) { smi_log(SMI_LOG_ERR, "%s: Unable to create new socket: %s", name, strerror(errno)); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &sockopt, @@ -370,7 +374,7 @@ mi_milteropen(conn, backlog, socksize, name) smi_log(SMI_LOG_ERR, "%s: Unable to setsockopt: %s", name, strerror(errno)); (void) close(sock); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } if (bind(sock, &addr.sa, *socksize) < 0) @@ -379,7 +383,7 @@ mi_milteropen(conn, backlog, socksize, name) "%s: Unable to bind to port %s: %s", name, conn, strerror(errno)); (void) close(sock); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } if (listen(sock, backlog) < 0) @@ -387,7 +391,7 @@ mi_milteropen(conn, backlog, socksize, name) smi_log(SMI_LOG_ERR, "%s: listen call failed: %s", name, strerror(errno)); (void) close(sock); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } return sock; @@ -409,8 +413,34 @@ mi_thread_handle_wrapper(arg) return (void *) mi_handle_session(arg); } +static socket_t listenfd = INVALID_SOCKET; + +static smutex_t L_Mutex; + +/* +** MI_CLOSENER -- close listen socket +** +** Parameters: +** none. +** +** Returns: +** none. +*/ + +void +mi_closener() +{ + (void) smutex_lock(&L_Mutex); + if (ValidSocket(listenfd)) + { + (void) close(listenfd); + listenfd = INVALID_SOCKET; + } + (void) smutex_unlock(&L_Mutex); +} + /* -** MI_MILTER_LISTENER -- Generic listener harness +** MI_LISTENER -- Generic listener harness ** ** Open up listen port ** Wait for connections @@ -428,23 +458,23 @@ mi_thread_handle_wrapper(arg) */ int -mi_listener(conn, dbg, smfi, timeout) +mi_listener(conn, dbg, smfi, timeout, backlog) char *conn; int dbg; smfiDesc_ptr smfi; time_t timeout; + int backlog; { - int connfd = -1; - int listenfd = -1; - int clilen; + socket_t connfd = INVALID_SOCKET; int sockopt = 1; int r; int ret = MI_SUCCESS; int cnt_m = 0; int cnt_t = 0; - pthread_t thread_id; + sthread_t thread_id; _SOCK_ADDR cliaddr; SOCKADDR_LEN_T socksize; + SOCKADDR_LEN_T clilen; SMFICTX_PTR ctx; fd_set readset, excset; struct timeval chktime; @@ -453,37 +483,56 @@ mi_listener(conn, dbg, smfi, timeout) smi_log(SMI_LOG_DEBUG, "%s: Opening listen socket on conn %s", smfi->xxfi_name, conn); - if ((listenfd = mi_milteropen(conn, SOMAXCONN, &socksize, - smfi->xxfi_name)) < 0) + (void) smutex_init(&L_Mutex); + (void) smutex_lock(&L_Mutex); + listenfd = mi_milteropen(conn, backlog, &socksize, smfi->xxfi_name); + if (!ValidSocket(listenfd)) { smi_log(SMI_LOG_FATAL, "%s: Unable to create listening socket on conn %s", smfi->xxfi_name, conn); + (void) smutex_unlock(&L_Mutex); return MI_FAILURE; } clilen = socksize; + if (listenfd >= FD_SETSIZE) { smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d", smfi->xxfi_name, listenfd, FD_SETSIZE); + (void) smutex_unlock(&L_Mutex); return MI_FAILURE; } + (void) smutex_unlock(&L_Mutex); while (mi_stop() == MILTER_CONT) { + (void) smutex_lock(&L_Mutex); + if (!ValidSocket(listenfd)) + { + (void) smutex_unlock(&L_Mutex); + break; + } + /* select on interface ports */ FD_ZERO(&readset); - FD_SET(listenfd, &readset); FD_ZERO(&excset); - FD_SET(listenfd, &excset); + FD_SET((u_int) listenfd, &readset); + FD_SET((u_int) listenfd, &excset); chktime.tv_sec = MI_CHK_TIME; chktime.tv_usec = 0; r = select(listenfd + 1, &readset, NULL, &excset, &chktime); if (r == 0) /* timeout */ + { + (void) smutex_unlock(&L_Mutex); continue; /* just check mi_stop() */ + } if (r < 0) { - if (errno == EINTR) + int err = errno; + + (void) smutex_unlock(&L_Mutex); + if (err == EINTR) continue; ret = MI_FAILURE; break; @@ -492,13 +541,15 @@ mi_listener(conn, dbg, smfi, timeout) { /* some error: just stop for now... */ ret = MI_FAILURE; + (void) smutex_unlock(&L_Mutex); break; } connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); + (void) smutex_unlock(&L_Mutex); - if (connfd < 0) + if (!ValidSocket(connfd)) { smi_log(SMI_LOG_ERR, "%s: accept() returned invalid socket", @@ -528,7 +579,7 @@ mi_listener(conn, dbg, smfi, timeout) } cnt_m = 0; memset(ctx, '\0', sizeof *ctx); - ctx->ctx_fd = connfd; + ctx->ctx_sd = connfd; ctx->ctx_dbg = dbg; ctx->ctx_timeout = timeout; ctx->ctx_smfi = smfi; @@ -539,24 +590,26 @@ mi_listener(conn, dbg, smfi, timeout) if (smfi->xxfi_close == NULL) #endif /* 0 */ if (smfi->xxfi_connect == NULL) - smfi->xxfi_flags |= SMFIF_NOCONNECT; + ctx->ctx_pflags |= SMFIP_NOCONNECT; if (smfi->xxfi_helo == NULL) - smfi->xxfi_flags |= SMFIF_NOHELO; + ctx->ctx_pflags |= SMFIP_NOHELO; if (smfi->xxfi_envfrom == NULL) - smfi->xxfi_flags |= SMFIF_NOMAIL; + ctx->ctx_pflags |= SMFIP_NOMAIL; if (smfi->xxfi_envrcpt == NULL) - smfi->xxfi_flags |= SMFIF_NORCPT; + ctx->ctx_pflags |= SMFIP_NORCPT; if (smfi->xxfi_header == NULL) - smfi->xxfi_flags |= SMFIF_NOHDRS; + ctx->ctx_pflags |= SMFIP_NOHDRS; + if (smfi->xxfi_eoh == NULL) + ctx->ctx_pflags |= SMFIP_NOEOH; if (smfi->xxfi_body == NULL) - smfi->xxfi_flags |= SMFIF_NOBODY; + ctx->ctx_pflags |= SMFIP_NOBODY; - if ((r = pthread_create(&thread_id, NULL, + if ((r = thread_create(&thread_id, mi_thread_handle_wrapper, (void *) ctx)) != 0) { smi_log(SMI_LOG_ERR, - "%s: pthread_create() failed: %d", + "%s: thread_create() failed: %d", smfi->xxfi_name, r); sleep(++cnt_t); (void) close(connfd); @@ -572,8 +625,9 @@ mi_listener(conn, dbg, smfi, timeout) } if (ret != MI_SUCCESS) mi_stop_milters(MILTER_ABRT); - if (listenfd >= 0) - (void) close(listenfd); + else + mi_closener(); + (void) smutex_destroy(&L_Mutex); return ret; } #endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libmilter/main.c b/gnu/usr.sbin/sendmail/libmilter/main.c index cf0bbcd2831..873eddafeff 100644 --- a/gnu/usr.sbin/sendmail/libmilter/main.c +++ b/gnu/usr.sbin/sendmail/libmilter/main.c @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: main.c,v 8.34 2000/02/11 02:43:45 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: main.c,v 8.34.4.9 2000/09/09 02:23:03 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -18,6 +18,7 @@ static char id[] = "@(#)$Sendmail: main.c,v 8.34 2000/02/11 02:43:45 gshapiro Ex #include <fcntl.h> #include <sys/stat.h> + static smfiDesc_ptr smfi = NULL; /* @@ -42,7 +43,7 @@ smfi_register(smfilter) if (smfi == NULL) return MI_FAILURE; } - (void)memcpy(smfi, &smfilter, sizeof *smfi); + (void) memcpy(smfi, &smfilter, sizeof *smfi); if (smfilter.xxfi_name == NULL) smfilter.xxfi_name = "Unknown"; @@ -51,12 +52,42 @@ smfi_register(smfilter) if (smfi->xxfi_name == NULL) return MI_FAILURE; (void) strlcpy(smfi->xxfi_name, smfilter.xxfi_name, len); + + /* compare milter version with hard coded version */ + if (smfi->xxfi_version != SMFI_VERSION) + { + /* hard failure for now! */ + smi_log(SMI_LOG_ERR, + "%s: smfi_register: version mismatch application: %d != milter: %d", + smfi->xxfi_name, smfi->xxfi_version, + (int) SMFI_VERSION); + return MI_FAILURE; + } + + return MI_SUCCESS; +} + +/* +** SMFI_STOP -- stop milter +** +** Parameters: +** none. +** +** Returns: +** success. +*/ + +int +smfi_stop() +{ + mi_stop_milters(MILTER_STOP); return MI_SUCCESS; } static int dbg = 0; static char *conn = NULL; static int timeout = MI_TIMEOUT; +static int backlog= MI_SOMAXCONN; int smfi_setdbg(odbg) @@ -91,6 +122,16 @@ smfi_setconn(oconn) } int +smfi_setbacklog(obacklog) + int obacklog; +{ + if (obacklog <= 0) + return MI_FAILURE; + backlog = obacklog; + return MI_SUCCESS; +} + +int smfi_main() { signal(SIGPIPE, SIG_IGN); @@ -98,7 +139,7 @@ smfi_main() { smi_log(SMI_LOG_FATAL, "%s: missing connection information", smfi->xxfi_name); - exit(EX_DATAERR); + return MI_FAILURE; } (void) atexit(mi_clean_signals); @@ -107,13 +148,13 @@ smfi_main() smi_log(SMI_LOG_FATAL, "%s: Couldn't start signal thread", smfi->xxfi_name); - exit(EX_OSERR); + return MI_FAILURE; } /* Startup the listener */ - if (mi_listener(conn, dbg, smfi, timeout) != MI_SUCCESS) - return(MI_FAILURE); + if (mi_listener(conn, dbg, smfi, timeout, backlog) != MI_SUCCESS) + return MI_FAILURE; - return(MI_SUCCESS); + return MI_SUCCESS; } #endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libmilter/signal.c b/gnu/usr.sbin/sendmail/libmilter/signal.c index 00ddd9fdcd4..19a79be2560 100644 --- a/gnu/usr.sbin/sendmail/libmilter/signal.c +++ b/gnu/usr.sbin/sendmail/libmilter/signal.c @@ -9,29 +9,21 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: signal.c,v 8.10 2000/02/26 01:32:14 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: signal.c,v 8.10.4.8 2000/11/20 21:15:37 ca Exp $"; #endif /* ! lint */ #if _FFR_MILTER #include "libmilter.h" /* -** thread to handle signals +** thread to handle signals */ -typedef pthread_mutex_t smutex_t; -#define smutex_init(mp) (pthread_mutex_init(mp, NULL) == 0) -#define smutex_destroy(mp) (pthread_mutex_destroy(mp) == 0) -#define smutex_lock(mp) (pthread_mutex_lock(mp) == 0) -#define smutex_unlock(mp) (pthread_mutex_unlock(mp) == 0) -#define smutex_trylock(mp) (pthread_mutex_trylock(mp) == 0) - static smutex_t M_Mutex; static int MilterStop = MILTER_CONT; - -/* +/* ** MI_STOP -- return value of MilterStop ** ** Parameters: @@ -44,11 +36,9 @@ static int MilterStop = MILTER_CONT; int mi_stop() { - return(MilterStop); + return MilterStop; } - - -/* +/* ** MI_STOP_MILTERS -- set value of MilterStop ** ** Parameters: @@ -65,10 +55,12 @@ mi_stop_milters(v) (void) smutex_lock(&M_Mutex); if (MilterStop < v) MilterStop = v; + + /* close listen socket */ + mi_closener(); (void) smutex_unlock(&M_Mutex); } - -/* +/* ** MI_CLEAN_SIGNALS -- clean up signal handler thread ** ** Parameters: @@ -83,9 +75,8 @@ mi_clean_signals() { (void) smutex_destroy(&M_Mutex); } - -/* -** MI -- thread to deal with signals +/* +** MI_SIGNAL_THREAD -- thread to deal with signals ** ** Parameters: ** name -- name of milter @@ -147,8 +138,7 @@ mi_signal_thread(name) } } } - -/* +/* ** MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals ** ** Parameters: @@ -162,8 +152,8 @@ static int mi_spawn_signal_thread(name) char *name; { + sthread_t tid; sigset_t set; - pthread_t tid; /* Mask HUP and KILL signals */ sigemptyset(&set); @@ -177,8 +167,8 @@ mi_spawn_signal_thread(name) "%s: Couldn't mask HUP and KILL signals", name); return MI_FAILURE; } - if (pthread_create(&tid, NULL, mi_signal_thread, (void *)name) - != MI_SUCCESS) + if (thread_create(&tid, mi_signal_thread, + (void *)name) != MI_SUCCESS) { smi_log(SMI_LOG_ERR, "%s: Couldn't start signal thread", name); @@ -186,8 +176,7 @@ mi_spawn_signal_thread(name) } return MI_SUCCESS; } - -/* +/* ** MI_CONTROL_STARTUP -- startup for thread to handle signals ** ** Parameters: diff --git a/gnu/usr.sbin/sendmail/libmilter/sm_gethost.c b/gnu/usr.sbin/sendmail/libmilter/sm_gethost.c index 9ee76a5f76e..b7de9775e08 100644 --- a/gnu/usr.sbin/sendmail/libmilter/sm_gethost.c +++ b/gnu/usr.sbin/sendmail/libmilter/sm_gethost.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: sm_gethost.c,v 8.7 2000/01/20 21:51:52 geir Exp $"; +static char id[] = "@(#)$Sendmail: sm_gethost.c,v 8.7.8.4 2000/12/19 04:26:33 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -39,7 +39,7 @@ static char id[] = "@(#)$Sendmail: sm_gethost.c,v 8.7 2000/01/20 21:51:52 geir E # endif /* ! AI_ALL */ static struct hostent * -mi_getipnodebyname(name, family, flags, err) +getipnodebyname(name, family, flags, err) char *name; int family; int flags; @@ -61,6 +61,20 @@ mi_getipnodebyname(name, family, flags, err) _res.options &= ~RES_USE_INET6; return h; } + +# if _FFR_FREEHOSTENT +void +freehostent(h) + struct hostent *h; +{ + /* + ** Stub routine -- if they don't have getipnodeby*(), + ** they probably don't have the free routine either. + */ + + return; +} +# endif /* _FFR_FREEHOSTENT */ #endif /* NEEDSGETIPNODE && NETINET6 && __RES < 19990909 */ struct hostent * @@ -87,7 +101,7 @@ mi_gethostbyname(name, family) # endif /* NETINET6 */ # if NETINET6 - h = mi_getipnodebyname(name, family, AI_V4MAPPED|AI_ALL, &err); + h = getipnodebyname(name, family, AI_V4MAPPED|AI_ALL, &err); h_errno = err; # else /* NETINET6 */ h = gethostbyname(name); diff --git a/gnu/usr.sbin/sendmail/libmilter/smfi.c b/gnu/usr.sbin/sendmail/libmilter/smfi.c index 5496e35318a..5297524e5fd 100644 --- a/gnu/usr.sbin/sendmail/libmilter/smfi.c +++ b/gnu/usr.sbin/sendmail/libmilter/smfi.c @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: smfi.c,v 8.28 2000/02/26 01:32:15 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: smfi.c,v 8.28.4.6 2000/06/28 23:48:56 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -40,9 +40,9 @@ smfi_addheader(ctx, headerf, headerv) char *buf; struct timeval timeout; - if (headerf == NULL || headerv == NULL) + if (headerf == NULL || *headerf == '\0' || headerv == NULL) return MI_FAILURE; - if (!mi_sendok(ctx, SMFIF_MODHDRS)) + if (!mi_sendok(ctx, SMFIF_ADDHDRS)) return MI_FAILURE; timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; @@ -54,7 +54,59 @@ smfi_addheader(ctx, headerf, headerv) return MI_FAILURE; (void) memcpy(buf, headerf, l1 + 1); (void) memcpy(buf + l1 + 1, headerv, l2 + 1); - r = mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_ADDHEADER, buf, len); + r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_ADDHEADER, buf, len); + free(buf); + return r; +} + +/* +** SMFI_CHGHEADER -- send a changed header to the MTA +** +** Parameters: +** ctx -- Opaque context structure +** headerf -- Header field name +** hdridx -- Header index value +** headerv -- Header field value +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +smfi_chgheader(ctx, headerf, hdridx, headerv) + SMFICTX *ctx; + char *headerf; + mi_int32 hdridx; + char *headerv; +{ + /* do we want to copy the stuff or have a special mi_wr_cmd call? */ + size_t len, l1, l2; + int r; + mi_int32 v; + char *buf; + struct timeval timeout; + + if (headerf == NULL || *headerf == '\0') + return MI_FAILURE; + if (hdridx < 0) + return MI_FAILURE; + if (!mi_sendok(ctx, SMFIF_CHGHDRS)) + return MI_FAILURE; + timeout.tv_sec = ctx->ctx_timeout; + timeout.tv_usec = 0; + if (headerv == NULL) + headerv = ""; + l1 = strlen(headerf); + l2 = strlen(headerv); + len = l1 + l2 + 2 + MILTER_LEN_BYTES; + buf = malloc(len); + if (buf == NULL) + return MI_FAILURE; + v = htonl(hdridx); + (void) memcpy(&(buf[0]), (void *) &v, MILTER_LEN_BYTES); + (void) memcpy(buf + MILTER_LEN_BYTES, headerf, l1 + 1); + (void) memcpy(buf + MILTER_LEN_BYTES + l1 + 1, headerv, l2 + 1); + r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_CHGHEADER, buf, len); free(buf); return r; } @@ -77,14 +129,14 @@ smfi_addrcpt(ctx, rcpt) size_t len; struct timeval timeout; - if (rcpt == NULL) + if (rcpt == NULL || *rcpt == '\0') return MI_FAILURE; if (!mi_sendok(ctx, SMFIF_ADDRCPT)) return MI_FAILURE; timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; len = strlen(rcpt) + 1; - return mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_ADDRCPT, rcpt, len); + return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_ADDRCPT, rcpt, len); } /* ** SMFI_DELRCPT -- send a recipient to be removed to the MTA @@ -105,14 +157,14 @@ smfi_delrcpt(ctx, rcpt) size_t len; struct timeval timeout; - if (rcpt == NULL) + if (rcpt == NULL || *rcpt == '\0') return MI_FAILURE; if (!mi_sendok(ctx, SMFIF_DELRCPT)) return MI_FAILURE; timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; len = strlen(rcpt) + 1; - return mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_DELRCPT, rcpt, len); + return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_DELRCPT, rcpt, len); } /* ** SMFI_REPLACEBODY -- send a body chunk to the MTA @@ -137,7 +189,7 @@ smfi_replacebody(ctx, bodyp, bodylen) if (bodyp == NULL && bodylen > 0) return MI_FAILURE; - if (!mi_sendok(ctx, SMFIF_MODBODY)) + if (!mi_sendok(ctx, SMFIF_CHGBODY)) return MI_FAILURE; timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; @@ -148,7 +200,7 @@ smfi_replacebody(ctx, bodyp, bodylen) { len = (bodylen >= MILTER_CHUNK_SIZE) ? MILTER_CHUNK_SIZE : bodylen; - if ((r = mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_REPLBODY, + if ((r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_REPLBODY, (char *) (bodyp + off), len)) != MI_SUCCESS) return r; off += len; @@ -302,10 +354,29 @@ smfi_getsymval(ctx, symname) { int i; char **s; + char one[2]; + char braces[4]; if (ctx == NULL || symname == NULL || *symname == '\0') return NULL; + if (strlen(symname) == 3 && symname[0] == '{' && symname[2] == '}') + { + one[0] = symname[1]; + one[1] = '\0'; + } + else + one[0] = '\0'; + if (strlen(symname) == 1) + { + braces[0] = '{'; + braces[1] = *symname; + braces[2] = '}'; + braces[3] = '\0'; + } + else + braces[0] = '\0'; + /* search backwards through the macro array */ for (i = MAX_MACROS_ENTRIES - 1 ; i >= 0; --i) { @@ -316,6 +387,10 @@ smfi_getsymval(ctx, symname) { if (strcmp(*s, symname) == 0) return *++s; + if (one[0] != '\0' && strcmp(*s, one) == 0) + return *++s; + if (braces[0] != '\0' && strcmp(*s, braces) == 0) + return *++s; ++s; /* skip over macro value */ ++s; /* points to next macro name */ } |