106f25ae9SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 1999-2007 Proofpoint, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro * All rights reserved.
406f25ae9SGregory Neil Shapiro *
506f25ae9SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
606f25ae9SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
706f25ae9SGregory Neil Shapiro * the sendmail distribution.
806f25ae9SGregory Neil Shapiro *
906f25ae9SGregory Neil Shapiro */
1006f25ae9SGregory Neil Shapiro
1140266059SGregory Neil Shapiro #include <sm/gen.h>
124313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: smfi.c,v 8.84 2013-11-22 20:51:36 ca Exp $")
1340266059SGregory Neil Shapiro #include <sm/varargs.h>
1406f25ae9SGregory Neil Shapiro #include "libmilter.h"
1540266059SGregory Neil Shapiro
16e92d3f3fSGregory Neil Shapiro static int smfi_header __P((SMFICTX *, int, int, char *, char *));
17b6bacd31SGregory Neil Shapiro static int myisenhsc __P((const char *, int));
18e92d3f3fSGregory Neil Shapiro
1940266059SGregory Neil Shapiro /* for smfi_set{ml}reply, let's be generous. 256/16 should be sufficient */
2040266059SGregory Neil Shapiro #define MAXREPLYLEN 980 /* max. length of a reply string */
2140266059SGregory Neil Shapiro #define MAXREPLIES 32 /* max. number of reply strings */
2206f25ae9SGregory Neil Shapiro
2306f25ae9SGregory Neil Shapiro /*
24e92d3f3fSGregory Neil Shapiro ** SMFI_HEADER -- send a header to the MTA
25e92d3f3fSGregory Neil Shapiro **
26e92d3f3fSGregory Neil Shapiro ** Parameters:
27e92d3f3fSGregory Neil Shapiro ** ctx -- Opaque context structure
28e92d3f3fSGregory Neil Shapiro ** cmd -- Header modification command
29e92d3f3fSGregory Neil Shapiro ** hdridx -- Header index
30e92d3f3fSGregory Neil Shapiro ** headerf -- Header field name
31e92d3f3fSGregory Neil Shapiro ** headerv -- Header field value
32e92d3f3fSGregory Neil Shapiro **
33e92d3f3fSGregory Neil Shapiro ** Returns:
34e92d3f3fSGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
35e92d3f3fSGregory Neil Shapiro */
36e92d3f3fSGregory Neil Shapiro
37e92d3f3fSGregory Neil Shapiro static int
smfi_header(ctx,cmd,hdridx,headerf,headerv)38e92d3f3fSGregory Neil Shapiro smfi_header(ctx, cmd, hdridx, headerf, headerv)
39e92d3f3fSGregory Neil Shapiro SMFICTX *ctx;
40e92d3f3fSGregory Neil Shapiro int cmd;
41e92d3f3fSGregory Neil Shapiro int hdridx;
42e92d3f3fSGregory Neil Shapiro char *headerf;
43e92d3f3fSGregory Neil Shapiro char *headerv;
44e92d3f3fSGregory Neil Shapiro {
45e92d3f3fSGregory Neil Shapiro size_t len, l1, l2, offset;
46e92d3f3fSGregory Neil Shapiro int r;
47e92d3f3fSGregory Neil Shapiro mi_int32 v;
48e92d3f3fSGregory Neil Shapiro char *buf;
49e92d3f3fSGregory Neil Shapiro struct timeval timeout;
50e92d3f3fSGregory Neil Shapiro
51e92d3f3fSGregory Neil Shapiro if (headerf == NULL || *headerf == '\0' || headerv == NULL)
52e92d3f3fSGregory Neil Shapiro return MI_FAILURE;
53e92d3f3fSGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout;
54e92d3f3fSGregory Neil Shapiro timeout.tv_usec = 0;
55e92d3f3fSGregory Neil Shapiro l1 = strlen(headerf) + 1;
56e92d3f3fSGregory Neil Shapiro l2 = strlen(headerv) + 1;
57e92d3f3fSGregory Neil Shapiro len = l1 + l2;
58e92d3f3fSGregory Neil Shapiro if (hdridx >= 0)
59e92d3f3fSGregory Neil Shapiro len += MILTER_LEN_BYTES;
60e92d3f3fSGregory Neil Shapiro buf = malloc(len);
61e92d3f3fSGregory Neil Shapiro if (buf == NULL)
62e92d3f3fSGregory Neil Shapiro return MI_FAILURE;
63e92d3f3fSGregory Neil Shapiro offset = 0;
64e92d3f3fSGregory Neil Shapiro if (hdridx >= 0)
65e92d3f3fSGregory Neil Shapiro {
66e92d3f3fSGregory Neil Shapiro v = htonl(hdridx);
67e92d3f3fSGregory Neil Shapiro (void) memcpy(&(buf[0]), (void *) &v, MILTER_LEN_BYTES);
68e92d3f3fSGregory Neil Shapiro offset += MILTER_LEN_BYTES;
69e92d3f3fSGregory Neil Shapiro }
70e92d3f3fSGregory Neil Shapiro (void) memcpy(buf + offset, headerf, l1);
71e92d3f3fSGregory Neil Shapiro (void) memcpy(buf + offset + l1, headerv, l2);
72e92d3f3fSGregory Neil Shapiro r = mi_wr_cmd(ctx->ctx_sd, &timeout, cmd, buf, len);
73e92d3f3fSGregory Neil Shapiro free(buf);
74e92d3f3fSGregory Neil Shapiro return r;
75e92d3f3fSGregory Neil Shapiro }
76e92d3f3fSGregory Neil Shapiro
77e92d3f3fSGregory Neil Shapiro /*
7806f25ae9SGregory Neil Shapiro ** SMFI_ADDHEADER -- send a new header to the MTA
7906f25ae9SGregory Neil Shapiro **
8006f25ae9SGregory Neil Shapiro ** Parameters:
8106f25ae9SGregory Neil Shapiro ** ctx -- Opaque context structure
8206f25ae9SGregory Neil Shapiro ** headerf -- Header field name
8306f25ae9SGregory Neil Shapiro ** headerv -- Header field value
8406f25ae9SGregory Neil Shapiro **
8506f25ae9SGregory Neil Shapiro ** Returns:
8606f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
8706f25ae9SGregory Neil Shapiro */
8806f25ae9SGregory Neil Shapiro
8906f25ae9SGregory Neil Shapiro int
smfi_addheader(ctx,headerf,headerv)9006f25ae9SGregory Neil Shapiro smfi_addheader(ctx, headerf, headerv)
9106f25ae9SGregory Neil Shapiro SMFICTX *ctx;
9206f25ae9SGregory Neil Shapiro char *headerf;
9306f25ae9SGregory Neil Shapiro char *headerv;
9406f25ae9SGregory Neil Shapiro {
9506f25ae9SGregory Neil Shapiro if (!mi_sendok(ctx, SMFIF_ADDHDRS))
9606f25ae9SGregory Neil Shapiro return MI_FAILURE;
97e92d3f3fSGregory Neil Shapiro
98e92d3f3fSGregory Neil Shapiro return smfi_header(ctx, SMFIR_ADDHEADER, -1, headerf, headerv);
99e92d3f3fSGregory Neil Shapiro }
100e92d3f3fSGregory Neil Shapiro
101e92d3f3fSGregory Neil Shapiro /*
102e92d3f3fSGregory Neil Shapiro ** SMFI_INSHEADER -- send a new header to the MTA (to be inserted)
103e92d3f3fSGregory Neil Shapiro **
104e92d3f3fSGregory Neil Shapiro ** Parameters:
105e92d3f3fSGregory Neil Shapiro ** ctx -- Opaque context structure
106e92d3f3fSGregory Neil Shapiro ** hdridx -- index into header list where insertion should occur
107e92d3f3fSGregory Neil Shapiro ** headerf -- Header field name
108e92d3f3fSGregory Neil Shapiro ** headerv -- Header field value
109e92d3f3fSGregory Neil Shapiro **
110e92d3f3fSGregory Neil Shapiro ** Returns:
111e92d3f3fSGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
112e92d3f3fSGregory Neil Shapiro */
113e92d3f3fSGregory Neil Shapiro
114e92d3f3fSGregory Neil Shapiro int
smfi_insheader(ctx,hdridx,headerf,headerv)115e92d3f3fSGregory Neil Shapiro smfi_insheader(ctx, hdridx, headerf, headerv)
116e92d3f3fSGregory Neil Shapiro SMFICTX *ctx;
117e92d3f3fSGregory Neil Shapiro int hdridx;
118e92d3f3fSGregory Neil Shapiro char *headerf;
119e92d3f3fSGregory Neil Shapiro char *headerv;
120e92d3f3fSGregory Neil Shapiro {
121e92d3f3fSGregory Neil Shapiro if (!mi_sendok(ctx, SMFIF_ADDHDRS) || hdridx < 0)
12206f25ae9SGregory Neil Shapiro return MI_FAILURE;
123e92d3f3fSGregory Neil Shapiro
124e92d3f3fSGregory Neil Shapiro return smfi_header(ctx, SMFIR_INSHEADER, hdridx, headerf, headerv);
12506f25ae9SGregory Neil Shapiro }
12606f25ae9SGregory Neil Shapiro
12706f25ae9SGregory Neil Shapiro /*
12806f25ae9SGregory Neil Shapiro ** SMFI_CHGHEADER -- send a changed header to the MTA
12906f25ae9SGregory Neil Shapiro **
13006f25ae9SGregory Neil Shapiro ** Parameters:
13106f25ae9SGregory Neil Shapiro ** ctx -- Opaque context structure
13206f25ae9SGregory Neil Shapiro ** headerf -- Header field name
13306f25ae9SGregory Neil Shapiro ** hdridx -- Header index value
13406f25ae9SGregory Neil Shapiro ** headerv -- Header field value
13506f25ae9SGregory Neil Shapiro **
13606f25ae9SGregory Neil Shapiro ** Returns:
13706f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
13806f25ae9SGregory Neil Shapiro */
13906f25ae9SGregory Neil Shapiro
14006f25ae9SGregory Neil Shapiro int
smfi_chgheader(ctx,headerf,hdridx,headerv)14106f25ae9SGregory Neil Shapiro smfi_chgheader(ctx, headerf, hdridx, headerv)
14206f25ae9SGregory Neil Shapiro SMFICTX *ctx;
14306f25ae9SGregory Neil Shapiro char *headerf;
14406f25ae9SGregory Neil Shapiro mi_int32 hdridx;
14506f25ae9SGregory Neil Shapiro char *headerv;
14606f25ae9SGregory Neil Shapiro {
147e92d3f3fSGregory Neil Shapiro if (!mi_sendok(ctx, SMFIF_CHGHDRS) || hdridx < 0)
14806f25ae9SGregory Neil Shapiro return MI_FAILURE;
14906f25ae9SGregory Neil Shapiro if (headerv == NULL)
15006f25ae9SGregory Neil Shapiro headerv = "";
151e92d3f3fSGregory Neil Shapiro
152e92d3f3fSGregory Neil Shapiro return smfi_header(ctx, SMFIR_CHGHEADER, hdridx, headerf, headerv);
15306f25ae9SGregory Neil Shapiro }
154605302a5SGregory Neil Shapiro
155d0cef73dSGregory Neil Shapiro #if 0
156d0cef73dSGregory Neil Shapiro /*
157d0cef73dSGregory Neil Shapiro ** BUF_CRT_SEND -- construct buffer to send from arguments
158d0cef73dSGregory Neil Shapiro **
159d0cef73dSGregory Neil Shapiro ** Parameters:
160d0cef73dSGregory Neil Shapiro ** ctx -- Opaque context structure
161d0cef73dSGregory Neil Shapiro ** cmd -- command
162d0cef73dSGregory Neil Shapiro ** arg0 -- first argument
163d0cef73dSGregory Neil Shapiro ** argv -- list of arguments (NULL terminated)
164d0cef73dSGregory Neil Shapiro **
165d0cef73dSGregory Neil Shapiro ** Returns:
166d0cef73dSGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
167d0cef73dSGregory Neil Shapiro */
168d0cef73dSGregory Neil Shapiro
169d0cef73dSGregory Neil Shapiro static int
170d0cef73dSGregory Neil Shapiro buf_crt_send __P((SMFICTX *, int cmd, char *, char **));
171d0cef73dSGregory Neil Shapiro
172d0cef73dSGregory Neil Shapiro static int
173d0cef73dSGregory Neil Shapiro buf_crt_send(ctx, cmd, arg0, argv)
174d0cef73dSGregory Neil Shapiro SMFICTX *ctx;
175d0cef73dSGregory Neil Shapiro int cmd;
176d0cef73dSGregory Neil Shapiro char *arg0;
177d0cef73dSGregory Neil Shapiro char **argv;
178d0cef73dSGregory Neil Shapiro {
179d0cef73dSGregory Neil Shapiro size_t len, l0, l1, offset;
180d0cef73dSGregory Neil Shapiro int r;
181d0cef73dSGregory Neil Shapiro char *buf, *arg, **argvl;
182d0cef73dSGregory Neil Shapiro struct timeval timeout;
183d0cef73dSGregory Neil Shapiro
184d0cef73dSGregory Neil Shapiro if (arg0 == NULL || *arg0 == '\0')
185d0cef73dSGregory Neil Shapiro return MI_FAILURE;
186d0cef73dSGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout;
187d0cef73dSGregory Neil Shapiro timeout.tv_usec = 0;
188d0cef73dSGregory Neil Shapiro l0 = strlen(arg0) + 1;
189d0cef73dSGregory Neil Shapiro len = l0;
190d0cef73dSGregory Neil Shapiro argvl = argv;
191d0cef73dSGregory Neil Shapiro while (argvl != NULL && (arg = *argv) != NULL && *arg != '\0')
192d0cef73dSGregory Neil Shapiro {
193d0cef73dSGregory Neil Shapiro l1 = strlen(arg) + 1;
194d0cef73dSGregory Neil Shapiro len += l1;
195d0cef73dSGregory Neil Shapiro SM_ASSERT(len > l1);
196d0cef73dSGregory Neil Shapiro }
197d0cef73dSGregory Neil Shapiro
198d0cef73dSGregory Neil Shapiro buf = malloc(len);
199d0cef73dSGregory Neil Shapiro if (buf == NULL)
200d0cef73dSGregory Neil Shapiro return MI_FAILURE;
201d0cef73dSGregory Neil Shapiro (void) memcpy(buf, arg0, l0);
202d0cef73dSGregory Neil Shapiro offset = l0;
203d0cef73dSGregory Neil Shapiro
204d0cef73dSGregory Neil Shapiro argvl = argv;
205d0cef73dSGregory Neil Shapiro while (argvl != NULL && (arg = *argv) != NULL && *arg != '\0')
206d0cef73dSGregory Neil Shapiro {
207d0cef73dSGregory Neil Shapiro l1 = strlen(arg) + 1;
208d0cef73dSGregory Neil Shapiro SM_ASSERT(offset < len);
209d0cef73dSGregory Neil Shapiro SM_ASSERT(offset + l1 <= len);
210d0cef73dSGregory Neil Shapiro (void) memcpy(buf + offset, arg, l1);
211d0cef73dSGregory Neil Shapiro offset += l1;
212d0cef73dSGregory Neil Shapiro SM_ASSERT(offset > l1);
213d0cef73dSGregory Neil Shapiro }
214d0cef73dSGregory Neil Shapiro
215d0cef73dSGregory Neil Shapiro r = mi_wr_cmd(ctx->ctx_sd, &timeout, cmd, buf, len);
216d0cef73dSGregory Neil Shapiro free(buf);
217d0cef73dSGregory Neil Shapiro return r;
218d0cef73dSGregory Neil Shapiro }
219d0cef73dSGregory Neil Shapiro #endif /* 0 */
220d0cef73dSGregory Neil Shapiro
221d0cef73dSGregory Neil Shapiro /*
222d0cef73dSGregory Neil Shapiro ** SEND2 -- construct buffer to send from arguments
223d0cef73dSGregory Neil Shapiro **
224d0cef73dSGregory Neil Shapiro ** Parameters:
225d0cef73dSGregory Neil Shapiro ** ctx -- Opaque context structure
226d0cef73dSGregory Neil Shapiro ** cmd -- command
227d0cef73dSGregory Neil Shapiro ** arg0 -- first argument
228d0cef73dSGregory Neil Shapiro ** argv -- list of arguments (NULL terminated)
229d0cef73dSGregory Neil Shapiro **
230d0cef73dSGregory Neil Shapiro ** Returns:
231d0cef73dSGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
232d0cef73dSGregory Neil Shapiro */
233d0cef73dSGregory Neil Shapiro
234d0cef73dSGregory Neil Shapiro static int
235d0cef73dSGregory Neil Shapiro send2 __P((SMFICTX *, int cmd, char *, char *));
236d0cef73dSGregory Neil Shapiro
237d0cef73dSGregory Neil Shapiro static int
send2(ctx,cmd,arg0,arg1)238d0cef73dSGregory Neil Shapiro send2(ctx, cmd, arg0, arg1)
239d0cef73dSGregory Neil Shapiro SMFICTX *ctx;
240d0cef73dSGregory Neil Shapiro int cmd;
241d0cef73dSGregory Neil Shapiro char *arg0;
242d0cef73dSGregory Neil Shapiro char *arg1;
243d0cef73dSGregory Neil Shapiro {
244d0cef73dSGregory Neil Shapiro size_t len, l0, l1, offset;
245d0cef73dSGregory Neil Shapiro int r;
246d0cef73dSGregory Neil Shapiro char *buf;
247d0cef73dSGregory Neil Shapiro struct timeval timeout;
248d0cef73dSGregory Neil Shapiro
249d0cef73dSGregory Neil Shapiro if (arg0 == NULL || *arg0 == '\0')
250d0cef73dSGregory Neil Shapiro return MI_FAILURE;
251d0cef73dSGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout;
252d0cef73dSGregory Neil Shapiro timeout.tv_usec = 0;
253d0cef73dSGregory Neil Shapiro l0 = strlen(arg0) + 1;
254d0cef73dSGregory Neil Shapiro len = l0;
255d0cef73dSGregory Neil Shapiro if (arg1 != NULL)
256d0cef73dSGregory Neil Shapiro {
257d0cef73dSGregory Neil Shapiro l1 = strlen(arg1) + 1;
258d0cef73dSGregory Neil Shapiro len += l1;
259d0cef73dSGregory Neil Shapiro SM_ASSERT(len > l1);
260d0cef73dSGregory Neil Shapiro }
261d0cef73dSGregory Neil Shapiro
262d0cef73dSGregory Neil Shapiro buf = malloc(len);
263d0cef73dSGregory Neil Shapiro if (buf == NULL)
264d0cef73dSGregory Neil Shapiro return MI_FAILURE;
265d0cef73dSGregory Neil Shapiro (void) memcpy(buf, arg0, l0);
266d0cef73dSGregory Neil Shapiro offset = l0;
267d0cef73dSGregory Neil Shapiro
268d0cef73dSGregory Neil Shapiro if (arg1 != NULL)
269d0cef73dSGregory Neil Shapiro {
270d0cef73dSGregory Neil Shapiro SM_ASSERT(offset < len);
271d0cef73dSGregory Neil Shapiro SM_ASSERT(offset + l1 <= len);
272d0cef73dSGregory Neil Shapiro (void) memcpy(buf + offset, arg1, l1);
273d0cef73dSGregory Neil Shapiro offset += l1;
274d0cef73dSGregory Neil Shapiro SM_ASSERT(offset > l1);
275d0cef73dSGregory Neil Shapiro }
276d0cef73dSGregory Neil Shapiro
277d0cef73dSGregory Neil Shapiro r = mi_wr_cmd(ctx->ctx_sd, &timeout, cmd, buf, len);
278d0cef73dSGregory Neil Shapiro free(buf);
279d0cef73dSGregory Neil Shapiro return r;
280d0cef73dSGregory Neil Shapiro }
281d0cef73dSGregory Neil Shapiro
282d0cef73dSGregory Neil Shapiro /*
283d0cef73dSGregory Neil Shapiro ** SMFI_CHGFROM -- change enveloper sender ("from") address
284d0cef73dSGregory Neil Shapiro **
285d0cef73dSGregory Neil Shapiro ** Parameters:
286d0cef73dSGregory Neil Shapiro ** ctx -- Opaque context structure
287d0cef73dSGregory Neil Shapiro ** from -- new envelope sender address ("MAIL From")
288d0cef73dSGregory Neil Shapiro ** args -- ESMTP arguments
289d0cef73dSGregory Neil Shapiro **
290d0cef73dSGregory Neil Shapiro ** Returns:
291d0cef73dSGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
292d0cef73dSGregory Neil Shapiro */
293d0cef73dSGregory Neil Shapiro
294d0cef73dSGregory Neil Shapiro int
smfi_chgfrom(ctx,from,args)295d0cef73dSGregory Neil Shapiro smfi_chgfrom(ctx, from, args)
296d0cef73dSGregory Neil Shapiro SMFICTX *ctx;
297d0cef73dSGregory Neil Shapiro char *from;
298d0cef73dSGregory Neil Shapiro char *args;
299d0cef73dSGregory Neil Shapiro {
300d0cef73dSGregory Neil Shapiro if (from == NULL || *from == '\0')
301d0cef73dSGregory Neil Shapiro return MI_FAILURE;
302d0cef73dSGregory Neil Shapiro if (!mi_sendok(ctx, SMFIF_CHGFROM))
303d0cef73dSGregory Neil Shapiro return MI_FAILURE;
304d0cef73dSGregory Neil Shapiro return send2(ctx, SMFIR_CHGFROM, from, args);
305d0cef73dSGregory Neil Shapiro }
306d0cef73dSGregory Neil Shapiro
307d0cef73dSGregory Neil Shapiro /*
308d0cef73dSGregory Neil Shapiro ** SMFI_SETSYMLIST -- set list of macros that the MTA should send.
309d0cef73dSGregory Neil Shapiro **
310d0cef73dSGregory Neil Shapiro ** Parameters:
311d0cef73dSGregory Neil Shapiro ** ctx -- Opaque context structure
312d0cef73dSGregory Neil Shapiro ** where -- SMTP stage
313d0cef73dSGregory Neil Shapiro ** macros -- list of macros
314d0cef73dSGregory Neil Shapiro **
315d0cef73dSGregory Neil Shapiro ** Returns:
316d0cef73dSGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
317d0cef73dSGregory Neil Shapiro */
318d0cef73dSGregory Neil Shapiro
319d0cef73dSGregory Neil Shapiro int
smfi_setsymlist(ctx,where,macros)320d0cef73dSGregory Neil Shapiro smfi_setsymlist(ctx, where, macros)
321d0cef73dSGregory Neil Shapiro SMFICTX *ctx;
322d0cef73dSGregory Neil Shapiro int where;
323d0cef73dSGregory Neil Shapiro char *macros;
324d0cef73dSGregory Neil Shapiro {
325d0cef73dSGregory Neil Shapiro SM_ASSERT(ctx != NULL);
326d0cef73dSGregory Neil Shapiro
327*da7d7b9cSGregory Neil Shapiro if (macros == NULL)
328d0cef73dSGregory Neil Shapiro return MI_FAILURE;
329d0cef73dSGregory Neil Shapiro if (where < SMFIM_FIRST || where > SMFIM_LAST)
330d0cef73dSGregory Neil Shapiro return MI_FAILURE;
331d0cef73dSGregory Neil Shapiro if (where < 0 || where >= MAX_MACROS_ENTRIES)
332d0cef73dSGregory Neil Shapiro return MI_FAILURE;
333d0cef73dSGregory Neil Shapiro
334d0cef73dSGregory Neil Shapiro if (ctx->ctx_mac_list[where] != NULL)
335d0cef73dSGregory Neil Shapiro return MI_FAILURE;
336d0cef73dSGregory Neil Shapiro
337d0cef73dSGregory Neil Shapiro ctx->ctx_mac_list[where] = strdup(macros);
338d0cef73dSGregory Neil Shapiro if (ctx->ctx_mac_list[where] == NULL)
339d0cef73dSGregory Neil Shapiro return MI_FAILURE;
340d0cef73dSGregory Neil Shapiro
341d0cef73dSGregory Neil Shapiro return MI_SUCCESS;
342d0cef73dSGregory Neil Shapiro }
343d0cef73dSGregory Neil Shapiro
344d0cef73dSGregory Neil Shapiro /*
345d0cef73dSGregory Neil Shapiro ** SMFI_ADDRCPT_PAR -- send an additional recipient to the MTA
346d0cef73dSGregory Neil Shapiro **
347d0cef73dSGregory Neil Shapiro ** Parameters:
348d0cef73dSGregory Neil Shapiro ** ctx -- Opaque context structure
349d0cef73dSGregory Neil Shapiro ** rcpt -- recipient address
350d0cef73dSGregory Neil Shapiro ** args -- ESMTP arguments
351d0cef73dSGregory Neil Shapiro **
352d0cef73dSGregory Neil Shapiro ** Returns:
353d0cef73dSGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
354d0cef73dSGregory Neil Shapiro */
355d0cef73dSGregory Neil Shapiro
356d0cef73dSGregory Neil Shapiro int
smfi_addrcpt_par(ctx,rcpt,args)357d0cef73dSGregory Neil Shapiro smfi_addrcpt_par(ctx, rcpt, args)
358d0cef73dSGregory Neil Shapiro SMFICTX *ctx;
359d0cef73dSGregory Neil Shapiro char *rcpt;
360d0cef73dSGregory Neil Shapiro char *args;
361d0cef73dSGregory Neil Shapiro {
362d0cef73dSGregory Neil Shapiro if (rcpt == NULL || *rcpt == '\0')
363d0cef73dSGregory Neil Shapiro return MI_FAILURE;
364d0cef73dSGregory Neil Shapiro if (!mi_sendok(ctx, SMFIF_ADDRCPT_PAR))
365d0cef73dSGregory Neil Shapiro return MI_FAILURE;
366d0cef73dSGregory Neil Shapiro return send2(ctx, SMFIR_ADDRCPT_PAR, rcpt, args);
367d0cef73dSGregory Neil Shapiro }
368d0cef73dSGregory Neil Shapiro
36940266059SGregory Neil Shapiro /*
37006f25ae9SGregory Neil Shapiro ** SMFI_ADDRCPT -- send an additional recipient to the MTA
37106f25ae9SGregory Neil Shapiro **
37206f25ae9SGregory Neil Shapiro ** Parameters:
37306f25ae9SGregory Neil Shapiro ** ctx -- Opaque context structure
37406f25ae9SGregory Neil Shapiro ** rcpt -- recipient address
37506f25ae9SGregory Neil Shapiro **
37606f25ae9SGregory Neil Shapiro ** Returns:
37706f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
37806f25ae9SGregory Neil Shapiro */
37906f25ae9SGregory Neil Shapiro
38006f25ae9SGregory Neil Shapiro int
smfi_addrcpt(ctx,rcpt)38106f25ae9SGregory Neil Shapiro smfi_addrcpt(ctx, rcpt)
38206f25ae9SGregory Neil Shapiro SMFICTX *ctx;
38306f25ae9SGregory Neil Shapiro char *rcpt;
38406f25ae9SGregory Neil Shapiro {
38506f25ae9SGregory Neil Shapiro size_t len;
38606f25ae9SGregory Neil Shapiro struct timeval timeout;
38706f25ae9SGregory Neil Shapiro
38806f25ae9SGregory Neil Shapiro if (rcpt == NULL || *rcpt == '\0')
38906f25ae9SGregory Neil Shapiro return MI_FAILURE;
39006f25ae9SGregory Neil Shapiro if (!mi_sendok(ctx, SMFIF_ADDRCPT))
39106f25ae9SGregory Neil Shapiro return MI_FAILURE;
39206f25ae9SGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout;
39306f25ae9SGregory Neil Shapiro timeout.tv_usec = 0;
39406f25ae9SGregory Neil Shapiro len = strlen(rcpt) + 1;
39506f25ae9SGregory Neil Shapiro return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_ADDRCPT, rcpt, len);
39606f25ae9SGregory Neil Shapiro }
397605302a5SGregory Neil Shapiro
39840266059SGregory Neil Shapiro /*
39906f25ae9SGregory Neil Shapiro ** SMFI_DELRCPT -- send a recipient to be removed to the MTA
40006f25ae9SGregory Neil Shapiro **
40106f25ae9SGregory Neil Shapiro ** Parameters:
40206f25ae9SGregory Neil Shapiro ** ctx -- Opaque context structure
40306f25ae9SGregory Neil Shapiro ** rcpt -- recipient address
40406f25ae9SGregory Neil Shapiro **
40506f25ae9SGregory Neil Shapiro ** Returns:
40606f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
40706f25ae9SGregory Neil Shapiro */
40806f25ae9SGregory Neil Shapiro
40906f25ae9SGregory Neil Shapiro int
smfi_delrcpt(ctx,rcpt)41006f25ae9SGregory Neil Shapiro smfi_delrcpt(ctx, rcpt)
41106f25ae9SGregory Neil Shapiro SMFICTX *ctx;
41206f25ae9SGregory Neil Shapiro char *rcpt;
41306f25ae9SGregory Neil Shapiro {
41406f25ae9SGregory Neil Shapiro size_t len;
41506f25ae9SGregory Neil Shapiro struct timeval timeout;
41606f25ae9SGregory Neil Shapiro
41706f25ae9SGregory Neil Shapiro if (rcpt == NULL || *rcpt == '\0')
41806f25ae9SGregory Neil Shapiro return MI_FAILURE;
41906f25ae9SGregory Neil Shapiro if (!mi_sendok(ctx, SMFIF_DELRCPT))
42006f25ae9SGregory Neil Shapiro return MI_FAILURE;
42106f25ae9SGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout;
42206f25ae9SGregory Neil Shapiro timeout.tv_usec = 0;
42306f25ae9SGregory Neil Shapiro len = strlen(rcpt) + 1;
42406f25ae9SGregory Neil Shapiro return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_DELRCPT, rcpt, len);
42506f25ae9SGregory Neil Shapiro }
426605302a5SGregory Neil Shapiro
42740266059SGregory Neil Shapiro /*
42806f25ae9SGregory Neil Shapiro ** SMFI_REPLACEBODY -- send a body chunk to the MTA
42906f25ae9SGregory Neil Shapiro **
43006f25ae9SGregory Neil Shapiro ** Parameters:
43106f25ae9SGregory Neil Shapiro ** ctx -- Opaque context structure
43206f25ae9SGregory Neil Shapiro ** bodyp -- body chunk
43306f25ae9SGregory Neil Shapiro ** bodylen -- length of body chunk
43406f25ae9SGregory Neil Shapiro **
43506f25ae9SGregory Neil Shapiro ** Returns:
43606f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
43706f25ae9SGregory Neil Shapiro */
43806f25ae9SGregory Neil Shapiro
43906f25ae9SGregory Neil Shapiro int
smfi_replacebody(ctx,bodyp,bodylen)44006f25ae9SGregory Neil Shapiro smfi_replacebody(ctx, bodyp, bodylen)
44106f25ae9SGregory Neil Shapiro SMFICTX *ctx;
44240266059SGregory Neil Shapiro unsigned char *bodyp;
44306f25ae9SGregory Neil Shapiro int bodylen;
44406f25ae9SGregory Neil Shapiro {
44506f25ae9SGregory Neil Shapiro int len, off, r;
44606f25ae9SGregory Neil Shapiro struct timeval timeout;
44706f25ae9SGregory Neil Shapiro
44840266059SGregory Neil Shapiro if (bodylen < 0 ||
44940266059SGregory Neil Shapiro (bodyp == NULL && bodylen > 0))
45006f25ae9SGregory Neil Shapiro return MI_FAILURE;
45106f25ae9SGregory Neil Shapiro if (!mi_sendok(ctx, SMFIF_CHGBODY))
45206f25ae9SGregory Neil Shapiro return MI_FAILURE;
45306f25ae9SGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout;
45406f25ae9SGregory Neil Shapiro timeout.tv_usec = 0;
45506f25ae9SGregory Neil Shapiro
45606f25ae9SGregory Neil Shapiro /* split body chunk if necessary */
45706f25ae9SGregory Neil Shapiro off = 0;
4584e4196cbSGregory Neil Shapiro do
45906f25ae9SGregory Neil Shapiro {
46006f25ae9SGregory Neil Shapiro len = (bodylen >= MILTER_CHUNK_SIZE) ? MILTER_CHUNK_SIZE :
46106f25ae9SGregory Neil Shapiro bodylen;
46206f25ae9SGregory Neil Shapiro if ((r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_REPLBODY,
46306f25ae9SGregory Neil Shapiro (char *) (bodyp + off), len)) != MI_SUCCESS)
46406f25ae9SGregory Neil Shapiro return r;
46506f25ae9SGregory Neil Shapiro off += len;
46606f25ae9SGregory Neil Shapiro bodylen -= len;
4674e4196cbSGregory Neil Shapiro } while (bodylen > 0);
46806f25ae9SGregory Neil Shapiro return MI_SUCCESS;
46906f25ae9SGregory Neil Shapiro }
470605302a5SGregory Neil Shapiro
47140266059SGregory Neil Shapiro /*
47240266059SGregory Neil Shapiro ** SMFI_QUARANTINE -- quarantine an envelope
47340266059SGregory Neil Shapiro **
47440266059SGregory Neil Shapiro ** Parameters:
47540266059SGregory Neil Shapiro ** ctx -- Opaque context structure
47640266059SGregory Neil Shapiro ** reason -- why?
47740266059SGregory Neil Shapiro **
47840266059SGregory Neil Shapiro ** Returns:
47940266059SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
48040266059SGregory Neil Shapiro */
48140266059SGregory Neil Shapiro
48240266059SGregory Neil Shapiro int
smfi_quarantine(ctx,reason)48340266059SGregory Neil Shapiro smfi_quarantine(ctx, reason)
48440266059SGregory Neil Shapiro SMFICTX *ctx;
48540266059SGregory Neil Shapiro char *reason;
48640266059SGregory Neil Shapiro {
48740266059SGregory Neil Shapiro size_t len;
48840266059SGregory Neil Shapiro int r;
48940266059SGregory Neil Shapiro char *buf;
49040266059SGregory Neil Shapiro struct timeval timeout;
49140266059SGregory Neil Shapiro
49240266059SGregory Neil Shapiro if (reason == NULL || *reason == '\0')
49340266059SGregory Neil Shapiro return MI_FAILURE;
49440266059SGregory Neil Shapiro if (!mi_sendok(ctx, SMFIF_QUARANTINE))
49540266059SGregory Neil Shapiro return MI_FAILURE;
49640266059SGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout;
49740266059SGregory Neil Shapiro timeout.tv_usec = 0;
49840266059SGregory Neil Shapiro len = strlen(reason) + 1;
49940266059SGregory Neil Shapiro buf = malloc(len);
50040266059SGregory Neil Shapiro if (buf == NULL)
50140266059SGregory Neil Shapiro return MI_FAILURE;
50240266059SGregory Neil Shapiro (void) memcpy(buf, reason, len);
50340266059SGregory Neil Shapiro r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_QUARANTINE, buf, len);
50440266059SGregory Neil Shapiro free(buf);
50540266059SGregory Neil Shapiro return r;
50640266059SGregory Neil Shapiro }
50740266059SGregory Neil Shapiro
50840266059SGregory Neil Shapiro /*
50906f25ae9SGregory Neil Shapiro ** MYISENHSC -- check whether a string contains an enhanced status code
51006f25ae9SGregory Neil Shapiro **
51106f25ae9SGregory Neil Shapiro ** Parameters:
51206f25ae9SGregory Neil Shapiro ** s -- string with possible enhanced status code.
51306f25ae9SGregory Neil Shapiro ** delim -- delim for enhanced status code.
51406f25ae9SGregory Neil Shapiro **
51506f25ae9SGregory Neil Shapiro ** Returns:
51606f25ae9SGregory Neil Shapiro ** 0 -- no enhanced status code.
51706f25ae9SGregory Neil Shapiro ** >4 -- length of enhanced status code.
51806f25ae9SGregory Neil Shapiro **
51906f25ae9SGregory Neil Shapiro ** Side Effects:
52006f25ae9SGregory Neil Shapiro ** none.
52106f25ae9SGregory Neil Shapiro */
52294c01205SGregory Neil Shapiro
52306f25ae9SGregory Neil Shapiro static int
myisenhsc(s,delim)52406f25ae9SGregory Neil Shapiro myisenhsc(s, delim)
52506f25ae9SGregory Neil Shapiro const char *s;
52606f25ae9SGregory Neil Shapiro int delim;
52706f25ae9SGregory Neil Shapiro {
52806f25ae9SGregory Neil Shapiro int l, h;
52906f25ae9SGregory Neil Shapiro
53006f25ae9SGregory Neil Shapiro if (s == NULL)
53106f25ae9SGregory Neil Shapiro return 0;
53206f25ae9SGregory Neil Shapiro if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.'))
53306f25ae9SGregory Neil Shapiro return 0;
53406f25ae9SGregory Neil Shapiro h = 0;
53506f25ae9SGregory Neil Shapiro l = 2;
53606f25ae9SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
53706f25ae9SGregory Neil Shapiro ++h;
53806f25ae9SGregory Neil Shapiro if (h == 0 || s[l + h] != '.')
53906f25ae9SGregory Neil Shapiro return 0;
54006f25ae9SGregory Neil Shapiro l += h + 1;
54106f25ae9SGregory Neil Shapiro h = 0;
54206f25ae9SGregory Neil Shapiro while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
54306f25ae9SGregory Neil Shapiro ++h;
54406f25ae9SGregory Neil Shapiro if (h == 0 || s[l + h] != delim)
54506f25ae9SGregory Neil Shapiro return 0;
54606f25ae9SGregory Neil Shapiro return l + h;
54706f25ae9SGregory Neil Shapiro }
54840266059SGregory Neil Shapiro
54940266059SGregory Neil Shapiro /*
55006f25ae9SGregory Neil Shapiro ** SMFI_SETREPLY -- set the reply code for the next reply to the MTA
55106f25ae9SGregory Neil Shapiro **
55206f25ae9SGregory Neil Shapiro ** Parameters:
55306f25ae9SGregory Neil Shapiro ** ctx -- Opaque context structure
55406f25ae9SGregory Neil Shapiro ** rcode -- The three-digit (RFC 821) SMTP reply code.
55506f25ae9SGregory Neil Shapiro ** xcode -- The extended (RFC 2034) reply code.
55606f25ae9SGregory Neil Shapiro ** message -- The text part of the SMTP reply.
55706f25ae9SGregory Neil Shapiro **
55806f25ae9SGregory Neil Shapiro ** Returns:
55906f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
56006f25ae9SGregory Neil Shapiro */
56106f25ae9SGregory Neil Shapiro
56206f25ae9SGregory Neil Shapiro int
smfi_setreply(ctx,rcode,xcode,message)56306f25ae9SGregory Neil Shapiro smfi_setreply(ctx, rcode, xcode, message)
56406f25ae9SGregory Neil Shapiro SMFICTX *ctx;
56506f25ae9SGregory Neil Shapiro char *rcode;
56606f25ae9SGregory Neil Shapiro char *xcode;
56706f25ae9SGregory Neil Shapiro char *message;
56806f25ae9SGregory Neil Shapiro {
56940266059SGregory Neil Shapiro size_t len;
57006f25ae9SGregory Neil Shapiro char *buf;
57106f25ae9SGregory Neil Shapiro
57206f25ae9SGregory Neil Shapiro if (rcode == NULL || ctx == NULL)
57306f25ae9SGregory Neil Shapiro return MI_FAILURE;
57440266059SGregory Neil Shapiro
57540266059SGregory Neil Shapiro /* ### <sp> \0 */
57640266059SGregory Neil Shapiro len = strlen(rcode) + 2;
57740266059SGregory Neil Shapiro if (len != 5)
57806f25ae9SGregory Neil Shapiro return MI_FAILURE;
57906f25ae9SGregory Neil Shapiro if ((rcode[0] != '4' && rcode[0] != '5') ||
58006f25ae9SGregory Neil Shapiro !isascii(rcode[1]) || !isdigit(rcode[1]) ||
58106f25ae9SGregory Neil Shapiro !isascii(rcode[2]) || !isdigit(rcode[2]))
58206f25ae9SGregory Neil Shapiro return MI_FAILURE;
58340266059SGregory Neil Shapiro if (xcode != NULL)
58440266059SGregory Neil Shapiro {
58540266059SGregory Neil Shapiro if (!myisenhsc(xcode, '\0'))
58606f25ae9SGregory Neil Shapiro return MI_FAILURE;
58740266059SGregory Neil Shapiro len += strlen(xcode) + 1;
58840266059SGregory Neil Shapiro }
58940266059SGregory Neil Shapiro if (message != NULL)
59040266059SGregory Neil Shapiro {
59140266059SGregory Neil Shapiro size_t ml;
59240266059SGregory Neil Shapiro
59340266059SGregory Neil Shapiro /* XXX check also for unprintable chars? */
59440266059SGregory Neil Shapiro if (strpbrk(message, "\r\n") != NULL)
59540266059SGregory Neil Shapiro return MI_FAILURE;
59640266059SGregory Neil Shapiro ml = strlen(message);
59740266059SGregory Neil Shapiro if (ml > MAXREPLYLEN)
59840266059SGregory Neil Shapiro return MI_FAILURE;
59940266059SGregory Neil Shapiro len += ml + 1;
60040266059SGregory Neil Shapiro }
60106f25ae9SGregory Neil Shapiro buf = malloc(len);
60206f25ae9SGregory Neil Shapiro if (buf == NULL)
60306f25ae9SGregory Neil Shapiro return MI_FAILURE; /* oops */
60440266059SGregory Neil Shapiro (void) sm_strlcpy(buf, rcode, len);
60540266059SGregory Neil Shapiro (void) sm_strlcat(buf, " ", len);
60640266059SGregory Neil Shapiro if (xcode != NULL)
60740266059SGregory Neil Shapiro (void) sm_strlcat(buf, xcode, len);
60840266059SGregory Neil Shapiro if (message != NULL)
60940266059SGregory Neil Shapiro {
61040266059SGregory Neil Shapiro if (xcode != NULL)
61140266059SGregory Neil Shapiro (void) sm_strlcat(buf, " ", len);
61240266059SGregory Neil Shapiro (void) sm_strlcat(buf, message, len);
61340266059SGregory Neil Shapiro }
61406f25ae9SGregory Neil Shapiro if (ctx->ctx_reply != NULL)
61506f25ae9SGregory Neil Shapiro free(ctx->ctx_reply);
61606f25ae9SGregory Neil Shapiro ctx->ctx_reply = buf;
61706f25ae9SGregory Neil Shapiro return MI_SUCCESS;
61806f25ae9SGregory Neil Shapiro }
61940266059SGregory Neil Shapiro
62040266059SGregory Neil Shapiro /*
62140266059SGregory Neil Shapiro ** SMFI_SETMLREPLY -- set multiline reply code for the next reply to the MTA
62240266059SGregory Neil Shapiro **
62340266059SGregory Neil Shapiro ** Parameters:
62440266059SGregory Neil Shapiro ** ctx -- Opaque context structure
62540266059SGregory Neil Shapiro ** rcode -- The three-digit (RFC 821) SMTP reply code.
62640266059SGregory Neil Shapiro ** xcode -- The extended (RFC 2034) reply code.
62740266059SGregory Neil Shapiro ** txt, ... -- The text part of the SMTP reply,
62840266059SGregory Neil Shapiro ** MUST be terminated with NULL.
62940266059SGregory Neil Shapiro **
63040266059SGregory Neil Shapiro ** Returns:
63140266059SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
63240266059SGregory Neil Shapiro */
63340266059SGregory Neil Shapiro
63440266059SGregory Neil Shapiro int
63540266059SGregory Neil Shapiro #if SM_VA_STD
smfi_setmlreply(SMFICTX * ctx,const char * rcode,const char * xcode,...)63640266059SGregory Neil Shapiro smfi_setmlreply(SMFICTX *ctx, const char *rcode, const char *xcode, ...)
63740266059SGregory Neil Shapiro #else /* SM_VA_STD */
63840266059SGregory Neil Shapiro smfi_setmlreply(ctx, rcode, xcode, va_alist)
63940266059SGregory Neil Shapiro SMFICTX *ctx;
64040266059SGregory Neil Shapiro const char *rcode;
64140266059SGregory Neil Shapiro const char *xcode;
64240266059SGregory Neil Shapiro va_dcl
64340266059SGregory Neil Shapiro #endif /* SM_VA_STD */
64440266059SGregory Neil Shapiro {
64540266059SGregory Neil Shapiro size_t len;
64640266059SGregory Neil Shapiro size_t rlen;
64740266059SGregory Neil Shapiro int args;
64840266059SGregory Neil Shapiro char *buf, *txt;
64940266059SGregory Neil Shapiro const char *xc;
65040266059SGregory Neil Shapiro char repl[16];
65140266059SGregory Neil Shapiro SM_VA_LOCAL_DECL
65240266059SGregory Neil Shapiro
65340266059SGregory Neil Shapiro if (rcode == NULL || ctx == NULL)
65440266059SGregory Neil Shapiro return MI_FAILURE;
65540266059SGregory Neil Shapiro
65640266059SGregory Neil Shapiro /* ### <sp> */
65740266059SGregory Neil Shapiro len = strlen(rcode) + 1;
65840266059SGregory Neil Shapiro if (len != 4)
65940266059SGregory Neil Shapiro return MI_FAILURE;
66040266059SGregory Neil Shapiro if ((rcode[0] != '4' && rcode[0] != '5') ||
66140266059SGregory Neil Shapiro !isascii(rcode[1]) || !isdigit(rcode[1]) ||
66240266059SGregory Neil Shapiro !isascii(rcode[2]) || !isdigit(rcode[2]))
66340266059SGregory Neil Shapiro return MI_FAILURE;
66440266059SGregory Neil Shapiro if (xcode != NULL)
66540266059SGregory Neil Shapiro {
66640266059SGregory Neil Shapiro if (!myisenhsc(xcode, '\0'))
66740266059SGregory Neil Shapiro return MI_FAILURE;
66840266059SGregory Neil Shapiro xc = xcode;
66940266059SGregory Neil Shapiro }
67040266059SGregory Neil Shapiro else
67140266059SGregory Neil Shapiro {
67240266059SGregory Neil Shapiro if (rcode[0] == '4')
67340266059SGregory Neil Shapiro xc = "4.0.0";
67440266059SGregory Neil Shapiro else
67540266059SGregory Neil Shapiro xc = "5.0.0";
67640266059SGregory Neil Shapiro }
67740266059SGregory Neil Shapiro
67840266059SGregory Neil Shapiro /* add trailing space */
67940266059SGregory Neil Shapiro len += strlen(xc) + 1;
68040266059SGregory Neil Shapiro rlen = len;
68140266059SGregory Neil Shapiro args = 0;
68240266059SGregory Neil Shapiro SM_VA_START(ap, xcode);
68340266059SGregory Neil Shapiro while ((txt = SM_VA_ARG(ap, char *)) != NULL)
68440266059SGregory Neil Shapiro {
68540266059SGregory Neil Shapiro size_t tl;
68640266059SGregory Neil Shapiro
68740266059SGregory Neil Shapiro tl = strlen(txt);
68840266059SGregory Neil Shapiro if (tl > MAXREPLYLEN)
689605302a5SGregory Neil Shapiro break;
69040266059SGregory Neil Shapiro
69140266059SGregory Neil Shapiro /* this text, reply codes, \r\n */
69240266059SGregory Neil Shapiro len += tl + 2 + rlen;
69340266059SGregory Neil Shapiro if (++args > MAXREPLIES)
694605302a5SGregory Neil Shapiro break;
69540266059SGregory Neil Shapiro
69640266059SGregory Neil Shapiro /* XXX check also for unprintable chars? */
69740266059SGregory Neil Shapiro if (strpbrk(txt, "\r\n") != NULL)
698605302a5SGregory Neil Shapiro break;
69940266059SGregory Neil Shapiro }
70040266059SGregory Neil Shapiro SM_VA_END(ap);
701605302a5SGregory Neil Shapiro if (txt != NULL)
702605302a5SGregory Neil Shapiro return MI_FAILURE;
70340266059SGregory Neil Shapiro
70440266059SGregory Neil Shapiro /* trailing '\0' */
70540266059SGregory Neil Shapiro ++len;
70640266059SGregory Neil Shapiro buf = malloc(len);
70740266059SGregory Neil Shapiro if (buf == NULL)
70840266059SGregory Neil Shapiro return MI_FAILURE; /* oops */
70940266059SGregory Neil Shapiro (void) sm_strlcpyn(buf, len, 3, rcode, args == 1 ? " " : "-", xc);
71040266059SGregory Neil Shapiro (void) sm_strlcpyn(repl, sizeof repl, 4, rcode, args == 1 ? " " : "-",
71140266059SGregory Neil Shapiro xc, " ");
71240266059SGregory Neil Shapiro SM_VA_START(ap, xcode);
71340266059SGregory Neil Shapiro txt = SM_VA_ARG(ap, char *);
71440266059SGregory Neil Shapiro if (txt != NULL)
71540266059SGregory Neil Shapiro {
71640266059SGregory Neil Shapiro (void) sm_strlcat2(buf, " ", txt, len);
71740266059SGregory Neil Shapiro while ((txt = SM_VA_ARG(ap, char *)) != NULL)
71840266059SGregory Neil Shapiro {
71940266059SGregory Neil Shapiro if (--args <= 1)
72040266059SGregory Neil Shapiro repl[3] = ' ';
72140266059SGregory Neil Shapiro (void) sm_strlcat2(buf, "\r\n", repl, len);
72240266059SGregory Neil Shapiro (void) sm_strlcat(buf, txt, len);
72340266059SGregory Neil Shapiro }
72440266059SGregory Neil Shapiro }
72540266059SGregory Neil Shapiro if (ctx->ctx_reply != NULL)
72640266059SGregory Neil Shapiro free(ctx->ctx_reply);
72740266059SGregory Neil Shapiro ctx->ctx_reply = buf;
72840266059SGregory Neil Shapiro SM_VA_END(ap);
72940266059SGregory Neil Shapiro return MI_SUCCESS;
73040266059SGregory Neil Shapiro }
73140266059SGregory Neil Shapiro
73240266059SGregory Neil Shapiro /*
73306f25ae9SGregory Neil Shapiro ** SMFI_SETPRIV -- set private data
73406f25ae9SGregory Neil Shapiro **
73506f25ae9SGregory Neil Shapiro ** Parameters:
73606f25ae9SGregory Neil Shapiro ** ctx -- Opaque context structure
73706f25ae9SGregory Neil Shapiro ** privatedata -- pointer to private data
73806f25ae9SGregory Neil Shapiro **
73906f25ae9SGregory Neil Shapiro ** Returns:
74006f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
74106f25ae9SGregory Neil Shapiro */
74206f25ae9SGregory Neil Shapiro
74306f25ae9SGregory Neil Shapiro int
smfi_setpriv(ctx,privatedata)74406f25ae9SGregory Neil Shapiro smfi_setpriv(ctx, privatedata)
74506f25ae9SGregory Neil Shapiro SMFICTX *ctx;
74606f25ae9SGregory Neil Shapiro void *privatedata;
74706f25ae9SGregory Neil Shapiro {
74806f25ae9SGregory Neil Shapiro if (ctx == NULL)
74906f25ae9SGregory Neil Shapiro return MI_FAILURE;
75006f25ae9SGregory Neil Shapiro ctx->ctx_privdata = privatedata;
75106f25ae9SGregory Neil Shapiro return MI_SUCCESS;
75206f25ae9SGregory Neil Shapiro }
753605302a5SGregory Neil Shapiro
75440266059SGregory Neil Shapiro /*
75506f25ae9SGregory Neil Shapiro ** SMFI_GETPRIV -- get private data
75606f25ae9SGregory Neil Shapiro **
75706f25ae9SGregory Neil Shapiro ** Parameters:
75806f25ae9SGregory Neil Shapiro ** ctx -- Opaque context structure
75906f25ae9SGregory Neil Shapiro **
76006f25ae9SGregory Neil Shapiro ** Returns:
76106f25ae9SGregory Neil Shapiro ** pointer to private data
76206f25ae9SGregory Neil Shapiro */
76306f25ae9SGregory Neil Shapiro
76406f25ae9SGregory Neil Shapiro void *
smfi_getpriv(ctx)76506f25ae9SGregory Neil Shapiro smfi_getpriv(ctx)
76606f25ae9SGregory Neil Shapiro SMFICTX *ctx;
76706f25ae9SGregory Neil Shapiro {
76806f25ae9SGregory Neil Shapiro if (ctx == NULL)
76906f25ae9SGregory Neil Shapiro return NULL;
77006f25ae9SGregory Neil Shapiro return ctx->ctx_privdata;
77106f25ae9SGregory Neil Shapiro }
772605302a5SGregory Neil Shapiro
77340266059SGregory Neil Shapiro /*
77406f25ae9SGregory Neil Shapiro ** SMFI_GETSYMVAL -- get the value of a macro
77506f25ae9SGregory Neil Shapiro **
77606f25ae9SGregory Neil Shapiro ** See explanation in mfapi.h about layout of the structures.
77706f25ae9SGregory Neil Shapiro **
77806f25ae9SGregory Neil Shapiro ** Parameters:
77906f25ae9SGregory Neil Shapiro ** ctx -- Opaque context structure
78006f25ae9SGregory Neil Shapiro ** symname -- name of macro
78106f25ae9SGregory Neil Shapiro **
78206f25ae9SGregory Neil Shapiro ** Returns:
78306f25ae9SGregory Neil Shapiro ** value of macro (NULL in case of failure)
78406f25ae9SGregory Neil Shapiro */
78506f25ae9SGregory Neil Shapiro
78606f25ae9SGregory Neil Shapiro char *
smfi_getsymval(ctx,symname)78706f25ae9SGregory Neil Shapiro smfi_getsymval(ctx, symname)
78806f25ae9SGregory Neil Shapiro SMFICTX *ctx;
78906f25ae9SGregory Neil Shapiro char *symname;
79006f25ae9SGregory Neil Shapiro {
79106f25ae9SGregory Neil Shapiro int i;
79206f25ae9SGregory Neil Shapiro char **s;
79306f25ae9SGregory Neil Shapiro char one[2];
79406f25ae9SGregory Neil Shapiro char braces[4];
79506f25ae9SGregory Neil Shapiro
79606f25ae9SGregory Neil Shapiro if (ctx == NULL || symname == NULL || *symname == '\0')
79706f25ae9SGregory Neil Shapiro return NULL;
79806f25ae9SGregory Neil Shapiro
79906f25ae9SGregory Neil Shapiro if (strlen(symname) == 3 && symname[0] == '{' && symname[2] == '}')
80006f25ae9SGregory Neil Shapiro {
80106f25ae9SGregory Neil Shapiro one[0] = symname[1];
80206f25ae9SGregory Neil Shapiro one[1] = '\0';
80306f25ae9SGregory Neil Shapiro }
80406f25ae9SGregory Neil Shapiro else
80506f25ae9SGregory Neil Shapiro one[0] = '\0';
80606f25ae9SGregory Neil Shapiro if (strlen(symname) == 1)
80706f25ae9SGregory Neil Shapiro {
80806f25ae9SGregory Neil Shapiro braces[0] = '{';
80906f25ae9SGregory Neil Shapiro braces[1] = *symname;
81006f25ae9SGregory Neil Shapiro braces[2] = '}';
81106f25ae9SGregory Neil Shapiro braces[3] = '\0';
81206f25ae9SGregory Neil Shapiro }
81306f25ae9SGregory Neil Shapiro else
81406f25ae9SGregory Neil Shapiro braces[0] = '\0';
81506f25ae9SGregory Neil Shapiro
81606f25ae9SGregory Neil Shapiro /* search backwards through the macro array */
81706f25ae9SGregory Neil Shapiro for (i = MAX_MACROS_ENTRIES - 1 ; i >= 0; --i)
81806f25ae9SGregory Neil Shapiro {
81906f25ae9SGregory Neil Shapiro if ((s = ctx->ctx_mac_ptr[i]) == NULL ||
82006f25ae9SGregory Neil Shapiro ctx->ctx_mac_buf[i] == NULL)
82106f25ae9SGregory Neil Shapiro continue;
82206f25ae9SGregory Neil Shapiro while (s != NULL && *s != NULL)
82306f25ae9SGregory Neil Shapiro {
82406f25ae9SGregory Neil Shapiro if (strcmp(*s, symname) == 0)
82506f25ae9SGregory Neil Shapiro return *++s;
82606f25ae9SGregory Neil Shapiro if (one[0] != '\0' && strcmp(*s, one) == 0)
82706f25ae9SGregory Neil Shapiro return *++s;
82806f25ae9SGregory Neil Shapiro if (braces[0] != '\0' && strcmp(*s, braces) == 0)
82906f25ae9SGregory Neil Shapiro return *++s;
83006f25ae9SGregory Neil Shapiro ++s; /* skip over macro value */
83106f25ae9SGregory Neil Shapiro ++s; /* points to next macro name */
83206f25ae9SGregory Neil Shapiro }
83306f25ae9SGregory Neil Shapiro }
83406f25ae9SGregory Neil Shapiro return NULL;
83506f25ae9SGregory Neil Shapiro }
836605302a5SGregory Neil Shapiro
837605302a5SGregory Neil Shapiro /*
838605302a5SGregory Neil Shapiro ** SMFI_PROGRESS -- send "progress" message to the MTA to prevent premature
839605302a5SGregory Neil Shapiro ** timeouts during long milter-side operations
840605302a5SGregory Neil Shapiro **
841605302a5SGregory Neil Shapiro ** Parameters:
842605302a5SGregory Neil Shapiro ** ctx -- Opaque context structure
843605302a5SGregory Neil Shapiro **
844605302a5SGregory Neil Shapiro ** Return value:
845605302a5SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
846605302a5SGregory Neil Shapiro */
847605302a5SGregory Neil Shapiro
848605302a5SGregory Neil Shapiro int
smfi_progress(ctx)849605302a5SGregory Neil Shapiro smfi_progress(ctx)
850605302a5SGregory Neil Shapiro SMFICTX *ctx;
851605302a5SGregory Neil Shapiro {
852605302a5SGregory Neil Shapiro struct timeval timeout;
853605302a5SGregory Neil Shapiro
854605302a5SGregory Neil Shapiro if (ctx == NULL)
855605302a5SGregory Neil Shapiro return MI_FAILURE;
856605302a5SGregory Neil Shapiro
857605302a5SGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout;
858605302a5SGregory Neil Shapiro timeout.tv_usec = 0;
859605302a5SGregory Neil Shapiro
860605302a5SGregory Neil Shapiro return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_PROGRESS, NULL, 0);
861605302a5SGregory Neil Shapiro }
862d0cef73dSGregory Neil Shapiro
863d0cef73dSGregory Neil Shapiro /*
864d0cef73dSGregory Neil Shapiro ** SMFI_VERSION -- return (runtime) version of libmilter
865d0cef73dSGregory Neil Shapiro **
866d0cef73dSGregory Neil Shapiro ** Parameters:
867d0cef73dSGregory Neil Shapiro ** major -- (pointer to) major version
868d0cef73dSGregory Neil Shapiro ** minor -- (pointer to) minor version
869d0cef73dSGregory Neil Shapiro ** patchlevel -- (pointer to) patchlevel version
870d0cef73dSGregory Neil Shapiro **
871d0cef73dSGregory Neil Shapiro ** Return value:
872d0cef73dSGregory Neil Shapiro ** MI_SUCCESS
873d0cef73dSGregory Neil Shapiro */
874d0cef73dSGregory Neil Shapiro
875d0cef73dSGregory Neil Shapiro int
smfi_version(major,minor,patchlevel)876d0cef73dSGregory Neil Shapiro smfi_version(major, minor, patchlevel)
877d0cef73dSGregory Neil Shapiro unsigned int *major;
878d0cef73dSGregory Neil Shapiro unsigned int *minor;
879d0cef73dSGregory Neil Shapiro unsigned int *patchlevel;
880d0cef73dSGregory Neil Shapiro {
881d0cef73dSGregory Neil Shapiro if (major != NULL)
882d0cef73dSGregory Neil Shapiro *major = SM_LM_VRS_MAJOR(SMFI_VERSION);
883d0cef73dSGregory Neil Shapiro if (minor != NULL)
884d0cef73dSGregory Neil Shapiro *minor = SM_LM_VRS_MINOR(SMFI_VERSION);
885d0cef73dSGregory Neil Shapiro if (patchlevel != NULL)
886ffb83623SGregory Neil Shapiro *patchlevel = SM_LM_VRS_PLVL(SMFI_VERSION);
887d0cef73dSGregory Neil Shapiro return MI_SUCCESS;
888d0cef73dSGregory Neil Shapiro }
889