engine.c revision 261363
1/*
2 *  Copyright (c) 1999-2004, 2006-2008 Proofpoint, Inc. and its suppliers.
3 *	All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11#include <sm/gen.h>
12SM_RCSID("@(#)$Id: engine.c,v 8.168 2013/11/22 20:51:36 ca Exp $")
13
14#include "libmilter.h"
15
16#if NETINET || NETINET6
17# include <arpa/inet.h>
18#endif /* NETINET || NETINET6 */
19
20/* generic argument for functions in the command table */
21struct arg_struct
22{
23	size_t		a_len;		/* length of buffer */
24	char		*a_buf;		/* argument string */
25	int		a_idx;		/* index for macro array */
26	SMFICTX_PTR	a_ctx;		/* context */
27};
28
29typedef struct arg_struct genarg;
30
31/* structure for commands received from MTA */
32struct cmdfct_t
33{
34	char	cm_cmd;				/* command */
35	int	cm_argt;			/* type of arguments expected */
36	int	cm_next;			/* next state */
37	int	cm_todo;			/* what to do next */
38	int	cm_macros;			/* index for macros */
39	int	(*cm_fct) __P((genarg *));	/* function to execute */
40};
41
42typedef struct cmdfct_t cmdfct;
43
44/* possible values for cm_argt */
45#define	CM_ARG0	0	/* no args */
46#define	CM_ARG1	1	/* one arg (string) */
47#define	CM_ARG2	2	/* two args (strings) */
48#define	CM_ARGA	4	/* one string and _SOCK_ADDR */
49#define	CM_ARGO	5	/* two integers */
50#define	CM_ARGV	8	/* \0 separated list of args, NULL-terminated */
51#define	CM_ARGN	9	/* \0 separated list of args (strings) */
52
53/* possible values for cm_todo */
54#define	CT_CONT		0x0000	/* continue reading commands */
55#define	CT_IGNO		0x0001	/* continue even when error  */
56
57/* not needed right now, done via return code instead */
58#define	CT_KEEP		0x0004	/* keep buffer (contains symbols) */
59#define	CT_END		0x0008	/* last command of session, stop replying */
60
61/* index in macro array: macros only for these commands */
62#define	CI_NONE		(-1)
63#define	CI_CONN		0
64#define	CI_HELO		1
65#define	CI_MAIL		2
66#define CI_RCPT		3
67#define CI_DATA		4
68#define CI_EOM		5
69#define CI_EOH		6
70#define CI_LAST		CI_EOH
71#if CI_LAST < CI_DATA
72ERROR: do not compile with CI_LAST < CI_DATA
73#endif
74#if CI_LAST < CI_EOM
75ERROR: do not compile with CI_LAST < CI_EOM
76#endif
77#if CI_LAST < CI_EOH
78ERROR: do not compile with CI_LAST < CI_EOH
79#endif
80#if CI_LAST < CI_ENVRCPT
81ERROR: do not compile with CI_LAST < CI_ENVRCPT
82#endif
83#if CI_LAST < CI_ENVFROM
84ERROR: do not compile with CI_LAST < CI_ENVFROM
85#endif
86#if CI_LAST < CI_HELO
87ERROR: do not compile with CI_LAST < CI_HELO
88#endif
89#if CI_LAST < CI_CONNECT
90ERROR: do not compile with CI_LAST < CI_CONNECT
91#endif
92#if CI_LAST >= MAX_MACROS_ENTRIES
93ERROR: do not compile with CI_LAST >= MAX_MACROS_ENTRIES
94#endif
95
96/* function prototypes */
97static int	st_abortfct __P((genarg *));
98static int	st_macros __P((genarg *));
99static int	st_optionneg __P((genarg *));
100static int	st_bodychunk __P((genarg *));
101static int	st_connectinfo __P((genarg *));
102static int	st_bodyend __P((genarg *));
103static int	st_helo __P((genarg *));
104static int	st_header __P((genarg *));
105static int	st_sender __P((genarg *));
106static int	st_rcpt __P((genarg *));
107static int	st_unknown __P((genarg *));
108static int	st_data __P((genarg *));
109static int	st_eoh __P((genarg *));
110static int	st_quit __P((genarg *));
111static int	sendreply __P((sfsistat, socket_t, struct timeval *, SMFICTX_PTR));
112static void	fix_stm __P((SMFICTX_PTR));
113static bool	trans_ok __P((int, int));
114static char	**dec_argv __P((char *, size_t));
115static int	dec_arg2 __P((char *, size_t, char **, char **));
116static void	mi_clr_symlist __P((SMFICTX_PTR));
117
118#if _FFR_WORKERS_POOL
119static bool     mi_rd_socket_ready __P((int));
120#endif /* _FFR_WORKERS_POOL */
121
122/* states */
123#define ST_NONE	(-1)
124#define ST_INIT	0	/* initial state */
125#define ST_OPTS	1	/* option negotiation */
126#define ST_CONN	2	/* connection info */
127#define ST_HELO	3	/* helo */
128#define ST_MAIL	4	/* mail from */
129#define ST_RCPT	5	/* rcpt to */
130#define ST_DATA	6	/* data */
131#define ST_HDRS	7	/* headers */
132#define ST_EOHS	8	/* end of headers */
133#define ST_BODY	9	/* body */
134#define ST_ENDM	10	/* end of message */
135#define ST_QUIT	11	/* quit */
136#define ST_ABRT	12	/* abort */
137#define ST_UNKN 13	/* unknown SMTP command */
138#define ST_Q_NC	14	/* quit, new connection follows */
139#define ST_LAST	ST_Q_NC	/* last valid state */
140#define ST_SKIP	16	/* not a state but required for the state table */
141
142/* in a mail transaction? must be before eom according to spec. */
143#define ST_IN_MAIL(st)	((st) >= ST_MAIL && (st) < ST_ENDM)
144
145/*
146**  set of next states
147**  each state (ST_*) corresponds to bit in an int value (1 << state)
148**  each state has a set of allowed transitions ('or' of bits of states)
149**  so a state transition is valid if the mask of the next state
150**  is set in the NX_* value
151**  this function is coded in trans_ok(), see below.
152*/
153
154#define MI_MASK(x)	(0x0001 << (x))	/* generate a bit "mask" for a state */
155#define NX_INIT	(MI_MASK(ST_OPTS))
156#define NX_OPTS	(MI_MASK(ST_CONN) | MI_MASK(ST_UNKN))
157#define NX_CONN	(MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN))
158#define NX_HELO	(MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN))
159#define NX_MAIL	(MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | MI_MASK(ST_UNKN))
160#define NX_RCPT	(MI_MASK(ST_HDRS) | MI_MASK(ST_EOHS) | MI_MASK(ST_DATA) | \
161		 MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | \
162		 MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | MI_MASK(ST_UNKN))
163#define NX_DATA	(MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT))
164#define NX_HDRS	(MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT))
165#define NX_EOHS	(MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | MI_MASK(ST_ABRT))
166#define NX_BODY	(MI_MASK(ST_ENDM) | MI_MASK(ST_BODY) | MI_MASK(ST_ABRT))
167#define NX_ENDM	(MI_MASK(ST_QUIT) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN) | \
168		MI_MASK(ST_Q_NC))
169#define NX_QUIT	0
170#define NX_ABRT	0
171#define NX_UNKN (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | \
172		 MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | \
173		 MI_MASK(ST_DATA) | \
174		 MI_MASK(ST_BODY) | MI_MASK(ST_UNKN) | \
175		 MI_MASK(ST_ABRT) | MI_MASK(ST_QUIT) | MI_MASK(ST_Q_NC))
176#define NX_Q_NC	(MI_MASK(ST_CONN) | MI_MASK(ST_UNKN))
177#define NX_SKIP MI_MASK(ST_SKIP)
178
179static int next_states[] =
180{
181	  NX_INIT
182	, NX_OPTS
183	, NX_CONN
184	, NX_HELO
185	, NX_MAIL
186	, NX_RCPT
187	, NX_DATA
188	, NX_HDRS
189	, NX_EOHS
190	, NX_BODY
191	, NX_ENDM
192	, NX_QUIT
193	, NX_ABRT
194	, NX_UNKN
195	, NX_Q_NC
196};
197
198#define SIZE_NEXT_STATES	(sizeof(next_states) / sizeof(next_states[0]))
199
200/* commands received by milter */
201static cmdfct cmds[] =
202{
203  {SMFIC_ABORT,	CM_ARG0, ST_ABRT,  CT_CONT,	CI_NONE, st_abortfct	}
204, {SMFIC_MACRO,	CM_ARGV, ST_NONE,  CT_KEEP,	CI_NONE, st_macros	}
205, {SMFIC_BODY,	CM_ARG1, ST_BODY,  CT_CONT,	CI_NONE, st_bodychunk	}
206, {SMFIC_CONNECT, CM_ARG2, ST_CONN,  CT_CONT,	CI_CONN, st_connectinfo	}
207, {SMFIC_BODYEOB, CM_ARG1, ST_ENDM,  CT_CONT,	CI_EOM,  st_bodyend	}
208, {SMFIC_HELO,	CM_ARG1, ST_HELO,  CT_CONT,	CI_HELO, st_helo	}
209, {SMFIC_HEADER, CM_ARG2, ST_HDRS,  CT_CONT,	CI_NONE, st_header	}
210, {SMFIC_MAIL,	CM_ARGV, ST_MAIL,  CT_CONT,	CI_MAIL, st_sender	}
211, {SMFIC_OPTNEG, CM_ARGO, ST_OPTS,  CT_CONT,	CI_NONE, st_optionneg	}
212, {SMFIC_EOH,	CM_ARG0, ST_EOHS,  CT_CONT,	CI_EOH,  st_eoh		}
213, {SMFIC_QUIT,	CM_ARG0, ST_QUIT,  CT_END,	CI_NONE, st_quit	}
214, {SMFIC_DATA,	CM_ARG0, ST_DATA,  CT_CONT,	CI_DATA, st_data	}
215, {SMFIC_RCPT,	CM_ARGV, ST_RCPT,  CT_IGNO,	CI_RCPT, st_rcpt	}
216, {SMFIC_UNKNOWN, CM_ARG1, ST_UNKN,  CT_IGNO,	CI_NONE, st_unknown	}
217, {SMFIC_QUIT_NC, CM_ARG0, ST_Q_NC,  CT_CONT,	CI_NONE, st_quit	}
218};
219
220/*
221**  Additional (internal) reply codes;
222**  must be coordinated wit libmilter/mfapi.h
223*/
224
225#define _SMFIS_KEEP	20
226#define _SMFIS_ABORT	21
227#define _SMFIS_OPTIONS	22
228#define _SMFIS_NOREPLY	SMFIS_NOREPLY
229#define _SMFIS_FAIL	(-1)
230#define _SMFIS_NONE	(-2)
231
232/*
233**  MI_ENGINE -- receive commands and process them
234**
235**	Parameters:
236**		ctx -- context structure
237**
238**	Returns:
239**		MI_FAILURE/MI_SUCCESS
240*/
241
242int
243mi_engine(ctx)
244	SMFICTX_PTR ctx;
245{
246	size_t len;
247	int i;
248	socket_t sd;
249	int ret = MI_SUCCESS;
250	int ncmds = sizeof(cmds) / sizeof(cmdfct);
251	int curstate = ST_INIT;
252	int newstate;
253	bool call_abort;
254	sfsistat r;
255	char cmd;
256	char *buf = NULL;
257	genarg arg;
258	struct timeval timeout;
259	int (*f) __P((genarg *));
260	sfsistat (*fi_abort) __P((SMFICTX *));
261	sfsistat (*fi_close) __P((SMFICTX *));
262
263	arg.a_ctx = ctx;
264	sd = ctx->ctx_sd;
265	fi_abort = ctx->ctx_smfi->xxfi_abort;
266#if _FFR_WORKERS_POOL
267	curstate = ctx->ctx_state;
268	if (curstate == ST_INIT)
269	{
270		mi_clr_macros(ctx, 0);
271		fix_stm(ctx);
272	}
273#else   /* _FFR_WORKERS_POOL */
274	mi_clr_macros(ctx, 0);
275	fix_stm(ctx);
276#endif  /* _FFR_WORKERS_POOL */
277	r = _SMFIS_NONE;
278	do
279	{
280		/* call abort only if in a mail transaction */
281		call_abort = ST_IN_MAIL(curstate);
282		timeout.tv_sec = ctx->ctx_timeout;
283		timeout.tv_usec = 0;
284		if (mi_stop() == MILTER_ABRT)
285		{
286			if (ctx->ctx_dbg > 3)
287				sm_dprintf("[%lu] milter_abort\n",
288					(long) ctx->ctx_id);
289			ret = MI_FAILURE;
290			break;
291		}
292
293		/*
294		**  Notice: buf is allocated by mi_rd_cmd() and it will
295		**  usually be free()d after it has been used in f().
296		**  However, if the function returns _SMFIS_KEEP then buf
297		**  contains macros and will not be free()d.
298		**  Hence r must be set to _SMFIS_NONE if a new buf is
299		**  allocated to avoid problem with housekeeping, esp.
300		**  if the code "break"s out of the loop.
301		*/
302
303#if _FFR_WORKERS_POOL
304		/* Is the socket ready to be read ??? */
305		if (!mi_rd_socket_ready(sd))
306		{
307			ret = MI_CONTINUE;
308			break;
309		}
310#endif  /* _FFR_WORKERS_POOL */
311
312		r = _SMFIS_NONE;
313		if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len,
314				     ctx->ctx_smfi->xxfi_name)) == NULL &&
315		    cmd < SMFIC_VALIDCMD)
316		{
317			if (ctx->ctx_dbg > 5)
318				sm_dprintf("[%lu] mi_engine: mi_rd_cmd error (%x)\n",
319					(long) ctx->ctx_id, (int) cmd);
320
321			/*
322			**  eof is currently treated as failure ->
323			**  abort() instead of close(), otherwise use:
324			**  if (cmd != SMFIC_EOF)
325			*/
326
327			ret = MI_FAILURE;
328			break;
329		}
330		if (ctx->ctx_dbg > 4)
331			sm_dprintf("[%lu] got cmd '%c' len %d\n",
332				(long) ctx->ctx_id, cmd, (int) len);
333		for (i = 0; i < ncmds; i++)
334		{
335			if (cmd == cmds[i].cm_cmd)
336				break;
337		}
338		if (i >= ncmds)
339		{
340			/* unknown command */
341			if (ctx->ctx_dbg > 1)
342				sm_dprintf("[%lu] cmd '%c' unknown\n",
343					(long) ctx->ctx_id, cmd);
344			ret = MI_FAILURE;
345			break;
346		}
347		if ((f = cmds[i].cm_fct) == NULL)
348		{
349			/* stop for now */
350			if (ctx->ctx_dbg > 1)
351				sm_dprintf("[%lu] cmd '%c' not impl\n",
352					(long) ctx->ctx_id, cmd);
353			ret = MI_FAILURE;
354			break;
355		}
356
357		/* is new state ok? */
358		newstate = cmds[i].cm_next;
359		if (ctx->ctx_dbg > 5)
360			sm_dprintf("[%lu] cur %x new %x nextmask %x\n",
361				(long) ctx->ctx_id,
362				curstate, newstate, next_states[curstate]);
363
364		if (newstate != ST_NONE && !trans_ok(curstate, newstate))
365		{
366			if (ctx->ctx_dbg > 1)
367				sm_dprintf("[%lu] abort: cur %d (%x) new %d (%x) next %x\n",
368					(long) ctx->ctx_id,
369					curstate, MI_MASK(curstate),
370					newstate, MI_MASK(newstate),
371					next_states[curstate]);
372
373			/* call abort only if in a mail transaction */
374			if (fi_abort != NULL && call_abort)
375				(void) (*fi_abort)(ctx);
376
377			/*
378			**  try to reach the new state from HELO
379			**  if it can't be reached, ignore the command.
380			*/
381
382			curstate = ST_HELO;
383			if (!trans_ok(curstate, newstate))
384			{
385				if (buf != NULL)
386				{
387					free(buf);
388					buf = NULL;
389				}
390				continue;
391			}
392		}
393		arg.a_len = len;
394		arg.a_buf = buf;
395		if (newstate != ST_NONE)
396		{
397			curstate = newstate;
398			ctx->ctx_state = curstate;
399		}
400		arg.a_idx = cmds[i].cm_macros;
401		call_abort = ST_IN_MAIL(curstate);
402
403		/* call function to deal with command */
404		MI_MONITOR_BEGIN(ctx, cmd);
405		r = (*f)(&arg);
406		MI_MONITOR_END(ctx, cmd);
407		if (r != _SMFIS_KEEP && buf != NULL)
408		{
409			free(buf);
410			buf = NULL;
411		}
412		if (sendreply(r, sd, &timeout, ctx) != MI_SUCCESS)
413		{
414			ret = MI_FAILURE;
415			break;
416		}
417
418		if (r == SMFIS_ACCEPT)
419		{
420			/* accept mail, no further actions taken */
421			curstate = ST_HELO;
422		}
423		else if (r == SMFIS_REJECT || r == SMFIS_DISCARD ||
424			 r ==  SMFIS_TEMPFAIL)
425		{
426			/*
427			**  further actions depend on current state
428			**  if the IGNO bit is set: "ignore" the error,
429			**  i.e., stay in the current state
430			*/
431			if (!bitset(CT_IGNO, cmds[i].cm_todo))
432				curstate = ST_HELO;
433		}
434		else if (r == _SMFIS_ABORT)
435		{
436			if (ctx->ctx_dbg > 5)
437				sm_dprintf("[%lu] function returned abort\n",
438					(long) ctx->ctx_id);
439			ret = MI_FAILURE;
440			break;
441		}
442	} while (!bitset(CT_END, cmds[i].cm_todo));
443
444	ctx->ctx_state = curstate;
445
446	if (ret == MI_FAILURE)
447	{
448		/* call abort only if in a mail transaction */
449		if (fi_abort != NULL && call_abort)
450			(void) (*fi_abort)(ctx);
451	}
452
453	/* has close been called? */
454	if (ctx->ctx_state != ST_QUIT
455#if _FFR_WORKERS_POOL
456	   && ret != MI_CONTINUE
457#endif /* _FFR_WORKERS_POOL */
458	   )
459	{
460		if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL)
461			(void) (*fi_close)(ctx);
462	}
463	if (r != _SMFIS_KEEP && buf != NULL)
464		free(buf);
465#if !_FFR_WORKERS_POOL
466	mi_clr_macros(ctx, 0);
467#endif /* _FFR_WORKERS_POOL */
468	return ret;
469}
470
471static size_t milter_addsymlist __P((SMFICTX_PTR, char *, char **));
472
473static size_t
474milter_addsymlist(ctx, buf, newbuf)
475	SMFICTX_PTR ctx;
476	char *buf;
477	char **newbuf;
478{
479	size_t len;
480	int i;
481	mi_int32 v;
482	char *buffer;
483
484	SM_ASSERT(ctx != NULL);
485	SM_ASSERT(buf != NULL);
486	SM_ASSERT(newbuf != NULL);
487	len = 0;
488	for (i = 0; i < MAX_MACROS_ENTRIES; i++)
489	{
490		if (ctx->ctx_mac_list[i] != NULL)
491		{
492			len += strlen(ctx->ctx_mac_list[i]) + 1 +
493				MILTER_LEN_BYTES;
494		}
495	}
496	if (len > 0)
497	{
498		size_t offset;
499
500		SM_ASSERT(len + MILTER_OPTLEN > len);
501		len += MILTER_OPTLEN;
502		buffer = malloc(len);
503		if (buffer != NULL)
504		{
505			(void) memcpy(buffer, buf, MILTER_OPTLEN);
506			offset = MILTER_OPTLEN;
507			for (i = 0; i < MAX_MACROS_ENTRIES; i++)
508			{
509				size_t l;
510
511				if (ctx->ctx_mac_list[i] == NULL)
512					continue;
513
514				SM_ASSERT(offset + MILTER_LEN_BYTES < len);
515				v = htonl(i);
516				(void) memcpy(buffer + offset, (void *) &v,
517						MILTER_LEN_BYTES);
518				offset += MILTER_LEN_BYTES;
519				l = strlen(ctx->ctx_mac_list[i]) + 1;
520				SM_ASSERT(offset + l <= len);
521				(void) memcpy(buffer + offset,
522						ctx->ctx_mac_list[i], l);
523				offset += l;
524			}
525		}
526		else
527		{
528			/* oops ... */
529		}
530	}
531	else
532	{
533		len = MILTER_OPTLEN;
534		buffer = buf;
535	}
536	*newbuf = buffer;
537	return len;
538}
539
540/*
541**  GET_NR_BIT -- get "no reply" bit matching state
542**
543**	Parameters:
544**		state -- current protocol stage
545**
546**	Returns:
547**		0: no matching bit
548**		>0: the matching "no reply" bit
549*/
550
551static unsigned long get_nr_bit __P((int));
552
553static unsigned long
554get_nr_bit(state)
555	int state;
556{
557	unsigned long bit;
558
559	switch (state)
560	{
561	  case ST_CONN:
562		bit = SMFIP_NR_CONN;
563		break;
564	  case ST_HELO:
565		bit = SMFIP_NR_HELO;
566		break;
567	  case ST_MAIL:
568		bit = SMFIP_NR_MAIL;
569		break;
570	  case ST_RCPT:
571		bit = SMFIP_NR_RCPT;
572		break;
573	  case ST_DATA:
574		bit = SMFIP_NR_DATA;
575		break;
576	  case ST_UNKN:
577		bit = SMFIP_NR_UNKN;
578		break;
579	  case ST_HDRS:
580		bit = SMFIP_NR_HDR;
581		break;
582	  case ST_EOHS:
583		bit = SMFIP_NR_EOH;
584		break;
585	  case ST_BODY:
586		bit = SMFIP_NR_BODY;
587		break;
588	  default:
589		bit = 0;
590		break;
591	}
592	return bit;
593}
594
595/*
596**  SENDREPLY -- send a reply to the MTA
597**
598**	Parameters:
599**		r -- reply code
600**		sd -- socket descriptor
601**		timeout_ptr -- (ptr to) timeout to use for sending
602**		ctx -- context structure
603**
604**	Returns:
605**		MI_SUCCESS/MI_FAILURE
606*/
607
608static int
609sendreply(r, sd, timeout_ptr, ctx)
610	sfsistat r;
611	socket_t sd;
612	struct timeval *timeout_ptr;
613	SMFICTX_PTR ctx;
614{
615	int ret;
616	unsigned long bit;
617
618	ret = MI_SUCCESS;
619
620	bit = get_nr_bit(ctx->ctx_state);
621	if (bit != 0 && (ctx->ctx_pflags & bit) != 0 && r != SMFIS_NOREPLY)
622	{
623		if (r >= SMFIS_CONTINUE && r < _SMFIS_KEEP)
624		{
625			/* milter said it wouldn't reply, but it lied... */
626			smi_log(SMI_LOG_ERR,
627				"%s: milter claimed not to reply in state %d but did anyway %d\n",
628				ctx->ctx_smfi->xxfi_name,
629				ctx->ctx_state, r);
630
631		}
632
633		/*
634		**  Force specified behavior, otherwise libmilter
635		**  and MTA will fail to communicate properly.
636		*/
637
638		switch (r)
639		{
640		  case SMFIS_CONTINUE:
641		  case SMFIS_TEMPFAIL:
642		  case SMFIS_REJECT:
643		  case SMFIS_DISCARD:
644		  case SMFIS_ACCEPT:
645		  case SMFIS_SKIP:
646		  case _SMFIS_OPTIONS:
647			r = SMFIS_NOREPLY;
648			break;
649		}
650	}
651
652	switch (r)
653	{
654	  case SMFIS_CONTINUE:
655		ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 0);
656		break;
657	  case SMFIS_TEMPFAIL:
658	  case SMFIS_REJECT:
659		if (ctx->ctx_reply != NULL &&
660		    ((r == SMFIS_TEMPFAIL && *ctx->ctx_reply == '4') ||
661		     (r == SMFIS_REJECT && *ctx->ctx_reply == '5')))
662		{
663			ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_REPLYCODE,
664					ctx->ctx_reply,
665					strlen(ctx->ctx_reply) + 1);
666			free(ctx->ctx_reply);
667			ctx->ctx_reply = NULL;
668		}
669		else
670		{
671			ret = mi_wr_cmd(sd, timeout_ptr, r == SMFIS_REJECT ?
672					SMFIR_REJECT : SMFIR_TEMPFAIL, NULL, 0);
673		}
674		break;
675	  case SMFIS_DISCARD:
676		ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_DISCARD, NULL, 0);
677		break;
678	  case SMFIS_ACCEPT:
679		ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_ACCEPT, NULL, 0);
680		break;
681	  case SMFIS_SKIP:
682		ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_SKIP, NULL, 0);
683		break;
684	  case _SMFIS_OPTIONS:
685		{
686			mi_int32 v;
687			size_t len;
688			char *buffer;
689			char buf[MILTER_OPTLEN];
690
691			v = htonl(ctx->ctx_prot_vers2mta);
692			(void) memcpy(&(buf[0]), (void *) &v,
693				      MILTER_LEN_BYTES);
694			v = htonl(ctx->ctx_aflags);
695			(void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v,
696				      MILTER_LEN_BYTES);
697			v = htonl(ctx->ctx_pflags2mta);
698			(void) memcpy(&(buf[MILTER_LEN_BYTES * 2]),
699				      (void *) &v, MILTER_LEN_BYTES);
700			len = milter_addsymlist(ctx, buf, &buffer);
701			if (buffer != NULL)
702				ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG,
703						buffer, len);
704			else
705				ret = MI_FAILURE;
706		}
707		break;
708	  case SMFIS_NOREPLY:
709		if (bit != 0 &&
710		    (ctx->ctx_pflags & bit) != 0 &&
711		    (ctx->ctx_mta_pflags & bit) == 0)
712		{
713			/*
714			**  milter doesn't want to send a reply,
715			**  but the MTA doesn't have that feature: fake it.
716			*/
717
718			ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL,
719					0);
720		}
721		break;
722	  default:	/* don't send a reply */
723		break;
724	}
725	return ret;
726}
727
728/*
729**  CLR_MACROS -- clear set of macros starting from a given index
730**
731**	Parameters:
732**		ctx -- context structure
733**		m -- index from which to clear all macros
734**
735**	Returns:
736**		None.
737*/
738
739void
740mi_clr_macros(ctx, m)
741	SMFICTX_PTR ctx;
742	int m;
743{
744	int i;
745
746	for (i = m; i < MAX_MACROS_ENTRIES; i++)
747	{
748		if (ctx->ctx_mac_ptr[i] != NULL)
749		{
750			free(ctx->ctx_mac_ptr[i]);
751			ctx->ctx_mac_ptr[i] = NULL;
752		}
753		if (ctx->ctx_mac_buf[i] != NULL)
754		{
755			free(ctx->ctx_mac_buf[i]);
756			ctx->ctx_mac_buf[i] = NULL;
757		}
758	}
759}
760
761/*
762**  MI_CLR_SYMLIST -- clear list of macros
763**
764**	Parameters:
765**		ctx -- context structure
766**
767**	Returns:
768**		None.
769*/
770
771static void
772mi_clr_symlist(ctx)
773	SMFICTX *ctx;
774{
775	int i;
776
777	SM_ASSERT(ctx != NULL);
778	for (i = SMFIM_FIRST; i <= SMFIM_LAST; i++)
779	{
780		if (ctx->ctx_mac_list[i] != NULL)
781		{
782			free(ctx->ctx_mac_list[i]);
783			ctx->ctx_mac_list[i] = NULL;
784		}
785	}
786}
787
788/*
789**  MI_CLR_CTX -- clear context
790**
791**	Parameters:
792**		ctx -- context structure
793**
794**	Returns:
795**		None.
796*/
797
798void
799mi_clr_ctx(ctx)
800	SMFICTX *ctx;
801{
802	SM_ASSERT(ctx != NULL);
803	if (ValidSocket(ctx->ctx_sd))
804	{
805		(void) closesocket(ctx->ctx_sd);
806		ctx->ctx_sd = INVALID_SOCKET;
807	}
808	if (ctx->ctx_reply != NULL)
809	{
810		free(ctx->ctx_reply);
811		ctx->ctx_reply = NULL;
812	}
813	if (ctx->ctx_privdata != NULL)
814	{
815		smi_log(SMI_LOG_WARN,
816			"%s: private data not NULL",
817			ctx->ctx_smfi->xxfi_name);
818	}
819	mi_clr_macros(ctx, 0);
820	mi_clr_symlist(ctx);
821	free(ctx);
822}
823
824/*
825**  ST_OPTIONNEG -- negotiate options
826**
827**	Parameters:
828**		g -- generic argument structure
829**
830**	Returns:
831**		abort/send options/continue
832*/
833
834static int
835st_optionneg(g)
836	genarg *g;
837{
838	mi_int32 i, v, fake_pflags, internal_pflags;
839	SMFICTX_PTR ctx;
840#if _FFR_MILTER_CHECK
841	bool testmode = false;
842#endif /* _FFR_MILTER_CHECK */
843	int (*fi_negotiate) __P((SMFICTX *,
844					unsigned long, unsigned long,
845					unsigned long, unsigned long,
846					unsigned long *, unsigned long *,
847					unsigned long *, unsigned long *));
848
849	if (g == NULL || g->a_ctx->ctx_smfi == NULL)
850		return SMFIS_CONTINUE;
851	ctx = g->a_ctx;
852	mi_clr_macros(ctx, g->a_idx + 1);
853	ctx->ctx_prot_vers = SMFI_PROT_VERSION;
854
855	/* check for minimum length */
856	if (g->a_len < MILTER_OPTLEN)
857	{
858		smi_log(SMI_LOG_ERR,
859			"%s: st_optionneg[%ld]: len too short %d < %d",
860			ctx->ctx_smfi->xxfi_name,
861			(long) ctx->ctx_id, (int) g->a_len,
862			MILTER_OPTLEN);
863		return _SMFIS_ABORT;
864	}
865
866	/* protocol version */
867	(void) memcpy((void *) &i, (void *) &(g->a_buf[0]), MILTER_LEN_BYTES);
868	v = ntohl(i);
869
870#define SMFI_PROT_VERSION_MIN	2
871
872	/* check for minimum version */
873	if (v < SMFI_PROT_VERSION_MIN)
874	{
875		smi_log(SMI_LOG_ERR,
876			"%s: st_optionneg[%ld]: protocol version too old %d < %d",
877			ctx->ctx_smfi->xxfi_name,
878			(long) ctx->ctx_id, v, SMFI_PROT_VERSION_MIN);
879		return _SMFIS_ABORT;
880	}
881	ctx->ctx_mta_prot_vers = v;
882	if (ctx->ctx_prot_vers < ctx->ctx_mta_prot_vers)
883		ctx->ctx_prot_vers2mta = ctx->ctx_prot_vers;
884	else
885		ctx->ctx_prot_vers2mta = ctx->ctx_mta_prot_vers;
886
887	(void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]),
888		      MILTER_LEN_BYTES);
889	v = ntohl(i);
890
891	/* no flags? set to default value for V1 actions */
892	if (v == 0)
893		v = SMFI_V1_ACTS;
894	ctx->ctx_mta_aflags = v;	/* MTA action flags */
895
896	internal_pflags = 0;
897	(void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES * 2]),
898		      MILTER_LEN_BYTES);
899	v = ntohl(i);
900
901	/* no flags? set to default value for V1 protocol */
902	if (v == 0)
903		v = SMFI_V1_PROT;
904#if _FFR_MDS_NEGOTIATE
905	else if (ctx->ctx_smfi->xxfi_version >= SMFI_VERSION_MDS)
906	{
907		/*
908		**  Allow changing the size only if milter is compiled
909		**  against a version that supports this.
910		**  If a milter is dynamically linked against a newer
911		**  libmilter version, we don't want to "surprise"
912		**  it with a larger buffer as it may rely on it
913		**  even though it is not documented as a limit.
914		*/
915
916		if (bitset(SMFIP_MDS_1M, v))
917		{
918			internal_pflags |= SMFIP_MDS_1M;
919			(void) smfi_setmaxdatasize(MILTER_MDS_1M);
920		}
921		else if (bitset(SMFIP_MDS_256K, v))
922		{
923			internal_pflags |= SMFIP_MDS_256K;
924			(void) smfi_setmaxdatasize(MILTER_MDS_256K);
925		}
926	}
927# if 0
928	/* don't log this for now... */
929	else if (ctx->ctx_smfi->xxfi_version < SMFI_VERSION_MDS &&
930		 bitset(SMFIP_MDS_1M|SMFIP_MDS_256K, v))
931	{
932		smi_log(SMI_LOG_WARN,
933			"%s: st_optionneg[%ld]: milter version=%X, trying flags=%X",
934			ctx->ctx_smfi->xxfi_name,
935			(long) ctx->ctx_id, ctx->ctx_smfi->xxfi_version, v);
936	}
937# endif /* 0 */
938#endif /* _FFR_MDS_NEGOTIATE */
939
940	/*
941	**  MTA protocol flags.
942	**  We pass the internal flags to the milter as "read only",
943	**  i.e., a milter can read them so it knows which size
944	**  will be used, but any changes by a milter will be ignored
945	**  (see below, search for SMFI_INTERNAL).
946	*/
947
948	ctx->ctx_mta_pflags = (v & ~SMFI_INTERNAL) | internal_pflags;
949
950	/*
951	**  Copy flags from milter struct into libmilter context;
952	**  this variable will be used later on to check whether
953	**  the MTA "actions" can fulfill the milter requirements,
954	**  but it may be overwritten by the negotiate callback.
955	*/
956
957	ctx->ctx_aflags = ctx->ctx_smfi->xxfi_flags;
958	fake_pflags = SMFIP_NR_CONN
959			|SMFIP_NR_HELO
960			|SMFIP_NR_MAIL
961			|SMFIP_NR_RCPT
962			|SMFIP_NR_DATA
963			|SMFIP_NR_UNKN
964			|SMFIP_NR_HDR
965			|SMFIP_NR_EOH
966			|SMFIP_NR_BODY
967			;
968
969	if (g->a_ctx->ctx_smfi != NULL &&
970	    g->a_ctx->ctx_smfi->xxfi_version > 4 &&
971	    (fi_negotiate = g->a_ctx->ctx_smfi->xxfi_negotiate) != NULL)
972	{
973		int r;
974		unsigned long m_aflags, m_pflags, m_f2, m_f3;
975
976		/*
977		**  let milter decide whether the features offered by the
978		**  MTA are "good enough".
979		**  Notes:
980		**  - libmilter can "fake" some features (e.g., SMFIP_NR_HDR)
981		**  - m_f2, m_f3 are for future extensions
982		*/
983
984		m_f2 = m_f3 = 0;
985		m_aflags = ctx->ctx_mta_aflags;
986		m_pflags = ctx->ctx_pflags;
987		if ((SMFIP_SKIP & ctx->ctx_mta_pflags) != 0)
988			m_pflags |= SMFIP_SKIP;
989		r = fi_negotiate(g->a_ctx,
990				ctx->ctx_mta_aflags,
991				ctx->ctx_mta_pflags|fake_pflags,
992				0, 0,
993				&m_aflags, &m_pflags, &m_f2, &m_f3);
994
995#if _FFR_MILTER_CHECK
996		testmode = bitset(SMFIP_TEST, m_pflags);
997		if (testmode)
998			m_pflags &= ~SMFIP_TEST;
999#endif /* _FFR_MILTER_CHECK */
1000
1001		/*
1002		**  Types of protocol flags (pflags):
1003		**  1. do NOT send protocol step X
1004		**  2. MTA can do/understand something extra (SKIP,
1005		**	send unknown RCPTs)
1006		**  3. MTA can deal with "no reply" for various protocol steps
1007		**  Note: this mean that it isn't possible to simply set all
1008		**	flags to get "everything":
1009		**	setting a flag of type 1 turns off a step
1010		**		(it should be the other way around:
1011		**		a flag means a protocol step can be sent)
1012		**	setting a flag of type 3 requires that milter
1013		**	never sends a reply for the corresponding step.
1014		**  Summary: the "negation" of protocol flags is causing
1015		**	problems, but at least for type 3 there is no simple
1016		**	solution.
1017		**
1018		**  What should "all options" mean?
1019		**  send all protocol steps _except_ those for which there is
1020		**	no callback (currently registered in ctx_pflags)
1021		**  expect SKIP as return code?		Yes
1022		**  send unknown RCPTs?			No,
1023		**				must be explicitly requested?
1024		**  "no reply" for some protocol steps?	No,
1025		**				must be explicitly requested.
1026		*/
1027
1028		if (SMFIS_ALL_OPTS == r)
1029		{
1030			ctx->ctx_aflags = ctx->ctx_mta_aflags;
1031			ctx->ctx_pflags2mta = ctx->ctx_pflags;
1032			if ((SMFIP_SKIP & ctx->ctx_mta_pflags) != 0)
1033				ctx->ctx_pflags2mta |= SMFIP_SKIP;
1034		}
1035		else if (r != SMFIS_CONTINUE)
1036		{
1037			smi_log(SMI_LOG_ERR,
1038				"%s: st_optionneg[%ld]: xxfi_negotiate returned %d (protocol options=0x%lx, actions=0x%lx)",
1039				ctx->ctx_smfi->xxfi_name,
1040				(long) ctx->ctx_id, r, ctx->ctx_mta_pflags,
1041				ctx->ctx_mta_aflags);
1042			return _SMFIS_ABORT;
1043		}
1044		else
1045		{
1046			ctx->ctx_aflags = m_aflags;
1047			ctx->ctx_pflags = m_pflags;
1048			ctx->ctx_pflags2mta = m_pflags;
1049		}
1050
1051		/* check whether some flags need to be "faked" */
1052		i = ctx->ctx_pflags2mta;
1053		if ((ctx->ctx_mta_pflags & i) != i)
1054		{
1055			unsigned int idx;
1056			unsigned long b;
1057
1058			/*
1059			**  If some behavior can be faked (set in fake_pflags),
1060			**  but the MTA doesn't support it, then unset
1061			**  that flag in the value that is sent to the MTA.
1062			*/
1063
1064			for (idx = 0; idx < 32; idx++)
1065			{
1066				b = 1 << idx;
1067				if ((ctx->ctx_mta_pflags & b) != b &&
1068				    (fake_pflags & b) == b)
1069					ctx->ctx_pflags2mta &= ~b;
1070			}
1071		}
1072	}
1073	else
1074	{
1075		/*
1076		**  Set the protocol flags based on the values determined
1077		**  in mi_listener() which checked the defined callbacks.
1078		*/
1079
1080		ctx->ctx_pflags2mta = ctx->ctx_pflags;
1081	}
1082
1083	/* check whether actions and protocol requirements can be satisfied */
1084	i = ctx->ctx_aflags;
1085	if ((i & ctx->ctx_mta_aflags) != i)
1086	{
1087		smi_log(SMI_LOG_ERR,
1088			"%s: st_optionneg[%ld]: 0x%lx does not fulfill action requirements 0x%x",
1089			ctx->ctx_smfi->xxfi_name,
1090			(long) ctx->ctx_id, ctx->ctx_mta_aflags, i);
1091		return _SMFIS_ABORT;
1092	}
1093
1094	i = ctx->ctx_pflags2mta;
1095	if ((ctx->ctx_mta_pflags & i) != i)
1096	{
1097		/*
1098		**  Older MTAs do not support some protocol steps.
1099		**  As this protocol is a bit "wierd" (it asks for steps
1100		**  NOT to be taken/sent) we have to check whether we
1101		**  should turn off those "negative" requests.
1102		**  Currently these are only SMFIP_NODATA and SMFIP_NOUNKNOWN.
1103		*/
1104
1105		if (bitset(SMFIP_NODATA, ctx->ctx_pflags2mta) &&
1106		    !bitset(SMFIP_NODATA, ctx->ctx_mta_pflags))
1107			ctx->ctx_pflags2mta &= ~SMFIP_NODATA;
1108		if (bitset(SMFIP_NOUNKNOWN, ctx->ctx_pflags2mta) &&
1109		    !bitset(SMFIP_NOUNKNOWN, ctx->ctx_mta_pflags))
1110			ctx->ctx_pflags2mta &= ~SMFIP_NOUNKNOWN;
1111		i = ctx->ctx_pflags2mta;
1112	}
1113
1114	if ((ctx->ctx_mta_pflags & i) != i)
1115	{
1116		smi_log(SMI_LOG_ERR,
1117			"%s: st_optionneg[%ld]: 0x%lx does not fulfill protocol requirements 0x%x",
1118			ctx->ctx_smfi->xxfi_name,
1119			(long) ctx->ctx_id, ctx->ctx_mta_pflags, i);
1120		return _SMFIS_ABORT;
1121	}
1122	fix_stm(ctx);
1123
1124	if (ctx->ctx_dbg > 3)
1125		sm_dprintf("[%lu] milter_negotiate:"
1126			" mta_actions=0x%lx, mta_flags=0x%lx"
1127			" actions=0x%lx, flags=0x%lx\n"
1128			, (long) ctx->ctx_id
1129			, ctx->ctx_mta_aflags, ctx->ctx_mta_pflags
1130			, ctx->ctx_aflags, ctx->ctx_pflags);
1131
1132#if _FFR_MILTER_CHECK
1133	if (ctx->ctx_dbg > 3)
1134		sm_dprintf("[%lu] milter_negotiate:"
1135			" testmode=%d, pflags2mta=%X, internal_pflags=%X\n"
1136			, (long) ctx->ctx_id, testmode
1137			, ctx->ctx_pflags2mta, internal_pflags);
1138
1139	/* in test mode: take flags without further modifications */
1140	if (!testmode)
1141		/* Warning: check statement below! */
1142#endif /* _FFR_MILTER_CHECK */
1143
1144	/*
1145	**  Remove the internal flags that might have been set by a milter
1146	**  and set only those determined above.
1147	*/
1148
1149	ctx->ctx_pflags2mta = (ctx->ctx_pflags2mta & ~SMFI_INTERNAL)
1150			      | internal_pflags;
1151	return _SMFIS_OPTIONS;
1152}
1153
1154/*
1155**  ST_CONNECTINFO -- receive connection information
1156**
1157**	Parameters:
1158**		g -- generic argument structure
1159**
1160**	Returns:
1161**		continue or filter-specified value
1162*/
1163
1164static int
1165st_connectinfo(g)
1166	genarg *g;
1167{
1168	size_t l;
1169	size_t i;
1170	char *s, family;
1171	unsigned short port = 0;
1172	_SOCK_ADDR sockaddr;
1173	sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *));
1174
1175	if (g == NULL)
1176		return _SMFIS_ABORT;
1177	mi_clr_macros(g->a_ctx, g->a_idx + 1);
1178	if (g->a_ctx->ctx_smfi == NULL ||
1179	    (fi_connect = g->a_ctx->ctx_smfi->xxfi_connect) == NULL)
1180		return SMFIS_CONTINUE;
1181
1182	s = g->a_buf;
1183	i = 0;
1184	l = g->a_len;
1185	while (s[i] != '\0' && i <= l)
1186		++i;
1187	if (i + 1 >= l)
1188		return _SMFIS_ABORT;
1189
1190	/* Move past trailing \0 in host string */
1191	i++;
1192	family = s[i++];
1193	(void) memset(&sockaddr, '\0', sizeof sockaddr);
1194	if (family != SMFIA_UNKNOWN)
1195	{
1196		if (i + sizeof port >= l)
1197		{
1198			smi_log(SMI_LOG_ERR,
1199				"%s: connect[%ld]: wrong len %d >= %d",
1200				g->a_ctx->ctx_smfi->xxfi_name,
1201				(long) g->a_ctx->ctx_id, (int) i, (int) l);
1202			return _SMFIS_ABORT;
1203		}
1204		(void) memcpy((void *) &port, (void *) (s + i),
1205			      sizeof port);
1206		i += sizeof port;
1207
1208		/* make sure string is terminated */
1209		if (s[l - 1] != '\0')
1210			return _SMFIS_ABORT;
1211# if NETINET
1212		if (family == SMFIA_INET)
1213		{
1214			if (inet_aton(s + i, (struct in_addr *) &sockaddr.sin.sin_addr)
1215			    != 1)
1216			{
1217				smi_log(SMI_LOG_ERR,
1218					"%s: connect[%ld]: inet_aton failed",
1219					g->a_ctx->ctx_smfi->xxfi_name,
1220					(long) g->a_ctx->ctx_id);
1221				return _SMFIS_ABORT;
1222			}
1223			sockaddr.sa.sa_family = AF_INET;
1224			if (port > 0)
1225				sockaddr.sin.sin_port = port;
1226		}
1227		else
1228# endif /* NETINET */
1229# if NETINET6
1230		if (family == SMFIA_INET6)
1231		{
1232			if (mi_inet_pton(AF_INET6, s + i,
1233					 &sockaddr.sin6.sin6_addr) != 1)
1234			{
1235				smi_log(SMI_LOG_ERR,
1236					"%s: connect[%ld]: mi_inet_pton failed",
1237					g->a_ctx->ctx_smfi->xxfi_name,
1238					(long) g->a_ctx->ctx_id);
1239				return _SMFIS_ABORT;
1240			}
1241			sockaddr.sa.sa_family = AF_INET6;
1242			if (port > 0)
1243				sockaddr.sin6.sin6_port = port;
1244		}
1245		else
1246# endif /* NETINET6 */
1247# if NETUNIX
1248		if (family == SMFIA_UNIX)
1249		{
1250			if (sm_strlcpy(sockaddr.sunix.sun_path, s + i,
1251			    sizeof sockaddr.sunix.sun_path) >=
1252			    sizeof sockaddr.sunix.sun_path)
1253			{
1254				smi_log(SMI_LOG_ERR,
1255					"%s: connect[%ld]: path too long",
1256					g->a_ctx->ctx_smfi->xxfi_name,
1257					(long) g->a_ctx->ctx_id);
1258				return _SMFIS_ABORT;
1259			}
1260			sockaddr.sunix.sun_family = AF_UNIX;
1261		}
1262		else
1263# endif /* NETUNIX */
1264		{
1265			smi_log(SMI_LOG_ERR,
1266				"%s: connect[%ld]: unknown family %d",
1267				g->a_ctx->ctx_smfi->xxfi_name,
1268				(long) g->a_ctx->ctx_id, family);
1269			return _SMFIS_ABORT;
1270		}
1271	}
1272	return (*fi_connect)(g->a_ctx, g->a_buf,
1273			     family != SMFIA_UNKNOWN ? &sockaddr : NULL);
1274}
1275
1276/*
1277**  ST_EOH -- end of headers
1278**
1279**	Parameters:
1280**		g -- generic argument structure
1281**
1282**	Returns:
1283**		continue or filter-specified value
1284*/
1285
1286static int
1287st_eoh(g)
1288	genarg *g;
1289{
1290	sfsistat (*fi_eoh) __P((SMFICTX *));
1291
1292	if (g == NULL)
1293		return _SMFIS_ABORT;
1294	if (g->a_ctx->ctx_smfi != NULL &&
1295	    (fi_eoh = g->a_ctx->ctx_smfi->xxfi_eoh) != NULL)
1296		return (*fi_eoh)(g->a_ctx);
1297	return SMFIS_CONTINUE;
1298}
1299
1300/*
1301**  ST_DATA -- DATA command
1302**
1303**	Parameters:
1304**		g -- generic argument structure
1305**
1306**	Returns:
1307**		continue or filter-specified value
1308*/
1309
1310static int
1311st_data(g)
1312	genarg *g;
1313{
1314	sfsistat (*fi_data) __P((SMFICTX *));
1315
1316	if (g == NULL)
1317		return _SMFIS_ABORT;
1318	if (g->a_ctx->ctx_smfi != NULL &&
1319	    g->a_ctx->ctx_smfi->xxfi_version > 3 &&
1320	    (fi_data = g->a_ctx->ctx_smfi->xxfi_data) != NULL)
1321		return (*fi_data)(g->a_ctx);
1322	return SMFIS_CONTINUE;
1323}
1324
1325/*
1326**  ST_HELO -- helo/ehlo command
1327**
1328**	Parameters:
1329**		g -- generic argument structure
1330**
1331**	Returns:
1332**		continue or filter-specified value
1333*/
1334
1335static int
1336st_helo(g)
1337	genarg *g;
1338{
1339	sfsistat (*fi_helo) __P((SMFICTX *, char *));
1340
1341	if (g == NULL)
1342		return _SMFIS_ABORT;
1343	mi_clr_macros(g->a_ctx, g->a_idx + 1);
1344	if (g->a_ctx->ctx_smfi != NULL &&
1345	    (fi_helo = g->a_ctx->ctx_smfi->xxfi_helo) != NULL)
1346	{
1347		/* paranoia: check for terminating '\0' */
1348		if (g->a_len == 0 || g->a_buf[g->a_len - 1] != '\0')
1349			return MI_FAILURE;
1350		return (*fi_helo)(g->a_ctx, g->a_buf);
1351	}
1352	return SMFIS_CONTINUE;
1353}
1354
1355/*
1356**  ST_HEADER -- header line
1357**
1358**	Parameters:
1359**		g -- generic argument structure
1360**
1361**	Returns:
1362**		continue or filter-specified value
1363*/
1364
1365static int
1366st_header(g)
1367	genarg *g;
1368{
1369	char *hf, *hv;
1370	sfsistat (*fi_header) __P((SMFICTX *, char *, char *));
1371
1372	if (g == NULL)
1373		return _SMFIS_ABORT;
1374	if (g->a_ctx->ctx_smfi == NULL ||
1375	    (fi_header = g->a_ctx->ctx_smfi->xxfi_header) == NULL)
1376		return SMFIS_CONTINUE;
1377	if (dec_arg2(g->a_buf, g->a_len, &hf, &hv) == MI_SUCCESS)
1378		return (*fi_header)(g->a_ctx, hf, hv);
1379	else
1380		return _SMFIS_ABORT;
1381}
1382
1383#define ARGV_FCT(lf, rf, idx)					\
1384	char **argv;						\
1385	sfsistat (*lf) __P((SMFICTX *, char **));		\
1386	int r;							\
1387								\
1388	if (g == NULL)						\
1389		return _SMFIS_ABORT;				\
1390	mi_clr_macros(g->a_ctx, g->a_idx + 1);			\
1391	if (g->a_ctx->ctx_smfi == NULL ||			\
1392	    (lf = g->a_ctx->ctx_smfi->rf) == NULL)		\
1393		return SMFIS_CONTINUE;				\
1394	if ((argv = dec_argv(g->a_buf, g->a_len)) == NULL)	\
1395		return _SMFIS_ABORT;				\
1396	r = (*lf)(g->a_ctx, argv);				\
1397	free(argv);						\
1398	return r;
1399
1400/*
1401**  ST_SENDER -- MAIL FROM command
1402**
1403**	Parameters:
1404**		g -- generic argument structure
1405**
1406**	Returns:
1407**		continue or filter-specified value
1408*/
1409
1410static int
1411st_sender(g)
1412	genarg *g;
1413{
1414	ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL)
1415}
1416
1417/*
1418**  ST_RCPT -- RCPT TO command
1419**
1420**	Parameters:
1421**		g -- generic argument structure
1422**
1423**	Returns:
1424**		continue or filter-specified value
1425*/
1426
1427static int
1428st_rcpt(g)
1429	genarg *g;
1430{
1431	ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT)
1432}
1433
1434/*
1435**  ST_UNKNOWN -- unrecognized or unimplemented command
1436**
1437**	Parameters:
1438**		g -- generic argument structure
1439**
1440**	Returns:
1441**		continue or filter-specified value
1442*/
1443
1444static int
1445st_unknown(g)
1446	genarg *g;
1447{
1448	sfsistat (*fi_unknown) __P((SMFICTX *, const char *));
1449
1450	if (g == NULL)
1451		return _SMFIS_ABORT;
1452	if (g->a_ctx->ctx_smfi != NULL &&
1453	    g->a_ctx->ctx_smfi->xxfi_version > 2 &&
1454	    (fi_unknown = g->a_ctx->ctx_smfi->xxfi_unknown) != NULL)
1455		return (*fi_unknown)(g->a_ctx, (const char *) g->a_buf);
1456	return SMFIS_CONTINUE;
1457}
1458
1459/*
1460**  ST_MACROS -- deal with macros received from the MTA
1461**
1462**	Parameters:
1463**		g -- generic argument structure
1464**
1465**	Returns:
1466**		continue/keep
1467**
1468**	Side effects:
1469**		set pointer in macro array to current values.
1470*/
1471
1472static int
1473st_macros(g)
1474	genarg *g;
1475{
1476	int i;
1477	char **argv;
1478
1479	if (g == NULL || g->a_len < 1)
1480		return _SMFIS_FAIL;
1481	if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL)
1482		return _SMFIS_FAIL;
1483	switch (g->a_buf[0])
1484	{
1485	  case SMFIC_CONNECT:
1486		i = CI_CONN;
1487		break;
1488	  case SMFIC_HELO:
1489		i = CI_HELO;
1490		break;
1491	  case SMFIC_MAIL:
1492		i = CI_MAIL;
1493		break;
1494	  case SMFIC_RCPT:
1495		i = CI_RCPT;
1496		break;
1497	  case SMFIC_DATA:
1498		i = CI_DATA;
1499		break;
1500	  case SMFIC_BODYEOB:
1501		i = CI_EOM;
1502		break;
1503	  case SMFIC_EOH:
1504		i = CI_EOH;
1505		break;
1506	  default:
1507		free(argv);
1508		return _SMFIS_FAIL;
1509	}
1510	if (g->a_ctx->ctx_mac_ptr[i] != NULL)
1511		free(g->a_ctx->ctx_mac_ptr[i]);
1512	if (g->a_ctx->ctx_mac_buf[i] != NULL)
1513		free(g->a_ctx->ctx_mac_buf[i]);
1514	g->a_ctx->ctx_mac_ptr[i] = argv;
1515	g->a_ctx->ctx_mac_buf[i] = g->a_buf;
1516	return _SMFIS_KEEP;
1517}
1518
1519/*
1520**  ST_QUIT -- quit command
1521**
1522**	Parameters:
1523**		g -- generic argument structure
1524**
1525**	Returns:
1526**		noreply
1527*/
1528
1529/* ARGSUSED */
1530static int
1531st_quit(g)
1532	genarg *g;
1533{
1534	sfsistat (*fi_close) __P((SMFICTX *));
1535
1536	if (g == NULL)
1537		return _SMFIS_ABORT;
1538	if (g->a_ctx->ctx_smfi != NULL &&
1539	    (fi_close = g->a_ctx->ctx_smfi->xxfi_close) != NULL)
1540		(void) (*fi_close)(g->a_ctx);
1541	mi_clr_macros(g->a_ctx, 0);
1542	return _SMFIS_NOREPLY;
1543}
1544
1545/*
1546**  ST_BODYCHUNK -- deal with a piece of the mail body
1547**
1548**	Parameters:
1549**		g -- generic argument structure
1550**
1551**	Returns:
1552**		continue or filter-specified value
1553*/
1554
1555static int
1556st_bodychunk(g)
1557	genarg *g;
1558{
1559	sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t));
1560
1561	if (g == NULL)
1562		return _SMFIS_ABORT;
1563	if (g->a_ctx->ctx_smfi != NULL &&
1564	    (fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL)
1565		return (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf,
1566				  g->a_len);
1567	return SMFIS_CONTINUE;
1568}
1569
1570/*
1571**  ST_BODYEND -- deal with the last piece of the mail body
1572**
1573**	Parameters:
1574**		g -- generic argument structure
1575**
1576**	Returns:
1577**		continue or filter-specified value
1578**
1579**	Side effects:
1580**		sends a reply for the body part (if non-empty).
1581*/
1582
1583static int
1584st_bodyend(g)
1585	genarg *g;
1586{
1587	sfsistat r;
1588	sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t));
1589	sfsistat (*fi_eom) __P((SMFICTX *));
1590
1591	if (g == NULL)
1592		return _SMFIS_ABORT;
1593	r = SMFIS_CONTINUE;
1594	if (g->a_ctx->ctx_smfi != NULL)
1595	{
1596		if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL &&
1597		    g->a_len > 0)
1598		{
1599			socket_t sd;
1600			struct timeval timeout;
1601
1602			timeout.tv_sec = g->a_ctx->ctx_timeout;
1603			timeout.tv_usec = 0;
1604			sd = g->a_ctx->ctx_sd;
1605			r = (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf,
1606				       g->a_len);
1607			if (r != SMFIS_CONTINUE &&
1608			    sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS)
1609				return _SMFIS_ABORT;
1610		}
1611	}
1612	if (r == SMFIS_CONTINUE &&
1613	    (fi_eom = g->a_ctx->ctx_smfi->xxfi_eom) != NULL)
1614		return (*fi_eom)(g->a_ctx);
1615	return r;
1616}
1617
1618/*
1619**  ST_ABORTFCT -- deal with aborts
1620**
1621**	Parameters:
1622**		g -- generic argument structure
1623**
1624**	Returns:
1625**		abort or filter-specified value
1626*/
1627
1628static int
1629st_abortfct(g)
1630	genarg *g;
1631{
1632	sfsistat (*fi_abort) __P((SMFICTX *));
1633
1634	if (g == NULL)
1635		return _SMFIS_ABORT;
1636	if (g != NULL && g->a_ctx->ctx_smfi != NULL &&
1637	    (fi_abort = g->a_ctx->ctx_smfi->xxfi_abort) != NULL)
1638		(void) (*fi_abort)(g->a_ctx);
1639	return _SMFIS_NOREPLY;
1640}
1641
1642/*
1643**  TRANS_OK -- is the state transition ok?
1644**
1645**	Parameters:
1646**		old -- old state
1647**		new -- new state
1648**
1649**	Returns:
1650**		state transition ok
1651*/
1652
1653static bool
1654trans_ok(old, new)
1655	int old, new;
1656{
1657	int s, n;
1658
1659	s = old;
1660	if (s >= SIZE_NEXT_STATES)
1661		return false;
1662	do
1663	{
1664		/* is this state transition allowed? */
1665		if ((MI_MASK(new) & next_states[s]) != 0)
1666			return true;
1667
1668		/*
1669		**  no: try next state;
1670		**  this works since the relevant states are ordered
1671		**  strict sequentially
1672		*/
1673
1674		n = s + 1;
1675		if (n >= SIZE_NEXT_STATES)
1676			return false;
1677
1678		/*
1679		**  can we actually "skip" this state?
1680		**  see fix_stm() which sets this bit for those
1681		**  states which the filter program is not interested in
1682		*/
1683
1684		if (bitset(NX_SKIP, next_states[n]))
1685			s = n;
1686		else
1687			return false;
1688	} while (s < SIZE_NEXT_STATES);
1689	return false;
1690}
1691
1692/*
1693**  FIX_STM -- add "skip" bits to the state transition table
1694**
1695**	Parameters:
1696**		ctx -- context structure
1697**
1698**	Returns:
1699**		None.
1700**
1701**	Side effects:
1702**		may change state transition table.
1703*/
1704
1705static void
1706fix_stm(ctx)
1707	SMFICTX_PTR ctx;
1708{
1709	unsigned long fl;
1710
1711	if (ctx == NULL || ctx->ctx_smfi == NULL)
1712		return;
1713	fl = ctx->ctx_pflags;
1714	if (bitset(SMFIP_NOCONNECT, fl))
1715		next_states[ST_CONN] |= NX_SKIP;
1716	if (bitset(SMFIP_NOHELO, fl))
1717		next_states[ST_HELO] |= NX_SKIP;
1718	if (bitset(SMFIP_NOMAIL, fl))
1719		next_states[ST_MAIL] |= NX_SKIP;
1720	if (bitset(SMFIP_NORCPT, fl))
1721		next_states[ST_RCPT] |= NX_SKIP;
1722	if (bitset(SMFIP_NOHDRS, fl))
1723		next_states[ST_HDRS] |= NX_SKIP;
1724	if (bitset(SMFIP_NOEOH, fl))
1725		next_states[ST_EOHS] |= NX_SKIP;
1726	if (bitset(SMFIP_NOBODY, fl))
1727		next_states[ST_BODY] |= NX_SKIP;
1728	if (bitset(SMFIP_NODATA, fl))
1729		next_states[ST_DATA] |= NX_SKIP;
1730	if (bitset(SMFIP_NOUNKNOWN, fl))
1731		next_states[ST_UNKN] |= NX_SKIP;
1732}
1733
1734/*
1735**  DEC_ARGV -- split a buffer into a list of strings, NULL terminated
1736**
1737**	Parameters:
1738**		buf -- buffer with several strings
1739**		len -- length of buffer
1740**
1741**	Returns:
1742**		array of pointers to the individual strings
1743*/
1744
1745static char **
1746dec_argv(buf, len)
1747	char *buf;
1748	size_t len;
1749{
1750	char **s;
1751	size_t i;
1752	int elem, nelem;
1753
1754	nelem = 0;
1755	for (i = 0; i < len; i++)
1756	{
1757		if (buf[i] == '\0')
1758			++nelem;
1759	}
1760	if (nelem == 0)
1761		return NULL;
1762
1763	/* last entry is only for the name */
1764	s = (char **)malloc((nelem + 1) * (sizeof *s));
1765	if (s == NULL)
1766		return NULL;
1767	s[0] = buf;
1768	for (i = 0, elem = 0; i < len && elem < nelem; i++)
1769	{
1770		if (buf[i] == '\0')
1771		{
1772			++elem;
1773			if (i + 1 >= len)
1774				s[elem] = NULL;
1775			else
1776				s[elem] = &(buf[i + 1]);
1777		}
1778	}
1779
1780	/* overwrite last entry (already done above, just paranoia) */
1781	s[elem] = NULL;
1782	return s;
1783}
1784
1785/*
1786**  DEC_ARG2 -- split a buffer into two strings
1787**
1788**	Parameters:
1789**		buf -- buffer with two strings
1790**		len -- length of buffer
1791**		s1,s2 -- pointer to result strings
1792**
1793**	Returns:
1794**		MI_FAILURE/MI_SUCCESS
1795*/
1796
1797static int
1798dec_arg2(buf, len, s1, s2)
1799	char *buf;
1800	size_t len;
1801	char **s1;
1802	char **s2;
1803{
1804	size_t i;
1805
1806	/* paranoia: check for terminating '\0' */
1807	if (len == 0 || buf[len - 1] != '\0')
1808		return MI_FAILURE;
1809	*s1 = buf;
1810	for (i = 1; i < len && buf[i] != '\0'; i++)
1811		continue;
1812	if (i >= len - 1)
1813		return MI_FAILURE;
1814	*s2 = buf + i + 1;
1815	return MI_SUCCESS;
1816}
1817
1818/*
1819**  SENDOK -- is it ok for the filter to send stuff to the MTA?
1820**
1821**	Parameters:
1822**		ctx -- context structure
1823**		flag -- flag to check
1824**
1825**	Returns:
1826**		sending allowed (in current state)
1827*/
1828
1829bool
1830mi_sendok(ctx, flag)
1831	SMFICTX_PTR ctx;
1832	int flag;
1833{
1834	if (ctx == NULL || ctx->ctx_smfi == NULL)
1835		return false;
1836
1837	/* did the milter request this operation? */
1838	if (flag != 0 && !bitset(flag, ctx->ctx_aflags))
1839		return false;
1840
1841	/* are we in the correct state? It must be "End of Message". */
1842	return ctx->ctx_state == ST_ENDM;
1843}
1844
1845#if _FFR_WORKERS_POOL
1846/*
1847**  MI_RD_SOCKET_READY - checks if the socket is ready for read(2)
1848**
1849**	Parameters:
1850**		sd -- socket_t
1851**
1852**	Returns:
1853**		true iff socket is ready for read(2)
1854*/
1855
1856#define MI_RD_CMD_TO  1
1857#define MI_RD_MAX_ERR 16
1858
1859static bool
1860mi_rd_socket_ready (sd)
1861	socket_t sd;
1862{
1863	int n;
1864	int nerr = 0;
1865#if SM_CONF_POLL
1866	struct pollfd pfd;
1867#else /* SM_CONF_POLL */
1868	fd_set	rd_set, exc_set;
1869#endif /* SM_CONF_POLL */
1870
1871	do
1872	{
1873#if SM_CONF_POLL
1874		pfd.fd = sd;
1875		pfd.events = POLLIN;
1876		pfd.revents = 0;
1877
1878		n = poll(&pfd, 1, MI_RD_CMD_TO);
1879#else /* SM_CONF_POLL */
1880		struct timeval timeout;
1881
1882		FD_ZERO(&rd_set);
1883		FD_ZERO(&exc_set);
1884		FD_SET(sd, &rd_set);
1885		FD_SET(sd, &exc_set);
1886
1887		timeout.tv_sec = MI_RD_CMD_TO / 1000;
1888		timeout.tv_usec = 0;
1889		n = select(sd + 1, &rd_set, NULL, &exc_set, &timeout);
1890#endif /* SM_CONF_POLL */
1891
1892		if (n < 0)
1893		{
1894			if (errno == EINTR)
1895			{
1896				nerr++;
1897				continue;
1898			}
1899			return true;
1900		}
1901
1902		if (n == 0)
1903			return false;
1904		break;
1905	} while (nerr < MI_RD_MAX_ERR);
1906	if (nerr >= MI_RD_MAX_ERR)
1907		return false;
1908
1909#if SM_CONF_POLL
1910	return (pfd.revents != 0);
1911#else /* SM_CONF_POLL */
1912	return FD_ISSET(sd, &rd_set) || FD_ISSET(sd, &exc_set);
1913#endif /* SM_CONF_POLL */
1914}
1915#endif /* _FFR_WORKERS_POOL */
1916