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