The first a bug in pax and should be commited to FBSD, too.
[dragonfly.git] / contrib / sendmail / libmilter / engine.c
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.4 2002/12/03 17:27:32 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         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 static int
873 st_quit(g)
874         genarg *g;
875 {
876         return _SMFIS_NOREPLY;
877 }
878 /*
879 **  ST_BODYCHUNK -- deal with a piece of the mail body
880 **
881 **      Parameters:
882 **              g -- generic argument structure
883 **
884 **      Returns:
885 **              continue or filter-specified value
886 */
887
888 static int
889 st_bodychunk(g)
890         genarg *g;
891 {
892         sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t));
893
894         if (g == NULL)
895                 return _SMFIS_ABORT;
896         if (g->a_ctx->ctx_smfi != NULL &&
897             (fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL)
898                 return (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf,
899                                   g->a_len);
900         return SMFIS_CONTINUE;
901 }
902 /*
903 **  ST_BODYEND -- deal with the last piece of the mail body
904 **
905 **      Parameters:
906 **              g -- generic argument structure
907 **
908 **      Returns:
909 **              continue or filter-specified value
910 **
911 **      Side effects:
912 **              sends a reply for the body part (if non-empty).
913 */
914
915 static int
916 st_bodyend(g)
917         genarg *g;
918 {
919         sfsistat r;
920         sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t));
921         sfsistat (*fi_eom) __P((SMFICTX *));
922
923         if (g == NULL)
924                 return _SMFIS_ABORT;
925         r = SMFIS_CONTINUE;
926         if (g->a_ctx->ctx_smfi != NULL)
927         {
928                 if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL &&
929                     g->a_len > 0)
930                 {
931                         socket_t sd;
932                         struct timeval timeout;
933
934                         timeout.tv_sec = g->a_ctx->ctx_timeout;
935                         timeout.tv_usec = 0;
936                         sd = g->a_ctx->ctx_sd;
937                         r = (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf,
938                                        g->a_len);
939                         if (r != SMFIS_CONTINUE &&
940                             sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS)
941                                 return _SMFIS_ABORT;
942                 }
943         }
944         if (r == SMFIS_CONTINUE &&
945             (fi_eom = g->a_ctx->ctx_smfi->xxfi_eom) != NULL)
946                 return (*fi_eom)(g->a_ctx);
947         return r;
948 }
949 /*
950 **  ST_ABORTFCT -- deal with aborts
951 **
952 **      Parameters:
953 **              g -- generic argument structure
954 **
955 **      Returns:
956 **              abort or filter-specified value
957 */
958
959 static int
960 st_abortfct(g)
961         genarg *g;
962 {
963         sfsistat (*fi_abort) __P((SMFICTX *));
964
965         if (g == NULL)
966                 return _SMFIS_ABORT;
967         if (g != NULL && g->a_ctx->ctx_smfi != NULL &&
968             (fi_abort = g->a_ctx->ctx_smfi->xxfi_abort) != NULL)
969                 (void) (*fi_abort)(g->a_ctx);
970         return _SMFIS_NOREPLY;
971 }
972 /*
973 **  TRANS_OK -- is the state transition ok?
974 **
975 **      Parameters:
976 **              old -- old state
977 **              new -- new state
978 **
979 **      Returns:
980 **              state transition ok
981 */
982
983 static bool
984 trans_ok(old, new)
985         int old, new;
986 {
987         int s, n;
988
989         s = old;
990         do
991         {
992                 /* is this state transition allowed? */
993                 if ((MI_MASK(new) & next_states[s]) != 0)
994                         return true;
995
996                 /*
997                 **  no: try next state;
998                 **  this works since the relevant states are ordered
999                 **  strict sequentially
1000                 */
1001
1002                 n = s + 1;
1003
1004                 /*
1005                 **  can we actually "skip" this state?
1006                 **  see fix_stm() which sets this bit for those
1007                 **  states which the filter program is not interested in
1008                 */
1009
1010                 if (bitset(NX_SKIP, next_states[n]))
1011                         s = n;
1012                 else
1013                         return false;
1014         } while (s <= ST_LAST);
1015         return false;
1016 }
1017 /*
1018 **  FIX_STM -- add "skip" bits to the state transition table
1019 **
1020 **      Parameters:
1021 **              ctx -- context structure
1022 **
1023 **      Returns:
1024 **              None.
1025 **
1026 **      Side effects:
1027 **              may change state transition table.
1028 */
1029
1030 static void
1031 fix_stm(ctx)
1032         SMFICTX_PTR ctx;
1033 {
1034         unsigned long fl;
1035
1036         if (ctx == NULL || ctx->ctx_smfi == NULL)
1037                 return;
1038         fl = ctx->ctx_pflags;
1039         if (bitset(SMFIP_NOCONNECT, fl))
1040                 next_states[ST_CONN] |= NX_SKIP;
1041         if (bitset(SMFIP_NOHELO, fl))
1042                 next_states[ST_HELO] |= NX_SKIP;
1043         if (bitset(SMFIP_NOMAIL, fl))
1044                 next_states[ST_MAIL] |= NX_SKIP;
1045         if (bitset(SMFIP_NORCPT, fl))
1046                 next_states[ST_RCPT] |= NX_SKIP;
1047         if (bitset(SMFIP_NOHDRS, fl))
1048                 next_states[ST_HDRS] |= NX_SKIP;
1049         if (bitset(SMFIP_NOEOH, fl))
1050                 next_states[ST_EOHS] |= NX_SKIP;
1051         if (bitset(SMFIP_NOBODY, fl))
1052                 next_states[ST_BODY] |= NX_SKIP;
1053 }
1054 /*
1055 **  DEC_ARGV -- split a buffer into a list of strings, NULL terminated
1056 **
1057 **      Parameters:
1058 **              buf -- buffer with several strings
1059 **              len -- length of buffer
1060 **
1061 **      Returns:
1062 **              array of pointers to the individual strings
1063 */
1064
1065 static char **
1066 dec_argv(buf, len)
1067         char *buf;
1068         size_t len;
1069 {
1070         char **s;
1071         size_t i;
1072         int elem, nelem;
1073
1074         nelem = 0;
1075         for (i = 0; i < len; i++)
1076         {
1077                 if (buf[i] == '\0')
1078                         ++nelem;
1079         }
1080         if (nelem == 0)
1081                 return NULL;
1082
1083         /* last entry is only for the name */
1084         s = (char **)malloc((nelem + 1) * (sizeof *s));
1085         if (s == NULL)
1086                 return NULL;
1087         s[0] = buf;
1088         for (i = 0, elem = 0; i < len && elem < nelem; i++)
1089         {
1090                 if (buf[i] == '\0')
1091                         s[++elem] = &(buf[i + 1]);
1092         }
1093
1094         /* overwrite last entry */
1095         s[elem] = NULL;
1096         return s;
1097 }
1098 /*
1099 **  DEC_ARG2 -- split a buffer into two strings
1100 **
1101 **      Parameters:
1102 **              buf -- buffer with two strings
1103 **              len -- length of buffer
1104 **              s1,s2 -- pointer to result strings
1105 **
1106 **      Returns:
1107 **              MI_FAILURE/MI_SUCCESS
1108 */
1109
1110 static int
1111 dec_arg2(buf, len, s1, s2)
1112         char *buf;
1113         size_t len;
1114         char **s1;
1115         char **s2;
1116 {
1117         size_t i;
1118
1119         *s1 = buf;
1120         for (i = 1; i < len && buf[i] != '\0'; i++)
1121                 continue;
1122         if (i >= len - 1)
1123                 return MI_FAILURE;
1124         *s2 = buf + i + 1;
1125         return MI_SUCCESS;
1126 }
1127 /*
1128 **  SENDOK -- is it ok for the filter to send stuff to the MTA?
1129 **
1130 **      Parameters:
1131 **              ctx -- context structure
1132 **              flag -- flag to check
1133 **
1134 **      Returns:
1135 **              sending allowed (in current state)
1136 */
1137
1138 bool
1139 mi_sendok(ctx, flag)
1140         SMFICTX_PTR ctx;
1141         int flag;
1142 {
1143         if (ctx == NULL || ctx->ctx_smfi == NULL)
1144                 return false;
1145
1146         /* did the milter request this operation? */
1147         if (flag != 0 && !bitset(flag, ctx->ctx_smfi->xxfi_flags))
1148                 return false;
1149
1150         /* are we in the correct state? It must be "End of Message". */
1151         return ctx->ctx_state == ST_ENDM;
1152 }