xref: /netbsd-src/external/ibm-public/postfix/dist/src/milter/milter_macros.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: milter_macros.c,v 1.2 2017/02/14 01:16:45 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	milter_macros
6 /* SUMMARY
7 /*	manipulate MILTER_MACROS structures
8 /* SYNOPSIS
9 /*	#include <milter.h>
10 /*
11 /*	MILTER_MACROS *milter_macros_create(conn_macros, helo_macros,
12 /*					mail_macros, rcpt_macros,
13 /*					data_macros, eoh_macros,
14 /*					eod_macros, unk_macros)
15 /*	const char *conn_macros;
16 /*	const char *helo_macros;
17 /*	const char *mail_macros;
18 /*	const char *rcpt_macrps;
19 /*	const char *data_macros;
20 /*	const char *eoh_macros;
21 /*	const char *eod_macros;
22 /*	const char *unk_macros;
23 /*
24 /*	MILTER_MACROS *milter_macros_alloc(init_mode)
25 /*	int	init_mode;
26 /*
27 /*	void	milter_macros_free(mp)
28 /*	MILTER_MACROS *mp;
29 /*
30 /*	int     milter_macros_print(print_fn, stream, flags, ptr)
31 /*	ATTR_PRINT_MASTER_FN print_fn;
32 /*	VSTREAM *stream;
33 /*	int	flags;
34 /*	void	*ptr;
35 /*
36 /*	int	milter_macros_scan(scan_fn, fp, flags, ptr)
37 /*	ATTR_SCAN_MASTER_FN scan_fn;
38 /*	VSTREAM	*fp;
39 /*	int	flags;
40 /*	void	*ptr;
41 /* DESCRIPTION
42 /*	Sendmail mail filter (Milter) applications receive sets of
43 /*	macro name=value pairs with each SMTP or content event.
44 /*	In Postfix, these macro names are stored in MILTER_MACROS
45 /*	structures, as one list for each event type. By default,
46 /*	the same structure is shared by all Milter applications;
47 /*	it is initialized with information from main.cf. With
48 /*	Sendmail 8.14 a Milter can override one or more lists of
49 /*	macro names. Postfix implements this by giving the Milter
50 /*	its own MILTER_MACROS structure and by storing the per-Milter
51 /*	information there.
52 /*
53 /*	This module maintains per-event macro name lists as
54 /*	mystrdup()'ed values. The user is explicitly allowed to
55 /*	update these values directly, as long as the result is
56 /*	compatible with mystrdup().
57 /*
58 /*	milter_macros_create() creates a MILTER_MACROS structure
59 /*	and initializes it with copies of its string arguments.
60 /*	Null pointers are not valid as input.
61 /*
62 /*	milter_macros_alloc() creates am empty MILTER_MACROS structure
63 /*	that is initialized according to its init_mode argument.
64 /* .IP MILTER_MACROS_ALLOC_ZERO
65 /*	Initialize all structure members as null pointers. This
66 /*	mode must be used with milter_macros_scan(), because that
67 /*	function blindly overwrites all structure members.  No other
68 /*	function except milter_macros_free() allows structure members
69 /*	with null pointer values.
70 /* .IP MILTER_MACROS_ALLOC_EMPTY
71 /*	Initialize all structure members with mystrdup(""). This
72 /*	is not as expensive as it appears to be.
73 /* .PP
74 /*	milter_macros_free() destroys a MILTER_MACROS structure and
75 /*	frees any strings referenced by it.
76 /*
77 /*	milter_macros_print() writes the contents of a MILTER_MACROS
78 /*	structure to the named stream using the specified attribute
79 /*	print routine.  milter_macros_print() is meant to be passed
80 /*	as a call-back to attr_print*(), thusly:
81 /*
82 /*	SEND_ATTR_FUNC(milter_macros_print, (void *) macros),
83 /*
84 /*	milter_macros_scan() reads a MILTER_MACROS structure from
85 /*	the named stream using the specified attribute scan routine.
86 /*	No attempt is made to free the memory of existing structure
87 /*	members.  milter_macros_scan() is meant to be passed as a
88 /*	call-back to attr_scan*(), thusly:
89 /*
90 /*	RECV_ATTR_FUNC(milter_macros_scan, (void *) macros),
91 /* DIAGNOSTICS
92 /*	Fatal: out of memory.
93 /* LICENSE
94 /* .ad
95 /* .fi
96 /*	The Secure Mailer license must be distributed with this
97 /*	software.
98 /* AUTHOR(S)
99 /*	Wietse Venema
100 /*	IBM T.J. Watson Research
101 /*	P.O. Box 704
102 /*	Yorktown Heights, NY 10598, USA
103 /*--*/
104 
105 /* System library. */
106 
107 #include <sys_defs.h>
108 
109 /* Utility library. */
110 
111 #include <msg.h>
112 #include <attr.h>
113 #include <mymalloc.h>
114 #include <vstring.h>
115 
116 /* Global library. */
117 
118 #include <mail_proto.h>
119 #include <milter.h>
120 
121  /*
122   * Ad-hoc protocol to send/receive milter macro name lists.
123   */
124 #define MAIL_ATTR_MILT_MAC_CONN	"conn_macros"
125 #define MAIL_ATTR_MILT_MAC_HELO	"helo_macros"
126 #define MAIL_ATTR_MILT_MAC_MAIL	"mail_macros"
127 #define MAIL_ATTR_MILT_MAC_RCPT	"rcpt_macros"
128 #define MAIL_ATTR_MILT_MAC_DATA	"data_macros"
129 #define MAIL_ATTR_MILT_MAC_EOH	"eoh_macros"
130 #define MAIL_ATTR_MILT_MAC_EOD	"eod_macros"
131 #define MAIL_ATTR_MILT_MAC_UNK	"unk_macros"
132 
133 /* milter_macros_print - write macros structure to stream */
134 
135 int     milter_macros_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
136 			            int flags, void *ptr)
137 {
138     MILTER_MACROS *mp = (MILTER_MACROS *) ptr;
139     int     ret;
140 
141     /*
142      * The attribute order does not matter, except that it must be the same
143      * as in the milter_macros_scan() function.
144      */
145     ret = print_fn(fp, flags | ATTR_FLAG_MORE,
146 		   SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_CONN, mp->conn_macros),
147 		   SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_HELO, mp->helo_macros),
148 		   SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_MAIL, mp->mail_macros),
149 		   SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_RCPT, mp->rcpt_macros),
150 		   SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_DATA, mp->data_macros),
151 		   SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_EOH, mp->eoh_macros),
152 		   SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_EOD, mp->eod_macros),
153 		   SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_UNK, mp->unk_macros),
154 		   ATTR_TYPE_END);
155     return (ret);
156 }
157 
158 /* milter_macros_scan - receive macros structure from stream */
159 
160 int     milter_macros_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
161 			           int flags, void *ptr)
162 {
163     MILTER_MACROS *mp = (MILTER_MACROS *) ptr;
164     int     ret;
165 
166     /*
167      * We could simplify this by moving memory allocation into attr_scan*().
168      */
169     VSTRING *conn_macros = vstring_alloc(10);
170     VSTRING *helo_macros = vstring_alloc(10);
171     VSTRING *mail_macros = vstring_alloc(10);
172     VSTRING *rcpt_macros = vstring_alloc(10);
173     VSTRING *data_macros = vstring_alloc(10);
174     VSTRING *eoh_macros = vstring_alloc(10);
175     VSTRING *eod_macros = vstring_alloc(10);
176     VSTRING *unk_macros = vstring_alloc(10);
177 
178     /*
179      * The attribute order does not matter, except that it must be the same
180      * as in the milter_macros_print() function.
181      */
182     ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
183 		  RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_CONN, conn_macros),
184 		  RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_HELO, helo_macros),
185 		  RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_MAIL, mail_macros),
186 		  RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_RCPT, rcpt_macros),
187 		  RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_DATA, data_macros),
188 		  RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_EOH, eoh_macros),
189 		  RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_EOD, eod_macros),
190 		  RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_UNK, unk_macros),
191 		  ATTR_TYPE_END);
192 
193     /*
194      * Don't optimize for error.
195      */
196     mp->conn_macros = vstring_export(conn_macros);
197     mp->helo_macros = vstring_export(helo_macros);
198     mp->mail_macros = vstring_export(mail_macros);
199     mp->rcpt_macros = vstring_export(rcpt_macros);
200     mp->data_macros = vstring_export(data_macros);
201     mp->eoh_macros = vstring_export(eoh_macros);
202     mp->eod_macros = vstring_export(eod_macros);
203     mp->unk_macros = vstring_export(unk_macros);
204 
205     return (ret == 8 ? 1 : -1);
206 }
207 
208 /* milter_macros_create - create and initialize macros structure */
209 
210 MILTER_MACROS *milter_macros_create(const char *conn_macros,
211 				            const char *helo_macros,
212 				            const char *mail_macros,
213 				            const char *rcpt_macros,
214 				            const char *data_macros,
215 				            const char *eoh_macros,
216 				            const char *eod_macros,
217 				            const char *unk_macros)
218 {
219     MILTER_MACROS *mp;
220 
221     mp = (MILTER_MACROS *) mymalloc(sizeof(*mp));
222     mp->conn_macros = mystrdup(conn_macros);
223     mp->helo_macros = mystrdup(helo_macros);
224     mp->mail_macros = mystrdup(mail_macros);
225     mp->rcpt_macros = mystrdup(rcpt_macros);
226     mp->data_macros = mystrdup(data_macros);
227     mp->eoh_macros = mystrdup(eoh_macros);
228     mp->eod_macros = mystrdup(eod_macros);
229     mp->unk_macros = mystrdup(unk_macros);
230 
231     return (mp);
232 }
233 
234 /* milter_macros_alloc - allocate macros structure with simple initialization */
235 
236 MILTER_MACROS *milter_macros_alloc(int mode)
237 {
238     MILTER_MACROS *mp;
239 
240     /*
241      * This macro was originally in milter.h, but no-one else needed it.
242      */
243 #define milter_macros_init(mp, expr) do { \
244 	MILTER_MACROS *__mp = (mp); \
245 	char *__expr = (expr); \
246 	__mp->conn_macros = __expr; \
247 	__mp->helo_macros = __expr; \
248 	__mp->mail_macros = __expr; \
249 	__mp->rcpt_macros = __expr; \
250 	__mp->data_macros = __expr; \
251 	__mp->eoh_macros = __expr; \
252 	__mp->eod_macros = __expr; \
253 	__mp->unk_macros = __expr; \
254     } while (0)
255 
256     mp = (MILTER_MACROS *) mymalloc(sizeof(*mp));
257     switch (mode) {
258     case MILTER_MACROS_ALLOC_ZERO:
259 	milter_macros_init(mp, 0);
260 	break;
261     case MILTER_MACROS_ALLOC_EMPTY:
262 	milter_macros_init(mp, mystrdup(""));
263 	break;
264     default:
265 	msg_panic("milter_macros_alloc: unknown mode %d", mode);
266     }
267     return (mp);
268 }
269 
270 /* milter_macros_free - destroy memory for MILTER_MACROS structure */
271 
272 void    milter_macros_free(MILTER_MACROS *mp)
273 {
274 
275     /*
276      * This macro was originally in milter.h, but no-one else needed it.
277      */
278 #define milter_macros_wipe(mp) do { \
279 	MILTER_MACROS *__mp = mp; \
280 	if (__mp->conn_macros) \
281 	    myfree(__mp->conn_macros); \
282 	if (__mp->helo_macros) \
283 	    myfree(__mp->helo_macros); \
284 	if (__mp->mail_macros) \
285 	    myfree(__mp->mail_macros); \
286 	if (__mp->rcpt_macros) \
287 	    myfree(__mp->rcpt_macros); \
288 	if (__mp->data_macros) \
289 	    myfree(__mp->data_macros); \
290 	if (__mp->eoh_macros) \
291 	    myfree(__mp->eoh_macros); \
292 	if (__mp->eod_macros) \
293 	    myfree(__mp->eod_macros); \
294 	if (__mp->unk_macros) \
295 	    myfree(__mp->unk_macros); \
296     } while (0)
297 
298     milter_macros_wipe(mp);
299     myfree((void *) mp);
300 }
301