106f25ae9SGregory Neil Shapiro /* 2af9557fdSGregory Neil Shapiro * Copyright (c) 1999-2004, 2006 Sendmail, Inc. and its suppliers. 306f25ae9SGregory Neil Shapiro * All rights reserved. 406f25ae9SGregory Neil Shapiro * 506f25ae9SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set 606f25ae9SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of 706f25ae9SGregory Neil Shapiro * the sendmail distribution. 806f25ae9SGregory Neil Shapiro * 906f25ae9SGregory Neil Shapiro */ 1006f25ae9SGregory Neil Shapiro 1140266059SGregory Neil Shapiro #include <sm/gen.h> 12af9557fdSGregory Neil Shapiro SM_RCSID("@(#)$Id: engine.c,v 8.121 2006/04/18 21:01:46 ca Exp $") 1306f25ae9SGregory Neil Shapiro 1406f25ae9SGregory Neil Shapiro #include "libmilter.h" 1506f25ae9SGregory Neil Shapiro 1606f25ae9SGregory Neil Shapiro #if NETINET || NETINET6 1706f25ae9SGregory Neil Shapiro # include <arpa/inet.h> 1806f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */ 1906f25ae9SGregory Neil Shapiro 2006f25ae9SGregory Neil Shapiro /* generic argument for functions in the command table */ 2106f25ae9SGregory Neil Shapiro struct arg_struct 2206f25ae9SGregory Neil Shapiro { 2306f25ae9SGregory Neil Shapiro size_t a_len; /* length of buffer */ 2406f25ae9SGregory Neil Shapiro char *a_buf; /* argument string */ 2506f25ae9SGregory Neil Shapiro int a_idx; /* index for macro array */ 2606f25ae9SGregory Neil Shapiro SMFICTX_PTR a_ctx; /* context */ 2706f25ae9SGregory Neil Shapiro }; 2806f25ae9SGregory Neil Shapiro 2906f25ae9SGregory Neil Shapiro typedef struct arg_struct genarg; 3006f25ae9SGregory Neil Shapiro 3106f25ae9SGregory Neil Shapiro /* structure for commands received from MTA */ 3206f25ae9SGregory Neil Shapiro struct cmdfct_t 3306f25ae9SGregory Neil Shapiro { 3406f25ae9SGregory Neil Shapiro char cm_cmd; /* command */ 3506f25ae9SGregory Neil Shapiro int cm_argt; /* type of arguments expected */ 3606f25ae9SGregory Neil Shapiro int cm_next; /* next state */ 3706f25ae9SGregory Neil Shapiro int cm_todo; /* what to do next */ 3806f25ae9SGregory Neil Shapiro int cm_macros; /* index for macros */ 3906f25ae9SGregory Neil Shapiro int (*cm_fct) __P((genarg *)); /* function to execute */ 4006f25ae9SGregory Neil Shapiro }; 4106f25ae9SGregory Neil Shapiro 4206f25ae9SGregory Neil Shapiro typedef struct cmdfct_t cmdfct; 4306f25ae9SGregory Neil Shapiro 4406f25ae9SGregory Neil Shapiro /* possible values for cm_argt */ 4506f25ae9SGregory Neil Shapiro #define CM_ARG0 0 /* no args */ 4606f25ae9SGregory Neil Shapiro #define CM_ARG1 1 /* one arg (string) */ 4706f25ae9SGregory Neil Shapiro #define CM_ARG2 2 /* two args (strings) */ 4806f25ae9SGregory Neil Shapiro #define CM_ARGA 4 /* one string and _SOCK_ADDR */ 4906f25ae9SGregory Neil Shapiro #define CM_ARGO 5 /* two integers */ 5006f25ae9SGregory Neil Shapiro #define CM_ARGV 8 /* \0 separated list of args, NULL-terminated */ 5106f25ae9SGregory Neil Shapiro #define CM_ARGN 9 /* \0 separated list of args (strings) */ 5206f25ae9SGregory Neil Shapiro 5306f25ae9SGregory Neil Shapiro /* possible values for cm_todo */ 5406f25ae9SGregory Neil Shapiro #define CT_CONT 0x0000 /* continue reading commands */ 5506f25ae9SGregory Neil Shapiro #define CT_IGNO 0x0001 /* continue even when error */ 5606f25ae9SGregory Neil Shapiro 5706f25ae9SGregory Neil Shapiro /* not needed right now, done via return code instead */ 5806f25ae9SGregory Neil Shapiro #define CT_KEEP 0x0004 /* keep buffer (contains symbols) */ 5906f25ae9SGregory Neil Shapiro #define CT_END 0x0008 /* start replying */ 6006f25ae9SGregory Neil Shapiro 6106f25ae9SGregory Neil Shapiro /* index in macro array: macros only for these commands */ 6206f25ae9SGregory Neil Shapiro #define CI_NONE (-1) 6306f25ae9SGregory Neil Shapiro #define CI_CONN 0 6406f25ae9SGregory Neil Shapiro #define CI_HELO 1 6506f25ae9SGregory Neil Shapiro #define CI_MAIL 2 6606f25ae9SGregory Neil Shapiro #define CI_RCPT 3 67323f6dcbSGregory Neil Shapiro #define CI_EOM 4 68323f6dcbSGregory Neil Shapiro #if CI_EOM >= MAX_MACROS_ENTRIES 69323f6dcbSGregory Neil Shapiro ERROR: do not compile with CI_EOM >= MAX_MACROS_ENTRIES 70323f6dcbSGregory Neil Shapiro #endif 7106f25ae9SGregory Neil Shapiro 7206f25ae9SGregory Neil Shapiro /* function prototypes */ 7306f25ae9SGregory Neil Shapiro static int st_abortfct __P((genarg *)); 7406f25ae9SGregory Neil Shapiro static int st_macros __P((genarg *)); 7506f25ae9SGregory Neil Shapiro static int st_optionneg __P((genarg *)); 7606f25ae9SGregory Neil Shapiro static int st_bodychunk __P((genarg *)); 7706f25ae9SGregory Neil Shapiro static int st_connectinfo __P((genarg *)); 7806f25ae9SGregory Neil Shapiro static int st_bodyend __P((genarg *)); 7906f25ae9SGregory Neil Shapiro static int st_helo __P((genarg *)); 8006f25ae9SGregory Neil Shapiro static int st_header __P((genarg *)); 8106f25ae9SGregory Neil Shapiro static int st_sender __P((genarg *)); 8206f25ae9SGregory Neil Shapiro static int st_rcpt __P((genarg *)); 83e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 2 84e92d3f3fSGregory Neil Shapiro static int st_unknown __P((genarg *)); 85e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 2 */ 86e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 3 87e92d3f3fSGregory Neil Shapiro static int st_data __P((genarg *)); 88e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 3 */ 8906f25ae9SGregory Neil Shapiro static int st_eoh __P((genarg *)); 9006f25ae9SGregory Neil Shapiro static int st_quit __P((genarg *)); 9106f25ae9SGregory Neil Shapiro static int sendreply __P((sfsistat, socket_t, struct timeval *, SMFICTX_PTR)); 9206f25ae9SGregory Neil Shapiro static void fix_stm __P((SMFICTX_PTR)); 9306f25ae9SGregory Neil Shapiro static bool trans_ok __P((int, int)); 9406f25ae9SGregory Neil Shapiro static char **dec_argv __P((char *, size_t)); 9506f25ae9SGregory Neil Shapiro static int dec_arg2 __P((char *, size_t, char **, char **)); 9606f25ae9SGregory Neil Shapiro 9706f25ae9SGregory Neil Shapiro /* states */ 9806f25ae9SGregory Neil Shapiro #define ST_NONE (-1) 9906f25ae9SGregory Neil Shapiro #define ST_INIT 0 /* initial state */ 10006f25ae9SGregory Neil Shapiro #define ST_OPTS 1 /* option negotiation */ 10106f25ae9SGregory Neil Shapiro #define ST_CONN 2 /* connection info */ 10206f25ae9SGregory Neil Shapiro #define ST_HELO 3 /* helo */ 10306f25ae9SGregory Neil Shapiro #define ST_MAIL 4 /* mail from */ 10406f25ae9SGregory Neil Shapiro #define ST_RCPT 5 /* rcpt to */ 105e92d3f3fSGregory Neil Shapiro #define ST_DATA 6 /* data */ 106e92d3f3fSGregory Neil Shapiro #define ST_HDRS 7 /* headers */ 107e92d3f3fSGregory Neil Shapiro #define ST_EOHS 8 /* end of headers */ 108e92d3f3fSGregory Neil Shapiro #define ST_BODY 9 /* body */ 109e92d3f3fSGregory Neil Shapiro #define ST_ENDM 10 /* end of message */ 110e92d3f3fSGregory Neil Shapiro #define ST_QUIT 11 /* quit */ 111e92d3f3fSGregory Neil Shapiro #define ST_ABRT 12 /* abort */ 112e92d3f3fSGregory Neil Shapiro #define ST_UNKN 13 /* unknown SMTP command */ 113e92d3f3fSGregory Neil Shapiro #define ST_LAST ST_UNKN /* last valid state */ 11406f25ae9SGregory Neil Shapiro #define ST_SKIP 15 /* not a state but required for the state table */ 11506f25ae9SGregory Neil Shapiro 11606f25ae9SGregory Neil Shapiro /* in a mail transaction? must be before eom according to spec. */ 11706f25ae9SGregory Neil Shapiro #define ST_IN_MAIL(st) ((st) >= ST_MAIL && (st) < ST_ENDM) 11806f25ae9SGregory Neil Shapiro 11906f25ae9SGregory Neil Shapiro /* 12006f25ae9SGregory Neil Shapiro ** set of next states 12106f25ae9SGregory Neil Shapiro ** each state (ST_*) corresponds to bit in an int value (1 << state) 12206f25ae9SGregory Neil Shapiro ** each state has a set of allowed transitions ('or' of bits of states) 12306f25ae9SGregory Neil Shapiro ** so a state transition is valid if the mask of the next state 12406f25ae9SGregory Neil Shapiro ** is set in the NX_* value 12506f25ae9SGregory Neil Shapiro ** this function is coded in trans_ok(), see below. 12606f25ae9SGregory Neil Shapiro */ 12740266059SGregory Neil Shapiro 12813bd1963SGregory Neil Shapiro #define MI_MASK(x) (0x0001 << (x)) /* generate a bit "mask" for a state */ 12913bd1963SGregory Neil Shapiro #define NX_INIT (MI_MASK(ST_OPTS)) 130e92d3f3fSGregory Neil Shapiro #define NX_OPTS (MI_MASK(ST_CONN) | MI_MASK(ST_UNKN)) 131e92d3f3fSGregory Neil Shapiro #define NX_CONN (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN)) 132e92d3f3fSGregory Neil Shapiro #define NX_HELO (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN)) 133e92d3f3fSGregory Neil Shapiro #define NX_MAIL (MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | MI_MASK(ST_UNKN)) 134e92d3f3fSGregory Neil Shapiro #define NX_RCPT (MI_MASK(ST_HDRS) | MI_MASK(ST_EOHS) | MI_MASK(ST_DATA) | \ 13513bd1963SGregory Neil Shapiro MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | \ 136e92d3f3fSGregory Neil Shapiro MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | MI_MASK(ST_UNKN)) 137e92d3f3fSGregory Neil Shapiro #define NX_DATA (MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT)) 13813bd1963SGregory Neil Shapiro #define NX_HDRS (MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT)) 13913bd1963SGregory Neil Shapiro #define NX_EOHS (MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | MI_MASK(ST_ABRT)) 14013bd1963SGregory Neil Shapiro #define NX_BODY (MI_MASK(ST_ENDM) | MI_MASK(ST_BODY) | MI_MASK(ST_ABRT)) 141e92d3f3fSGregory Neil Shapiro #define NX_ENDM (MI_MASK(ST_QUIT) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN)) 14206f25ae9SGregory Neil Shapiro #define NX_QUIT 0 14306f25ae9SGregory Neil Shapiro #define NX_ABRT 0 144e92d3f3fSGregory Neil Shapiro #define NX_UNKN (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | \ 145e92d3f3fSGregory Neil Shapiro MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | \ 146e92d3f3fSGregory Neil Shapiro MI_MASK(ST_DATA) | \ 147e92d3f3fSGregory Neil Shapiro MI_MASK(ST_BODY) | MI_MASK(ST_UNKN) | \ 148e92d3f3fSGregory Neil Shapiro MI_MASK(ST_ABRT) | MI_MASK(ST_QUIT)) 14913bd1963SGregory Neil Shapiro #define NX_SKIP MI_MASK(ST_SKIP) 15006f25ae9SGregory Neil Shapiro 15106f25ae9SGregory Neil Shapiro static int next_states[] = 15206f25ae9SGregory Neil Shapiro { 15306f25ae9SGregory Neil Shapiro NX_INIT, 15406f25ae9SGregory Neil Shapiro NX_OPTS, 15506f25ae9SGregory Neil Shapiro NX_CONN, 15606f25ae9SGregory Neil Shapiro NX_HELO, 15706f25ae9SGregory Neil Shapiro NX_MAIL, 15806f25ae9SGregory Neil Shapiro NX_RCPT, 159e92d3f3fSGregory Neil Shapiro NX_DATA, 16006f25ae9SGregory Neil Shapiro NX_HDRS, 16106f25ae9SGregory Neil Shapiro NX_EOHS, 16206f25ae9SGregory Neil Shapiro NX_BODY, 16306f25ae9SGregory Neil Shapiro NX_ENDM, 16406f25ae9SGregory Neil Shapiro NX_QUIT, 165e92d3f3fSGregory Neil Shapiro NX_ABRT, 166e92d3f3fSGregory Neil Shapiro NX_UNKN 16706f25ae9SGregory Neil Shapiro }; 16806f25ae9SGregory Neil Shapiro 169af9557fdSGregory Neil Shapiro #define SIZE_NEXT_STATES (sizeof(next_states) / sizeof(next_states[0])) 170af9557fdSGregory Neil Shapiro 17106f25ae9SGregory Neil Shapiro /* commands received by milter */ 17206f25ae9SGregory Neil Shapiro static cmdfct cmds[] = 17306f25ae9SGregory Neil Shapiro { 17406f25ae9SGregory Neil Shapiro {SMFIC_ABORT, CM_ARG0, ST_ABRT, CT_CONT, CI_NONE, st_abortfct }, 17506f25ae9SGregory Neil Shapiro {SMFIC_MACRO, CM_ARGV, ST_NONE, CT_KEEP, CI_NONE, st_macros }, 17606f25ae9SGregory Neil Shapiro {SMFIC_BODY, CM_ARG1, ST_BODY, CT_CONT, CI_NONE, st_bodychunk }, 17706f25ae9SGregory Neil Shapiro {SMFIC_CONNECT, CM_ARG2, ST_CONN, CT_CONT, CI_CONN, st_connectinfo }, 178323f6dcbSGregory Neil Shapiro {SMFIC_BODYEOB, CM_ARG1, ST_ENDM, CT_CONT, CI_EOM, st_bodyend }, 17906f25ae9SGregory Neil Shapiro {SMFIC_HELO, CM_ARG1, ST_HELO, CT_CONT, CI_HELO, st_helo }, 18006f25ae9SGregory Neil Shapiro {SMFIC_HEADER, CM_ARG2, ST_HDRS, CT_CONT, CI_NONE, st_header }, 18106f25ae9SGregory Neil Shapiro {SMFIC_MAIL, CM_ARGV, ST_MAIL, CT_CONT, CI_MAIL, st_sender }, 18206f25ae9SGregory Neil Shapiro {SMFIC_OPTNEG, CM_ARGO, ST_OPTS, CT_CONT, CI_NONE, st_optionneg }, 18306f25ae9SGregory Neil Shapiro {SMFIC_EOH, CM_ARG0, ST_EOHS, CT_CONT, CI_NONE, st_eoh }, 18406f25ae9SGregory Neil Shapiro {SMFIC_QUIT, CM_ARG0, ST_QUIT, CT_END, CI_NONE, st_quit }, 185e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 3 186e92d3f3fSGregory Neil Shapiro {SMFIC_DATA, CM_ARG0, ST_DATA, CT_CONT, CI_NONE, st_data }, 187e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 3 */ 18806f25ae9SGregory Neil Shapiro {SMFIC_RCPT, CM_ARGV, ST_RCPT, CT_IGNO, CI_RCPT, st_rcpt } 189e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 2 190e92d3f3fSGregory Neil Shapiro ,{SMFIC_UNKNOWN,CM_ARG1, ST_UNKN, CT_IGNO, CI_NONE, st_unknown } 191e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 2 */ 19206f25ae9SGregory Neil Shapiro }; 19306f25ae9SGregory Neil Shapiro 19406f25ae9SGregory Neil Shapiro /* additional (internal) reply codes */ 19506f25ae9SGregory Neil Shapiro #define _SMFIS_KEEP 20 19606f25ae9SGregory Neil Shapiro #define _SMFIS_ABORT 21 19706f25ae9SGregory Neil Shapiro #define _SMFIS_OPTIONS 22 19806f25ae9SGregory Neil Shapiro #define _SMFIS_NOREPLY 23 19906f25ae9SGregory Neil Shapiro #define _SMFIS_FAIL (-1) 20040266059SGregory Neil Shapiro #define _SMFIS_NONE (-2) 20106f25ae9SGregory Neil Shapiro 20240266059SGregory Neil Shapiro /* 20306f25ae9SGregory Neil Shapiro ** MI_ENGINE -- receive commands and process them 20406f25ae9SGregory Neil Shapiro ** 20506f25ae9SGregory Neil Shapiro ** Parameters: 20606f25ae9SGregory Neil Shapiro ** ctx -- context structure 20706f25ae9SGregory Neil Shapiro ** 20806f25ae9SGregory Neil Shapiro ** Returns: 20906f25ae9SGregory Neil Shapiro ** MI_FAILURE/MI_SUCCESS 21006f25ae9SGregory Neil Shapiro */ 21106f25ae9SGregory Neil Shapiro int 21206f25ae9SGregory Neil Shapiro mi_engine(ctx) 21306f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 21406f25ae9SGregory Neil Shapiro { 21506f25ae9SGregory Neil Shapiro size_t len; 21606f25ae9SGregory Neil Shapiro int i; 21706f25ae9SGregory Neil Shapiro socket_t sd; 21806f25ae9SGregory Neil Shapiro int ret = MI_SUCCESS; 21906f25ae9SGregory Neil Shapiro int ncmds = sizeof(cmds) / sizeof(cmdfct); 22006f25ae9SGregory Neil Shapiro int curstate = ST_INIT; 22106f25ae9SGregory Neil Shapiro int newstate; 22206f25ae9SGregory Neil Shapiro bool call_abort; 22306f25ae9SGregory Neil Shapiro sfsistat r; 22406f25ae9SGregory Neil Shapiro char cmd; 22506f25ae9SGregory Neil Shapiro char *buf = NULL; 22606f25ae9SGregory Neil Shapiro genarg arg; 22706f25ae9SGregory Neil Shapiro struct timeval timeout; 22806f25ae9SGregory Neil Shapiro int (*f) __P((genarg *)); 22906f25ae9SGregory Neil Shapiro sfsistat (*fi_abort) __P((SMFICTX *)); 23006f25ae9SGregory Neil Shapiro sfsistat (*fi_close) __P((SMFICTX *)); 23106f25ae9SGregory Neil Shapiro 23206f25ae9SGregory Neil Shapiro arg.a_ctx = ctx; 23306f25ae9SGregory Neil Shapiro sd = ctx->ctx_sd; 23406f25ae9SGregory Neil Shapiro fi_abort = ctx->ctx_smfi->xxfi_abort; 23506f25ae9SGregory Neil Shapiro mi_clr_macros(ctx, 0); 23606f25ae9SGregory Neil Shapiro fix_stm(ctx); 23740266059SGregory Neil Shapiro r = _SMFIS_NONE; 23842e5d165SGregory Neil Shapiro do 23942e5d165SGregory Neil Shapiro { 24006f25ae9SGregory Neil Shapiro /* call abort only if in a mail transaction */ 24106f25ae9SGregory Neil Shapiro call_abort = ST_IN_MAIL(curstate); 24206f25ae9SGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout; 24306f25ae9SGregory Neil Shapiro timeout.tv_usec = 0; 24406f25ae9SGregory Neil Shapiro if (mi_stop() == MILTER_ABRT) 24506f25ae9SGregory Neil Shapiro { 24606f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 3) 24740266059SGregory Neil Shapiro sm_dprintf("[%d] milter_abort\n", 24806f25ae9SGregory Neil Shapiro (int) ctx->ctx_id); 24906f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 25006f25ae9SGregory Neil Shapiro break; 25106f25ae9SGregory Neil Shapiro } 25240266059SGregory Neil Shapiro 25340266059SGregory Neil Shapiro /* 25440266059SGregory Neil Shapiro ** Notice: buf is allocated by mi_rd_cmd() and it will 25540266059SGregory Neil Shapiro ** usually be free()d after it has been used in f(). 25640266059SGregory Neil Shapiro ** However, if the function returns _SMFIS_KEEP then buf 25740266059SGregory Neil Shapiro ** contains macros and will not be free()d. 25840266059SGregory Neil Shapiro ** Hence r must be set to _SMFIS_NONE if a new buf is 25940266059SGregory Neil Shapiro ** allocated to avoid problem with housekeeping, esp. 26040266059SGregory Neil Shapiro ** if the code "break"s out of the loop. 26140266059SGregory Neil Shapiro */ 26240266059SGregory Neil Shapiro 26340266059SGregory Neil Shapiro r = _SMFIS_NONE; 26406f25ae9SGregory Neil Shapiro if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len, 26506f25ae9SGregory Neil Shapiro ctx->ctx_smfi->xxfi_name)) == NULL && 26606f25ae9SGregory Neil Shapiro cmd < SMFIC_VALIDCMD) 26706f25ae9SGregory Neil Shapiro { 26806f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 5) 26940266059SGregory Neil Shapiro sm_dprintf("[%d] mi_engine: mi_rd_cmd error (%x)\n", 27006f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, (int) cmd); 27106f25ae9SGregory Neil Shapiro 27206f25ae9SGregory Neil Shapiro /* 27306f25ae9SGregory Neil Shapiro ** eof is currently treated as failure -> 27406f25ae9SGregory Neil Shapiro ** abort() instead of close(), otherwise use: 27506f25ae9SGregory Neil Shapiro ** if (cmd != SMFIC_EOF) 27606f25ae9SGregory Neil Shapiro */ 27706f25ae9SGregory Neil Shapiro 27806f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 27906f25ae9SGregory Neil Shapiro break; 28006f25ae9SGregory Neil Shapiro } 28106f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 4) 28240266059SGregory Neil Shapiro sm_dprintf("[%d] got cmd '%c' len %d\n", 28313bd1963SGregory Neil Shapiro (int) ctx->ctx_id, cmd, (int) len); 28406f25ae9SGregory Neil Shapiro for (i = 0; i < ncmds; i++) 28506f25ae9SGregory Neil Shapiro { 28606f25ae9SGregory Neil Shapiro if (cmd == cmds[i].cm_cmd) 28706f25ae9SGregory Neil Shapiro break; 28806f25ae9SGregory Neil Shapiro } 28906f25ae9SGregory Neil Shapiro if (i >= ncmds) 29006f25ae9SGregory Neil Shapiro { 29106f25ae9SGregory Neil Shapiro /* unknown command */ 29206f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 1) 29340266059SGregory Neil Shapiro sm_dprintf("[%d] cmd '%c' unknown\n", 29406f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, cmd); 29506f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 29606f25ae9SGregory Neil Shapiro break; 29706f25ae9SGregory Neil Shapiro } 29806f25ae9SGregory Neil Shapiro if ((f = cmds[i].cm_fct) == NULL) 29906f25ae9SGregory Neil Shapiro { 30006f25ae9SGregory Neil Shapiro /* stop for now */ 30106f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 1) 30240266059SGregory Neil Shapiro sm_dprintf("[%d] cmd '%c' not impl\n", 30306f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, cmd); 30406f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 30506f25ae9SGregory Neil Shapiro break; 30606f25ae9SGregory Neil Shapiro } 30706f25ae9SGregory Neil Shapiro 30806f25ae9SGregory Neil Shapiro /* is new state ok? */ 30906f25ae9SGregory Neil Shapiro newstate = cmds[i].cm_next; 31006f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 5) 31140266059SGregory Neil Shapiro sm_dprintf("[%d] cur %x new %x nextmask %x\n", 31206f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, 31306f25ae9SGregory Neil Shapiro curstate, newstate, next_states[curstate]); 31406f25ae9SGregory Neil Shapiro 31506f25ae9SGregory Neil Shapiro if (newstate != ST_NONE && !trans_ok(curstate, newstate)) 31606f25ae9SGregory Neil Shapiro { 31706f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 1) 31840266059SGregory Neil Shapiro sm_dprintf("[%d] abort: cur %d (%x) new %d (%x) next %x\n", 31906f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, 32013bd1963SGregory Neil Shapiro curstate, MI_MASK(curstate), 32113bd1963SGregory Neil Shapiro newstate, MI_MASK(newstate), 32206f25ae9SGregory Neil Shapiro next_states[curstate]); 32306f25ae9SGregory Neil Shapiro 32406f25ae9SGregory Neil Shapiro /* call abort only if in a mail transaction */ 32506f25ae9SGregory Neil Shapiro if (fi_abort != NULL && call_abort) 32606f25ae9SGregory Neil Shapiro (void) (*fi_abort)(ctx); 32706f25ae9SGregory Neil Shapiro 32806f25ae9SGregory Neil Shapiro /* 32906f25ae9SGregory Neil Shapiro ** try to reach the new state from HELO 33006f25ae9SGregory Neil Shapiro ** if it can't be reached, ignore the command. 33106f25ae9SGregory Neil Shapiro */ 33206f25ae9SGregory Neil Shapiro 33306f25ae9SGregory Neil Shapiro curstate = ST_HELO; 33406f25ae9SGregory Neil Shapiro if (!trans_ok(curstate, newstate)) 33540266059SGregory Neil Shapiro { 336959366dcSGregory Neil Shapiro if (buf != NULL) 337959366dcSGregory Neil Shapiro { 33840266059SGregory Neil Shapiro free(buf); 33940266059SGregory Neil Shapiro buf = NULL; 340959366dcSGregory Neil Shapiro } 34106f25ae9SGregory Neil Shapiro continue; 34206f25ae9SGregory Neil Shapiro } 34340266059SGregory Neil Shapiro } 34406f25ae9SGregory Neil Shapiro arg.a_len = len; 34506f25ae9SGregory Neil Shapiro arg.a_buf = buf; 34606f25ae9SGregory Neil Shapiro if (newstate != ST_NONE) 34706f25ae9SGregory Neil Shapiro { 34806f25ae9SGregory Neil Shapiro curstate = newstate; 34906f25ae9SGregory Neil Shapiro ctx->ctx_state = curstate; 35006f25ae9SGregory Neil Shapiro } 35106f25ae9SGregory Neil Shapiro arg.a_idx = cmds[i].cm_macros; 352b6bacd31SGregory Neil Shapiro call_abort = ST_IN_MAIL(curstate); 35306f25ae9SGregory Neil Shapiro 35406f25ae9SGregory Neil Shapiro /* call function to deal with command */ 35506f25ae9SGregory Neil Shapiro r = (*f)(&arg); 35606f25ae9SGregory Neil Shapiro if (r != _SMFIS_KEEP && buf != NULL) 35706f25ae9SGregory Neil Shapiro { 35806f25ae9SGregory Neil Shapiro free(buf); 35906f25ae9SGregory Neil Shapiro buf = NULL; 36006f25ae9SGregory Neil Shapiro } 36106f25ae9SGregory Neil Shapiro if (sendreply(r, sd, &timeout, ctx) != MI_SUCCESS) 36206f25ae9SGregory Neil Shapiro { 36306f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 36406f25ae9SGregory Neil Shapiro break; 36506f25ae9SGregory Neil Shapiro } 36606f25ae9SGregory Neil Shapiro 36706f25ae9SGregory Neil Shapiro if (r == SMFIS_ACCEPT) 36806f25ae9SGregory Neil Shapiro { 36906f25ae9SGregory Neil Shapiro /* accept mail, no further actions taken */ 37006f25ae9SGregory Neil Shapiro curstate = ST_HELO; 37106f25ae9SGregory Neil Shapiro } 37206f25ae9SGregory Neil Shapiro else if (r == SMFIS_REJECT || r == SMFIS_DISCARD || 37306f25ae9SGregory Neil Shapiro r == SMFIS_TEMPFAIL) 37406f25ae9SGregory Neil Shapiro { 37506f25ae9SGregory Neil Shapiro /* 37606f25ae9SGregory Neil Shapiro ** further actions depend on current state 37706f25ae9SGregory Neil Shapiro ** if the IGNO bit is set: "ignore" the error, 37806f25ae9SGregory Neil Shapiro ** i.e., stay in the current state 37906f25ae9SGregory Neil Shapiro */ 38006f25ae9SGregory Neil Shapiro if (!bitset(CT_IGNO, cmds[i].cm_todo)) 38106f25ae9SGregory Neil Shapiro curstate = ST_HELO; 38206f25ae9SGregory Neil Shapiro } 38306f25ae9SGregory Neil Shapiro else if (r == _SMFIS_ABORT) 38406f25ae9SGregory Neil Shapiro { 38506f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 5) 38640266059SGregory Neil Shapiro sm_dprintf("[%d] function returned abort\n", 38706f25ae9SGregory Neil Shapiro (int) ctx->ctx_id); 38806f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 38906f25ae9SGregory Neil Shapiro break; 39006f25ae9SGregory Neil Shapiro } 39106f25ae9SGregory Neil Shapiro } while (!bitset(CT_END, cmds[i].cm_todo)); 39206f25ae9SGregory Neil Shapiro 39306f25ae9SGregory Neil Shapiro if (ret != MI_SUCCESS) 39406f25ae9SGregory Neil Shapiro { 39506f25ae9SGregory Neil Shapiro /* call abort only if in a mail transaction */ 39606f25ae9SGregory Neil Shapiro if (fi_abort != NULL && call_abort) 39706f25ae9SGregory Neil Shapiro (void) (*fi_abort)(ctx); 39806f25ae9SGregory Neil Shapiro } 39906f25ae9SGregory Neil Shapiro 40006f25ae9SGregory Neil Shapiro /* close must always be called */ 40106f25ae9SGregory Neil Shapiro if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) 40206f25ae9SGregory Neil Shapiro (void) (*fi_close)(ctx); 40340266059SGregory Neil Shapiro if (r != _SMFIS_KEEP && buf != NULL) 40406f25ae9SGregory Neil Shapiro free(buf); 40506f25ae9SGregory Neil Shapiro mi_clr_macros(ctx, 0); 40606f25ae9SGregory Neil Shapiro return ret; 40706f25ae9SGregory Neil Shapiro } 40840266059SGregory Neil Shapiro /* 40906f25ae9SGregory Neil Shapiro ** SENDREPLY -- send a reply to the MTA 41006f25ae9SGregory Neil Shapiro ** 41106f25ae9SGregory Neil Shapiro ** Parameters: 41206f25ae9SGregory Neil Shapiro ** r -- reply code 41306f25ae9SGregory Neil Shapiro ** sd -- socket descriptor 41406f25ae9SGregory Neil Shapiro ** timeout_ptr -- (ptr to) timeout to use for sending 41506f25ae9SGregory Neil Shapiro ** ctx -- context structure 41606f25ae9SGregory Neil Shapiro ** 41706f25ae9SGregory Neil Shapiro ** Returns: 41806f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE 41906f25ae9SGregory Neil Shapiro */ 42006f25ae9SGregory Neil Shapiro 42106f25ae9SGregory Neil Shapiro static int 42206f25ae9SGregory Neil Shapiro sendreply(r, sd, timeout_ptr, ctx) 42306f25ae9SGregory Neil Shapiro sfsistat r; 42406f25ae9SGregory Neil Shapiro socket_t sd; 42506f25ae9SGregory Neil Shapiro struct timeval *timeout_ptr; 42606f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 42706f25ae9SGregory Neil Shapiro { 42806f25ae9SGregory Neil Shapiro int ret = MI_SUCCESS; 42906f25ae9SGregory Neil Shapiro 43006f25ae9SGregory Neil Shapiro switch (r) 43106f25ae9SGregory Neil Shapiro { 43206f25ae9SGregory Neil Shapiro case SMFIS_CONTINUE: 43306f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 0); 43406f25ae9SGregory Neil Shapiro break; 43506f25ae9SGregory Neil Shapiro case SMFIS_TEMPFAIL: 43606f25ae9SGregory Neil Shapiro case SMFIS_REJECT: 437605302a5SGregory Neil Shapiro if (ctx->ctx_reply != NULL && 438605302a5SGregory Neil Shapiro ((r == SMFIS_TEMPFAIL && *ctx->ctx_reply == '4') || 439605302a5SGregory Neil Shapiro (r == SMFIS_REJECT && *ctx->ctx_reply == '5'))) 44006f25ae9SGregory Neil Shapiro { 44106f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_REPLYCODE, 44206f25ae9SGregory Neil Shapiro ctx->ctx_reply, 44306f25ae9SGregory Neil Shapiro strlen(ctx->ctx_reply) + 1); 44406f25ae9SGregory Neil Shapiro free(ctx->ctx_reply); 44506f25ae9SGregory Neil Shapiro ctx->ctx_reply = NULL; 44606f25ae9SGregory Neil Shapiro } 44706f25ae9SGregory Neil Shapiro else 44806f25ae9SGregory Neil Shapiro { 44906f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, r == SMFIS_REJECT ? 45006f25ae9SGregory Neil Shapiro SMFIR_REJECT : SMFIR_TEMPFAIL, NULL, 0); 45106f25ae9SGregory Neil Shapiro } 45206f25ae9SGregory Neil Shapiro break; 45306f25ae9SGregory Neil Shapiro case SMFIS_DISCARD: 45406f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_DISCARD, NULL, 0); 45506f25ae9SGregory Neil Shapiro break; 45606f25ae9SGregory Neil Shapiro case SMFIS_ACCEPT: 45706f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_ACCEPT, NULL, 0); 45806f25ae9SGregory Neil Shapiro break; 45906f25ae9SGregory Neil Shapiro case _SMFIS_OPTIONS: 46006f25ae9SGregory Neil Shapiro { 46106f25ae9SGregory Neil Shapiro char buf[MILTER_OPTLEN]; 46206f25ae9SGregory Neil Shapiro mi_int32 v; 46306f25ae9SGregory Neil Shapiro 46406f25ae9SGregory Neil Shapiro v = htonl(ctx->ctx_smfi->xxfi_version); 46506f25ae9SGregory Neil Shapiro (void) memcpy(&(buf[0]), (void *) &v, MILTER_LEN_BYTES); 46606f25ae9SGregory Neil Shapiro v = htonl(ctx->ctx_smfi->xxfi_flags); 46706f25ae9SGregory Neil Shapiro (void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v, 46806f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 46906f25ae9SGregory Neil Shapiro v = htonl(ctx->ctx_pflags); 47006f25ae9SGregory Neil Shapiro (void) memcpy(&(buf[MILTER_LEN_BYTES * 2]), (void *) &v, 47106f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 47206f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG, buf, 47306f25ae9SGregory Neil Shapiro MILTER_OPTLEN); 47406f25ae9SGregory Neil Shapiro } 47506f25ae9SGregory Neil Shapiro break; 47606f25ae9SGregory Neil Shapiro default: /* don't send a reply */ 47706f25ae9SGregory Neil Shapiro break; 47806f25ae9SGregory Neil Shapiro } 47906f25ae9SGregory Neil Shapiro return ret; 48006f25ae9SGregory Neil Shapiro } 48106f25ae9SGregory Neil Shapiro 48206f25ae9SGregory Neil Shapiro /* 48306f25ae9SGregory Neil Shapiro ** CLR_MACROS -- clear set of macros starting from a given index 48406f25ae9SGregory Neil Shapiro ** 48506f25ae9SGregory Neil Shapiro ** Parameters: 48606f25ae9SGregory Neil Shapiro ** ctx -- context structure 48706f25ae9SGregory Neil Shapiro ** m -- index from which to clear all macros 48806f25ae9SGregory Neil Shapiro ** 48906f25ae9SGregory Neil Shapiro ** Returns: 49006f25ae9SGregory Neil Shapiro ** None. 49106f25ae9SGregory Neil Shapiro */ 49206f25ae9SGregory Neil Shapiro void 49306f25ae9SGregory Neil Shapiro mi_clr_macros(ctx, m) 49406f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 49506f25ae9SGregory Neil Shapiro int m; 49606f25ae9SGregory Neil Shapiro { 49706f25ae9SGregory Neil Shapiro int i; 49806f25ae9SGregory Neil Shapiro 49906f25ae9SGregory Neil Shapiro for (i = m; i < MAX_MACROS_ENTRIES; i++) 50006f25ae9SGregory Neil Shapiro { 50106f25ae9SGregory Neil Shapiro if (ctx->ctx_mac_ptr[i] != NULL) 50206f25ae9SGregory Neil Shapiro { 50306f25ae9SGregory Neil Shapiro free(ctx->ctx_mac_ptr[i]); 50406f25ae9SGregory Neil Shapiro ctx->ctx_mac_ptr[i] = NULL; 50506f25ae9SGregory Neil Shapiro } 50606f25ae9SGregory Neil Shapiro if (ctx->ctx_mac_buf[i] != NULL) 50706f25ae9SGregory Neil Shapiro { 50806f25ae9SGregory Neil Shapiro free(ctx->ctx_mac_buf[i]); 50906f25ae9SGregory Neil Shapiro ctx->ctx_mac_buf[i] = NULL; 51006f25ae9SGregory Neil Shapiro } 51106f25ae9SGregory Neil Shapiro } 51206f25ae9SGregory Neil Shapiro } 51340266059SGregory Neil Shapiro /* 51406f25ae9SGregory Neil Shapiro ** ST_OPTIONNEG -- negotiate options 51506f25ae9SGregory Neil Shapiro ** 51606f25ae9SGregory Neil Shapiro ** Parameters: 51706f25ae9SGregory Neil Shapiro ** g -- generic argument structure 51806f25ae9SGregory Neil Shapiro ** 51906f25ae9SGregory Neil Shapiro ** Returns: 52006f25ae9SGregory Neil Shapiro ** abort/send options/continue 52106f25ae9SGregory Neil Shapiro */ 52206f25ae9SGregory Neil Shapiro 52306f25ae9SGregory Neil Shapiro static int 52406f25ae9SGregory Neil Shapiro st_optionneg(g) 52506f25ae9SGregory Neil Shapiro genarg *g; 52606f25ae9SGregory Neil Shapiro { 52706f25ae9SGregory Neil Shapiro mi_int32 i, v; 52806f25ae9SGregory Neil Shapiro 52906f25ae9SGregory Neil Shapiro if (g == NULL || g->a_ctx->ctx_smfi == NULL) 53006f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 53106f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 53206f25ae9SGregory Neil Shapiro 53306f25ae9SGregory Neil Shapiro /* check for minimum length */ 53406f25ae9SGregory Neil Shapiro if (g->a_len < MILTER_OPTLEN) 53506f25ae9SGregory Neil Shapiro { 53606f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 53706f25ae9SGregory Neil Shapiro "%s: st_optionneg[%d]: len too short %d < %d", 53806f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 53913bd1963SGregory Neil Shapiro (int) g->a_ctx->ctx_id, (int) g->a_len, 54006f25ae9SGregory Neil Shapiro MILTER_OPTLEN); 54106f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 54206f25ae9SGregory Neil Shapiro } 54306f25ae9SGregory Neil Shapiro 54406f25ae9SGregory Neil Shapiro (void) memcpy((void *) &i, (void *) &(g->a_buf[0]), 54506f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 54606f25ae9SGregory Neil Shapiro v = ntohl(i); 54706f25ae9SGregory Neil Shapiro if (v < g->a_ctx->ctx_smfi->xxfi_version) 54806f25ae9SGregory Neil Shapiro { 54906f25ae9SGregory Neil Shapiro /* hard failure for now! */ 55006f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 55106f25ae9SGregory Neil Shapiro "%s: st_optionneg[%d]: version mismatch MTA: %d < milter: %d", 55206f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 55306f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id, (int) v, 55406f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_version); 55506f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 55606f25ae9SGregory Neil Shapiro } 55706f25ae9SGregory Neil Shapiro 55806f25ae9SGregory Neil Shapiro (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]), 55906f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 56006f25ae9SGregory Neil Shapiro v = ntohl(i); 56106f25ae9SGregory Neil Shapiro 56206f25ae9SGregory Neil Shapiro /* no flags? set to default value for V1 actions */ 56306f25ae9SGregory Neil Shapiro if (v == 0) 56406f25ae9SGregory Neil Shapiro v = SMFI_V1_ACTS; 56506f25ae9SGregory Neil Shapiro i = g->a_ctx->ctx_smfi->xxfi_flags; 56606f25ae9SGregory Neil Shapiro if ((v & i) != i) 56706f25ae9SGregory Neil Shapiro { 56806f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 56906f25ae9SGregory Neil Shapiro "%s: st_optionneg[%d]: 0x%x does not fulfill action requirements 0x%x", 57006f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 57106f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id, v, i); 57206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 57306f25ae9SGregory Neil Shapiro } 57406f25ae9SGregory Neil Shapiro 57506f25ae9SGregory Neil Shapiro (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES * 2]), 57606f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 57706f25ae9SGregory Neil Shapiro v = ntohl(i); 57806f25ae9SGregory Neil Shapiro 57906f25ae9SGregory Neil Shapiro /* no flags? set to default value for V1 protocol */ 58006f25ae9SGregory Neil Shapiro if (v == 0) 58106f25ae9SGregory Neil Shapiro v = SMFI_V1_PROT; 58206f25ae9SGregory Neil Shapiro i = g->a_ctx->ctx_pflags; 58306f25ae9SGregory Neil Shapiro if ((v & i) != i) 58406f25ae9SGregory Neil Shapiro { 58506f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 58606f25ae9SGregory Neil Shapiro "%s: st_optionneg[%d]: 0x%x does not fulfill protocol requirements 0x%x", 58706f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 58806f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id, v, i); 58906f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 59006f25ae9SGregory Neil Shapiro } 59106f25ae9SGregory Neil Shapiro 59206f25ae9SGregory Neil Shapiro return _SMFIS_OPTIONS; 59306f25ae9SGregory Neil Shapiro } 59440266059SGregory Neil Shapiro /* 59506f25ae9SGregory Neil Shapiro ** ST_CONNECTINFO -- receive connection information 59606f25ae9SGregory Neil Shapiro ** 59706f25ae9SGregory Neil Shapiro ** Parameters: 59806f25ae9SGregory Neil Shapiro ** g -- generic argument structure 59906f25ae9SGregory Neil Shapiro ** 60006f25ae9SGregory Neil Shapiro ** Returns: 60106f25ae9SGregory Neil Shapiro ** continue or filter-specified value 60206f25ae9SGregory Neil Shapiro */ 60306f25ae9SGregory Neil Shapiro 60406f25ae9SGregory Neil Shapiro static int 60506f25ae9SGregory Neil Shapiro st_connectinfo(g) 60606f25ae9SGregory Neil Shapiro genarg *g; 60706f25ae9SGregory Neil Shapiro { 60806f25ae9SGregory Neil Shapiro size_t l; 60906f25ae9SGregory Neil Shapiro size_t i; 61006f25ae9SGregory Neil Shapiro char *s, family; 61140266059SGregory Neil Shapiro unsigned short port = 0; 61206f25ae9SGregory Neil Shapiro _SOCK_ADDR sockaddr; 61306f25ae9SGregory Neil Shapiro sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *)); 61406f25ae9SGregory Neil Shapiro 61506f25ae9SGregory Neil Shapiro if (g == NULL) 61606f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 61706f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 61806f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi == NULL || 61906f25ae9SGregory Neil Shapiro (fi_connect = g->a_ctx->ctx_smfi->xxfi_connect) == NULL) 62006f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 62106f25ae9SGregory Neil Shapiro 62206f25ae9SGregory Neil Shapiro s = g->a_buf; 62306f25ae9SGregory Neil Shapiro i = 0; 62406f25ae9SGregory Neil Shapiro l = g->a_len; 62506f25ae9SGregory Neil Shapiro while (s[i] != '\0' && i <= l) 62606f25ae9SGregory Neil Shapiro ++i; 627323f6dcbSGregory Neil Shapiro if (i + 1 >= l) 62806f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 62906f25ae9SGregory Neil Shapiro 63006f25ae9SGregory Neil Shapiro /* Move past trailing \0 in host string */ 63106f25ae9SGregory Neil Shapiro i++; 63206f25ae9SGregory Neil Shapiro family = s[i++]; 633a7ec597cSGregory Neil Shapiro (void) memset(&sockaddr, '\0', sizeof sockaddr); 63406f25ae9SGregory Neil Shapiro if (family != SMFIA_UNKNOWN) 63506f25ae9SGregory Neil Shapiro { 636323f6dcbSGregory Neil Shapiro if (i + sizeof port >= l) 63706f25ae9SGregory Neil Shapiro { 63806f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 63906f25ae9SGregory Neil Shapiro "%s: connect[%d]: wrong len %d >= %d", 64006f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 64113bd1963SGregory Neil Shapiro (int) g->a_ctx->ctx_id, (int) i, (int) l); 64206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 64306f25ae9SGregory Neil Shapiro } 644323f6dcbSGregory Neil Shapiro (void) memcpy((void *) &port, (void *) (s + i), 645323f6dcbSGregory Neil Shapiro sizeof port); 646323f6dcbSGregory Neil Shapiro i += sizeof port; 647605302a5SGregory Neil Shapiro 648605302a5SGregory Neil Shapiro /* make sure string is terminated */ 649605302a5SGregory Neil Shapiro if (s[l - 1] != '\0') 650605302a5SGregory Neil Shapiro return _SMFIS_ABORT; 65106f25ae9SGregory Neil Shapiro # if NETINET 65206f25ae9SGregory Neil Shapiro if (family == SMFIA_INET) 65306f25ae9SGregory Neil Shapiro { 65406f25ae9SGregory Neil Shapiro if (inet_aton(s + i, (struct in_addr *) &sockaddr.sin.sin_addr) 655605302a5SGregory Neil Shapiro != 1) 65606f25ae9SGregory Neil Shapiro { 65706f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 65806f25ae9SGregory Neil Shapiro "%s: connect[%d]: inet_aton failed", 65906f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 66006f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id); 66106f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 66206f25ae9SGregory Neil Shapiro } 66306f25ae9SGregory Neil Shapiro sockaddr.sa.sa_family = AF_INET; 66406f25ae9SGregory Neil Shapiro if (port > 0) 66506f25ae9SGregory Neil Shapiro sockaddr.sin.sin_port = port; 66606f25ae9SGregory Neil Shapiro } 66706f25ae9SGregory Neil Shapiro else 66806f25ae9SGregory Neil Shapiro # endif /* NETINET */ 66906f25ae9SGregory Neil Shapiro # if NETINET6 67006f25ae9SGregory Neil Shapiro if (family == SMFIA_INET6) 67106f25ae9SGregory Neil Shapiro { 67240266059SGregory Neil Shapiro if (mi_inet_pton(AF_INET6, s + i, 67306f25ae9SGregory Neil Shapiro &sockaddr.sin6.sin6_addr) != 1) 67406f25ae9SGregory Neil Shapiro { 67506f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 67640266059SGregory Neil Shapiro "%s: connect[%d]: mi_inet_pton failed", 67706f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 67806f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id); 67906f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 68006f25ae9SGregory Neil Shapiro } 68106f25ae9SGregory Neil Shapiro sockaddr.sa.sa_family = AF_INET6; 68206f25ae9SGregory Neil Shapiro if (port > 0) 68306f25ae9SGregory Neil Shapiro sockaddr.sin6.sin6_port = port; 68406f25ae9SGregory Neil Shapiro } 68506f25ae9SGregory Neil Shapiro else 68606f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 68706f25ae9SGregory Neil Shapiro # if NETUNIX 68806f25ae9SGregory Neil Shapiro if (family == SMFIA_UNIX) 68906f25ae9SGregory Neil Shapiro { 69040266059SGregory Neil Shapiro if (sm_strlcpy(sockaddr.sunix.sun_path, s + i, 69106f25ae9SGregory Neil Shapiro sizeof sockaddr.sunix.sun_path) >= 69206f25ae9SGregory Neil Shapiro sizeof sockaddr.sunix.sun_path) 69306f25ae9SGregory Neil Shapiro { 69406f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 69506f25ae9SGregory Neil Shapiro "%s: connect[%d]: path too long", 69606f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 69706f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id); 69806f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 69906f25ae9SGregory Neil Shapiro } 70006f25ae9SGregory Neil Shapiro sockaddr.sunix.sun_family = AF_UNIX; 70106f25ae9SGregory Neil Shapiro } 70206f25ae9SGregory Neil Shapiro else 70306f25ae9SGregory Neil Shapiro # endif /* NETUNIX */ 70406f25ae9SGregory Neil Shapiro { 70506f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 70606f25ae9SGregory Neil Shapiro "%s: connect[%d]: unknown family %d", 70706f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 70806f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id, family); 70906f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 71006f25ae9SGregory Neil Shapiro } 71106f25ae9SGregory Neil Shapiro } 71206f25ae9SGregory Neil Shapiro return (*fi_connect)(g->a_ctx, g->a_buf, 71306f25ae9SGregory Neil Shapiro family != SMFIA_UNKNOWN ? &sockaddr : NULL); 71406f25ae9SGregory Neil Shapiro } 715e92d3f3fSGregory Neil Shapiro 71640266059SGregory Neil Shapiro /* 71706f25ae9SGregory Neil Shapiro ** ST_EOH -- end of headers 71806f25ae9SGregory Neil Shapiro ** 71906f25ae9SGregory Neil Shapiro ** Parameters: 72006f25ae9SGregory Neil Shapiro ** g -- generic argument structure 72106f25ae9SGregory Neil Shapiro ** 72206f25ae9SGregory Neil Shapiro ** Returns: 72306f25ae9SGregory Neil Shapiro ** continue or filter-specified value 72406f25ae9SGregory Neil Shapiro */ 72506f25ae9SGregory Neil Shapiro 72606f25ae9SGregory Neil Shapiro static int 72706f25ae9SGregory Neil Shapiro st_eoh(g) 72806f25ae9SGregory Neil Shapiro genarg *g; 72906f25ae9SGregory Neil Shapiro { 73006f25ae9SGregory Neil Shapiro sfsistat (*fi_eoh) __P((SMFICTX *)); 73106f25ae9SGregory Neil Shapiro 73206f25ae9SGregory Neil Shapiro if (g == NULL) 73306f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 73406f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 73506f25ae9SGregory Neil Shapiro (fi_eoh = g->a_ctx->ctx_smfi->xxfi_eoh) != NULL) 73606f25ae9SGregory Neil Shapiro return (*fi_eoh)(g->a_ctx); 73706f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 73806f25ae9SGregory Neil Shapiro } 739e92d3f3fSGregory Neil Shapiro 740e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 3 741e92d3f3fSGregory Neil Shapiro /* 742e92d3f3fSGregory Neil Shapiro ** ST_DATA -- DATA command 743e92d3f3fSGregory Neil Shapiro ** 744e92d3f3fSGregory Neil Shapiro ** Parameters: 745e92d3f3fSGregory Neil Shapiro ** g -- generic argument structure 746e92d3f3fSGregory Neil Shapiro ** 747e92d3f3fSGregory Neil Shapiro ** Returns: 748e92d3f3fSGregory Neil Shapiro ** continue or filter-specified value 749e92d3f3fSGregory Neil Shapiro */ 750e92d3f3fSGregory Neil Shapiro 751e92d3f3fSGregory Neil Shapiro static int 752e92d3f3fSGregory Neil Shapiro st_data(g) 753e92d3f3fSGregory Neil Shapiro genarg *g; 754e92d3f3fSGregory Neil Shapiro { 755e92d3f3fSGregory Neil Shapiro sfsistat (*fi_data) __P((SMFICTX *)); 756e92d3f3fSGregory Neil Shapiro 757e92d3f3fSGregory Neil Shapiro if (g == NULL) 758e92d3f3fSGregory Neil Shapiro return _SMFIS_ABORT; 759e92d3f3fSGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 760e92d3f3fSGregory Neil Shapiro (fi_data = g->a_ctx->ctx_smfi->xxfi_data) != NULL) 761e92d3f3fSGregory Neil Shapiro return (*fi_data)(g->a_ctx); 762e92d3f3fSGregory Neil Shapiro return SMFIS_CONTINUE; 763e92d3f3fSGregory Neil Shapiro } 764e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 3 */ 765e92d3f3fSGregory Neil Shapiro 76640266059SGregory Neil Shapiro /* 76706f25ae9SGregory Neil Shapiro ** ST_HELO -- helo/ehlo command 76806f25ae9SGregory Neil Shapiro ** 76906f25ae9SGregory Neil Shapiro ** Parameters: 77006f25ae9SGregory Neil Shapiro ** g -- generic argument structure 77106f25ae9SGregory Neil Shapiro ** 77206f25ae9SGregory Neil Shapiro ** Returns: 77306f25ae9SGregory Neil Shapiro ** continue or filter-specified value 77406f25ae9SGregory Neil Shapiro */ 77506f25ae9SGregory Neil Shapiro static int 77606f25ae9SGregory Neil Shapiro st_helo(g) 77706f25ae9SGregory Neil Shapiro genarg *g; 77806f25ae9SGregory Neil Shapiro { 77906f25ae9SGregory Neil Shapiro sfsistat (*fi_helo) __P((SMFICTX *, char *)); 78006f25ae9SGregory Neil Shapiro 78106f25ae9SGregory Neil Shapiro if (g == NULL) 78206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 78306f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 78406f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 78506f25ae9SGregory Neil Shapiro (fi_helo = g->a_ctx->ctx_smfi->xxfi_helo) != NULL) 786323f6dcbSGregory Neil Shapiro { 787323f6dcbSGregory Neil Shapiro /* paranoia: check for terminating '\0' */ 788323f6dcbSGregory Neil Shapiro if (g->a_len == 0 || g->a_buf[g->a_len - 1] != '\0') 789323f6dcbSGregory Neil Shapiro return MI_FAILURE; 79006f25ae9SGregory Neil Shapiro return (*fi_helo)(g->a_ctx, g->a_buf); 791323f6dcbSGregory Neil Shapiro } 79206f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 79306f25ae9SGregory Neil Shapiro } 79440266059SGregory Neil Shapiro /* 79506f25ae9SGregory Neil Shapiro ** ST_HEADER -- header line 79606f25ae9SGregory Neil Shapiro ** 79706f25ae9SGregory Neil Shapiro ** Parameters: 79806f25ae9SGregory Neil Shapiro ** g -- generic argument structure 79906f25ae9SGregory Neil Shapiro ** 80006f25ae9SGregory Neil Shapiro ** Returns: 80106f25ae9SGregory Neil Shapiro ** continue or filter-specified value 80206f25ae9SGregory Neil Shapiro */ 80306f25ae9SGregory Neil Shapiro 80406f25ae9SGregory Neil Shapiro static int 80506f25ae9SGregory Neil Shapiro st_header(g) 80606f25ae9SGregory Neil Shapiro genarg *g; 80706f25ae9SGregory Neil Shapiro { 80806f25ae9SGregory Neil Shapiro char *hf, *hv; 80906f25ae9SGregory Neil Shapiro sfsistat (*fi_header) __P((SMFICTX *, char *, char *)); 81006f25ae9SGregory Neil Shapiro 81106f25ae9SGregory Neil Shapiro if (g == NULL) 81206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 81306f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi == NULL || 81406f25ae9SGregory Neil Shapiro (fi_header = g->a_ctx->ctx_smfi->xxfi_header) == NULL) 81506f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 81606f25ae9SGregory Neil Shapiro if (dec_arg2(g->a_buf, g->a_len, &hf, &hv) == MI_SUCCESS) 81706f25ae9SGregory Neil Shapiro return (*fi_header)(g->a_ctx, hf, hv); 81806f25ae9SGregory Neil Shapiro else 81906f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 82006f25ae9SGregory Neil Shapiro } 82106f25ae9SGregory Neil Shapiro 82206f25ae9SGregory Neil Shapiro #define ARGV_FCT(lf, rf, idx) \ 82306f25ae9SGregory Neil Shapiro char **argv; \ 82406f25ae9SGregory Neil Shapiro sfsistat (*lf) __P((SMFICTX *, char **)); \ 82506f25ae9SGregory Neil Shapiro int r; \ 82606f25ae9SGregory Neil Shapiro \ 82706f25ae9SGregory Neil Shapiro if (g == NULL) \ 82806f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; \ 82906f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); \ 83006f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi == NULL || \ 83106f25ae9SGregory Neil Shapiro (lf = g->a_ctx->ctx_smfi->rf) == NULL) \ 83206f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; \ 83306f25ae9SGregory Neil Shapiro if ((argv = dec_argv(g->a_buf, g->a_len)) == NULL) \ 83406f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; \ 83506f25ae9SGregory Neil Shapiro r = (*lf)(g->a_ctx, argv); \ 83606f25ae9SGregory Neil Shapiro free(argv); \ 83706f25ae9SGregory Neil Shapiro return r; 83806f25ae9SGregory Neil Shapiro 83940266059SGregory Neil Shapiro /* 84006f25ae9SGregory Neil Shapiro ** ST_SENDER -- MAIL FROM command 84106f25ae9SGregory Neil Shapiro ** 84206f25ae9SGregory Neil Shapiro ** Parameters: 84306f25ae9SGregory Neil Shapiro ** g -- generic argument structure 84406f25ae9SGregory Neil Shapiro ** 84506f25ae9SGregory Neil Shapiro ** Returns: 84606f25ae9SGregory Neil Shapiro ** continue or filter-specified value 84706f25ae9SGregory Neil Shapiro */ 84806f25ae9SGregory Neil Shapiro 84906f25ae9SGregory Neil Shapiro static int 85006f25ae9SGregory Neil Shapiro st_sender(g) 85106f25ae9SGregory Neil Shapiro genarg *g; 85206f25ae9SGregory Neil Shapiro { 85306f25ae9SGregory Neil Shapiro ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL) 85406f25ae9SGregory Neil Shapiro } 85540266059SGregory Neil Shapiro /* 85606f25ae9SGregory Neil Shapiro ** ST_RCPT -- RCPT TO command 85706f25ae9SGregory Neil Shapiro ** 85806f25ae9SGregory Neil Shapiro ** Parameters: 85906f25ae9SGregory Neil Shapiro ** g -- generic argument structure 86006f25ae9SGregory Neil Shapiro ** 86106f25ae9SGregory Neil Shapiro ** Returns: 86206f25ae9SGregory Neil Shapiro ** continue or filter-specified value 86306f25ae9SGregory Neil Shapiro */ 86406f25ae9SGregory Neil Shapiro 86506f25ae9SGregory Neil Shapiro static int 86606f25ae9SGregory Neil Shapiro st_rcpt(g) 86706f25ae9SGregory Neil Shapiro genarg *g; 86806f25ae9SGregory Neil Shapiro { 86906f25ae9SGregory Neil Shapiro ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT) 87006f25ae9SGregory Neil Shapiro } 871e92d3f3fSGregory Neil Shapiro 872e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 2 873e92d3f3fSGregory Neil Shapiro /* 874e92d3f3fSGregory Neil Shapiro ** ST_UNKNOWN -- unrecognized or unimplemented command 875e92d3f3fSGregory Neil Shapiro ** 876e92d3f3fSGregory Neil Shapiro ** Parameters: 877e92d3f3fSGregory Neil Shapiro ** g -- generic argument structure 878e92d3f3fSGregory Neil Shapiro ** 879e92d3f3fSGregory Neil Shapiro ** Returns: 880e92d3f3fSGregory Neil Shapiro ** continue or filter-specified value 881e92d3f3fSGregory Neil Shapiro */ 882e92d3f3fSGregory Neil Shapiro 883e92d3f3fSGregory Neil Shapiro static int 884e92d3f3fSGregory Neil Shapiro st_unknown(g) 885e92d3f3fSGregory Neil Shapiro genarg *g; 886e92d3f3fSGregory Neil Shapiro { 887e92d3f3fSGregory Neil Shapiro sfsistat (*fi_unknown) __P((SMFICTX *, char *)); 888e92d3f3fSGregory Neil Shapiro 889e92d3f3fSGregory Neil Shapiro if (g == NULL) 890e92d3f3fSGregory Neil Shapiro return _SMFIS_ABORT; 891e92d3f3fSGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 892e92d3f3fSGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 893e92d3f3fSGregory Neil Shapiro (fi_unknown = g->a_ctx->ctx_smfi->xxfi_unknown) != NULL) 894e92d3f3fSGregory Neil Shapiro return (*fi_unknown)(g->a_ctx, g->a_buf); 895e92d3f3fSGregory Neil Shapiro return SMFIS_CONTINUE; 896e92d3f3fSGregory Neil Shapiro } 897e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 2 */ 898e92d3f3fSGregory Neil Shapiro 89940266059SGregory Neil Shapiro /* 90006f25ae9SGregory Neil Shapiro ** ST_MACROS -- deal with macros received from the MTA 90106f25ae9SGregory Neil Shapiro ** 90206f25ae9SGregory Neil Shapiro ** Parameters: 90306f25ae9SGregory Neil Shapiro ** g -- generic argument structure 90406f25ae9SGregory Neil Shapiro ** 90506f25ae9SGregory Neil Shapiro ** Returns: 90606f25ae9SGregory Neil Shapiro ** continue/keep 90706f25ae9SGregory Neil Shapiro ** 90806f25ae9SGregory Neil Shapiro ** Side effects: 90906f25ae9SGregory Neil Shapiro ** set pointer in macro array to current values. 91006f25ae9SGregory Neil Shapiro */ 91106f25ae9SGregory Neil Shapiro 91206f25ae9SGregory Neil Shapiro static int 91306f25ae9SGregory Neil Shapiro st_macros(g) 91406f25ae9SGregory Neil Shapiro genarg *g; 91506f25ae9SGregory Neil Shapiro { 91606f25ae9SGregory Neil Shapiro int i; 91706f25ae9SGregory Neil Shapiro char **argv; 91806f25ae9SGregory Neil Shapiro 91906f25ae9SGregory Neil Shapiro if (g == NULL || g->a_len < 1) 92006f25ae9SGregory Neil Shapiro return _SMFIS_FAIL; 92106f25ae9SGregory Neil Shapiro if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL) 92206f25ae9SGregory Neil Shapiro return _SMFIS_FAIL; 92306f25ae9SGregory Neil Shapiro switch (g->a_buf[0]) 92406f25ae9SGregory Neil Shapiro { 92506f25ae9SGregory Neil Shapiro case SMFIC_CONNECT: 92606f25ae9SGregory Neil Shapiro i = CI_CONN; 92706f25ae9SGregory Neil Shapiro break; 92806f25ae9SGregory Neil Shapiro case SMFIC_HELO: 92906f25ae9SGregory Neil Shapiro i = CI_HELO; 93006f25ae9SGregory Neil Shapiro break; 93106f25ae9SGregory Neil Shapiro case SMFIC_MAIL: 93206f25ae9SGregory Neil Shapiro i = CI_MAIL; 93306f25ae9SGregory Neil Shapiro break; 93406f25ae9SGregory Neil Shapiro case SMFIC_RCPT: 93506f25ae9SGregory Neil Shapiro i = CI_RCPT; 93606f25ae9SGregory Neil Shapiro break; 937323f6dcbSGregory Neil Shapiro case SMFIC_BODYEOB: 938323f6dcbSGregory Neil Shapiro i = CI_EOM; 939323f6dcbSGregory Neil Shapiro break; 94006f25ae9SGregory Neil Shapiro default: 94106f25ae9SGregory Neil Shapiro free(argv); 94206f25ae9SGregory Neil Shapiro return _SMFIS_FAIL; 94306f25ae9SGregory Neil Shapiro } 94406f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_mac_ptr[i] != NULL) 94506f25ae9SGregory Neil Shapiro free(g->a_ctx->ctx_mac_ptr[i]); 94606f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_mac_buf[i] != NULL) 94706f25ae9SGregory Neil Shapiro free(g->a_ctx->ctx_mac_buf[i]); 94806f25ae9SGregory Neil Shapiro g->a_ctx->ctx_mac_ptr[i] = argv; 94906f25ae9SGregory Neil Shapiro g->a_ctx->ctx_mac_buf[i] = g->a_buf; 95006f25ae9SGregory Neil Shapiro return _SMFIS_KEEP; 95106f25ae9SGregory Neil Shapiro } 95240266059SGregory Neil Shapiro /* 95306f25ae9SGregory Neil Shapiro ** ST_QUIT -- quit command 95406f25ae9SGregory Neil Shapiro ** 95506f25ae9SGregory Neil Shapiro ** Parameters: 95606f25ae9SGregory Neil Shapiro ** g -- generic argument structure 95706f25ae9SGregory Neil Shapiro ** 95806f25ae9SGregory Neil Shapiro ** Returns: 95906f25ae9SGregory Neil Shapiro ** noreply 96006f25ae9SGregory Neil Shapiro */ 96106f25ae9SGregory Neil Shapiro 962a7ec597cSGregory Neil Shapiro /* ARGSUSED */ 96306f25ae9SGregory Neil Shapiro static int 96406f25ae9SGregory Neil Shapiro st_quit(g) 96506f25ae9SGregory Neil Shapiro genarg *g; 96606f25ae9SGregory Neil Shapiro { 96706f25ae9SGregory Neil Shapiro return _SMFIS_NOREPLY; 96806f25ae9SGregory Neil Shapiro } 96940266059SGregory Neil Shapiro /* 97006f25ae9SGregory Neil Shapiro ** ST_BODYCHUNK -- deal with a piece of the mail body 97106f25ae9SGregory Neil Shapiro ** 97206f25ae9SGregory Neil Shapiro ** Parameters: 97306f25ae9SGregory Neil Shapiro ** g -- generic argument structure 97406f25ae9SGregory Neil Shapiro ** 97506f25ae9SGregory Neil Shapiro ** Returns: 97606f25ae9SGregory Neil Shapiro ** continue or filter-specified value 97706f25ae9SGregory Neil Shapiro */ 97806f25ae9SGregory Neil Shapiro 97906f25ae9SGregory Neil Shapiro static int 98006f25ae9SGregory Neil Shapiro st_bodychunk(g) 98106f25ae9SGregory Neil Shapiro genarg *g; 98206f25ae9SGregory Neil Shapiro { 98340266059SGregory Neil Shapiro sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t)); 98406f25ae9SGregory Neil Shapiro 98506f25ae9SGregory Neil Shapiro if (g == NULL) 98606f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 98706f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 98806f25ae9SGregory Neil Shapiro (fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL) 98940266059SGregory Neil Shapiro return (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf, 99040266059SGregory Neil Shapiro g->a_len); 99106f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 99206f25ae9SGregory Neil Shapiro } 99340266059SGregory Neil Shapiro /* 99406f25ae9SGregory Neil Shapiro ** ST_BODYEND -- deal with the last piece of the mail body 99506f25ae9SGregory Neil Shapiro ** 99606f25ae9SGregory Neil Shapiro ** Parameters: 99706f25ae9SGregory Neil Shapiro ** g -- generic argument structure 99806f25ae9SGregory Neil Shapiro ** 99906f25ae9SGregory Neil Shapiro ** Returns: 100006f25ae9SGregory Neil Shapiro ** continue or filter-specified value 100106f25ae9SGregory Neil Shapiro ** 100206f25ae9SGregory Neil Shapiro ** Side effects: 100306f25ae9SGregory Neil Shapiro ** sends a reply for the body part (if non-empty). 100406f25ae9SGregory Neil Shapiro */ 100506f25ae9SGregory Neil Shapiro 100606f25ae9SGregory Neil Shapiro static int 100706f25ae9SGregory Neil Shapiro st_bodyend(g) 100806f25ae9SGregory Neil Shapiro genarg *g; 100906f25ae9SGregory Neil Shapiro { 101006f25ae9SGregory Neil Shapiro sfsistat r; 101140266059SGregory Neil Shapiro sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t)); 101206f25ae9SGregory Neil Shapiro sfsistat (*fi_eom) __P((SMFICTX *)); 101306f25ae9SGregory Neil Shapiro 101406f25ae9SGregory Neil Shapiro if (g == NULL) 101506f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 101606f25ae9SGregory Neil Shapiro r = SMFIS_CONTINUE; 101706f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL) 101806f25ae9SGregory Neil Shapiro { 101906f25ae9SGregory Neil Shapiro if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL && 102006f25ae9SGregory Neil Shapiro g->a_len > 0) 102106f25ae9SGregory Neil Shapiro { 102206f25ae9SGregory Neil Shapiro socket_t sd; 102306f25ae9SGregory Neil Shapiro struct timeval timeout; 102406f25ae9SGregory Neil Shapiro 102506f25ae9SGregory Neil Shapiro timeout.tv_sec = g->a_ctx->ctx_timeout; 102606f25ae9SGregory Neil Shapiro timeout.tv_usec = 0; 102706f25ae9SGregory Neil Shapiro sd = g->a_ctx->ctx_sd; 102840266059SGregory Neil Shapiro r = (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf, 102940266059SGregory Neil Shapiro g->a_len); 103006f25ae9SGregory Neil Shapiro if (r != SMFIS_CONTINUE && 103106f25ae9SGregory Neil Shapiro sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS) 103206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 103306f25ae9SGregory Neil Shapiro } 103406f25ae9SGregory Neil Shapiro } 103506f25ae9SGregory Neil Shapiro if (r == SMFIS_CONTINUE && 103606f25ae9SGregory Neil Shapiro (fi_eom = g->a_ctx->ctx_smfi->xxfi_eom) != NULL) 103706f25ae9SGregory Neil Shapiro return (*fi_eom)(g->a_ctx); 103806f25ae9SGregory Neil Shapiro return r; 103906f25ae9SGregory Neil Shapiro } 104040266059SGregory Neil Shapiro /* 104106f25ae9SGregory Neil Shapiro ** ST_ABORTFCT -- deal with aborts 104206f25ae9SGregory Neil Shapiro ** 104306f25ae9SGregory Neil Shapiro ** Parameters: 104406f25ae9SGregory Neil Shapiro ** g -- generic argument structure 104506f25ae9SGregory Neil Shapiro ** 104606f25ae9SGregory Neil Shapiro ** Returns: 104706f25ae9SGregory Neil Shapiro ** abort or filter-specified value 104806f25ae9SGregory Neil Shapiro */ 104906f25ae9SGregory Neil Shapiro 105006f25ae9SGregory Neil Shapiro static int 105106f25ae9SGregory Neil Shapiro st_abortfct(g) 105206f25ae9SGregory Neil Shapiro genarg *g; 105306f25ae9SGregory Neil Shapiro { 105406f25ae9SGregory Neil Shapiro sfsistat (*fi_abort) __P((SMFICTX *)); 105506f25ae9SGregory Neil Shapiro 105606f25ae9SGregory Neil Shapiro if (g == NULL) 105706f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 105806f25ae9SGregory Neil Shapiro if (g != NULL && g->a_ctx->ctx_smfi != NULL && 105906f25ae9SGregory Neil Shapiro (fi_abort = g->a_ctx->ctx_smfi->xxfi_abort) != NULL) 106006f25ae9SGregory Neil Shapiro (void) (*fi_abort)(g->a_ctx); 106106f25ae9SGregory Neil Shapiro return _SMFIS_NOREPLY; 106206f25ae9SGregory Neil Shapiro } 106340266059SGregory Neil Shapiro /* 106406f25ae9SGregory Neil Shapiro ** TRANS_OK -- is the state transition ok? 106506f25ae9SGregory Neil Shapiro ** 106606f25ae9SGregory Neil Shapiro ** Parameters: 106706f25ae9SGregory Neil Shapiro ** old -- old state 106806f25ae9SGregory Neil Shapiro ** new -- new state 106906f25ae9SGregory Neil Shapiro ** 107006f25ae9SGregory Neil Shapiro ** Returns: 107106f25ae9SGregory Neil Shapiro ** state transition ok 107206f25ae9SGregory Neil Shapiro */ 107306f25ae9SGregory Neil Shapiro 107406f25ae9SGregory Neil Shapiro static bool 107506f25ae9SGregory Neil Shapiro trans_ok(old, new) 107606f25ae9SGregory Neil Shapiro int old, new; 107706f25ae9SGregory Neil Shapiro { 107806f25ae9SGregory Neil Shapiro int s, n; 107906f25ae9SGregory Neil Shapiro 108006f25ae9SGregory Neil Shapiro s = old; 1081af9557fdSGregory Neil Shapiro if (s >= SIZE_NEXT_STATES) 1082af9557fdSGregory Neil Shapiro return false; 108342e5d165SGregory Neil Shapiro do 108442e5d165SGregory Neil Shapiro { 108506f25ae9SGregory Neil Shapiro /* is this state transition allowed? */ 108613bd1963SGregory Neil Shapiro if ((MI_MASK(new) & next_states[s]) != 0) 108740266059SGregory Neil Shapiro return true; 108806f25ae9SGregory Neil Shapiro 108906f25ae9SGregory Neil Shapiro /* 109006f25ae9SGregory Neil Shapiro ** no: try next state; 109106f25ae9SGregory Neil Shapiro ** this works since the relevant states are ordered 109206f25ae9SGregory Neil Shapiro ** strict sequentially 109306f25ae9SGregory Neil Shapiro */ 109440266059SGregory Neil Shapiro 109506f25ae9SGregory Neil Shapiro n = s + 1; 1096af9557fdSGregory Neil Shapiro if (n >= SIZE_NEXT_STATES) 1097af9557fdSGregory Neil Shapiro return false; 109806f25ae9SGregory Neil Shapiro 109906f25ae9SGregory Neil Shapiro /* 110006f25ae9SGregory Neil Shapiro ** can we actually "skip" this state? 110106f25ae9SGregory Neil Shapiro ** see fix_stm() which sets this bit for those 110206f25ae9SGregory Neil Shapiro ** states which the filter program is not interested in 110306f25ae9SGregory Neil Shapiro */ 110440266059SGregory Neil Shapiro 110506f25ae9SGregory Neil Shapiro if (bitset(NX_SKIP, next_states[n])) 110606f25ae9SGregory Neil Shapiro s = n; 110706f25ae9SGregory Neil Shapiro else 110840266059SGregory Neil Shapiro return false; 1109af9557fdSGregory Neil Shapiro } while (s < SIZE_NEXT_STATES); 111040266059SGregory Neil Shapiro return false; 111106f25ae9SGregory Neil Shapiro } 111240266059SGregory Neil Shapiro /* 111306f25ae9SGregory Neil Shapiro ** FIX_STM -- add "skip" bits to the state transition table 111406f25ae9SGregory Neil Shapiro ** 111506f25ae9SGregory Neil Shapiro ** Parameters: 111606f25ae9SGregory Neil Shapiro ** ctx -- context structure 111706f25ae9SGregory Neil Shapiro ** 111806f25ae9SGregory Neil Shapiro ** Returns: 111906f25ae9SGregory Neil Shapiro ** None. 112006f25ae9SGregory Neil Shapiro ** 112106f25ae9SGregory Neil Shapiro ** Side effects: 112206f25ae9SGregory Neil Shapiro ** may change state transition table. 112306f25ae9SGregory Neil Shapiro */ 112406f25ae9SGregory Neil Shapiro 112506f25ae9SGregory Neil Shapiro static void 112606f25ae9SGregory Neil Shapiro fix_stm(ctx) 112706f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 112806f25ae9SGregory Neil Shapiro { 112940266059SGregory Neil Shapiro unsigned long fl; 113006f25ae9SGregory Neil Shapiro 113106f25ae9SGregory Neil Shapiro if (ctx == NULL || ctx->ctx_smfi == NULL) 113206f25ae9SGregory Neil Shapiro return; 113306f25ae9SGregory Neil Shapiro fl = ctx->ctx_pflags; 113406f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOCONNECT, fl)) 113506f25ae9SGregory Neil Shapiro next_states[ST_CONN] |= NX_SKIP; 113606f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOHELO, fl)) 113706f25ae9SGregory Neil Shapiro next_states[ST_HELO] |= NX_SKIP; 113806f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOMAIL, fl)) 113906f25ae9SGregory Neil Shapiro next_states[ST_MAIL] |= NX_SKIP; 114006f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NORCPT, fl)) 114106f25ae9SGregory Neil Shapiro next_states[ST_RCPT] |= NX_SKIP; 114206f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOHDRS, fl)) 114306f25ae9SGregory Neil Shapiro next_states[ST_HDRS] |= NX_SKIP; 114406f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOEOH, fl)) 114506f25ae9SGregory Neil Shapiro next_states[ST_EOHS] |= NX_SKIP; 114606f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOBODY, fl)) 114706f25ae9SGregory Neil Shapiro next_states[ST_BODY] |= NX_SKIP; 114806f25ae9SGregory Neil Shapiro } 114940266059SGregory Neil Shapiro /* 115006f25ae9SGregory Neil Shapiro ** DEC_ARGV -- split a buffer into a list of strings, NULL terminated 115106f25ae9SGregory Neil Shapiro ** 115206f25ae9SGregory Neil Shapiro ** Parameters: 115306f25ae9SGregory Neil Shapiro ** buf -- buffer with several strings 115406f25ae9SGregory Neil Shapiro ** len -- length of buffer 115506f25ae9SGregory Neil Shapiro ** 115606f25ae9SGregory Neil Shapiro ** Returns: 115706f25ae9SGregory Neil Shapiro ** array of pointers to the individual strings 115806f25ae9SGregory Neil Shapiro */ 115906f25ae9SGregory Neil Shapiro 116006f25ae9SGregory Neil Shapiro static char ** 116106f25ae9SGregory Neil Shapiro dec_argv(buf, len) 116206f25ae9SGregory Neil Shapiro char *buf; 116306f25ae9SGregory Neil Shapiro size_t len; 116406f25ae9SGregory Neil Shapiro { 116506f25ae9SGregory Neil Shapiro char **s; 116606f25ae9SGregory Neil Shapiro size_t i; 116706f25ae9SGregory Neil Shapiro int elem, nelem; 116806f25ae9SGregory Neil Shapiro 116906f25ae9SGregory Neil Shapiro nelem = 0; 117006f25ae9SGregory Neil Shapiro for (i = 0; i < len; i++) 117106f25ae9SGregory Neil Shapiro { 117206f25ae9SGregory Neil Shapiro if (buf[i] == '\0') 117306f25ae9SGregory Neil Shapiro ++nelem; 117406f25ae9SGregory Neil Shapiro } 117506f25ae9SGregory Neil Shapiro if (nelem == 0) 117606f25ae9SGregory Neil Shapiro return NULL; 117706f25ae9SGregory Neil Shapiro 117806f25ae9SGregory Neil Shapiro /* last entry is only for the name */ 117906f25ae9SGregory Neil Shapiro s = (char **)malloc((nelem + 1) * (sizeof *s)); 118006f25ae9SGregory Neil Shapiro if (s == NULL) 118106f25ae9SGregory Neil Shapiro return NULL; 118206f25ae9SGregory Neil Shapiro s[0] = buf; 118306f25ae9SGregory Neil Shapiro for (i = 0, elem = 0; i < len && elem < nelem; i++) 118406f25ae9SGregory Neil Shapiro { 118506f25ae9SGregory Neil Shapiro if (buf[i] == '\0') 1186323f6dcbSGregory Neil Shapiro { 1187323f6dcbSGregory Neil Shapiro ++elem; 1188323f6dcbSGregory Neil Shapiro if (i + 1 >= len) 1189323f6dcbSGregory Neil Shapiro s[elem] = NULL; 1190323f6dcbSGregory Neil Shapiro else 1191323f6dcbSGregory Neil Shapiro s[elem] = &(buf[i + 1]); 1192323f6dcbSGregory Neil Shapiro } 119306f25ae9SGregory Neil Shapiro } 119406f25ae9SGregory Neil Shapiro 1195323f6dcbSGregory Neil Shapiro /* overwrite last entry (already done above, just paranoia) */ 119606f25ae9SGregory Neil Shapiro s[elem] = NULL; 119706f25ae9SGregory Neil Shapiro return s; 119806f25ae9SGregory Neil Shapiro } 119940266059SGregory Neil Shapiro /* 120006f25ae9SGregory Neil Shapiro ** DEC_ARG2 -- split a buffer into two strings 120106f25ae9SGregory Neil Shapiro ** 120206f25ae9SGregory Neil Shapiro ** Parameters: 120306f25ae9SGregory Neil Shapiro ** buf -- buffer with two strings 120406f25ae9SGregory Neil Shapiro ** len -- length of buffer 120506f25ae9SGregory Neil Shapiro ** s1,s2 -- pointer to result strings 120606f25ae9SGregory Neil Shapiro ** 120706f25ae9SGregory Neil Shapiro ** Returns: 120806f25ae9SGregory Neil Shapiro ** MI_FAILURE/MI_SUCCESS 120906f25ae9SGregory Neil Shapiro */ 121006f25ae9SGregory Neil Shapiro 121106f25ae9SGregory Neil Shapiro static int 121206f25ae9SGregory Neil Shapiro dec_arg2(buf, len, s1, s2) 121306f25ae9SGregory Neil Shapiro char *buf; 121406f25ae9SGregory Neil Shapiro size_t len; 121506f25ae9SGregory Neil Shapiro char **s1; 121606f25ae9SGregory Neil Shapiro char **s2; 121706f25ae9SGregory Neil Shapiro { 121806f25ae9SGregory Neil Shapiro size_t i; 121906f25ae9SGregory Neil Shapiro 1220323f6dcbSGregory Neil Shapiro /* paranoia: check for terminating '\0' */ 1221323f6dcbSGregory Neil Shapiro if (len == 0 || buf[len - 1] != '\0') 1222323f6dcbSGregory Neil Shapiro return MI_FAILURE; 122306f25ae9SGregory Neil Shapiro *s1 = buf; 122406f25ae9SGregory Neil Shapiro for (i = 1; i < len && buf[i] != '\0'; i++) 122506f25ae9SGregory Neil Shapiro continue; 122606f25ae9SGregory Neil Shapiro if (i >= len - 1) 122706f25ae9SGregory Neil Shapiro return MI_FAILURE; 122806f25ae9SGregory Neil Shapiro *s2 = buf + i + 1; 122906f25ae9SGregory Neil Shapiro return MI_SUCCESS; 123006f25ae9SGregory Neil Shapiro } 123140266059SGregory Neil Shapiro /* 123206f25ae9SGregory Neil Shapiro ** SENDOK -- is it ok for the filter to send stuff to the MTA? 123306f25ae9SGregory Neil Shapiro ** 123406f25ae9SGregory Neil Shapiro ** Parameters: 123506f25ae9SGregory Neil Shapiro ** ctx -- context structure 123606f25ae9SGregory Neil Shapiro ** flag -- flag to check 123706f25ae9SGregory Neil Shapiro ** 123806f25ae9SGregory Neil Shapiro ** Returns: 123906f25ae9SGregory Neil Shapiro ** sending allowed (in current state) 124006f25ae9SGregory Neil Shapiro */ 124106f25ae9SGregory Neil Shapiro 124206f25ae9SGregory Neil Shapiro bool 124306f25ae9SGregory Neil Shapiro mi_sendok(ctx, flag) 124406f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 124506f25ae9SGregory Neil Shapiro int flag; 124606f25ae9SGregory Neil Shapiro { 124706f25ae9SGregory Neil Shapiro if (ctx == NULL || ctx->ctx_smfi == NULL) 124840266059SGregory Neil Shapiro return false; 124940266059SGregory Neil Shapiro 125040266059SGregory Neil Shapiro /* did the milter request this operation? */ 125106f25ae9SGregory Neil Shapiro if (flag != 0 && !bitset(flag, ctx->ctx_smfi->xxfi_flags)) 125240266059SGregory Neil Shapiro return false; 125340266059SGregory Neil Shapiro 125440266059SGregory Neil Shapiro /* are we in the correct state? It must be "End of Message". */ 125506f25ae9SGregory Neil Shapiro return ctx->ctx_state == ST_ENDM; 125606f25ae9SGregory Neil Shapiro } 1257