xref: /freebsd/contrib/sendmail/libmilter/engine.c (revision f0adf7f5cdd241db2f2c817683191a6ef64a4e95)
1 /*
2  *  Copyright (c) 1999-2003 Sendmail, 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>
12 SM_RCSID("@(#)$Id: engine.c,v 8.109.2.8 2003/12/01 23:57:45 msk 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 */
21 struct 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 
29 typedef struct arg_struct genarg;
30 
31 /* structure for commands received from MTA */
32 struct 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 
42 typedef 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	/* start 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 #if _FFR_MILTER_MACROS_EOM
68 # define CI_EOM		4
69 # if CI_EOM >= MAX_MACROS_ENTRIES
70 ERROR: do not compile with CI_EOM >= MAX_MACROS_ENTRIES
71 # endif
72 #else /* _FFR_MILTER_MACROS_EOM */
73 # if CI_RCPT >= MAX_MACROS_ENTRIES
74 ERROR: do not compile with CI_RCPT >= MAX_MACROS_ENTRIES
75 # endif
76 #endif /* _FFR_MILTER_MACROS_EOM */
77 
78 /* function prototypes */
79 static int	st_abortfct __P((genarg *));
80 static int	st_macros __P((genarg *));
81 static int	st_optionneg __P((genarg *));
82 static int	st_bodychunk __P((genarg *));
83 static int	st_connectinfo __P((genarg *));
84 static int	st_bodyend __P((genarg *));
85 static int	st_helo __P((genarg *));
86 static int	st_header __P((genarg *));
87 static int	st_sender __P((genarg *));
88 static int	st_rcpt __P((genarg *));
89 static int	st_eoh __P((genarg *));
90 static int	st_quit __P((genarg *));
91 static int	sendreply __P((sfsistat, socket_t, struct timeval *, SMFICTX_PTR));
92 static void	fix_stm __P((SMFICTX_PTR));
93 static bool	trans_ok __P((int, int));
94 static char	**dec_argv __P((char *, size_t));
95 static int	dec_arg2 __P((char *, size_t, char **, char **));
96 
97 /* states */
98 #define ST_NONE	(-1)
99 #define ST_INIT	0	/* initial state */
100 #define ST_OPTS	1	/* option negotiation */
101 #define ST_CONN	2	/* connection info */
102 #define ST_HELO	3	/* helo */
103 #define ST_MAIL	4	/* mail from */
104 #define ST_RCPT	5	/* rcpt to */
105 #define ST_HDRS	6	/* headers */
106 #define ST_EOHS	7	/* end of headers */
107 #define ST_BODY	8	/* body */
108 #define ST_ENDM	9	/* end of message */
109 #define ST_QUIT	10	/* quit */
110 #define ST_ABRT	11	/* abort */
111 #define ST_LAST	ST_ABRT
112 #define ST_SKIP	15	/* not a state but required for the state table */
113 
114 /* in a mail transaction? must be before eom according to spec. */
115 #define ST_IN_MAIL(st)	((st) >= ST_MAIL && (st) < ST_ENDM)
116 
117 /*
118 **  set of next states
119 **  each state (ST_*) corresponds to bit in an int value (1 << state)
120 **  each state has a set of allowed transitions ('or' of bits of states)
121 **  so a state transition is valid if the mask of the next state
122 **  is set in the NX_* value
123 **  this function is coded in trans_ok(), see below.
124 */
125 
126 #define MI_MASK(x)	(0x0001 << (x))	/* generate a bit "mask" for a state */
127 #define NX_INIT	(MI_MASK(ST_OPTS))
128 #define NX_OPTS	(MI_MASK(ST_CONN))
129 #define NX_CONN	(MI_MASK(ST_HELO) | MI_MASK(ST_MAIL))
130 #define NX_HELO	(MI_MASK(ST_HELO) | MI_MASK(ST_MAIL))
131 #define NX_MAIL	(MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT))
132 #define NX_RCPT	(MI_MASK(ST_HDRS) | MI_MASK(ST_EOHS) | \
133 		 MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | \
134 		 MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT))
135 #define NX_HDRS	(MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT))
136 #define NX_EOHS	(MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | MI_MASK(ST_ABRT))
137 #define NX_BODY	(MI_MASK(ST_ENDM) | MI_MASK(ST_BODY) | MI_MASK(ST_ABRT))
138 #define NX_ENDM	(MI_MASK(ST_QUIT) | MI_MASK(ST_MAIL))
139 #define NX_QUIT	0
140 #define NX_ABRT	0
141 #define NX_SKIP MI_MASK(ST_SKIP)
142 
143 static int next_states[] =
144 {
145 	NX_INIT,
146 	NX_OPTS,
147 	NX_CONN,
148 	NX_HELO,
149 	NX_MAIL,
150 	NX_RCPT,
151 	NX_HDRS,
152 	NX_EOHS,
153 	NX_BODY,
154 	NX_ENDM,
155 	NX_QUIT,
156 	NX_ABRT
157 };
158 
159 /* commands received by milter */
160 static cmdfct cmds[] =
161 {
162 {SMFIC_ABORT,	CM_ARG0, ST_ABRT,  CT_CONT,	CI_NONE, st_abortfct	},
163 {SMFIC_MACRO,	CM_ARGV, ST_NONE,  CT_KEEP,	CI_NONE, st_macros	},
164 {SMFIC_BODY,	CM_ARG1, ST_BODY,  CT_CONT,	CI_NONE, st_bodychunk	},
165 {SMFIC_CONNECT,	CM_ARG2, ST_CONN,  CT_CONT,	CI_CONN, st_connectinfo	},
166 #if _FFR_MILTER_MACROS_EOM
167 {SMFIC_BODYEOB,	CM_ARG1, ST_ENDM,  CT_CONT,	CI_EOM,  st_bodyend	},
168 #else /* _FFR_MILTER_MACROS_EOM */
169 {SMFIC_BODYEOB,	CM_ARG1, ST_ENDM,  CT_CONT,	CI_NONE, st_bodyend	},
170 #endif /* _FFR_MILTER_MACROS_EOM */
171 {SMFIC_HELO,	CM_ARG1, ST_HELO,  CT_CONT,	CI_HELO, st_helo	},
172 {SMFIC_HEADER,	CM_ARG2, ST_HDRS,  CT_CONT,	CI_NONE, st_header	},
173 {SMFIC_MAIL,	CM_ARGV, ST_MAIL,  CT_CONT,	CI_MAIL, st_sender	},
174 {SMFIC_OPTNEG,	CM_ARGO, ST_OPTS,  CT_CONT,	CI_NONE, st_optionneg	},
175 {SMFIC_EOH,	CM_ARG0, ST_EOHS,  CT_CONT,	CI_NONE, st_eoh		},
176 {SMFIC_QUIT,	CM_ARG0, ST_QUIT,  CT_END,	CI_NONE, st_quit	},
177 {SMFIC_RCPT,	CM_ARGV, ST_RCPT,  CT_IGNO,	CI_RCPT, st_rcpt	}
178 };
179 
180 /* additional (internal) reply codes */
181 #define _SMFIS_KEEP	20
182 #define _SMFIS_ABORT	21
183 #define _SMFIS_OPTIONS	22
184 #define _SMFIS_NOREPLY	23
185 #define _SMFIS_FAIL	(-1)
186 #define _SMFIS_NONE	(-2)
187 
188 /*
189 **  MI_ENGINE -- receive commands and process them
190 **
191 **	Parameters:
192 **		ctx -- context structure
193 **
194 **	Returns:
195 **		MI_FAILURE/MI_SUCCESS
196 */
197 int
198 mi_engine(ctx)
199 	SMFICTX_PTR ctx;
200 {
201 	size_t len;
202 	int i;
203 	socket_t sd;
204 	int ret = MI_SUCCESS;
205 	int ncmds = sizeof(cmds) / sizeof(cmdfct);
206 	int curstate = ST_INIT;
207 	int newstate;
208 	bool call_abort;
209 	sfsistat r;
210 	char cmd;
211 	char *buf = NULL;
212 	genarg arg;
213 	struct timeval timeout;
214 	int (*f) __P((genarg *));
215 	sfsistat (*fi_abort) __P((SMFICTX *));
216 	sfsistat (*fi_close) __P((SMFICTX *));
217 
218 	arg.a_ctx = ctx;
219 	sd = ctx->ctx_sd;
220 	fi_abort = ctx->ctx_smfi->xxfi_abort;
221 	mi_clr_macros(ctx, 0);
222 	fix_stm(ctx);
223 	r = _SMFIS_NONE;
224 	do
225 	{
226 		/* call abort only if in a mail transaction */
227 		call_abort = ST_IN_MAIL(curstate);
228 		timeout.tv_sec = ctx->ctx_timeout;
229 		timeout.tv_usec = 0;
230 		if (mi_stop() == MILTER_ABRT)
231 		{
232 			if (ctx->ctx_dbg > 3)
233 				sm_dprintf("[%d] milter_abort\n",
234 					(int) ctx->ctx_id);
235 			ret = MI_FAILURE;
236 			break;
237 		}
238 
239 		/*
240 		**  Notice: buf is allocated by mi_rd_cmd() and it will
241 		**  usually be free()d after it has been used in f().
242 		**  However, if the function returns _SMFIS_KEEP then buf
243 		**  contains macros and will not be free()d.
244 		**  Hence r must be set to _SMFIS_NONE if a new buf is
245 		**  allocated to avoid problem with housekeeping, esp.
246 		**  if the code "break"s out of the loop.
247 		*/
248 
249 		r = _SMFIS_NONE;
250 		if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len,
251 				     ctx->ctx_smfi->xxfi_name)) == NULL &&
252 		    cmd < SMFIC_VALIDCMD)
253 		{
254 			if (ctx->ctx_dbg > 5)
255 				sm_dprintf("[%d] mi_engine: mi_rd_cmd error (%x)\n",
256 					(int) ctx->ctx_id, (int) cmd);
257 
258 			/*
259 			**  eof is currently treated as failure ->
260 			**  abort() instead of close(), otherwise use:
261 			**  if (cmd != SMFIC_EOF)
262 			*/
263 
264 			ret = MI_FAILURE;
265 			break;
266 		}
267 		if (ctx->ctx_dbg > 4)
268 			sm_dprintf("[%d] got cmd '%c' len %d\n",
269 				(int) ctx->ctx_id, cmd, (int) len);
270 		for (i = 0; i < ncmds; i++)
271 		{
272 			if (cmd == cmds[i].cm_cmd)
273 				break;
274 		}
275 		if (i >= ncmds)
276 		{
277 			/* unknown command */
278 			if (ctx->ctx_dbg > 1)
279 				sm_dprintf("[%d] cmd '%c' unknown\n",
280 					(int) ctx->ctx_id, cmd);
281 			ret = MI_FAILURE;
282 			break;
283 		}
284 		if ((f = cmds[i].cm_fct) == NULL)
285 		{
286 			/* stop for now */
287 			if (ctx->ctx_dbg > 1)
288 				sm_dprintf("[%d] cmd '%c' not impl\n",
289 					(int) ctx->ctx_id, cmd);
290 			ret = MI_FAILURE;
291 			break;
292 		}
293 
294 		/* is new state ok? */
295 		newstate = cmds[i].cm_next;
296 		if (ctx->ctx_dbg > 5)
297 			sm_dprintf("[%d] cur %x new %x nextmask %x\n",
298 				(int) ctx->ctx_id,
299 				curstate, newstate, next_states[curstate]);
300 
301 		if (newstate != ST_NONE && !trans_ok(curstate, newstate))
302 		{
303 			if (ctx->ctx_dbg > 1)
304 				sm_dprintf("[%d] abort: cur %d (%x) new %d (%x) next %x\n",
305 					(int) ctx->ctx_id,
306 					curstate, MI_MASK(curstate),
307 					newstate, MI_MASK(newstate),
308 					next_states[curstate]);
309 
310 			/* call abort only if in a mail transaction */
311 			if (fi_abort != NULL && call_abort)
312 				(void) (*fi_abort)(ctx);
313 
314 			/*
315 			**  try to reach the new state from HELO
316 			**  if it can't be reached, ignore the command.
317 			*/
318 
319 			curstate = ST_HELO;
320 			if (!trans_ok(curstate, newstate))
321 			{
322 				if (buf != NULL)
323 				{
324 					free(buf);
325 					buf = NULL;
326 				}
327 				continue;
328 			}
329 		}
330 		arg.a_len = len;
331 		arg.a_buf = buf;
332 		if (newstate != ST_NONE)
333 		{
334 			curstate = newstate;
335 			ctx->ctx_state = curstate;
336 		}
337 		arg.a_idx = cmds[i].cm_macros;
338 
339 		/* call function to deal with command */
340 		r = (*f)(&arg);
341 		if (r != _SMFIS_KEEP && buf != NULL)
342 		{
343 			free(buf);
344 			buf = NULL;
345 		}
346 		if (sendreply(r, sd, &timeout, ctx) != MI_SUCCESS)
347 		{
348 			ret = MI_FAILURE;
349 			break;
350 		}
351 
352 		call_abort = ST_IN_MAIL(curstate);
353 		if (r == SMFIS_ACCEPT)
354 		{
355 			/* accept mail, no further actions taken */
356 			curstate = ST_HELO;
357 		}
358 		else if (r == SMFIS_REJECT || r == SMFIS_DISCARD ||
359 			 r ==  SMFIS_TEMPFAIL)
360 		{
361 			/*
362 			**  further actions depend on current state
363 			**  if the IGNO bit is set: "ignore" the error,
364 			**  i.e., stay in the current state
365 			*/
366 			if (!bitset(CT_IGNO, cmds[i].cm_todo))
367 				curstate = ST_HELO;
368 		}
369 		else if (r == _SMFIS_ABORT)
370 		{
371 			if (ctx->ctx_dbg > 5)
372 				sm_dprintf("[%d] function returned abort\n",
373 					(int) ctx->ctx_id);
374 			ret = MI_FAILURE;
375 			break;
376 		}
377 	} while (!bitset(CT_END, cmds[i].cm_todo));
378 
379 	if (ret != MI_SUCCESS)
380 	{
381 		/* call abort only if in a mail transaction */
382 		if (fi_abort != NULL && call_abort)
383 			(void) (*fi_abort)(ctx);
384 	}
385 
386 	/* close must always be called */
387 	if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL)
388 		(void) (*fi_close)(ctx);
389 	if (r != _SMFIS_KEEP && buf != NULL)
390 		free(buf);
391 	mi_clr_macros(ctx, 0);
392 	return ret;
393 }
394 /*
395 **  SENDREPLY -- send a reply to the MTA
396 **
397 **	Parameters:
398 **		r -- reply code
399 **		sd -- socket descriptor
400 **		timeout_ptr -- (ptr to) timeout to use for sending
401 **		ctx -- context structure
402 **
403 **	Returns:
404 **		MI_SUCCESS/MI_FAILURE
405 */
406 
407 static int
408 sendreply(r, sd, timeout_ptr, ctx)
409 	sfsistat r;
410 	socket_t sd;
411 	struct timeval *timeout_ptr;
412 	SMFICTX_PTR ctx;
413 {
414 	int ret = MI_SUCCESS;
415 
416 	switch (r)
417 	{
418 	  case SMFIS_CONTINUE:
419 		ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 0);
420 		break;
421 	  case SMFIS_TEMPFAIL:
422 	  case SMFIS_REJECT:
423 		if (ctx->ctx_reply != NULL &&
424 		    ((r == SMFIS_TEMPFAIL && *ctx->ctx_reply == '4') ||
425 		     (r == SMFIS_REJECT && *ctx->ctx_reply == '5')))
426 		{
427 			ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_REPLYCODE,
428 					ctx->ctx_reply,
429 					strlen(ctx->ctx_reply) + 1);
430 			free(ctx->ctx_reply);
431 			ctx->ctx_reply = NULL;
432 		}
433 		else
434 		{
435 			ret = mi_wr_cmd(sd, timeout_ptr, r == SMFIS_REJECT ?
436 					SMFIR_REJECT : SMFIR_TEMPFAIL, NULL, 0);
437 		}
438 		break;
439 	  case SMFIS_DISCARD:
440 		ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_DISCARD, NULL, 0);
441 		break;
442 	  case SMFIS_ACCEPT:
443 		ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_ACCEPT, NULL, 0);
444 		break;
445 	  case _SMFIS_OPTIONS:
446 		{
447 			char buf[MILTER_OPTLEN];
448 			mi_int32 v;
449 
450 			v = htonl(ctx->ctx_smfi->xxfi_version);
451 			(void) memcpy(&(buf[0]), (void *) &v, MILTER_LEN_BYTES);
452 			v = htonl(ctx->ctx_smfi->xxfi_flags);
453 			(void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v,
454 				      MILTER_LEN_BYTES);
455 			v = htonl(ctx->ctx_pflags);
456 			(void) memcpy(&(buf[MILTER_LEN_BYTES * 2]), (void *) &v,
457 				      MILTER_LEN_BYTES);
458 			ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG, buf,
459 				       MILTER_OPTLEN);
460 		}
461 		break;
462 	  default:	/* don't send a reply */
463 		break;
464 	}
465 	return ret;
466 }
467 
468 /*
469 **  CLR_MACROS -- clear set of macros starting from a given index
470 **
471 **	Parameters:
472 **		ctx -- context structure
473 **		m -- index from which to clear all macros
474 **
475 **	Returns:
476 **		None.
477 */
478 void
479 mi_clr_macros(ctx, m)
480 	SMFICTX_PTR ctx;
481 	int m;
482 {
483 	int i;
484 
485 	for (i = m; i < MAX_MACROS_ENTRIES; i++)
486 	{
487 		if (ctx->ctx_mac_ptr[i] != NULL)
488 		{
489 			free(ctx->ctx_mac_ptr[i]);
490 			ctx->ctx_mac_ptr[i] = NULL;
491 		}
492 		if (ctx->ctx_mac_buf[i] != NULL)
493 		{
494 			free(ctx->ctx_mac_buf[i]);
495 			ctx->ctx_mac_buf[i] = NULL;
496 		}
497 	}
498 }
499 /*
500 **  ST_OPTIONNEG -- negotiate options
501 **
502 **	Parameters:
503 **		g -- generic argument structure
504 **
505 **	Returns:
506 **		abort/send options/continue
507 */
508 
509 static int
510 st_optionneg(g)
511 	genarg *g;
512 {
513 	mi_int32 i, v;
514 
515 	if (g == NULL || g->a_ctx->ctx_smfi == NULL)
516 		return SMFIS_CONTINUE;
517 	mi_clr_macros(g->a_ctx, g->a_idx + 1);
518 
519 	/* check for minimum length */
520 	if (g->a_len < MILTER_OPTLEN)
521 	{
522 		smi_log(SMI_LOG_ERR,
523 			"%s: st_optionneg[%d]: len too short %d < %d",
524 			g->a_ctx->ctx_smfi->xxfi_name,
525 			(int) g->a_ctx->ctx_id, (int) g->a_len,
526 			MILTER_OPTLEN);
527 		return _SMFIS_ABORT;
528 	}
529 
530 	(void) memcpy((void *) &i, (void *) &(g->a_buf[0]),
531 		      MILTER_LEN_BYTES);
532 	v = ntohl(i);
533 	if (v < g->a_ctx->ctx_smfi->xxfi_version)
534 	{
535 		/* hard failure for now! */
536 		smi_log(SMI_LOG_ERR,
537 			"%s: st_optionneg[%d]: version mismatch MTA: %d < milter: %d",
538 			g->a_ctx->ctx_smfi->xxfi_name,
539 			(int) g->a_ctx->ctx_id, (int) v,
540 			g->a_ctx->ctx_smfi->xxfi_version);
541 		return _SMFIS_ABORT;
542 	}
543 
544 	(void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]),
545 		      MILTER_LEN_BYTES);
546 	v = ntohl(i);
547 
548 	/* no flags? set to default value for V1 actions */
549 	if (v == 0)
550 		v = SMFI_V1_ACTS;
551 	i = g->a_ctx->ctx_smfi->xxfi_flags;
552 	if ((v & i) != i)
553 	{
554 		smi_log(SMI_LOG_ERR,
555 			"%s: st_optionneg[%d]: 0x%x does not fulfill action requirements 0x%x",
556 			g->a_ctx->ctx_smfi->xxfi_name,
557 			(int) g->a_ctx->ctx_id, v, i);
558 		return _SMFIS_ABORT;
559 	}
560 
561 	(void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES * 2]),
562 		      MILTER_LEN_BYTES);
563 	v = ntohl(i);
564 
565 	/* no flags? set to default value for V1 protocol */
566 	if (v == 0)
567 		v = SMFI_V1_PROT;
568 	i = g->a_ctx->ctx_pflags;
569 	if ((v & i) != i)
570 	{
571 		smi_log(SMI_LOG_ERR,
572 			"%s: st_optionneg[%d]: 0x%x does not fulfill protocol requirements 0x%x",
573 			g->a_ctx->ctx_smfi->xxfi_name,
574 			(int) g->a_ctx->ctx_id, v, i);
575 		return _SMFIS_ABORT;
576 	}
577 
578 	return _SMFIS_OPTIONS;
579 }
580 /*
581 **  ST_CONNECTINFO -- receive connection information
582 **
583 **	Parameters:
584 **		g -- generic argument structure
585 **
586 **	Returns:
587 **		continue or filter-specified value
588 */
589 
590 static int
591 st_connectinfo(g)
592 	genarg *g;
593 {
594 	size_t l;
595 	size_t i;
596 	char *s, family;
597 	unsigned short port = 0;
598 	_SOCK_ADDR sockaddr;
599 	sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *));
600 
601 	if (g == NULL)
602 		return _SMFIS_ABORT;
603 	mi_clr_macros(g->a_ctx, g->a_idx + 1);
604 	if (g->a_ctx->ctx_smfi == NULL ||
605 	    (fi_connect = g->a_ctx->ctx_smfi->xxfi_connect) == NULL)
606 		return SMFIS_CONTINUE;
607 
608 	s = g->a_buf;
609 	i = 0;
610 	l = g->a_len;
611 	while (s[i] != '\0' && i <= l)
612 		++i;
613 	if (i + 1 >= l)
614 		return _SMFIS_ABORT;
615 
616 	/* Move past trailing \0 in host string */
617 	i++;
618 	family = s[i++];
619 	(void) memset(&sockaddr, '\0', sizeof sockaddr);
620 	if (family != SMFIA_UNKNOWN)
621 	{
622 		if (i + sizeof port >= l)
623 		{
624 			smi_log(SMI_LOG_ERR,
625 				"%s: connect[%d]: wrong len %d >= %d",
626 				g->a_ctx->ctx_smfi->xxfi_name,
627 				(int) g->a_ctx->ctx_id, (int) i, (int) l);
628 			return _SMFIS_ABORT;
629 		}
630 		(void) memcpy((void *) &port, (void *) (s + i),
631 			      sizeof port);
632 		i += sizeof port;
633 
634 		/* make sure string is terminated */
635 		if (s[l - 1] != '\0')
636 			return _SMFIS_ABORT;
637 # if NETINET
638 		if (family == SMFIA_INET)
639 		{
640 			if (inet_aton(s + i, (struct in_addr *) &sockaddr.sin.sin_addr)
641 			    != 1)
642 			{
643 				smi_log(SMI_LOG_ERR,
644 					"%s: connect[%d]: inet_aton failed",
645 					g->a_ctx->ctx_smfi->xxfi_name,
646 					(int) g->a_ctx->ctx_id);
647 				return _SMFIS_ABORT;
648 			}
649 			sockaddr.sa.sa_family = AF_INET;
650 			if (port > 0)
651 				sockaddr.sin.sin_port = port;
652 		}
653 		else
654 # endif /* NETINET */
655 # if NETINET6
656 		if (family == SMFIA_INET6)
657 		{
658 			if (mi_inet_pton(AF_INET6, s + i,
659 					 &sockaddr.sin6.sin6_addr) != 1)
660 			{
661 				smi_log(SMI_LOG_ERR,
662 					"%s: connect[%d]: mi_inet_pton failed",
663 					g->a_ctx->ctx_smfi->xxfi_name,
664 					(int) g->a_ctx->ctx_id);
665 				return _SMFIS_ABORT;
666 			}
667 			sockaddr.sa.sa_family = AF_INET6;
668 			if (port > 0)
669 				sockaddr.sin6.sin6_port = port;
670 		}
671 		else
672 # endif /* NETINET6 */
673 # if NETUNIX
674 		if (family == SMFIA_UNIX)
675 		{
676 			if (sm_strlcpy(sockaddr.sunix.sun_path, s + i,
677 			    sizeof sockaddr.sunix.sun_path) >=
678 			    sizeof sockaddr.sunix.sun_path)
679 			{
680 				smi_log(SMI_LOG_ERR,
681 					"%s: connect[%d]: path too long",
682 					g->a_ctx->ctx_smfi->xxfi_name,
683 					(int) g->a_ctx->ctx_id);
684 				return _SMFIS_ABORT;
685 			}
686 			sockaddr.sunix.sun_family = AF_UNIX;
687 		}
688 		else
689 # endif /* NETUNIX */
690 		{
691 			smi_log(SMI_LOG_ERR,
692 				"%s: connect[%d]: unknown family %d",
693 				g->a_ctx->ctx_smfi->xxfi_name,
694 				(int) g->a_ctx->ctx_id, family);
695 			return _SMFIS_ABORT;
696 		}
697 	}
698 	return (*fi_connect)(g->a_ctx, g->a_buf,
699 			     family != SMFIA_UNKNOWN ? &sockaddr : NULL);
700 }
701 /*
702 **  ST_EOH -- end of headers
703 **
704 **	Parameters:
705 **		g -- generic argument structure
706 **
707 **	Returns:
708 **		continue or filter-specified value
709 */
710 
711 static int
712 st_eoh(g)
713 	genarg *g;
714 {
715 	sfsistat (*fi_eoh) __P((SMFICTX *));
716 
717 	if (g == NULL)
718 		return _SMFIS_ABORT;
719 	if (g->a_ctx->ctx_smfi != NULL &&
720 	    (fi_eoh = g->a_ctx->ctx_smfi->xxfi_eoh) != NULL)
721 		return (*fi_eoh)(g->a_ctx);
722 	return SMFIS_CONTINUE;
723 }
724 /*
725 **  ST_HELO -- helo/ehlo command
726 **
727 **	Parameters:
728 **		g -- generic argument structure
729 **
730 **	Returns:
731 **		continue or filter-specified value
732 */
733 static int
734 st_helo(g)
735 	genarg *g;
736 {
737 	sfsistat (*fi_helo) __P((SMFICTX *, char *));
738 
739 	if (g == NULL)
740 		return _SMFIS_ABORT;
741 	mi_clr_macros(g->a_ctx, g->a_idx + 1);
742 	if (g->a_ctx->ctx_smfi != NULL &&
743 	    (fi_helo = g->a_ctx->ctx_smfi->xxfi_helo) != NULL)
744 	{
745 		/* paranoia: check for terminating '\0' */
746 		if (g->a_len == 0 || g->a_buf[g->a_len - 1] != '\0')
747 			return MI_FAILURE;
748 		return (*fi_helo)(g->a_ctx, g->a_buf);
749 	}
750 	return SMFIS_CONTINUE;
751 }
752 /*
753 **  ST_HEADER -- header line
754 **
755 **	Parameters:
756 **		g -- generic argument structure
757 **
758 **	Returns:
759 **		continue or filter-specified value
760 */
761 
762 static int
763 st_header(g)
764 	genarg *g;
765 {
766 	char *hf, *hv;
767 	sfsistat (*fi_header) __P((SMFICTX *, char *, char *));
768 
769 	if (g == NULL)
770 		return _SMFIS_ABORT;
771 	if (g->a_ctx->ctx_smfi == NULL ||
772 	    (fi_header = g->a_ctx->ctx_smfi->xxfi_header) == NULL)
773 		return SMFIS_CONTINUE;
774 	if (dec_arg2(g->a_buf, g->a_len, &hf, &hv) == MI_SUCCESS)
775 		return (*fi_header)(g->a_ctx, hf, hv);
776 	else
777 		return _SMFIS_ABORT;
778 }
779 
780 #define ARGV_FCT(lf, rf, idx)					\
781 	char **argv;						\
782 	sfsistat (*lf) __P((SMFICTX *, char **));		\
783 	int r;							\
784 								\
785 	if (g == NULL)						\
786 		return _SMFIS_ABORT;				\
787 	mi_clr_macros(g->a_ctx, g->a_idx + 1);			\
788 	if (g->a_ctx->ctx_smfi == NULL ||			\
789 	    (lf = g->a_ctx->ctx_smfi->rf) == NULL)		\
790 		return SMFIS_CONTINUE;				\
791 	if ((argv = dec_argv(g->a_buf, g->a_len)) == NULL)	\
792 		return _SMFIS_ABORT;				\
793 	r = (*lf)(g->a_ctx, argv);				\
794 	free(argv);						\
795 	return r;
796 
797 /*
798 **  ST_SENDER -- MAIL FROM command
799 **
800 **	Parameters:
801 **		g -- generic argument structure
802 **
803 **	Returns:
804 **		continue or filter-specified value
805 */
806 
807 static int
808 st_sender(g)
809 	genarg *g;
810 {
811 	ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL)
812 }
813 /*
814 **  ST_RCPT -- RCPT TO command
815 **
816 **	Parameters:
817 **		g -- generic argument structure
818 **
819 **	Returns:
820 **		continue or filter-specified value
821 */
822 
823 static int
824 st_rcpt(g)
825 	genarg *g;
826 {
827 	ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT)
828 }
829 /*
830 **  ST_MACROS -- deal with macros received from the MTA
831 **
832 **	Parameters:
833 **		g -- generic argument structure
834 **
835 **	Returns:
836 **		continue/keep
837 **
838 **	Side effects:
839 **		set pointer in macro array to current values.
840 */
841 
842 static int
843 st_macros(g)
844 	genarg *g;
845 {
846 	int i;
847 	char **argv;
848 
849 	if (g == NULL || g->a_len < 1)
850 		return _SMFIS_FAIL;
851 	if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL)
852 		return _SMFIS_FAIL;
853 	switch (g->a_buf[0])
854 	{
855 	  case SMFIC_CONNECT:
856 		i = CI_CONN;
857 		break;
858 	  case SMFIC_HELO:
859 		i = CI_HELO;
860 		break;
861 	  case SMFIC_MAIL:
862 		i = CI_MAIL;
863 		break;
864 	  case SMFIC_RCPT:
865 		i = CI_RCPT;
866 		break;
867 #if _FFR_MILTER_MACROS_EOM
868 	  case SMFIC_BODYEOB:
869 		i = CI_EOM;
870 		break;
871 #endif /* _FFR_MILTER_MACROS_EOM */
872 	  default:
873 		free(argv);
874 		return _SMFIS_FAIL;
875 	}
876 	if (g->a_ctx->ctx_mac_ptr[i] != NULL)
877 		free(g->a_ctx->ctx_mac_ptr[i]);
878 	if (g->a_ctx->ctx_mac_buf[i] != NULL)
879 		free(g->a_ctx->ctx_mac_buf[i]);
880 	g->a_ctx->ctx_mac_ptr[i] = argv;
881 	g->a_ctx->ctx_mac_buf[i] = g->a_buf;
882 	return _SMFIS_KEEP;
883 }
884 /*
885 **  ST_QUIT -- quit command
886 **
887 **	Parameters:
888 **		g -- generic argument structure
889 **
890 **	Returns:
891 **		noreply
892 */
893 
894 /* ARGSUSED */
895 static int
896 st_quit(g)
897 	genarg *g;
898 {
899 	return _SMFIS_NOREPLY;
900 }
901 /*
902 **  ST_BODYCHUNK -- deal with a piece of the mail body
903 **
904 **	Parameters:
905 **		g -- generic argument structure
906 **
907 **	Returns:
908 **		continue or filter-specified value
909 */
910 
911 static int
912 st_bodychunk(g)
913 	genarg *g;
914 {
915 	sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t));
916 
917 	if (g == NULL)
918 		return _SMFIS_ABORT;
919 	if (g->a_ctx->ctx_smfi != NULL &&
920 	    (fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL)
921 		return (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf,
922 				  g->a_len);
923 	return SMFIS_CONTINUE;
924 }
925 /*
926 **  ST_BODYEND -- deal with the last piece of the mail body
927 **
928 **	Parameters:
929 **		g -- generic argument structure
930 **
931 **	Returns:
932 **		continue or filter-specified value
933 **
934 **	Side effects:
935 **		sends a reply for the body part (if non-empty).
936 */
937 
938 static int
939 st_bodyend(g)
940 	genarg *g;
941 {
942 	sfsistat r;
943 	sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t));
944 	sfsistat (*fi_eom) __P((SMFICTX *));
945 
946 	if (g == NULL)
947 		return _SMFIS_ABORT;
948 	r = SMFIS_CONTINUE;
949 	if (g->a_ctx->ctx_smfi != NULL)
950 	{
951 		if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL &&
952 		    g->a_len > 0)
953 		{
954 			socket_t sd;
955 			struct timeval timeout;
956 
957 			timeout.tv_sec = g->a_ctx->ctx_timeout;
958 			timeout.tv_usec = 0;
959 			sd = g->a_ctx->ctx_sd;
960 			r = (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf,
961 				       g->a_len);
962 			if (r != SMFIS_CONTINUE &&
963 			    sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS)
964 				return _SMFIS_ABORT;
965 		}
966 	}
967 	if (r == SMFIS_CONTINUE &&
968 	    (fi_eom = g->a_ctx->ctx_smfi->xxfi_eom) != NULL)
969 		return (*fi_eom)(g->a_ctx);
970 	return r;
971 }
972 /*
973 **  ST_ABORTFCT -- deal with aborts
974 **
975 **	Parameters:
976 **		g -- generic argument structure
977 **
978 **	Returns:
979 **		abort or filter-specified value
980 */
981 
982 static int
983 st_abortfct(g)
984 	genarg *g;
985 {
986 	sfsistat (*fi_abort) __P((SMFICTX *));
987 
988 	if (g == NULL)
989 		return _SMFIS_ABORT;
990 	if (g != NULL && g->a_ctx->ctx_smfi != NULL &&
991 	    (fi_abort = g->a_ctx->ctx_smfi->xxfi_abort) != NULL)
992 		(void) (*fi_abort)(g->a_ctx);
993 	return _SMFIS_NOREPLY;
994 }
995 /*
996 **  TRANS_OK -- is the state transition ok?
997 **
998 **	Parameters:
999 **		old -- old state
1000 **		new -- new state
1001 **
1002 **	Returns:
1003 **		state transition ok
1004 */
1005 
1006 static bool
1007 trans_ok(old, new)
1008 	int old, new;
1009 {
1010 	int s, n;
1011 
1012 	s = old;
1013 	do
1014 	{
1015 		/* is this state transition allowed? */
1016 		if ((MI_MASK(new) & next_states[s]) != 0)
1017 			return true;
1018 
1019 		/*
1020 		**  no: try next state;
1021 		**  this works since the relevant states are ordered
1022 		**  strict sequentially
1023 		*/
1024 
1025 		n = s + 1;
1026 
1027 		/*
1028 		**  can we actually "skip" this state?
1029 		**  see fix_stm() which sets this bit for those
1030 		**  states which the filter program is not interested in
1031 		*/
1032 
1033 		if (bitset(NX_SKIP, next_states[n]))
1034 			s = n;
1035 		else
1036 			return false;
1037 	} while (s <= ST_LAST);
1038 	return false;
1039 }
1040 /*
1041 **  FIX_STM -- add "skip" bits to the state transition table
1042 **
1043 **	Parameters:
1044 **		ctx -- context structure
1045 **
1046 **	Returns:
1047 **		None.
1048 **
1049 **	Side effects:
1050 **		may change state transition table.
1051 */
1052 
1053 static void
1054 fix_stm(ctx)
1055 	SMFICTX_PTR ctx;
1056 {
1057 	unsigned long fl;
1058 
1059 	if (ctx == NULL || ctx->ctx_smfi == NULL)
1060 		return;
1061 	fl = ctx->ctx_pflags;
1062 	if (bitset(SMFIP_NOCONNECT, fl))
1063 		next_states[ST_CONN] |= NX_SKIP;
1064 	if (bitset(SMFIP_NOHELO, fl))
1065 		next_states[ST_HELO] |= NX_SKIP;
1066 	if (bitset(SMFIP_NOMAIL, fl))
1067 		next_states[ST_MAIL] |= NX_SKIP;
1068 	if (bitset(SMFIP_NORCPT, fl))
1069 		next_states[ST_RCPT] |= NX_SKIP;
1070 	if (bitset(SMFIP_NOHDRS, fl))
1071 		next_states[ST_HDRS] |= NX_SKIP;
1072 	if (bitset(SMFIP_NOEOH, fl))
1073 		next_states[ST_EOHS] |= NX_SKIP;
1074 	if (bitset(SMFIP_NOBODY, fl))
1075 		next_states[ST_BODY] |= NX_SKIP;
1076 }
1077 /*
1078 **  DEC_ARGV -- split a buffer into a list of strings, NULL terminated
1079 **
1080 **	Parameters:
1081 **		buf -- buffer with several strings
1082 **		len -- length of buffer
1083 **
1084 **	Returns:
1085 **		array of pointers to the individual strings
1086 */
1087 
1088 static char **
1089 dec_argv(buf, len)
1090 	char *buf;
1091 	size_t len;
1092 {
1093 	char **s;
1094 	size_t i;
1095 	int elem, nelem;
1096 
1097 	nelem = 0;
1098 	for (i = 0; i < len; i++)
1099 	{
1100 		if (buf[i] == '\0')
1101 			++nelem;
1102 	}
1103 	if (nelem == 0)
1104 		return NULL;
1105 
1106 	/* last entry is only for the name */
1107 	s = (char **)malloc((nelem + 1) * (sizeof *s));
1108 	if (s == NULL)
1109 		return NULL;
1110 	s[0] = buf;
1111 	for (i = 0, elem = 0; i < len && elem < nelem; i++)
1112 	{
1113 		if (buf[i] == '\0')
1114 		{
1115 			++elem;
1116 			if (i + 1 >= len)
1117 				s[elem] = NULL;
1118 			else
1119 				s[elem] = &(buf[i + 1]);
1120 		}
1121 	}
1122 
1123 	/* overwrite last entry (already done above, just paranoia) */
1124 	s[elem] = NULL;
1125 	return s;
1126 }
1127 /*
1128 **  DEC_ARG2 -- split a buffer into two strings
1129 **
1130 **	Parameters:
1131 **		buf -- buffer with two strings
1132 **		len -- length of buffer
1133 **		s1,s2 -- pointer to result strings
1134 **
1135 **	Returns:
1136 **		MI_FAILURE/MI_SUCCESS
1137 */
1138 
1139 static int
1140 dec_arg2(buf, len, s1, s2)
1141 	char *buf;
1142 	size_t len;
1143 	char **s1;
1144 	char **s2;
1145 {
1146 	size_t i;
1147 
1148 	/* paranoia: check for terminating '\0' */
1149 	if (len == 0 || buf[len - 1] != '\0')
1150 		return MI_FAILURE;
1151 	*s1 = buf;
1152 	for (i = 1; i < len && buf[i] != '\0'; i++)
1153 		continue;
1154 	if (i >= len - 1)
1155 		return MI_FAILURE;
1156 	*s2 = buf + i + 1;
1157 	return MI_SUCCESS;
1158 }
1159 /*
1160 **  SENDOK -- is it ok for the filter to send stuff to the MTA?
1161 **
1162 **	Parameters:
1163 **		ctx -- context structure
1164 **		flag -- flag to check
1165 **
1166 **	Returns:
1167 **		sending allowed (in current state)
1168 */
1169 
1170 bool
1171 mi_sendok(ctx, flag)
1172 	SMFICTX_PTR ctx;
1173 	int flag;
1174 {
1175 	if (ctx == NULL || ctx->ctx_smfi == NULL)
1176 		return false;
1177 
1178 	/* did the milter request this operation? */
1179 	if (flag != 0 && !bitset(flag, ctx->ctx_smfi->xxfi_flags))
1180 		return false;
1181 
1182 	/* are we in the correct state? It must be "End of Message". */
1183 	return ctx->ctx_state == ST_ENDM;
1184 }
1185