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