summaryrefslogtreecommitdiffstats
path: root/src/milter/milter_macros.c
blob: 95126b1ed92fbe4a5833f3e79ec6df283d6c9c00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/*++
/* 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, 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, (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
/*--*/

/* 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_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,
		   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_MASTER_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);
}