From owner-freebsd-bugs Sat Dec 23 17:40:20 2000 From owner-freebsd-bugs@FreeBSD.ORG Sat Dec 23 17:40:01 2000 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 24DE837B402 for ; Sat, 23 Dec 2000 17:40:01 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id eBO1e1H29108; Sat, 23 Dec 2000 17:40:01 -0800 (PST) (envelope-from gnats) Resent-Date: Sat, 23 Dec 2000 17:40:01 -0800 (PST) Resent-Message-Id: <200012240140.eBO1e1H29108@freefall.freebsd.org> Resent-From: gnats-admin@FreeBSD.org (GNATS Management) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: gnats-admin@FreeBSD.org, hetzels@westbend.net Received: from spare.westbend.net (unknown [209.224.254.133]) by hub.freebsd.org (Postfix) with ESMTP id 4ADC337B400; Sat, 23 Dec 2000 17:35:31 -0800 (PST) Received: (from root@localhost) by spare.westbend.net (8.11.1/8.11.1) id eBO1ZUT01117; Sat, 23 Dec 2000 19:35:30 -0600 (CST) (envelope-from admin) Message-Id: <200012240135.eBO1ZUT01117@spare.westbend.net> Date: Sat, 23 Dec 2000 19:35:30 -0600 (CST) From: "Scot W. Hetzel" Sender: admin@spare.westbend.net Reply-To: hetzels@westbend.net To: FreeBSD-gnats-submit@freebsd.org Cc: gshapiro@freebsd.org, hetzels@westbend.net X-Send-Pr-Version: 3.2 Subject: bin/23811: Sendmail Mail Filter (Milter) Resent-Sender: gnats@FreeBSD.org Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 23811 >Category: bin >Synopsis: Patch to Sendmail Mail Filter (Milter) API >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sat Dec 23 17:40:00 PST 2000 >Closed-Date: >Last-Modified: >Originator: Scot W. Hetzel >Release: FreeBSD 4.2-STABLE i386 >Organization: West Bend Internet >Environment: >Description: The sendmail Mail Filter API (Milter) is designed to allow third-party programs access to mail messages as they are being processed in order to filter meta-information and content. (from libmilter/README) While there is a way to enable the Milter API within sendmail, the libmilter, libsmutil and header files needed to build a Milter daemon are not installed. A Milter daemon can be used for: - Filtering messages for viruses - changing extentions on attachements to prevent them from being accidenlty executed by the user. - Achiving messages sent/received thru the server - Append company disclaimer to all outgoing messages. I was able to compile libmilter as a shared library. But when I compiled libsmutil as a shared library and tried to compile the sample.c from libmilter/README, it gave me the following error: cc -I/usr/include/sendmail -o sample sample.c -lmilter -lsmutil -pthread /usr/lib/libsmutil.so: undefined reference to `message' /usr/lib/libsmutil.so: undefined reference to `syserr' both of these are defined in /usr/include/sendmail/sendmail.h. Due to the above error with a shared libsmutil, the attached patch doesn't build a shared libsmutil. I had no problem building sample.c with: cc -I/usr/include/sendmail -o sample sample.c -lmilter /usr/lib/libsmutil.a -pthread I tested the sample milter dameon (w/shared libmilter) and sendmail. The sample milter dameon wrote the incoming message to a file in /tmp and delivered it to the recipent mailbox (as described in libmilter/README). NOTE: to use a milter daemon with sendmail, the *.mc file needs to define _FFR_MILTER, as well as specifying the milter daemon (see libmilter/README). define(_FFR_MILTER)dnl INPUT_MAIL_FILTER(`sample', `S=local:/var/run/f1.sock')dnl >How-To-Repeat: >Fix: The attached patch makes it so that the Milter API is compiled in to Sendmail, and that the proper libraries and header files are installed. Milter daemons need to start before sendmail is started. A new startup directory rc.milter is created in $PREFIX/etc/. This directory should contain milter startup scripts (similar to the scripts in rc.d). rc/rc.shutdown have been modified to start/stop the milter daemon before/after sendmail is started/stopped. Changed Files: New Files: Makefile lib/libmilter/Makefile etc/defaults/make.conf lib/libmilter/sample.c etc/defaults/rc.conf lib/libmilter/sample.sh etc/mtree/BSD.include.dist etc/mtree/BSD.local.dist etc/rc etc/rc.shutdown lib/Makefile lib/libsmutil/Makefile src/usr.sbin/sendmail/Makefile NOTE: This patch was created on 4.2-STABLE, but does apply to a 5.0-CURRENT source tree (with a little fuzziness on some files). diff -ruN src.orig/Makefile.inc1 src/Makefile.inc1 --- src.orig/Makefile.inc1 Fri Dec 15 23:08:54 2000 +++ src/Makefile.inc1 Fri Dec 22 20:53:30 2000 @@ -208,6 +208,10 @@ INCDIRS= arpa g++/std objc protocols readline rpc rpcsvc openssl \ security ss +.if defined(SENDMAIL_MILTER) +INCDIRS+= sendmail/libmilter sendmail/sendmail +.endif + # # buildworld # diff -ruN src.orig/etc/defaults/make.conf src/etc/defaults/make.conf --- src.orig/etc/defaults/make.conf Mon Nov 20 23:16:23 2000 +++ src/etc/defaults/make.conf Sat Dec 16 01:21:38 2000 @@ -314,3 +314,18 @@ #SENDMAIL_LDFLAGS= #SENDMAIL_LDADD= #SENDMAIL_DPADD= +# +# Sendmail Mail Filter API (Experimental): +# +# The sendmail Mail Filter API (Milter) is designed to allow third-party +# programs access to mail messages as they are being processed in order to +# filter meta-information and content. +# +# see src/contrib/sendmail/libmilter/README for more information. +# +# By enableing the following variable, the sendmail daemon is built so that +# it can talk to the mail filter daemons. libmilter.a, libsmutils.a and +# the sendmail headers are installed, so that mail filter daemons can be +# built. +# +#SENDMAIL_MILTER= yes diff -ruN src.orig/etc/defaults/rc.conf src/etc/defaults/rc.conf --- src.orig/etc/defaults/rc.conf Fri Dec 15 23:14:24 2000 +++ src/etc/defaults/rc.conf Sat Dec 16 14:58:19 2000 @@ -302,6 +302,7 @@ usbd_flags="" # Flags to usbd (if enabled). sendmail_enable="YES" # Run the sendmail daemon (or NO). sendmail_flags="-bd -q30m" # Flags to sendmail (if enabled) +sendmail_milter_startup="/usr/local/etc/rc.milter" # milter startup script dirs. dumpdev="NO" # Device name to crashdump to (or NO). enable_quotas="NO" # turn on quotas on startup (or NO). check_quotas="YES" # Check quotas on startup (or NO). diff -ruN src.orig/etc/mtree/BSD.include.dist src/etc/mtree/BSD.include.dist --- src.orig/etc/mtree/BSD.include.dist Sun Nov 5 06:30:01 2000 +++ src/etc/mtree/BSD.include.dist Sat Dec 16 14:32:03 2000 @@ -77,6 +77,12 @@ .. security .. + sendmail + libmilter + .. + sendmail + .. + .. ss .. sys diff -ruN src.orig/etc/mtree/BSD.local.dist src/etc/mtree/BSD.local.dist --- src.orig/etc/mtree/BSD.local.dist Sat Sep 16 17:26:07 2000 +++ src/etc/mtree/BSD.local.dist Sat Dec 16 15:49:48 2000 @@ -10,6 +10,8 @@ etc rc.d .. + rc.milter + .. .. include .. diff -ruN src.orig/etc/rc src/etc/rc --- src.orig/etc/rc Fri Dec 15 23:14:26 2000 +++ src/etc/rc Sat Dec 23 14:48:07 2000 @@ -442,6 +442,31 @@ case ${sendmail_enable} in [Yy][Ee][Ss]) if [ -r /etc/mail/sendmail.cf ]; then + # For each valid dir in $sendmail_milter_startup, + # search for init scripts matching *.sh + # + # (Hmm.. maybe this code should be turned into a function + # and shared between local_startup & sendmail_milter_startup) + # + case ${sendmail_milter_startup} in + [Nn][Oo] | '') + ;; + *) + # echo -n 'Sendmail Milter initialization:' + for dir in ${sendmail_milter_startup}; do + if [ -d "${dir}" ]; then + for script in ${dir}/*.sh; do + if [ -x "${script}" ]; then + (set -T + trap 'exit 1' 2 + ${script} start) + fi + done + fi + done + # echo . + ;; + esac echo -n ' sendmail'; /usr/sbin/sendmail ${sendmail_flags} fi ;; diff -ruN src.orig/etc/rc.shutdown src/etc/rc.shutdown --- src.orig/etc/rc.shutdown Thu Nov 2 13:27:06 2000 +++ src/etc/rc.shutdown Sat Dec 16 15:27:01 2000 @@ -91,6 +91,41 @@ ;; esac +case ${sendmail_enable} in +[Yy][Ee][Ss]) + # Should we shutdown sendmail daemon here also? +# killall -TERM sendmail + + # for each valid dir in $sendmail_milter_startup, search for init scripts matching *.sh + case ${sendmail_milter_startup} in + [Nn][Oo] | '') + ;; + *) + for dir in ${sendmail_milter_startup}; do + if [ -d "${dir}" ]; then + for script in ${dir}/*.sh; do + if [ -x "${script}" ]; then + grep -wq stop "${script}" || \ + oldmilterscripts="${oldmilterscripts} ${script}" +# XXX not yet +# (set -T +# trap 'exit 1' 2 +# ${script} stop) + fi + done + fi + done + if [ ! -z "${oldmilterscripts}" ]; then + echo 'You still seem to have old-style rc.milter scripts:' + echo ${oldmilterscripts} + echo 'Please change them to recognize the "stop" option.' + fi + echo . + ;; + esac + ;; +esac + # Insert other shutdown procedures here echo '.' diff -ruN src.orig/lib/Makefile src/lib/Makefile --- src.orig/lib/Makefile Fri Oct 27 20:43:31 2000 +++ src/lib/Makefile Sat Dec 16 01:21:38 2000 @@ -28,6 +28,10 @@ libposix1e libresolv librpcsvc libsmdb libsmutil libss \ libstand ${_libtelnet} libusb ${_libvgl} libwrap libxpg4 liby libz +.if defined(SENDMAIL_MILTER) +SUBDIR+= libmilter +.endif + .if exists(${.CURDIR}/csu/${MACHINE_ARCH}-${OBJFORMAT}) _csu=csu/${MACHINE_ARCH}-${OBJFORMAT} .elif exists(${.CURDIR}/csu/${MACHINE_ARCH}) diff -ruN src.orig/lib/libmilter/Makefile src/lib/libmilter/Makefile --- src.orig/lib/libmilter/Makefile Wed Dec 31 18:00:00 1969 +++ src/lib/libmilter/Makefile Sat Dec 23 14:57:27 2000 @@ -0,0 +1,51 @@ +# $FreeBSD$ + +MAINTAINER= gshapiro@FreeBSD.org + +SENDMAIL_DIR=${.CURDIR}/../../contrib/sendmail +.PATH: ${SENDMAIL_DIR}/libmilter + +CFLAGS+=-I${SENDMAIL_DIR}/src -I${SENDMAIL_DIR}/include +CFLAGS+=-DNEWDB -DNIS -DMAP_REGEX -DNOT_SENDMAIL -D_FFR_MILTER + +# User customizations to the sendmail build environment +CFLAGS+=${SENDMAIL_CFLAGS} + +LIB= milter + +SRCS+= comm.c engine.c handler.c listener.c main.c signal.c \ + sm_gethost.c smfi.c + +SM_HDRS=src/bf.h src/bf_portable.h src/bf_torek.h src/conf.h \ + src/sendmail.h src/sfsasl.h src/statusd_shm.h src/timers.h + +M_HDRS= libmilter/mfapi.h libmilter/milter.h + +SM2_HDRS=sendmail/cdefs.h sendmail/errstring.h sendmail/mailstats.h \ + sendmail/pathnames.h sendmail/sendmail.h sendmail/useful.h + +.for h in ${SM_HDRS} +SENDMAIL_HDRS+= ${SENDMAIL_DIR}/${h} +.endfor + +.for h in ${M_HDRS} +MILTER_HDRS+= ${SENDMAIL_DIR}/include/${h} +.endfor + +.for h in ${SM2_HDRS} +SENDMAIL2_HDRS+= ${SENDMAIL_DIR}/include/${h} +.endfor + +beforeinstall: + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m 444 \ + ${SENDMAIL_HDRS} ${DESTDIR}/usr/include/sendmail + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m 444 \ + ${MILTER_HDRS} ${DESTDIR}/usr/include/sendmail/libmilter + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m 444 \ + ${SENDMAIL2_HDRS} ${DESTDIR}/usr/include/sendmail/sendmail + +sample: + cc -I/usr/include/sendmail -o sample sample.c -lmilter \ + /usr/lib/libsmutil.a -pthread + +.include diff -ruN src.orig/lib/libmilter/sample.c src/lib/libmilter/sample.c --- src.orig/lib/libmilter/sample.c Wed Dec 31 18:00:00 1969 +++ src/lib/libmilter/sample.c Sat Dec 23 14:56:17 2000 @@ -0,0 +1,233 @@ +/* A trivial filter that logs all email to a file. */ + +#include +#include +#include +#include +#include +#include + +#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; + FILE *mlfi_fp; +}; + +#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx)) + +extern sfsistat mlfi_cleanup(SMFICTX *, bool); + +sfsistat +mlfi_envfrom(ctx, envfrom) + SMFICTX *ctx; + char **envfrom; +{ + struct mlfiPriv *priv; + int fd; + + /* allocate some private memory */ + priv = malloc(sizeof *priv); + if (priv == NULL) + { + /* can't accept this message right now */ + return SMFIS_TEMPFAIL; + } + memset(priv, '\0', sizeof *priv); + + /* open a file to store this message */ + priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX"); + if (priv->mlfi_fname == NULL) + { + free(priv); + return SMFIS_TEMPFAIL; + } + if ((fd = mkstemp(priv->mlfi_fname)) < 0 || + (priv->mlfi_fp = fdopen(fd, "w+")) == NULL) + { + free(priv->mlfi_fname); + free(priv); + return SMFIS_TEMPFAIL; + } + + /* save the private data */ + smfi_setpriv(ctx, priv); + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_header(ctx, headerf, headerv) + SMFICTX *ctx; + char *headerf; + char *headerv; +{ + /* write the header to the log file */ + fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv); + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_eoh(ctx) + SMFICTX *ctx; +{ + /* output the blank line between the header and the body */ + fprintf(MLFIPRIV->mlfi_fp, "\r\n"); + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_body(ctx, bodyp, bodylen) + SMFICTX *ctx; + u_char *bodyp; + size_t bodylen; +{ + /* output body block to log file */ + if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) <= 0) + { + /* write failed */ + (void) mlfi_cleanup(ctx, FALSE); + return SMFIS_TEMPFAIL; + } + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_eom(ctx) + SMFICTX *ctx; +{ + return mlfi_cleanup(ctx, TRUE); +} + +sfsistat +mlfi_close(ctx) + SMFICTX *ctx; +{ + return SMFIS_ACCEPT; +} + +sfsistat +mlfi_abort(ctx) + SMFICTX *ctx; +{ + return mlfi_cleanup(ctx, FALSE); +} + +sfsistat +mlfi_cleanup(ctx, ok) + SMFICTX *ctx; + bool ok; +{ + sfsistat rstat = SMFIS_CONTINUE; + struct mlfiPriv *priv = MLFIPRIV; + char *p; + char host[512]; + char hbuf[1024]; + + if (priv == NULL) + return rstat; + + /* close the archive file */ + if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF) + { + /* failed; we have to wait until later */ + rstat = SMFIS_TEMPFAIL; + (void) unlink(priv->mlfi_fname); + } + else if (ok) + { + /* add a header to the message announcing our presence */ + if (gethostname(host, sizeof host) < 0) + strlcpy(host, "localhost", sizeof host); + p = strrchr(priv->mlfi_fname, '/'); + if (p == NULL) + p = priv->mlfi_fname; + else + p++; + snprintf(hbuf, sizeof hbuf, "%s@%s", p, host); + smfi_addheader(ctx, "X-Archived", hbuf); + } + else + { + /* message was aborted -- delete the archive file */ + (void) unlink(priv->mlfi_fname); + } + + /* release private memory */ + free(priv->mlfi_fname); + free(priv); + smfi_setpriv(ctx, NULL); + + /* return status */ + return rstat; +} + +struct smfiDesc smfilter = +{ + "SampleFilter", /* filter name */ + SMFI_VERSION, /* version code -- do not change */ + SMFIF_ADDHDRS, /* flags */ + NULL, /* connection info filter */ + NULL, /* SMTP HELO command filter */ + mlfi_envfrom, /* envelope sender filter */ + NULL, /* envelope recipient filter */ + mlfi_header, /* header filter */ + mlfi_eoh, /* end of header */ + mlfi_body, /* body block filter */ + mlfi_eom, /* end of message */ + mlfi_abort, /* message aborted */ + mlfi_close /* connection cleanup */ +}; + + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int c; + const char *args = "p:"; + + /* Process command line options */ + while ((c = getopt(argc, argv, args)) != -1) + { + switch (c) + { + case 'p': + if (optarg == NULL || *optarg == '\0') + { + (void) fprintf(stderr, "Illegal conn: %s\n", + optarg); + exit(EX_USAGE); + } + (void) smfi_setconn(optarg); + break; + + } + } + if (smfi_register(smfilter) == MI_FAILURE) + { + fprintf(stderr, "smfi_register failed\n"); + exit(EX_UNAVAILABLE); + } + return smfi_main(); +} + +/* eof */ diff -ruN src.orig/lib/libmilter/sample.sh src/lib/libmilter/sample.sh --- src.orig/lib/libmilter/sample.sh Wed Dec 31 18:00:00 1969 +++ src/lib/libmilter/sample.sh Sat Dec 23 15:14:19 2000 @@ -0,0 +1,20 @@ +#!/bin/sh +# Sample Filter Startup Scipt +# +# $FreeBSD$ +# + +case "$1" in + +start) + # We need to remove the old sock connection + # otherwise ./sample will not run. + if [ -S /var/run/f1.sock ] + then + rm /var/run/f1.sock + fi + ./sample -p local:/var/run/f1.sock & + echo -n ' sample' + +stop) + killall -TERM sample diff -ruN src.orig/lib/libsmutil/Makefile src/lib/libsmutil/Makefile --- src.orig/lib/libsmutil/Makefile Thu Oct 26 18:05:12 2000 +++ src/lib/libsmutil/Makefile Sat Dec 23 14:51:45 2000 @@ -15,8 +15,11 @@ SRCS+= debug.c errstring.c lockfile.c safefile.c snprintf.c strl.c -INTERNALLIB= true NOPIC= true + +.if !defined(SENDMAIL_MILTER) +INTERNALLIB= true INTERNALSTATICLIB= true +.endif .include diff -ruN src.orig/usr.sbin/sendmail/Makefile src/usr.sbin/sendmail/Makefile --- src.orig/usr.sbin/sendmail/Makefile Tue Oct 31 11:04:10 2000 +++ src/usr.sbin/sendmail/Makefile Sat Dec 16 01:21:39 2000 @@ -23,6 +23,10 @@ CFLAGS+=-I${SMDIR} -I${SENDMAIL_DIR}/include CFLAGS+=${DBMDEF} ${NIS} -DNETINET6 -DTCPWRAPPERS ${MAPS} +.if defined(SENDMAIL_MILTER) +CFLAGS+= -D_FFR_MILTER +.endif + SRCS= alias.c arpadate.c bf_torek.c clock.c collect.c conf.c control.c \ convtime.c daemon.c deliver.c domain.c envelope.c err.c headers.c \ macro.c main.c map.c mci.c milter.c mime.c parseaddr.c queue.c \ >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message