summaryrefslogtreecommitdiffstats
path: root/src/milter/milter_macros.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/milter/milter_macros.c')
-rw-r--r--src/milter/milter_macros.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/src/milter/milter_macros.c b/src/milter/milter_macros.c
new file mode 100644
index 0000000..27f5509
--- /dev/null
+++ b/src/milter/milter_macros.c
@@ -0,0 +1,303 @@
+/*++
+/* NAME
+/* milter_macros
+/* SUMMARY
+/* manipulate MILTER_MACROS structures
+/* SYNOPSIS
+/* #include <milter.h>
+/*
+/* MILTER_MACROS *milter_macros_create(conn_macros, helo_macros,
+/* mail_macros, rcpt_macros,
+/* data_macros, eoh_macros,
+/* eod_macros, unk_macros)
+/* const char *conn_macros;
+/* const char *helo_macros;
+/* const char *mail_macros;
+/* const char *rcpt_macrps;
+/* const char *data_macros;
+/* const char *eoh_macros;
+/* const char *eod_macros;
+/* const char *unk_macros;
+/*
+/* MILTER_MACROS *milter_macros_alloc(init_mode)
+/* int init_mode;
+/*
+/* void milter_macros_free(mp)
+/* MILTER_MACROS *mp;
+/*
+/* int milter_macros_print(print_fn, stream, flags, ptr)
+/* ATTR_PRINT_COMMON_FN print_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/*
+/* int milter_macros_scan(scan_fn, fp, flags, ptr)
+/* ATTR_SCAN_COMMON_FN scan_fn;
+/* VSTREAM *fp;
+/* int flags;
+/* void *ptr;
+/* DESCRIPTION
+/* Sendmail mail filter (Milter) applications receive sets of
+/* macro name=value pairs with each SMTP or content event.
+/* In Postfix, these macro names are stored in MILTER_MACROS
+/* structures, as one list for each event type. By default,
+/* the same structure is shared by all Milter applications;
+/* it is initialized with information from main.cf. With
+/* Sendmail 8.14 a Milter can override one or more lists of
+/* macro names. Postfix implements this by giving the Milter
+/* its own MILTER_MACROS structure and by storing the per-Milter
+/* information there.
+/*
+/* This module maintains per-event macro name lists as
+/* mystrdup()'ed values. The user is explicitly allowed to
+/* update these values directly, as long as the result is
+/* compatible with mystrdup().
+/*
+/* milter_macros_create() creates a MILTER_MACROS structure
+/* and initializes it with copies of its string arguments.
+/* Null pointers are not valid as input.
+/*
+/* milter_macros_alloc() creates am empty MILTER_MACROS structure
+/* that is initialized according to its init_mode argument.
+/* .IP MILTER_MACROS_ALLOC_ZERO
+/* Initialize all structure members as null pointers. This
+/* mode must be used with milter_macros_scan(), because that
+/* function blindly overwrites all structure members. No other
+/* function except milter_macros_free() allows structure members
+/* with null pointer values.
+/* .IP MILTER_MACROS_ALLOC_EMPTY
+/* Initialize all structure members with mystrdup(""). This
+/* is not as expensive as it appears to be.
+/* .PP
+/* milter_macros_free() destroys a MILTER_MACROS structure and
+/* frees any strings referenced by it.
+/*
+/* milter_macros_print() writes the contents of a MILTER_MACROS
+/* structure to the named stream using the specified attribute
+/* print routine. milter_macros_print() is meant to be passed
+/* as a call-back to attr_print*(), thusly:
+/*
+/* SEND_ATTR_FUNC(milter_macros_print, (const void *) macros),
+/*
+/* milter_macros_scan() reads a MILTER_MACROS structure from
+/* the named stream using the specified attribute scan routine.
+/* No attempt is made to free the memory of existing structure
+/* members. milter_macros_scan() is meant to be passed as a
+/* call-back to attr_scan*(), thusly:
+/*
+/* RECV_ATTR_FUNC(milter_macros_scan, (void *) macros),
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this
+/* software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <attr.h>
+#include <mymalloc.h>
+#include <vstring.h>
+
+/* Global library. */
+
+#include <mail_proto.h>
+#include <milter.h>
+
+ /*
+ * Ad-hoc protocol to send/receive milter macro name lists.
+ */
+#define MAIL_ATTR_MILT_MAC_CONN "conn_macros"
+#define MAIL_ATTR_MILT_MAC_HELO "helo_macros"
+#define MAIL_ATTR_MILT_MAC_MAIL "mail_macros"
+#define MAIL_ATTR_MILT_MAC_RCPT "rcpt_macros"
+#define MAIL_ATTR_MILT_MAC_DATA "data_macros"
+#define MAIL_ATTR_MILT_MAC_EOH "eoh_macros"
+#define MAIL_ATTR_MILT_MAC_EOD "eod_macros"
+#define MAIL_ATTR_MILT_MAC_UNK "unk_macros"
+
+/* milter_macros_print - write macros structure to stream */
+
+int milter_macros_print(ATTR_PRINT_COMMON_FN print_fn, VSTREAM *fp,
+ int flags, const void *ptr)
+{
+ MILTER_MACROS *mp = (MILTER_MACROS *) ptr;
+ int ret;
+
+ /*
+ * The attribute order does not matter, except that it must be the same
+ * as in the milter_macros_scan() function.
+ */
+ ret = print_fn(fp, flags | ATTR_FLAG_MORE,
+ SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_CONN, mp->conn_macros),
+ SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_HELO, mp->helo_macros),
+ SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_MAIL, mp->mail_macros),
+ SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_RCPT, mp->rcpt_macros),
+ SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_DATA, mp->data_macros),
+ SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_EOH, mp->eoh_macros),
+ SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_EOD, mp->eod_macros),
+ SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_UNK, mp->unk_macros),
+ ATTR_TYPE_END);
+ return (ret);
+}
+
+/* milter_macros_scan - receive macros structure from stream */
+
+int milter_macros_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ MILTER_MACROS *mp = (MILTER_MACROS *) ptr;
+ int ret;
+
+ /*
+ * We could simplify this by moving memory allocation into attr_scan*().
+ */
+ VSTRING *conn_macros = vstring_alloc(10);
+ VSTRING *helo_macros = vstring_alloc(10);
+ VSTRING *mail_macros = vstring_alloc(10);
+ VSTRING *rcpt_macros = vstring_alloc(10);
+ VSTRING *data_macros = vstring_alloc(10);
+ VSTRING *eoh_macros = vstring_alloc(10);
+ VSTRING *eod_macros = vstring_alloc(10);
+ VSTRING *unk_macros = vstring_alloc(10);
+
+ /*
+ * The attribute order does not matter, except that it must be the same
+ * as in the milter_macros_print() function.
+ */
+ ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_CONN, conn_macros),
+ RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_HELO, helo_macros),
+ RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_MAIL, mail_macros),
+ RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_RCPT, rcpt_macros),
+ RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_DATA, data_macros),
+ RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_EOH, eoh_macros),
+ RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_EOD, eod_macros),
+ RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_UNK, unk_macros),
+ ATTR_TYPE_END);
+
+ /*
+ * Don't optimize for error.
+ */
+ mp->conn_macros = vstring_export(conn_macros);
+ mp->helo_macros = vstring_export(helo_macros);
+ mp->mail_macros = vstring_export(mail_macros);
+ mp->rcpt_macros = vstring_export(rcpt_macros);
+ mp->data_macros = vstring_export(data_macros);
+ mp->eoh_macros = vstring_export(eoh_macros);
+ mp->eod_macros = vstring_export(eod_macros);
+ mp->unk_macros = vstring_export(unk_macros);
+
+ return (ret == 8 ? 1 : -1);
+}
+
+/* milter_macros_create - create and initialize macros structure */
+
+MILTER_MACROS *milter_macros_create(const char *conn_macros,
+ const char *helo_macros,
+ const char *mail_macros,
+ const char *rcpt_macros,
+ const char *data_macros,
+ const char *eoh_macros,
+ const char *eod_macros,
+ const char *unk_macros)
+{
+ MILTER_MACROS *mp;
+
+ mp = (MILTER_MACROS *) mymalloc(sizeof(*mp));
+ mp->conn_macros = mystrdup(conn_macros);
+ mp->helo_macros = mystrdup(helo_macros);
+ mp->mail_macros = mystrdup(mail_macros);
+ mp->rcpt_macros = mystrdup(rcpt_macros);
+ mp->data_macros = mystrdup(data_macros);
+ mp->eoh_macros = mystrdup(eoh_macros);
+ mp->eod_macros = mystrdup(eod_macros);
+ mp->unk_macros = mystrdup(unk_macros);
+
+ return (mp);
+}
+
+/* milter_macros_alloc - allocate macros structure with simple initialization */
+
+MILTER_MACROS *milter_macros_alloc(int mode)
+{
+ MILTER_MACROS *mp;
+
+ /*
+ * This macro was originally in milter.h, but no-one else needed it.
+ */
+#define milter_macros_init(mp, expr) do { \
+ MILTER_MACROS *__mp = (mp); \
+ char *__expr = (expr); \
+ __mp->conn_macros = __expr; \
+ __mp->helo_macros = __expr; \
+ __mp->mail_macros = __expr; \
+ __mp->rcpt_macros = __expr; \
+ __mp->data_macros = __expr; \
+ __mp->eoh_macros = __expr; \
+ __mp->eod_macros = __expr; \
+ __mp->unk_macros = __expr; \
+ } while (0)
+
+ mp = (MILTER_MACROS *) mymalloc(sizeof(*mp));
+ switch (mode) {
+ case MILTER_MACROS_ALLOC_ZERO:
+ milter_macros_init(mp, 0);
+ break;
+ case MILTER_MACROS_ALLOC_EMPTY:
+ milter_macros_init(mp, mystrdup(""));
+ break;
+ default:
+ msg_panic("milter_macros_alloc: unknown mode %d", mode);
+ }
+ return (mp);
+}
+
+/* milter_macros_free - destroy memory for MILTER_MACROS structure */
+
+void milter_macros_free(MILTER_MACROS *mp)
+{
+
+ /*
+ * This macro was originally in milter.h, but no-one else needed it.
+ */
+#define milter_macros_wipe(mp) do { \
+ MILTER_MACROS *__mp = mp; \
+ if (__mp->conn_macros) \
+ myfree(__mp->conn_macros); \
+ if (__mp->helo_macros) \
+ myfree(__mp->helo_macros); \
+ if (__mp->mail_macros) \
+ myfree(__mp->mail_macros); \
+ if (__mp->rcpt_macros) \
+ myfree(__mp->rcpt_macros); \
+ if (__mp->data_macros) \
+ myfree(__mp->data_macros); \
+ if (__mp->eoh_macros) \
+ myfree(__mp->eoh_macros); \
+ if (__mp->eod_macros) \
+ myfree(__mp->eod_macros); \
+ if (__mp->unk_macros) \
+ myfree(__mp->unk_macros); \
+ } while (0)
+
+ milter_macros_wipe(mp);
+ myfree((void *) mp);
+}