2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-31 14:17:41 +00:00

postfix-2.5-20071223

This commit is contained in:
Wietse Venema
2007-12-23 00:00:00 -05:00
committed by Viktor Dukhovni
parent 99dd94c9fd
commit a82a55628d
13 changed files with 509 additions and 208 deletions

1
postfix/.indent.pro vendored
View File

@@ -143,6 +143,7 @@
-TMILTER
-TMILTER8
-TMILTERS
-TMILTER_MACROS
-TMILTER_MSG_CONTEXT
-TMIME_ENCODING
-TMIME_INFO

View File

@@ -14053,3 +14053,12 @@ Apologies for any names omitted.
Further polishing of the Milter code and logging. File:
milter/milter8.c.
20071123
Further polishing of the Milter code. With SETSYMLIST, each
Milter can update its own macros instead of clobbering
the global copy is shared with other Milters. Also an
opportunity to clean up some ad-hoc code for sending macro
lists from smtp(8) to cleanup(8). Files: milter/milter.c,
milter/milter8.c, milter/milter_macros.c.

View File

@@ -16,7 +16,7 @@
/* specified attribute scan routine. dsb_scan() is meant
/* to be passed as a call-back to attr_scan(), thusly:
/*
/* ... ATTR_SCAN_FUNC, dsb_scan, (void *) &dsbuf, ...
/* ... ATTR_TYPE_FUNC, dsb_scan, (void *) &dsbuf, ...
/* DIAGNOSTICS
/* Fatal: out of memory.
/* LICENSE

View File

@@ -16,7 +16,7 @@
/* the specified attribute print routine. dsn_print() is meant
/* to be passed as a call-back to attr_print(), thusly:
/*
/* ... ATTR_PRINT_FUNC, dsn_print, (void *) dsn, ...
/* ... ATTR_TYPE_FUNC, dsn_print, (void *) dsn, ...
/* DIAGNOSTICS
/* Fatal: out of memory.
/* LICENSE

View File

@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
#define MAIL_RELEASE_DATE "20071222"
#define MAIL_RELEASE_DATE "20071223"
#define MAIL_VERSION_NUMBER "2.5"
#ifdef SNAPSHOT

View File

@@ -17,7 +17,7 @@
/* msg_stats_print() is meant to be passed as a call-back to
/* attr_print(), thusly:
/*
/* ... ATTR_PRINT_FUNC, msg_stats_print, (void *) stats, ...
/* ... ATTR_TYPE_FUNC, msg_stats_print, (void *) stats, ...
/* DIAGNOSTICS
/* Fatal: out of memory.
/* LICENSE

View File

@@ -41,7 +41,7 @@
/* using the specified attribute scan routine. rcpb_scan()
/* is meant to be passed as a call-back to attr_scan(), thusly:
/*
/* ... ATTR_SCAN_FUNC, rcpb_scan, (void *) rcpt_buf, ...
/* ... ATTR_TYPE_FUNC, rcpb_scan, (void *) rcpt_buf, ...
/*
/* rcpb_create(), rcpb_reset() and rcpb_free() create, wipe
/* and destroy recipient buffer instances.

View File

@@ -17,7 +17,7 @@
/* routine. rcpt_print() is meant to be passed as a call-back
/* to attr_print(), thusly:
/*
/* ... ATTR_PRINT_FUNC, rcpt_print, (void *) recipient, ...
/* ... ATTR_TYPE_FUNC, rcpt_print, (void *) recipient, ...
/* DIAGNOSTICS
/* Fatal: out of memory.
/* LICENSE

View File

@@ -1,6 +1,6 @@
SHELL = /bin/sh
SRCS = milter.c milter8.c
OBJS = milter.o milter8.o
SRCS = milter.c milter8.c milter_macros.c
OBJS = milter.o milter8.o milter_macros.o
HDRS = milter.h
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
@@ -117,4 +117,15 @@ milter8.o: ../../include/vstream.h
milter8.o: ../../include/vstring.h
milter8.o: milter.h
milter8.o: milter8.c
milter_macros.o: ../../include/argv.h
milter_macros.o: ../../include/attr.h
milter_macros.o: ../../include/iostuff.h
milter_macros.o: ../../include/mail_proto.h
milter_macros.o: ../../include/mymalloc.h
milter_macros.o: ../../include/sys_defs.h
milter_macros.o: ../../include/vbuf.h
milter_macros.o: ../../include/vstream.h
milter_macros.o: ../../include/vstring.h
milter_macros.o: milter.h
milter_macros.o: milter_macros.c
test-milter.o: test-milter.c

View File

@@ -310,15 +310,27 @@ const char *milter_conn_event(MILTERS *milters,
{
const char *resp;
MILTER *m;
ARGV *macros;
ARGV *global_macros = 0;
ARGV *any_macros;
#define MILTER_MACRO_EVAL(global_macros, m, milters, member) \
((m->macros && m->macros->member[0]) ? \
milter_macro_lookup(milters, m->macros->member) : \
global_macros ? global_macros : \
(global_macros = \
milter_macro_lookup(milters, milters->macros->member)))
if (msg_verbose)
msg_info("report connect to all milters");
macros = milter_macro_lookup(milters, milters->conn_macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next)
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next) {
any_macros = MILTER_MACRO_EVAL(global_macros, m, milters, conn_macros);
resp = m->conn_event(m, client_name, client_addr, client_port,
addr_family, macros);
argv_free(macros);
addr_family, any_macros);
if (any_macros != global_macros)
argv_free(any_macros);
}
if (global_macros)
argv_free(global_macros);
return (resp);
}
@@ -329,16 +341,19 @@ const char *milter_helo_event(MILTERS *milters, const char *helo_name,
{
const char *resp;
MILTER *m;
ARGV *macros;
ARGV *global_macros = 0;
ARGV *any_macros;
if (msg_verbose)
msg_info("report helo to all milters");
macros = milters->helo_macros == 0 ? 0 :
milter_macro_lookup(milters, milters->helo_macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next)
resp = m->helo_event(m, helo_name, esmtp_flag, macros);
if (macros)
argv_free(macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next) {
any_macros = MILTER_MACRO_EVAL(global_macros, m, milters, helo_macros);
resp = m->helo_event(m, helo_name, esmtp_flag, any_macros);
if (any_macros != global_macros)
argv_free(any_macros);
}
if (global_macros)
argv_free(global_macros);
return (resp);
}
@@ -348,16 +363,19 @@ const char *milter_mail_event(MILTERS *milters, const char **argv)
{
const char *resp;
MILTER *m;
ARGV *macros;
ARGV *global_macros = 0;
ARGV *any_macros;
if (msg_verbose)
msg_info("report sender to all milters");
macros = milters->mail_macros == 0 ? 0 :
milter_macro_lookup(milters, milters->mail_macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next)
resp = m->mail_event(m, argv, macros);
if (macros)
argv_free(macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next) {
any_macros = MILTER_MACRO_EVAL(global_macros, m, milters, mail_macros);
resp = m->mail_event(m, argv, any_macros);
if (any_macros != global_macros)
argv_free(any_macros);
}
if (global_macros)
argv_free(global_macros);
return (resp);
}
@@ -367,16 +385,19 @@ const char *milter_rcpt_event(MILTERS *milters, const char **argv)
{
const char *resp;
MILTER *m;
ARGV *macros;
ARGV *global_macros = 0;
ARGV *any_macros;
if (msg_verbose)
msg_info("report recipient to all milters");
macros = milters->rcpt_macros == 0 ? 0 :
milter_macro_lookup(milters, milters->rcpt_macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next)
resp = m->rcpt_event(m, argv, macros);
if (macros)
argv_free(macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next) {
any_macros = MILTER_MACRO_EVAL(global_macros, m, milters, rcpt_macros);
resp = m->rcpt_event(m, argv, any_macros);
if (any_macros != global_macros)
argv_free(any_macros);
}
if (global_macros)
argv_free(global_macros);
return (resp);
}
@@ -384,26 +405,21 @@ const char *milter_rcpt_event(MILTERS *milters, const char **argv)
const char *milter_data_event(MILTERS *milters)
{
const char *myname = "milter_data_event";
const char *resp;
MILTER *m;
ARGV *macros = 0;
ARGV *global_macros = 0;
ARGV *any_macros;
if (msg_verbose)
msg_info("report data to all milters");
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next) {
if (m->data_event) {
if (macros == 0 && milters->data_macros)
macros = milter_macro_lookup(milters, milters->data_macros);
resp = m->data_event(m, macros);
} else {
if (msg_verbose)
msg_info("%s: skip milter %s (command unimplemented)",
myname, m->name);
}
any_macros = MILTER_MACRO_EVAL(global_macros, m, milters, data_macros);
resp = m->data_event(m, any_macros);
if (any_macros != global_macros)
argv_free(any_macros);
}
if (macros)
argv_free(macros);
if (global_macros)
argv_free(global_macros);
return (resp);
}
@@ -411,26 +427,21 @@ const char *milter_data_event(MILTERS *milters)
const char *milter_unknown_event(MILTERS *milters, const char *command)
{
const char *myname = "milter_unknown_event";
const char *resp;
MILTER *m;
ARGV *macros = 0;
ARGV *global_macros = 0;
ARGV *any_macros;
if (msg_verbose)
msg_info("report unknown command to all milters");
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next) {
if (m->unknown_event) {
if (macros == 0 && milters->unk_macros)
macros = milter_macro_lookup(milters, milters->unk_macros);
resp = m->unknown_event(m, command, macros);
} else {
if (msg_verbose)
msg_info("%s: skip milter %s (command unimplemented)",
myname, m->name);
}
any_macros = MILTER_MACRO_EVAL(global_macros, m, milters, unk_macros);
resp = m->unknown_event(m, command, any_macros);
if (any_macros != global_macros)
argv_free(any_macros);
}
if (macros)
argv_free(macros);
if (global_macros)
argv_free(global_macros);
return (resp);
}
@@ -454,21 +465,26 @@ const char *milter_message(MILTERS *milters, VSTREAM *fp, off_t data_offset)
{
const char *resp;
MILTER *m;
ARGV *eoh_macros;
ARGV *eod_macros;
ARGV *global_eoh_macros = 0;
ARGV *global_eod_macros = 0;
ARGV *any_eoh_macros;
ARGV *any_eod_macros;
if (msg_verbose)
msg_info("inspect content by all milters");
eoh_macros = milters->eoh_macros == 0 ? 0 :
milter_macro_lookup(milters, milters->eoh_macros);
eod_macros = milters->eod_macros == 0 ? 0 :
milter_macro_lookup(milters, milters->eod_macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next)
resp = m->message(m, fp, data_offset, eoh_macros, eod_macros);
if (eoh_macros)
argv_free(eoh_macros);
if (eod_macros)
argv_free(eod_macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next) {
any_eoh_macros = MILTER_MACRO_EVAL(global_eoh_macros, m, milters, eoh_macros);
any_eod_macros = MILTER_MACRO_EVAL(global_eod_macros, m, milters, eod_macros);
resp = m->message(m, fp, data_offset, any_eoh_macros, any_eod_macros);
if (any_eoh_macros != global_eoh_macros)
argv_free(any_eoh_macros);
if (any_eod_macros != global_eod_macros)
argv_free(any_eod_macros);
}
if (global_eoh_macros)
argv_free(global_eoh_macros);
if (global_eod_macros)
argv_free(global_eod_macros);
return (resp);
}
@@ -496,22 +512,15 @@ void milter_disc_event(MILTERS *milters)
m->disc_event(m);
}
/* milter_create - create milter list */
/* milter_new - create milter list */
MILTERS *milter_create(const char *names,
int conn_timeout,
int cmd_timeout,
int msg_timeout,
const char *protocol,
const char *def_action,
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)
MILTERS *milter_new(const char *names,
int conn_timeout,
int cmd_timeout,
int msg_timeout,
const char *protocol,
const char *def_action,
MILTER_MACROS *macros)
{
MILTERS *milters;
MILTER *head = 0;
@@ -544,14 +553,7 @@ MILTERS *milter_create(const char *names,
milters->milter_list = head;
milters->mac_lookup = 0;
milters->mac_context = 0;
milters->conn_macros = mystrdup(conn_macros);
milters->helo_macros = mystrdup(helo_macros);
milters->mail_macros = mystrdup(mail_macros);
milters->rcpt_macros = mystrdup(rcpt_macros);
milters->data_macros = mystrdup(data_macros);
milters->eoh_macros = mystrdup(eoh_macros);
milters->eod_macros = mystrdup(eod_macros);
milters->unk_macros = mystrdup(unk_macros);
milters->macros = macros;
milters->add_header = 0;
milters->upd_header = milters->ins_header = 0;
milters->del_header = 0;
@@ -572,39 +574,11 @@ void milter_free(MILTERS *milters)
msg_info("free all milters");
for (m = milters->milter_list; m != 0; m = next)
next = m->next, m->free(m);
if (milters->conn_macros)
myfree(milters->conn_macros);
if (milters->helo_macros)
myfree(milters->helo_macros);
if (milters->mail_macros)
myfree(milters->mail_macros);
if (milters->rcpt_macros)
myfree(milters->rcpt_macros);
if (milters->rcpt_macros)
myfree(milters->data_macros);
if (milters->eoh_macros)
myfree(milters->eoh_macros);
if (milters->eod_macros)
myfree(milters->eod_macros);
if (milters->unk_macros)
myfree(milters->unk_macros);
if (milters->macros)
milter_macros_free(milters->macros);
myfree((char *) milters);
}
/*
* Temporary protocol to send /receive milter instances. This needs to be
* extended with type information when we support both Sendmail8 and
* Sendmail X protocols.
*/
#define MAIL_ATTR_MILT_CONN "conn_macros"
#define MAIL_ATTR_MILT_HELO "helo_macros"
#define MAIL_ATTR_MILT_MAIL "mail_macros"
#define MAIL_ATTR_MILT_RCPT "rcpt_macros"
#define MAIL_ATTR_MILT_DATA "data_macros"
#define MAIL_ATTR_MILT_EOH "eoh_macros"
#define MAIL_ATTR_MILT_EOD "eod_macros"
#define MAIL_ATTR_MILT_UNK "unk_macros"
/* milter_dummy - send empty milter list */
int milter_dummy(MILTERS *milters, VSTREAM *stream)
@@ -640,14 +614,8 @@ int milter_send(MILTERS *milters, VSTREAM *stream)
* Send the filter macro names.
*/
(void) attr_print(stream, ATTR_FLAG_MORE,
ATTR_TYPE_STR, MAIL_ATTR_MILT_CONN, milters->conn_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_HELO, milters->helo_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAIL, milters->mail_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_RCPT, milters->rcpt_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_DATA, milters->data_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_EOH, milters->eoh_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_EOD, milters->eod_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_UNK, milters->unk_macros,
ATTR_TYPE_FUNC, milter_macros_print,
(void *) milters->macros,
ATTR_TYPE_END);
/*
@@ -675,44 +643,12 @@ MILTERS *milter_receive(VSTREAM *stream, int count)
MILTER *head = 0;
MILTER *tail = 0;
MILTER *milter = 0;
VSTRING *conn_macros;
VSTRING *helo_macros;
VSTRING *mail_macros;
VSTRING *rcpt_macros;
VSTRING *data_macros;
VSTRING *eoh_macros;
VSTRING *eod_macros;
VSTRING *unk_macros;
MILTER_MACROS *macros = milter_macros_alloc(MILTER_MACROS_ALLOC_ZERO);
/*
* Receive filter macros.
*/
#define FREE_BUFFERS() do { \
vstring_free(conn_macros); vstring_free(helo_macros); \
vstring_free(mail_macros); vstring_free(rcpt_macros); \
vstring_free(data_macros); vstring_free(eoh_macros); \
vstring_free(eod_macros); vstring_free(unk_macros); \
} while (0)
conn_macros = vstring_alloc(10);
helo_macros = vstring_alloc(10);
mail_macros = vstring_alloc(10);
rcpt_macros = vstring_alloc(10);
data_macros = vstring_alloc(10);
eoh_macros = vstring_alloc(10);
eod_macros = vstring_alloc(10);
unk_macros = vstring_alloc(10);
if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
ATTR_TYPE_STR, MAIL_ATTR_MILT_CONN, conn_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_HELO, helo_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAIL, mail_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_RCPT, rcpt_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_DATA, data_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_EOH, eoh_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_EOD, eod_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_UNK, unk_macros,
ATTR_TYPE_END) != 8) {
FREE_BUFFERS();
ATTR_TYPE_FUNC, milter_macros_scan, (void *) macros,
ATTR_TYPE_END) != 1) {
milter_macros_free(macros);
return (0);
}
#define NO_MILTERS ((char *) 0)
@@ -720,12 +656,7 @@ MILTERS *milter_receive(VSTREAM *stream, int count)
#define NO_PROTOCOL ((char *) 0)
#define NO_ACTION ((char *) 0)
milters = milter_create(NO_MILTERS, NO_TIMEOUTS, NO_PROTOCOL, NO_ACTION,
STR(conn_macros), STR(helo_macros),
STR(mail_macros), STR(rcpt_macros),
STR(data_macros), STR(eoh_macros),
STR(eod_macros), STR(unk_macros));
FREE_BUFFERS();
milters = milter_new(NO_MILTERS, NO_TIMEOUTS, NO_PROTOCOL, NO_ACTION, macros);
/*
* Receive the filters.

View File

@@ -18,6 +18,11 @@
#include <vstream.h>
#include <argv.h>
/*
* Global library.
*/
#include <attr.h>
/*
* Each Milter handle is an element of a null-terminated linked list. The
* functions are virtual so that we can support multiple MTA-side Milter
@@ -28,6 +33,7 @@ typedef struct MILTER {
char *name; /* full name including transport */
struct MILTER *next; /* linkage */
struct MILTERS *parent; /* parent information */
struct MILTER_MACROS *macros; /* private macros */
const char *(*conn_event) (struct MILTER *, const char *, const char *, const char *, unsigned, ARGV *);
const char *(*helo_event) (struct MILTER *, const char *, int, ARGV *);
const char *(*mail_event) (struct MILTER *, const char **, ARGV *);
@@ -46,6 +52,70 @@ typedef struct MILTER {
extern MILTER *milter8_create(const char *, int, int, int, const char *, const char *, struct MILTERS *);
extern MILTER *milter8_receive(VSTREAM *, struct MILTERS *);
/*
* As of Sendmail 8.14 each milter can override the default macro list. If a
* Milter has its own macro list, a null member means use the global
* definition.
*/
typedef struct MILTER_MACROS {
char *conn_macros; /* macros for connect event */
char *helo_macros; /* macros for HELO/EHLO command */
char *mail_macros; /* macros for MAIL FROM command */
char *rcpt_macros; /* macros for RCPT TO command */
char *data_macros; /* macros for DATA command */
char *eoh_macros; /* macros for end-of-headers */
char *eod_macros; /* macros for END-OF-DATA command */
char *unk_macros; /* macros for unknown command */
} MILTER_MACROS;
extern MILTER_MACROS *milter_macros_create(const char *, const char *,
const char *, const char *,
const char *, const char *,
const char *, const char *);
extern MILTER_MACROS *milter_macros_alloc(int);
extern void milter_macros_free(MILTER_MACROS *);
extern int milter_macros_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
extern int milter_macros_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
#define MILTER_MACROS_ALLOC_ZERO 1 /* null pointer */
#define MILTER_MACROS_ALLOC_EMPTY 2 /* mystrdup(""); */
#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)
#define milter_macros_zero(mp) milter_macros_init(mp, 0)
#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)
/*
* A bunch of Milters.
*/
@@ -60,14 +130,7 @@ typedef struct MILTERS {
MILTER *milter_list; /* linked list of Milters */
MILTER_MAC_LOOKUP_FN mac_lookup;
void *mac_context; /* macro lookup context */
char *conn_macros; /* macros for connect event */
char *helo_macros; /* macros for HELO/EHLO command */
char *mail_macros; /* macros for MAIL FROM command */
char *rcpt_macros; /* macros for RCPT TO command */
char *data_macros; /* macros for DATA command */
char *eoh_macros; /* macros for end-of-headers */
char *eod_macros; /* macros for END-OF-DATA command */
char *unk_macros; /* macros for unknown command */
struct MILTER_MACROS *macros;
void *chg_context; /* context for queue file changes */
MILTER_ADD_HEADER_FN add_header;
MILTER_EDIT_HEADER_FN upd_header;
@@ -78,12 +141,17 @@ typedef struct MILTERS {
MILTER_EDIT_BODY_FN repl_body;
} MILTERS;
extern MILTERS *milter_create(const char *, int, int, int,
const char *, const char *,
const char *, const char *,
const char *, const char *,
const char *, const char *,
const char *, const char *);
#define milter_create(milter_names, conn_timeout, cmd_timeout, msg_timeout, \
protocol, def_action, conn_macros, helo_macros, \
mail_macros, rcpt_macros, data_macros, eoh_macros, \
eod_macros, unk_macros) \
milter_new(milter_names, conn_timeout, cmd_timeout, msg_timeout, \
protocol, def_action, milter_macros_create(conn_macros, \
helo_macros, mail_macros, rcpt_macros, data_macros, \
eoh_macros, eod_macros, unk_macros))
extern MILTERS *milter_new(const char *, int, int, int, const char *,
const char *, MILTER_MACROS *);
extern void milter_macro_callback(MILTERS *, MILTER_MAC_LOOKUP_FN, void *);
extern void milter_edit_callback(MILTERS *milters, MILTER_ADD_HEADER_FN,
MILTER_EDIT_HEADER_FN, MILTER_EDIT_HEADER_FN,

View File

@@ -322,17 +322,17 @@ static NAME_CODE smfim_table[] = {
* members, without using a switch statement.
*/
static size_t milter8_macro_offsets[] = {
offsetof(MILTERS, conn_macros), /* SMFIM_CONNECT */
offsetof(MILTERS, helo_macros), /* SMFIM_HELO */
offsetof(MILTERS, mail_macros), /* SMFIM_ENVFROM */
offsetof(MILTERS, rcpt_macros), /* SMFIM_ENVRCPT */
offsetof(MILTERS, data_macros), /* SMFIM_DATA */
offsetof(MILTERS, eod_macros), /* Note: SMFIM_EOM < SMFIM_EOH */
offsetof(MILTERS, eoh_macros), /* Note: SMFIM_EOH > SMFIM_EOM */
offsetof(MILTER_MACROS, conn_macros), /* SMFIM_CONNECT */
offsetof(MILTER_MACROS, helo_macros), /* SMFIM_HELO */
offsetof(MILTER_MACROS, mail_macros), /* SMFIM_ENVFROM */
offsetof(MILTER_MACROS, rcpt_macros), /* SMFIM_ENVRCPT */
offsetof(MILTER_MACROS, data_macros), /* SMFIM_DATA */
offsetof(MILTER_MACROS, eod_macros),/* Note: SMFIM_EOM < SMFIM_EOH */
offsetof(MILTER_MACROS, eoh_macros),/* Note: SMFIM_EOH > SMFIM_EOM */
};
#define MILTER8_MACRO_PTR(__milters, __type) \
((char **) (((char *) (__milters)) + milter8_macro_offsets[(__type)]))
#define MILTER8_MACRO_PTR(__macros, __type) \
((char **) (((char *) (__macros)) + milter8_macro_offsets[(__type)]))
/*
* How much buffer space is available for sending body content.
@@ -1734,6 +1734,8 @@ static void milter8_connect(MILTER8 *milter)
const char *smfim_name;
char **mac_value_ptr;
milter->m.macros = milter_macros_alloc(MILTER_MACROS_ALLOC_EMPTY);
while (data_len > 0
&& milter8_read_data(milter, &data_len,
MILTER8_DATA_HLONG, &mac_type,
@@ -1747,7 +1749,7 @@ static void milter8_connect(MILTER8 *milter)
if (msg_verbose)
msg_info("override %s macro list with \"%s\"",
smfim_name, STR(buf));
mac_value_ptr = MILTER8_MACRO_PTR(milter->m.parent, mac_type);
mac_value_ptr = MILTER8_MACRO_PTR(milter->m.macros, mac_type);
if (*mac_value_ptr != 0)
myfree(*mac_value_ptr);
*mac_value_ptr = mystrdup(STR(buf));
@@ -2467,6 +2469,7 @@ static const char *milter8_message(MILTER *m, VSTREAM *qfile,
#define MAIL_ATTR_MILT_CMD "milter_cmd_timeout"
#define MAIL_ATTR_MILT_MSG "milter_msg_timeout"
#define MAIL_ATTR_MILT_ACT "milter_action"
#define MAIL_ATTR_MILT_MAC "milter_macro_list"
/* milter8_active - report if this milter still wants events */
@@ -2489,7 +2492,7 @@ static int milter8_send(MILTER *m, VSTREAM *stream)
if (msg_verbose)
msg_info("%s: milter %s", myname, milter->m.name);
if (attr_print(stream, ATTR_FLAG_NONE,
if (attr_print(stream, ATTR_FLAG_MORE,
ATTR_TYPE_STR, MAIL_ATTR_MILT_NAME, milter->m.name,
ATTR_TYPE_INT, MAIL_ATTR_MILT_VERS, milter->version,
ATTR_TYPE_INT, MAIL_ATTR_MILT_ACTS, milter->rq_mask,
@@ -2500,7 +2503,16 @@ static int milter8_send(MILTER *m, VSTREAM *stream)
ATTR_TYPE_INT, MAIL_ATTR_MILT_CMD, milter->cmd_timeout,
ATTR_TYPE_INT, MAIL_ATTR_MILT_MSG, milter->msg_timeout,
ATTR_TYPE_STR, MAIL_ATTR_MILT_ACT, milter->def_action,
ATTR_TYPE_INT, MAIL_ATTR_MILT_MAC, milter->m.macros != 0,
ATTR_TYPE_END) != 0
|| (milter->m.macros != 0
&& attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_FUNC, milter_macros_print,
(void *) milter->m.macros,
ATTR_TYPE_END) != 0)
|| (milter->m.macros == 0
&& attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_END) != 0)
|| vstream_fflush(stream) != 0) {
return (-1);
#ifdef CANT_WRITE_BEFORE_SENDING_FD
@@ -2524,7 +2536,7 @@ static int milter8_send(MILTER *m, VSTREAM *stream)
}
static MILTER8 *milter8_alloc(const char *, int, int, int, const char *,
const char *, MILTERS *);
const char *, MILTERS *);
/* milter8_receive - receive milter instance */
@@ -2543,12 +2555,20 @@ MILTER *milter8_receive(VSTREAM *stream, MILTERS *parent)
int cmd_timeout;
int msg_timeout;
int fd;
int has_macros;
MILTER_MACROS *macros = 0;
#define FREE_MACROS_AND_RETURN(x) do { \
if (macros) \
milter_macros_free(macros); \
return (x); \
} while (0)
if (name_buf == 0) {
name_buf = vstring_alloc(10);
act_buf = vstring_alloc(10);
}
if (attr_scan(stream, ATTR_FLAG_STRICT,
if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
ATTR_TYPE_STR, MAIL_ATTR_MILT_NAME, name_buf,
ATTR_TYPE_INT, MAIL_ATTR_MILT_VERS, &version,
ATTR_TYPE_INT, MAIL_ATTR_MILT_ACTS, &rq_mask,
@@ -2559,22 +2579,32 @@ MILTER *milter8_receive(VSTREAM *stream, MILTERS *parent)
ATTR_TYPE_INT, MAIL_ATTR_MILT_CMD, &cmd_timeout,
ATTR_TYPE_INT, MAIL_ATTR_MILT_MSG, &msg_timeout,
ATTR_TYPE_STR, MAIL_ATTR_MILT_ACT, act_buf,
ATTR_TYPE_END) < 9) {
return (0);
ATTR_TYPE_INT, MAIL_ATTR_MILT_MAC, &has_macros,
ATTR_TYPE_END) < 10
|| (has_macros != 0
&& attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_FUNC, milter_macros_scan,
(void *) (macros =
milter_macros_alloc(MILTER_MACROS_ALLOC_ZERO)),
ATTR_TYPE_END) < 1)
|| (has_macros == 0
&& attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_END) < 0)) {
FREE_MACROS_AND_RETURN(0);
#ifdef CANT_WRITE_BEFORE_SENDING_FD
} else if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "",
ATTR_TYPE_END) != 0
|| vstream_fflush(stream) != 0) {
return (0);
FREE_MACROS_AND_RETURN(0);
#endif
} else if ((fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0) {
return (0);
FREE_MACROS_AND_RETURN(0);
#ifdef MUST_READ_AFTER_SENDING_FD
} else if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "",
ATTR_TYPE_END) != 0) {
return (0);
FREE_MACROS_AND_RETURN(0);
#endif
} else {
#define NO_PROTOCOL ((char *) 0)
@@ -2585,6 +2615,7 @@ MILTER *milter8_receive(VSTREAM *stream, MILTERS *parent)
milter = milter8_alloc(STR(name_buf), conn_timeout, cmd_timeout,
msg_timeout, NO_PROTOCOL, STR(act_buf), parent);
milter->fp = vstream_fdopen(fd, O_RDWR);
milter->m.macros = macros;
vstream_control(milter->fp, VSTREAM_CTL_DOUBLE, VSTREAM_CTL_END);
/* Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE. */
vstream_tweak_sock(milter->fp);
@@ -2615,6 +2646,8 @@ static void milter8_free(MILTER *m)
myfree(milter->def_action);
if (milter->def_reply)
myfree(milter->def_reply);
if (milter->m.macros)
milter_macros_free(milter->m.macros);
myfree((char *) milter);
}
@@ -2635,6 +2668,7 @@ static MILTER8 *milter8_alloc(const char *name, int conn_timeout,
milter->m.name = mystrdup(name);
milter->m.next = 0;
milter->m.parent = parent;
milter->m.macros = 0;
milter->m.conn_event = milter8_conn_event;
milter->m.helo_event = milter8_helo_event;
milter->m.mail_event = milter8_mail_event;
@@ -2678,7 +2712,7 @@ MILTER *milter8_create(const char *name, int conn_timeout, int cmd_timeout,
* Fill in the structure.
*/
milter = milter8_alloc(name, conn_timeout, cmd_timeout, msg_timeout,
protocol, def_action, parent);
protocol, def_action, parent);
/*
* XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds

View File

@@ -0,0 +1,247 @@
/*++
/* 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_MASTER_FN print_fn;
/* VSTREAM *stream;
/* int flags;
/* void *ptr;
/*
/* int milter_macros_scan(scan_fn, fp, flags, ptr)
/* ATTR_SCAN_MASTER_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, the lists of names are stored in MILTER_MACROS
/* structures. 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, and individual filters may
/* have their own partial list.
/*
/* This module maintains the macro name lists as mystrdup()'ed
/* values. The user is explicitly allowed to update these
/* values directly, as long as they respect the mystrdup()
/* interface.
/*
/* milter_macros_create() creates a MILTER_MACROS structure
/* and initializes it with copies of its string arguments.
/*
/* milter_macros_alloc() creates a MILTER_MACROS structure
/* that is initialized according to its init_mode argument.
/* .IP MILTER_MACROS_ALLOC_ZERO
/* Initialize all members as null pointers. This mode is
/* recommended for applications that use milter_macros_scan().
/* .IP MILTER_MACROS_ALLOC_EMPTY
/* Initialize all members with mystrdup(""). This is not as
/* expensive as it appears to be. This mode is recommend for
/* applications that update individual MILTER_MACROS members
/* directly.
/* .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:
/*
/* ATTR_TYPE_FUNC, milter_macros_print, (void *) macros,
/*
/* milter_macros_scan() reads a MILTER_MACROS structure from
/* the named stream using the specified attribute scan routine.
/* milter_macros_scan() is meant to be passed as a call-back
/* to attr_scan*(), thusly:
/*
/* ATTR_TYPE_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
/*--*/
/* 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 recipient to stream */
int milter_macros_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
int flags, 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,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_CONN, mp->conn_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_HELO, mp->helo_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_MAIL, mp->mail_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_RCPT, mp->rcpt_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_DATA, mp->data_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOH, mp->eoh_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOD, mp->eod_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_UNK, mp->unk_macros,
ATTR_TYPE_END);
return (ret);
}
/* milter_macros_scan - receive milter macro name list */
int milter_macros_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
int flags, void *ptr)
{
MILTER_MACROS *mp = (MILTER_MACROS *) ptr;
int ret;
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,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_CONN, conn_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_HELO, helo_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_MAIL, mail_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_RCPT, rcpt_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_DATA, data_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOH, eoh_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOD, eod_macros,
ATTR_TYPE_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 memory for structure with simple initialization */
MILTER_MACROS *milter_macros_alloc(int mode)
{
MILTER_MACROS *mp;
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)
{
milter_macros_wipe(mp);
myfree((char *) mp);
}