106f25ae9SGregory Neil Shapiro /* 2323f6dcbSGregory Neil Shapiro * Copyright (c) 1999-2003 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> 12b6bacd31SGregory Neil Shapiro SM_RCSID("@(#)$Id: engine.c,v 8.120 2004/10/20 21:09:00 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 16906f25ae9SGregory Neil Shapiro /* commands received by milter */ 17006f25ae9SGregory Neil Shapiro static cmdfct cmds[] = 17106f25ae9SGregory Neil Shapiro { 17206f25ae9SGregory Neil Shapiro {SMFIC_ABORT, CM_ARG0, ST_ABRT, CT_CONT, CI_NONE, st_abortfct }, 17306f25ae9SGregory Neil Shapiro {SMFIC_MACRO, CM_ARGV, ST_NONE, CT_KEEP, CI_NONE, st_macros }, 17406f25ae9SGregory Neil Shapiro {SMFIC_BODY, CM_ARG1, ST_BODY, CT_CONT, CI_NONE, st_bodychunk }, 17506f25ae9SGregory Neil Shapiro {SMFIC_CONNECT, CM_ARG2, ST_CONN, CT_CONT, CI_CONN, st_connectinfo }, 176323f6dcbSGregory Neil Shapiro {SMFIC_BODYEOB, CM_ARG1, ST_ENDM, CT_CONT, CI_EOM, st_bodyend }, 17706f25ae9SGregory Neil Shapiro {SMFIC_HELO, CM_ARG1, ST_HELO, CT_CONT, CI_HELO, st_helo }, 17806f25ae9SGregory Neil Shapiro {SMFIC_HEADER, CM_ARG2, ST_HDRS, CT_CONT, CI_NONE, st_header }, 17906f25ae9SGregory Neil Shapiro {SMFIC_MAIL, CM_ARGV, ST_MAIL, CT_CONT, CI_MAIL, st_sender }, 18006f25ae9SGregory Neil Shapiro {SMFIC_OPTNEG, CM_ARGO, ST_OPTS, CT_CONT, CI_NONE, st_optionneg }, 18106f25ae9SGregory Neil Shapiro {SMFIC_EOH, CM_ARG0, ST_EOHS, CT_CONT, CI_NONE, st_eoh }, 18206f25ae9SGregory Neil Shapiro {SMFIC_QUIT, CM_ARG0, ST_QUIT, CT_END, CI_NONE, st_quit }, 183e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 3 184e92d3f3fSGregory Neil Shapiro {SMFIC_DATA, CM_ARG0, ST_DATA, CT_CONT, CI_NONE, st_data }, 185e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 3 */ 18606f25ae9SGregory Neil Shapiro {SMFIC_RCPT, CM_ARGV, ST_RCPT, CT_IGNO, CI_RCPT, st_rcpt } 187e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 2 188e92d3f3fSGregory Neil Shapiro ,{SMFIC_UNKNOWN,CM_ARG1, ST_UNKN, CT_IGNO, CI_NONE, st_unknown } 189e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 2 */ 19006f25ae9SGregory Neil Shapiro }; 19106f25ae9SGregory Neil Shapiro 19206f25ae9SGregory Neil Shapiro /* additional (internal) reply codes */ 19306f25ae9SGregory Neil Shapiro #define _SMFIS_KEEP 20 19406f25ae9SGregory Neil Shapiro #define _SMFIS_ABORT 21 19506f25ae9SGregory Neil Shapiro #define _SMFIS_OPTIONS 22 19606f25ae9SGregory Neil Shapiro #define _SMFIS_NOREPLY 23 19706f25ae9SGregory Neil Shapiro #define _SMFIS_FAIL (-1) 19840266059SGregory Neil Shapiro #define _SMFIS_NONE (-2) 19906f25ae9SGregory Neil Shapiro 20040266059SGregory Neil Shapiro /* 20106f25ae9SGregory Neil Shapiro ** MI_ENGINE -- receive commands and process them 20206f25ae9SGregory Neil Shapiro ** 20306f25ae9SGregory Neil Shapiro ** Parameters: 20406f25ae9SGregory Neil Shapiro ** ctx -- context structure 20506f25ae9SGregory Neil Shapiro ** 20606f25ae9SGregory Neil Shapiro ** Returns: 20706f25ae9SGregory Neil Shapiro ** MI_FAILURE/MI_SUCCESS 20806f25ae9SGregory Neil Shapiro */ 20906f25ae9SGregory Neil Shapiro int 21006f25ae9SGregory Neil Shapiro mi_engine(ctx) 21106f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 21206f25ae9SGregory Neil Shapiro { 21306f25ae9SGregory Neil Shapiro size_t len; 21406f25ae9SGregory Neil Shapiro int i; 21506f25ae9SGregory Neil Shapiro socket_t sd; 21606f25ae9SGregory Neil Shapiro int ret = MI_SUCCESS; 21706f25ae9SGregory Neil Shapiro int ncmds = sizeof(cmds) / sizeof(cmdfct); 21806f25ae9SGregory Neil Shapiro int curstate = ST_INIT; 21906f25ae9SGregory Neil Shapiro int newstate; 22006f25ae9SGregory Neil Shapiro bool call_abort; 22106f25ae9SGregory Neil Shapiro sfsistat r; 22206f25ae9SGregory Neil Shapiro char cmd; 22306f25ae9SGregory Neil Shapiro char *buf = NULL; 22406f25ae9SGregory Neil Shapiro genarg arg; 22506f25ae9SGregory Neil Shapiro struct timeval timeout; 22606f25ae9SGregory Neil Shapiro int (*f) __P((genarg *)); 22706f25ae9SGregory Neil Shapiro sfsistat (*fi_abort) __P((SMFICTX *)); 22806f25ae9SGregory Neil Shapiro sfsistat (*fi_close) __P((SMFICTX *)); 22906f25ae9SGregory Neil Shapiro 23006f25ae9SGregory Neil Shapiro arg.a_ctx = ctx; 23106f25ae9SGregory Neil Shapiro sd = ctx->ctx_sd; 23206f25ae9SGregory Neil Shapiro fi_abort = ctx->ctx_smfi->xxfi_abort; 23306f25ae9SGregory Neil Shapiro mi_clr_macros(ctx, 0); 23406f25ae9SGregory Neil Shapiro fix_stm(ctx); 23540266059SGregory Neil Shapiro r = _SMFIS_NONE; 23642e5d165SGregory Neil Shapiro do 23742e5d165SGregory Neil Shapiro { 23806f25ae9SGregory Neil Shapiro /* call abort only if in a mail transaction */ 23906f25ae9SGregory Neil Shapiro call_abort = ST_IN_MAIL(curstate); 24006f25ae9SGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout; 24106f25ae9SGregory Neil Shapiro timeout.tv_usec = 0; 24206f25ae9SGregory Neil Shapiro if (mi_stop() == MILTER_ABRT) 24306f25ae9SGregory Neil Shapiro { 24406f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 3) 24540266059SGregory Neil Shapiro sm_dprintf("[%d] milter_abort\n", 24606f25ae9SGregory Neil Shapiro (int) ctx->ctx_id); 24706f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 24806f25ae9SGregory Neil Shapiro break; 24906f25ae9SGregory Neil Shapiro } 25040266059SGregory Neil Shapiro 25140266059SGregory Neil Shapiro /* 25240266059SGregory Neil Shapiro ** Notice: buf is allocated by mi_rd_cmd() and it will 25340266059SGregory Neil Shapiro ** usually be free()d after it has been used in f(). 25440266059SGregory Neil Shapiro ** However, if the function returns _SMFIS_KEEP then buf 25540266059SGregory Neil Shapiro ** contains macros and will not be free()d. 25640266059SGregory Neil Shapiro ** Hence r must be set to _SMFIS_NONE if a new buf is 25740266059SGregory Neil Shapiro ** allocated to avoid problem with housekeeping, esp. 25840266059SGregory Neil Shapiro ** if the code "break"s out of the loop. 25940266059SGregory Neil Shapiro */ 26040266059SGregory Neil Shapiro 26140266059SGregory Neil Shapiro r = _SMFIS_NONE; 26206f25ae9SGregory Neil Shapiro if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len, 26306f25ae9SGregory Neil Shapiro ctx->ctx_smfi->xxfi_name)) == NULL && 26406f25ae9SGregory Neil Shapiro cmd < SMFIC_VALIDCMD) 26506f25ae9SGregory Neil Shapiro { 26606f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 5) 26740266059SGregory Neil Shapiro sm_dprintf("[%d] mi_engine: mi_rd_cmd error (%x)\n", 26806f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, (int) cmd); 26906f25ae9SGregory Neil Shapiro 27006f25ae9SGregory Neil Shapiro /* 27106f25ae9SGregory Neil Shapiro ** eof is currently treated as failure -> 27206f25ae9SGregory Neil Shapiro ** abort() instead of close(), otherwise use: 27306f25ae9SGregory Neil Shapiro ** if (cmd != SMFIC_EOF) 27406f25ae9SGregory Neil Shapiro */ 27506f25ae9SGregory Neil Shapiro 27606f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 27706f25ae9SGregory Neil Shapiro break; 27806f25ae9SGregory Neil Shapiro } 27906f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 4) 28040266059SGregory Neil Shapiro sm_dprintf("[%d] got cmd '%c' len %d\n", 28113bd1963SGregory Neil Shapiro (int) ctx->ctx_id, cmd, (int) len); 28206f25ae9SGregory Neil Shapiro for (i = 0; i < ncmds; i++) 28306f25ae9SGregory Neil Shapiro { 28406f25ae9SGregory Neil Shapiro if (cmd == cmds[i].cm_cmd) 28506f25ae9SGregory Neil Shapiro break; 28606f25ae9SGregory Neil Shapiro } 28706f25ae9SGregory Neil Shapiro if (i >= ncmds) 28806f25ae9SGregory Neil Shapiro { 28906f25ae9SGregory Neil Shapiro /* unknown command */ 29006f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 1) 29140266059SGregory Neil Shapiro sm_dprintf("[%d] cmd '%c' unknown\n", 29206f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, cmd); 29306f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 29406f25ae9SGregory Neil Shapiro break; 29506f25ae9SGregory Neil Shapiro } 29606f25ae9SGregory Neil Shapiro if ((f = cmds[i].cm_fct) == NULL) 29706f25ae9SGregory Neil Shapiro { 29806f25ae9SGregory Neil Shapiro /* stop for now */ 29906f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 1) 30040266059SGregory Neil Shapiro sm_dprintf("[%d] cmd '%c' not impl\n", 30106f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, cmd); 30206f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 30306f25ae9SGregory Neil Shapiro break; 30406f25ae9SGregory Neil Shapiro } 30506f25ae9SGregory Neil Shapiro 30606f25ae9SGregory Neil Shapiro /* is new state ok? */ 30706f25ae9SGregory Neil Shapiro newstate = cmds[i].cm_next; 30806f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 5) 30940266059SGregory Neil Shapiro sm_dprintf("[%d] cur %x new %x nextmask %x\n", 31006f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, 31106f25ae9SGregory Neil Shapiro curstate, newstate, next_states[curstate]); 31206f25ae9SGregory Neil Shapiro 31306f25ae9SGregory Neil Shapiro if (newstate != ST_NONE && !trans_ok(curstate, newstate)) 31406f25ae9SGregory Neil Shapiro { 31506f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 1) 31640266059SGregory Neil Shapiro sm_dprintf("[%d] abort: cur %d (%x) new %d (%x) next %x\n", 31706f25ae9SGregory Neil Shapiro (int) ctx->ctx_id, 31813bd1963SGregory Neil Shapiro curstate, MI_MASK(curstate), 31913bd1963SGregory Neil Shapiro newstate, MI_MASK(newstate), 32006f25ae9SGregory Neil Shapiro next_states[curstate]); 32106f25ae9SGregory Neil Shapiro 32206f25ae9SGregory Neil Shapiro /* call abort only if in a mail transaction */ 32306f25ae9SGregory Neil Shapiro if (fi_abort != NULL && call_abort) 32406f25ae9SGregory Neil Shapiro (void) (*fi_abort)(ctx); 32506f25ae9SGregory Neil Shapiro 32606f25ae9SGregory Neil Shapiro /* 32706f25ae9SGregory Neil Shapiro ** try to reach the new state from HELO 32806f25ae9SGregory Neil Shapiro ** if it can't be reached, ignore the command. 32906f25ae9SGregory Neil Shapiro */ 33006f25ae9SGregory Neil Shapiro 33106f25ae9SGregory Neil Shapiro curstate = ST_HELO; 33206f25ae9SGregory Neil Shapiro if (!trans_ok(curstate, newstate)) 33340266059SGregory Neil Shapiro { 334959366dcSGregory Neil Shapiro if (buf != NULL) 335959366dcSGregory Neil Shapiro { 33640266059SGregory Neil Shapiro free(buf); 33740266059SGregory Neil Shapiro buf = NULL; 338959366dcSGregory Neil Shapiro } 33906f25ae9SGregory Neil Shapiro continue; 34006f25ae9SGregory Neil Shapiro } 34140266059SGregory Neil Shapiro } 34206f25ae9SGregory Neil Shapiro arg.a_len = len; 34306f25ae9SGregory Neil Shapiro arg.a_buf = buf; 34406f25ae9SGregory Neil Shapiro if (newstate != ST_NONE) 34506f25ae9SGregory Neil Shapiro { 34606f25ae9SGregory Neil Shapiro curstate = newstate; 34706f25ae9SGregory Neil Shapiro ctx->ctx_state = curstate; 34806f25ae9SGregory Neil Shapiro } 34906f25ae9SGregory Neil Shapiro arg.a_idx = cmds[i].cm_macros; 350b6bacd31SGregory Neil Shapiro call_abort = ST_IN_MAIL(curstate); 35106f25ae9SGregory Neil Shapiro 35206f25ae9SGregory Neil Shapiro /* call function to deal with command */ 35306f25ae9SGregory Neil Shapiro r = (*f)(&arg); 35406f25ae9SGregory Neil Shapiro if (r != _SMFIS_KEEP && buf != NULL) 35506f25ae9SGregory Neil Shapiro { 35606f25ae9SGregory Neil Shapiro free(buf); 35706f25ae9SGregory Neil Shapiro buf = NULL; 35806f25ae9SGregory Neil Shapiro } 35906f25ae9SGregory Neil Shapiro if (sendreply(r, sd, &timeout, ctx) != MI_SUCCESS) 36006f25ae9SGregory Neil Shapiro { 36106f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 36206f25ae9SGregory Neil Shapiro break; 36306f25ae9SGregory Neil Shapiro } 36406f25ae9SGregory Neil Shapiro 36506f25ae9SGregory Neil Shapiro if (r == SMFIS_ACCEPT) 36606f25ae9SGregory Neil Shapiro { 36706f25ae9SGregory Neil Shapiro /* accept mail, no further actions taken */ 36806f25ae9SGregory Neil Shapiro curstate = ST_HELO; 36906f25ae9SGregory Neil Shapiro } 37006f25ae9SGregory Neil Shapiro else if (r == SMFIS_REJECT || r == SMFIS_DISCARD || 37106f25ae9SGregory Neil Shapiro r == SMFIS_TEMPFAIL) 37206f25ae9SGregory Neil Shapiro { 37306f25ae9SGregory Neil Shapiro /* 37406f25ae9SGregory Neil Shapiro ** further actions depend on current state 37506f25ae9SGregory Neil Shapiro ** if the IGNO bit is set: "ignore" the error, 37606f25ae9SGregory Neil Shapiro ** i.e., stay in the current state 37706f25ae9SGregory Neil Shapiro */ 37806f25ae9SGregory Neil Shapiro if (!bitset(CT_IGNO, cmds[i].cm_todo)) 37906f25ae9SGregory Neil Shapiro curstate = ST_HELO; 38006f25ae9SGregory Neil Shapiro } 38106f25ae9SGregory Neil Shapiro else if (r == _SMFIS_ABORT) 38206f25ae9SGregory Neil Shapiro { 38306f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 5) 38440266059SGregory Neil Shapiro sm_dprintf("[%d] function returned abort\n", 38506f25ae9SGregory Neil Shapiro (int) ctx->ctx_id); 38606f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 38706f25ae9SGregory Neil Shapiro break; 38806f25ae9SGregory Neil Shapiro } 38906f25ae9SGregory Neil Shapiro } while (!bitset(CT_END, cmds[i].cm_todo)); 39006f25ae9SGregory Neil Shapiro 39106f25ae9SGregory Neil Shapiro if (ret != MI_SUCCESS) 39206f25ae9SGregory Neil Shapiro { 39306f25ae9SGregory Neil Shapiro /* call abort only if in a mail transaction */ 39406f25ae9SGregory Neil Shapiro if (fi_abort != NULL && call_abort) 39506f25ae9SGregory Neil Shapiro (void) (*fi_abort)(ctx); 39606f25ae9SGregory Neil Shapiro } 39706f25ae9SGregory Neil Shapiro 39806f25ae9SGregory Neil Shapiro /* close must always be called */ 39906f25ae9SGregory Neil Shapiro if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) 40006f25ae9SGregory Neil Shapiro (void) (*fi_close)(ctx); 40140266059SGregory Neil Shapiro if (r != _SMFIS_KEEP && buf != NULL) 40206f25ae9SGregory Neil Shapiro free(buf); 40306f25ae9SGregory Neil Shapiro mi_clr_macros(ctx, 0); 40406f25ae9SGregory Neil Shapiro return ret; 40506f25ae9SGregory Neil Shapiro } 40640266059SGregory Neil Shapiro /* 40706f25ae9SGregory Neil Shapiro ** SENDREPLY -- send a reply to the MTA 40806f25ae9SGregory Neil Shapiro ** 40906f25ae9SGregory Neil Shapiro ** Parameters: 41006f25ae9SGregory Neil Shapiro ** r -- reply code 41106f25ae9SGregory Neil Shapiro ** sd -- socket descriptor 41206f25ae9SGregory Neil Shapiro ** timeout_ptr -- (ptr to) timeout to use for sending 41306f25ae9SGregory Neil Shapiro ** ctx -- context structure 41406f25ae9SGregory Neil Shapiro ** 41506f25ae9SGregory Neil Shapiro ** Returns: 41606f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE 41706f25ae9SGregory Neil Shapiro */ 41806f25ae9SGregory Neil Shapiro 41906f25ae9SGregory Neil Shapiro static int 42006f25ae9SGregory Neil Shapiro sendreply(r, sd, timeout_ptr, ctx) 42106f25ae9SGregory Neil Shapiro sfsistat r; 42206f25ae9SGregory Neil Shapiro socket_t sd; 42306f25ae9SGregory Neil Shapiro struct timeval *timeout_ptr; 42406f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 42506f25ae9SGregory Neil Shapiro { 42606f25ae9SGregory Neil Shapiro int ret = MI_SUCCESS; 42706f25ae9SGregory Neil Shapiro 42806f25ae9SGregory Neil Shapiro switch (r) 42906f25ae9SGregory Neil Shapiro { 43006f25ae9SGregory Neil Shapiro case SMFIS_CONTINUE: 43106f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 0); 43206f25ae9SGregory Neil Shapiro break; 43306f25ae9SGregory Neil Shapiro case SMFIS_TEMPFAIL: 43406f25ae9SGregory Neil Shapiro case SMFIS_REJECT: 435605302a5SGregory Neil Shapiro if (ctx->ctx_reply != NULL && 436605302a5SGregory Neil Shapiro ((r == SMFIS_TEMPFAIL && *ctx->ctx_reply == '4') || 437605302a5SGregory Neil Shapiro (r == SMFIS_REJECT && *ctx->ctx_reply == '5'))) 43806f25ae9SGregory Neil Shapiro { 43906f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_REPLYCODE, 44006f25ae9SGregory Neil Shapiro ctx->ctx_reply, 44106f25ae9SGregory Neil Shapiro strlen(ctx->ctx_reply) + 1); 44206f25ae9SGregory Neil Shapiro free(ctx->ctx_reply); 44306f25ae9SGregory Neil Shapiro ctx->ctx_reply = NULL; 44406f25ae9SGregory Neil Shapiro } 44506f25ae9SGregory Neil Shapiro else 44606f25ae9SGregory Neil Shapiro { 44706f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, r == SMFIS_REJECT ? 44806f25ae9SGregory Neil Shapiro SMFIR_REJECT : SMFIR_TEMPFAIL, NULL, 0); 44906f25ae9SGregory Neil Shapiro } 45006f25ae9SGregory Neil Shapiro break; 45106f25ae9SGregory Neil Shapiro case SMFIS_DISCARD: 45206f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_DISCARD, NULL, 0); 45306f25ae9SGregory Neil Shapiro break; 45406f25ae9SGregory Neil Shapiro case SMFIS_ACCEPT: 45506f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_ACCEPT, NULL, 0); 45606f25ae9SGregory Neil Shapiro break; 45706f25ae9SGregory Neil Shapiro case _SMFIS_OPTIONS: 45806f25ae9SGregory Neil Shapiro { 45906f25ae9SGregory Neil Shapiro char buf[MILTER_OPTLEN]; 46006f25ae9SGregory Neil Shapiro mi_int32 v; 46106f25ae9SGregory Neil Shapiro 46206f25ae9SGregory Neil Shapiro v = htonl(ctx->ctx_smfi->xxfi_version); 46306f25ae9SGregory Neil Shapiro (void) memcpy(&(buf[0]), (void *) &v, MILTER_LEN_BYTES); 46406f25ae9SGregory Neil Shapiro v = htonl(ctx->ctx_smfi->xxfi_flags); 46506f25ae9SGregory Neil Shapiro (void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v, 46606f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 46706f25ae9SGregory Neil Shapiro v = htonl(ctx->ctx_pflags); 46806f25ae9SGregory Neil Shapiro (void) memcpy(&(buf[MILTER_LEN_BYTES * 2]), (void *) &v, 46906f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 47006f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG, buf, 47106f25ae9SGregory Neil Shapiro MILTER_OPTLEN); 47206f25ae9SGregory Neil Shapiro } 47306f25ae9SGregory Neil Shapiro break; 47406f25ae9SGregory Neil Shapiro default: /* don't send a reply */ 47506f25ae9SGregory Neil Shapiro break; 47606f25ae9SGregory Neil Shapiro } 47706f25ae9SGregory Neil Shapiro return ret; 47806f25ae9SGregory Neil Shapiro } 47906f25ae9SGregory Neil Shapiro 48006f25ae9SGregory Neil Shapiro /* 48106f25ae9SGregory Neil Shapiro ** CLR_MACROS -- clear set of macros starting from a given index 48206f25ae9SGregory Neil Shapiro ** 48306f25ae9SGregory Neil Shapiro ** Parameters: 48406f25ae9SGregory Neil Shapiro ** ctx -- context structure 48506f25ae9SGregory Neil Shapiro ** m -- index from which to clear all macros 48606f25ae9SGregory Neil Shapiro ** 48706f25ae9SGregory Neil Shapiro ** Returns: 48806f25ae9SGregory Neil Shapiro ** None. 48906f25ae9SGregory Neil Shapiro */ 49006f25ae9SGregory Neil Shapiro void 49106f25ae9SGregory Neil Shapiro mi_clr_macros(ctx, m) 49206f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 49306f25ae9SGregory Neil Shapiro int m; 49406f25ae9SGregory Neil Shapiro { 49506f25ae9SGregory Neil Shapiro int i; 49606f25ae9SGregory Neil Shapiro 49706f25ae9SGregory Neil Shapiro for (i = m; i < MAX_MACROS_ENTRIES; i++) 49806f25ae9SGregory Neil Shapiro { 49906f25ae9SGregory Neil Shapiro if (ctx->ctx_mac_ptr[i] != NULL) 50006f25ae9SGregory Neil Shapiro { 50106f25ae9SGregory Neil Shapiro free(ctx->ctx_mac_ptr[i]); 50206f25ae9SGregory Neil Shapiro ctx->ctx_mac_ptr[i] = NULL; 50306f25ae9SGregory Neil Shapiro } 50406f25ae9SGregory Neil Shapiro if (ctx->ctx_mac_buf[i] != NULL) 50506f25ae9SGregory Neil Shapiro { 50606f25ae9SGregory Neil Shapiro free(ctx->ctx_mac_buf[i]); 50706f25ae9SGregory Neil Shapiro ctx->ctx_mac_buf[i] = NULL; 50806f25ae9SGregory Neil Shapiro } 50906f25ae9SGregory Neil Shapiro } 51006f25ae9SGregory Neil Shapiro } 51140266059SGregory Neil Shapiro /* 51206f25ae9SGregory Neil Shapiro ** ST_OPTIONNEG -- negotiate options 51306f25ae9SGregory Neil Shapiro ** 51406f25ae9SGregory Neil Shapiro ** Parameters: 51506f25ae9SGregory Neil Shapiro ** g -- generic argument structure 51606f25ae9SGregory Neil Shapiro ** 51706f25ae9SGregory Neil Shapiro ** Returns: 51806f25ae9SGregory Neil Shapiro ** abort/send options/continue 51906f25ae9SGregory Neil Shapiro */ 52006f25ae9SGregory Neil Shapiro 52106f25ae9SGregory Neil Shapiro static int 52206f25ae9SGregory Neil Shapiro st_optionneg(g) 52306f25ae9SGregory Neil Shapiro genarg *g; 52406f25ae9SGregory Neil Shapiro { 52506f25ae9SGregory Neil Shapiro mi_int32 i, v; 52606f25ae9SGregory Neil Shapiro 52706f25ae9SGregory Neil Shapiro if (g == NULL || g->a_ctx->ctx_smfi == NULL) 52806f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 52906f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 53006f25ae9SGregory Neil Shapiro 53106f25ae9SGregory Neil Shapiro /* check for minimum length */ 53206f25ae9SGregory Neil Shapiro if (g->a_len < MILTER_OPTLEN) 53306f25ae9SGregory Neil Shapiro { 53406f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 53506f25ae9SGregory Neil Shapiro "%s: st_optionneg[%d]: len too short %d < %d", 53606f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 53713bd1963SGregory Neil Shapiro (int) g->a_ctx->ctx_id, (int) g->a_len, 53806f25ae9SGregory Neil Shapiro MILTER_OPTLEN); 53906f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 54006f25ae9SGregory Neil Shapiro } 54106f25ae9SGregory Neil Shapiro 54206f25ae9SGregory Neil Shapiro (void) memcpy((void *) &i, (void *) &(g->a_buf[0]), 54306f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 54406f25ae9SGregory Neil Shapiro v = ntohl(i); 54506f25ae9SGregory Neil Shapiro if (v < g->a_ctx->ctx_smfi->xxfi_version) 54606f25ae9SGregory Neil Shapiro { 54706f25ae9SGregory Neil Shapiro /* hard failure for now! */ 54806f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 54906f25ae9SGregory Neil Shapiro "%s: st_optionneg[%d]: version mismatch MTA: %d < milter: %d", 55006f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 55106f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id, (int) v, 55206f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_version); 55306f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 55406f25ae9SGregory Neil Shapiro } 55506f25ae9SGregory Neil Shapiro 55606f25ae9SGregory Neil Shapiro (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]), 55706f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 55806f25ae9SGregory Neil Shapiro v = ntohl(i); 55906f25ae9SGregory Neil Shapiro 56006f25ae9SGregory Neil Shapiro /* no flags? set to default value for V1 actions */ 56106f25ae9SGregory Neil Shapiro if (v == 0) 56206f25ae9SGregory Neil Shapiro v = SMFI_V1_ACTS; 56306f25ae9SGregory Neil Shapiro i = g->a_ctx->ctx_smfi->xxfi_flags; 56406f25ae9SGregory Neil Shapiro if ((v & i) != i) 56506f25ae9SGregory Neil Shapiro { 56606f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 56706f25ae9SGregory Neil Shapiro "%s: st_optionneg[%d]: 0x%x does not fulfill action requirements 0x%x", 56806f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 56906f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id, v, i); 57006f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 57106f25ae9SGregory Neil Shapiro } 57206f25ae9SGregory Neil Shapiro 57306f25ae9SGregory Neil Shapiro (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES * 2]), 57406f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 57506f25ae9SGregory Neil Shapiro v = ntohl(i); 57606f25ae9SGregory Neil Shapiro 57706f25ae9SGregory Neil Shapiro /* no flags? set to default value for V1 protocol */ 57806f25ae9SGregory Neil Shapiro if (v == 0) 57906f25ae9SGregory Neil Shapiro v = SMFI_V1_PROT; 58006f25ae9SGregory Neil Shapiro i = g->a_ctx->ctx_pflags; 58106f25ae9SGregory Neil Shapiro if ((v & i) != i) 58206f25ae9SGregory Neil Shapiro { 58306f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 58406f25ae9SGregory Neil Shapiro "%s: st_optionneg[%d]: 0x%x does not fulfill protocol requirements 0x%x", 58506f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 58606f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id, v, i); 58706f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 58806f25ae9SGregory Neil Shapiro } 58906f25ae9SGregory Neil Shapiro 59006f25ae9SGregory Neil Shapiro return _SMFIS_OPTIONS; 59106f25ae9SGregory Neil Shapiro } 59240266059SGregory Neil Shapiro /* 59306f25ae9SGregory Neil Shapiro ** ST_CONNECTINFO -- receive connection information 59406f25ae9SGregory Neil Shapiro ** 59506f25ae9SGregory Neil Shapiro ** Parameters: 59606f25ae9SGregory Neil Shapiro ** g -- generic argument structure 59706f25ae9SGregory Neil Shapiro ** 59806f25ae9SGregory Neil Shapiro ** Returns: 59906f25ae9SGregory Neil Shapiro ** continue or filter-specified value 60006f25ae9SGregory Neil Shapiro */ 60106f25ae9SGregory Neil Shapiro 60206f25ae9SGregory Neil Shapiro static int 60306f25ae9SGregory Neil Shapiro st_connectinfo(g) 60406f25ae9SGregory Neil Shapiro genarg *g; 60506f25ae9SGregory Neil Shapiro { 60606f25ae9SGregory Neil Shapiro size_t l; 60706f25ae9SGregory Neil Shapiro size_t i; 60806f25ae9SGregory Neil Shapiro char *s, family; 60940266059SGregory Neil Shapiro unsigned short port = 0; 61006f25ae9SGregory Neil Shapiro _SOCK_ADDR sockaddr; 61106f25ae9SGregory Neil Shapiro sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *)); 61206f25ae9SGregory Neil Shapiro 61306f25ae9SGregory Neil Shapiro if (g == NULL) 61406f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 61506f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 61606f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi == NULL || 61706f25ae9SGregory Neil Shapiro (fi_connect = g->a_ctx->ctx_smfi->xxfi_connect) == NULL) 61806f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 61906f25ae9SGregory Neil Shapiro 62006f25ae9SGregory Neil Shapiro s = g->a_buf; 62106f25ae9SGregory Neil Shapiro i = 0; 62206f25ae9SGregory Neil Shapiro l = g->a_len; 62306f25ae9SGregory Neil Shapiro while (s[i] != '\0' && i <= l) 62406f25ae9SGregory Neil Shapiro ++i; 625323f6dcbSGregory Neil Shapiro if (i + 1 >= l) 62606f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 62706f25ae9SGregory Neil Shapiro 62806f25ae9SGregory Neil Shapiro /* Move past trailing \0 in host string */ 62906f25ae9SGregory Neil Shapiro i++; 63006f25ae9SGregory Neil Shapiro family = s[i++]; 631a7ec597cSGregory Neil Shapiro (void) memset(&sockaddr, '\0', sizeof sockaddr); 63206f25ae9SGregory Neil Shapiro if (family != SMFIA_UNKNOWN) 63306f25ae9SGregory Neil Shapiro { 634323f6dcbSGregory Neil Shapiro if (i + sizeof port >= l) 63506f25ae9SGregory Neil Shapiro { 63606f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 63706f25ae9SGregory Neil Shapiro "%s: connect[%d]: wrong len %d >= %d", 63806f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 63913bd1963SGregory Neil Shapiro (int) g->a_ctx->ctx_id, (int) i, (int) l); 64006f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 64106f25ae9SGregory Neil Shapiro } 642323f6dcbSGregory Neil Shapiro (void) memcpy((void *) &port, (void *) (s + i), 643323f6dcbSGregory Neil Shapiro sizeof port); 644323f6dcbSGregory Neil Shapiro i += sizeof port; 645605302a5SGregory Neil Shapiro 646605302a5SGregory Neil Shapiro /* make sure string is terminated */ 647605302a5SGregory Neil Shapiro if (s[l - 1] != '\0') 648605302a5SGregory Neil Shapiro return _SMFIS_ABORT; 64906f25ae9SGregory Neil Shapiro # if NETINET 65006f25ae9SGregory Neil Shapiro if (family == SMFIA_INET) 65106f25ae9SGregory Neil Shapiro { 65206f25ae9SGregory Neil Shapiro if (inet_aton(s + i, (struct in_addr *) &sockaddr.sin.sin_addr) 653605302a5SGregory Neil Shapiro != 1) 65406f25ae9SGregory Neil Shapiro { 65506f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 65606f25ae9SGregory Neil Shapiro "%s: connect[%d]: inet_aton failed", 65706f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 65806f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id); 65906f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 66006f25ae9SGregory Neil Shapiro } 66106f25ae9SGregory Neil Shapiro sockaddr.sa.sa_family = AF_INET; 66206f25ae9SGregory Neil Shapiro if (port > 0) 66306f25ae9SGregory Neil Shapiro sockaddr.sin.sin_port = port; 66406f25ae9SGregory Neil Shapiro } 66506f25ae9SGregory Neil Shapiro else 66606f25ae9SGregory Neil Shapiro # endif /* NETINET */ 66706f25ae9SGregory Neil Shapiro # if NETINET6 66806f25ae9SGregory Neil Shapiro if (family == SMFIA_INET6) 66906f25ae9SGregory Neil Shapiro { 67040266059SGregory Neil Shapiro if (mi_inet_pton(AF_INET6, s + i, 67106f25ae9SGregory Neil Shapiro &sockaddr.sin6.sin6_addr) != 1) 67206f25ae9SGregory Neil Shapiro { 67306f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 67440266059SGregory Neil Shapiro "%s: connect[%d]: mi_inet_pton failed", 67506f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 67606f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id); 67706f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 67806f25ae9SGregory Neil Shapiro } 67906f25ae9SGregory Neil Shapiro sockaddr.sa.sa_family = AF_INET6; 68006f25ae9SGregory Neil Shapiro if (port > 0) 68106f25ae9SGregory Neil Shapiro sockaddr.sin6.sin6_port = port; 68206f25ae9SGregory Neil Shapiro } 68306f25ae9SGregory Neil Shapiro else 68406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 68506f25ae9SGregory Neil Shapiro # if NETUNIX 68606f25ae9SGregory Neil Shapiro if (family == SMFIA_UNIX) 68706f25ae9SGregory Neil Shapiro { 68840266059SGregory Neil Shapiro if (sm_strlcpy(sockaddr.sunix.sun_path, s + i, 68906f25ae9SGregory Neil Shapiro sizeof sockaddr.sunix.sun_path) >= 69006f25ae9SGregory Neil Shapiro sizeof sockaddr.sunix.sun_path) 69106f25ae9SGregory Neil Shapiro { 69206f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 69306f25ae9SGregory Neil Shapiro "%s: connect[%d]: path too long", 69406f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 69506f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id); 69606f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 69706f25ae9SGregory Neil Shapiro } 69806f25ae9SGregory Neil Shapiro sockaddr.sunix.sun_family = AF_UNIX; 69906f25ae9SGregory Neil Shapiro } 70006f25ae9SGregory Neil Shapiro else 70106f25ae9SGregory Neil Shapiro # endif /* NETUNIX */ 70206f25ae9SGregory Neil Shapiro { 70306f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 70406f25ae9SGregory Neil Shapiro "%s: connect[%d]: unknown family %d", 70506f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 70606f25ae9SGregory Neil Shapiro (int) g->a_ctx->ctx_id, family); 70706f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 70806f25ae9SGregory Neil Shapiro } 70906f25ae9SGregory Neil Shapiro } 71006f25ae9SGregory Neil Shapiro return (*fi_connect)(g->a_ctx, g->a_buf, 71106f25ae9SGregory Neil Shapiro family != SMFIA_UNKNOWN ? &sockaddr : NULL); 71206f25ae9SGregory Neil Shapiro } 713e92d3f3fSGregory Neil Shapiro 71440266059SGregory Neil Shapiro /* 71506f25ae9SGregory Neil Shapiro ** ST_EOH -- end of headers 71606f25ae9SGregory Neil Shapiro ** 71706f25ae9SGregory Neil Shapiro ** Parameters: 71806f25ae9SGregory Neil Shapiro ** g -- generic argument structure 71906f25ae9SGregory Neil Shapiro ** 72006f25ae9SGregory Neil Shapiro ** Returns: 72106f25ae9SGregory Neil Shapiro ** continue or filter-specified value 72206f25ae9SGregory Neil Shapiro */ 72306f25ae9SGregory Neil Shapiro 72406f25ae9SGregory Neil Shapiro static int 72506f25ae9SGregory Neil Shapiro st_eoh(g) 72606f25ae9SGregory Neil Shapiro genarg *g; 72706f25ae9SGregory Neil Shapiro { 72806f25ae9SGregory Neil Shapiro sfsistat (*fi_eoh) __P((SMFICTX *)); 72906f25ae9SGregory Neil Shapiro 73006f25ae9SGregory Neil Shapiro if (g == NULL) 73106f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 73206f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 73306f25ae9SGregory Neil Shapiro (fi_eoh = g->a_ctx->ctx_smfi->xxfi_eoh) != NULL) 73406f25ae9SGregory Neil Shapiro return (*fi_eoh)(g->a_ctx); 73506f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 73606f25ae9SGregory Neil Shapiro } 737e92d3f3fSGregory Neil Shapiro 738e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 3 739e92d3f3fSGregory Neil Shapiro /* 740e92d3f3fSGregory Neil Shapiro ** ST_DATA -- DATA command 741e92d3f3fSGregory Neil Shapiro ** 742e92d3f3fSGregory Neil Shapiro ** Parameters: 743e92d3f3fSGregory Neil Shapiro ** g -- generic argument structure 744e92d3f3fSGregory Neil Shapiro ** 745e92d3f3fSGregory Neil Shapiro ** Returns: 746e92d3f3fSGregory Neil Shapiro ** continue or filter-specified value 747e92d3f3fSGregory Neil Shapiro */ 748e92d3f3fSGregory Neil Shapiro 749e92d3f3fSGregory Neil Shapiro static int 750e92d3f3fSGregory Neil Shapiro st_data(g) 751e92d3f3fSGregory Neil Shapiro genarg *g; 752e92d3f3fSGregory Neil Shapiro { 753e92d3f3fSGregory Neil Shapiro sfsistat (*fi_data) __P((SMFICTX *)); 754e92d3f3fSGregory Neil Shapiro 755e92d3f3fSGregory Neil Shapiro if (g == NULL) 756e92d3f3fSGregory Neil Shapiro return _SMFIS_ABORT; 757e92d3f3fSGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 758e92d3f3fSGregory Neil Shapiro (fi_data = g->a_ctx->ctx_smfi->xxfi_data) != NULL) 759e92d3f3fSGregory Neil Shapiro return (*fi_data)(g->a_ctx); 760e92d3f3fSGregory Neil Shapiro return SMFIS_CONTINUE; 761e92d3f3fSGregory Neil Shapiro } 762e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 3 */ 763e92d3f3fSGregory Neil Shapiro 76440266059SGregory Neil Shapiro /* 76506f25ae9SGregory Neil Shapiro ** ST_HELO -- helo/ehlo command 76606f25ae9SGregory Neil Shapiro ** 76706f25ae9SGregory Neil Shapiro ** Parameters: 76806f25ae9SGregory Neil Shapiro ** g -- generic argument structure 76906f25ae9SGregory Neil Shapiro ** 77006f25ae9SGregory Neil Shapiro ** Returns: 77106f25ae9SGregory Neil Shapiro ** continue or filter-specified value 77206f25ae9SGregory Neil Shapiro */ 77306f25ae9SGregory Neil Shapiro static int 77406f25ae9SGregory Neil Shapiro st_helo(g) 77506f25ae9SGregory Neil Shapiro genarg *g; 77606f25ae9SGregory Neil Shapiro { 77706f25ae9SGregory Neil Shapiro sfsistat (*fi_helo) __P((SMFICTX *, char *)); 77806f25ae9SGregory Neil Shapiro 77906f25ae9SGregory Neil Shapiro if (g == NULL) 78006f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 78106f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 78206f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 78306f25ae9SGregory Neil Shapiro (fi_helo = g->a_ctx->ctx_smfi->xxfi_helo) != NULL) 784323f6dcbSGregory Neil Shapiro { 785323f6dcbSGregory Neil Shapiro /* paranoia: check for terminating '\0' */ 786323f6dcbSGregory Neil Shapiro if (g->a_len == 0 || g->a_buf[g->a_len - 1] != '\0') 787323f6dcbSGregory Neil Shapiro return MI_FAILURE; 78806f25ae9SGregory Neil Shapiro return (*fi_helo)(g->a_ctx, g->a_buf); 789323f6dcbSGregory Neil Shapiro } 79006f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 79106f25ae9SGregory Neil Shapiro } 79240266059SGregory Neil Shapiro /* 79306f25ae9SGregory Neil Shapiro ** ST_HEADER -- header line 79406f25ae9SGregory Neil Shapiro ** 79506f25ae9SGregory Neil Shapiro ** Parameters: 79606f25ae9SGregory Neil Shapiro ** g -- generic argument structure 79706f25ae9SGregory Neil Shapiro ** 79806f25ae9SGregory Neil Shapiro ** Returns: 79906f25ae9SGregory Neil Shapiro ** continue or filter-specified value 80006f25ae9SGregory Neil Shapiro */ 80106f25ae9SGregory Neil Shapiro 80206f25ae9SGregory Neil Shapiro static int 80306f25ae9SGregory Neil Shapiro st_header(g) 80406f25ae9SGregory Neil Shapiro genarg *g; 80506f25ae9SGregory Neil Shapiro { 80606f25ae9SGregory Neil Shapiro char *hf, *hv; 80706f25ae9SGregory Neil Shapiro sfsistat (*fi_header) __P((SMFICTX *, char *, char *)); 80806f25ae9SGregory Neil Shapiro 80906f25ae9SGregory Neil Shapiro if (g == NULL) 81006f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 81106f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi == NULL || 81206f25ae9SGregory Neil Shapiro (fi_header = g->a_ctx->ctx_smfi->xxfi_header) == NULL) 81306f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 81406f25ae9SGregory Neil Shapiro if (dec_arg2(g->a_buf, g->a_len, &hf, &hv) == MI_SUCCESS) 81506f25ae9SGregory Neil Shapiro return (*fi_header)(g->a_ctx, hf, hv); 81606f25ae9SGregory Neil Shapiro else 81706f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 81806f25ae9SGregory Neil Shapiro } 81906f25ae9SGregory Neil Shapiro 82006f25ae9SGregory Neil Shapiro #define ARGV_FCT(lf, rf, idx) \ 82106f25ae9SGregory Neil Shapiro char **argv; \ 82206f25ae9SGregory Neil Shapiro sfsistat (*lf) __P((SMFICTX *, char **)); \ 82306f25ae9SGregory Neil Shapiro int r; \ 82406f25ae9SGregory Neil Shapiro \ 82506f25ae9SGregory Neil Shapiro if (g == NULL) \ 82606f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; \ 82706f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); \ 82806f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi == NULL || \ 82906f25ae9SGregory Neil Shapiro (lf = g->a_ctx->ctx_smfi->rf) == NULL) \ 83006f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; \ 83106f25ae9SGregory Neil Shapiro if ((argv = dec_argv(g->a_buf, g->a_len)) == NULL) \ 83206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; \ 83306f25ae9SGregory Neil Shapiro r = (*lf)(g->a_ctx, argv); \ 83406f25ae9SGregory Neil Shapiro free(argv); \ 83506f25ae9SGregory Neil Shapiro return r; 83606f25ae9SGregory Neil Shapiro 83740266059SGregory Neil Shapiro /* 83806f25ae9SGregory Neil Shapiro ** ST_SENDER -- MAIL FROM command 83906f25ae9SGregory Neil Shapiro ** 84006f25ae9SGregory Neil Shapiro ** Parameters: 84106f25ae9SGregory Neil Shapiro ** g -- generic argument structure 84206f25ae9SGregory Neil Shapiro ** 84306f25ae9SGregory Neil Shapiro ** Returns: 84406f25ae9SGregory Neil Shapiro ** continue or filter-specified value 84506f25ae9SGregory Neil Shapiro */ 84606f25ae9SGregory Neil Shapiro 84706f25ae9SGregory Neil Shapiro static int 84806f25ae9SGregory Neil Shapiro st_sender(g) 84906f25ae9SGregory Neil Shapiro genarg *g; 85006f25ae9SGregory Neil Shapiro { 85106f25ae9SGregory Neil Shapiro ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL) 85206f25ae9SGregory Neil Shapiro } 85340266059SGregory Neil Shapiro /* 85406f25ae9SGregory Neil Shapiro ** ST_RCPT -- RCPT TO command 85506f25ae9SGregory Neil Shapiro ** 85606f25ae9SGregory Neil Shapiro ** Parameters: 85706f25ae9SGregory Neil Shapiro ** g -- generic argument structure 85806f25ae9SGregory Neil Shapiro ** 85906f25ae9SGregory Neil Shapiro ** Returns: 86006f25ae9SGregory Neil Shapiro ** continue or filter-specified value 86106f25ae9SGregory Neil Shapiro */ 86206f25ae9SGregory Neil Shapiro 86306f25ae9SGregory Neil Shapiro static int 86406f25ae9SGregory Neil Shapiro st_rcpt(g) 86506f25ae9SGregory Neil Shapiro genarg *g; 86606f25ae9SGregory Neil Shapiro { 86706f25ae9SGregory Neil Shapiro ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT) 86806f25ae9SGregory Neil Shapiro } 869e92d3f3fSGregory Neil Shapiro 870e92d3f3fSGregory Neil Shapiro #if SMFI_VERSION > 2 871e92d3f3fSGregory Neil Shapiro /* 872e92d3f3fSGregory Neil Shapiro ** ST_UNKNOWN -- unrecognized or unimplemented command 873e92d3f3fSGregory Neil Shapiro ** 874e92d3f3fSGregory Neil Shapiro ** Parameters: 875e92d3f3fSGregory Neil Shapiro ** g -- generic argument structure 876e92d3f3fSGregory Neil Shapiro ** 877e92d3f3fSGregory Neil Shapiro ** Returns: 878e92d3f3fSGregory Neil Shapiro ** continue or filter-specified value 879e92d3f3fSGregory Neil Shapiro */ 880e92d3f3fSGregory Neil Shapiro 881e92d3f3fSGregory Neil Shapiro static int 882e92d3f3fSGregory Neil Shapiro st_unknown(g) 883e92d3f3fSGregory Neil Shapiro genarg *g; 884e92d3f3fSGregory Neil Shapiro { 885e92d3f3fSGregory Neil Shapiro sfsistat (*fi_unknown) __P((SMFICTX *, char *)); 886e92d3f3fSGregory Neil Shapiro 887e92d3f3fSGregory Neil Shapiro if (g == NULL) 888e92d3f3fSGregory Neil Shapiro return _SMFIS_ABORT; 889e92d3f3fSGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 890e92d3f3fSGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 891e92d3f3fSGregory Neil Shapiro (fi_unknown = g->a_ctx->ctx_smfi->xxfi_unknown) != NULL) 892e92d3f3fSGregory Neil Shapiro return (*fi_unknown)(g->a_ctx, g->a_buf); 893e92d3f3fSGregory Neil Shapiro return SMFIS_CONTINUE; 894e92d3f3fSGregory Neil Shapiro } 895e92d3f3fSGregory Neil Shapiro #endif /* SMFI_VERSION > 2 */ 896e92d3f3fSGregory Neil Shapiro 89740266059SGregory Neil Shapiro /* 89806f25ae9SGregory Neil Shapiro ** ST_MACROS -- deal with macros received from the MTA 89906f25ae9SGregory Neil Shapiro ** 90006f25ae9SGregory Neil Shapiro ** Parameters: 90106f25ae9SGregory Neil Shapiro ** g -- generic argument structure 90206f25ae9SGregory Neil Shapiro ** 90306f25ae9SGregory Neil Shapiro ** Returns: 90406f25ae9SGregory Neil Shapiro ** continue/keep 90506f25ae9SGregory Neil Shapiro ** 90606f25ae9SGregory Neil Shapiro ** Side effects: 90706f25ae9SGregory Neil Shapiro ** set pointer in macro array to current values. 90806f25ae9SGregory Neil Shapiro */ 90906f25ae9SGregory Neil Shapiro 91006f25ae9SGregory Neil Shapiro static int 91106f25ae9SGregory Neil Shapiro st_macros(g) 91206f25ae9SGregory Neil Shapiro genarg *g; 91306f25ae9SGregory Neil Shapiro { 91406f25ae9SGregory Neil Shapiro int i; 91506f25ae9SGregory Neil Shapiro char **argv; 91606f25ae9SGregory Neil Shapiro 91706f25ae9SGregory Neil Shapiro if (g == NULL || g->a_len < 1) 91806f25ae9SGregory Neil Shapiro return _SMFIS_FAIL; 91906f25ae9SGregory Neil Shapiro if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL) 92006f25ae9SGregory Neil Shapiro return _SMFIS_FAIL; 92106f25ae9SGregory Neil Shapiro switch (g->a_buf[0]) 92206f25ae9SGregory Neil Shapiro { 92306f25ae9SGregory Neil Shapiro case SMFIC_CONNECT: 92406f25ae9SGregory Neil Shapiro i = CI_CONN; 92506f25ae9SGregory Neil Shapiro break; 92606f25ae9SGregory Neil Shapiro case SMFIC_HELO: 92706f25ae9SGregory Neil Shapiro i = CI_HELO; 92806f25ae9SGregory Neil Shapiro break; 92906f25ae9SGregory Neil Shapiro case SMFIC_MAIL: 93006f25ae9SGregory Neil Shapiro i = CI_MAIL; 93106f25ae9SGregory Neil Shapiro break; 93206f25ae9SGregory Neil Shapiro case SMFIC_RCPT: 93306f25ae9SGregory Neil Shapiro i = CI_RCPT; 93406f25ae9SGregory Neil Shapiro break; 935323f6dcbSGregory Neil Shapiro case SMFIC_BODYEOB: 936323f6dcbSGregory Neil Shapiro i = CI_EOM; 937323f6dcbSGregory Neil Shapiro break; 93806f25ae9SGregory Neil Shapiro default: 93906f25ae9SGregory Neil Shapiro free(argv); 94006f25ae9SGregory Neil Shapiro return _SMFIS_FAIL; 94106f25ae9SGregory Neil Shapiro } 94206f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_mac_ptr[i] != NULL) 94306f25ae9SGregory Neil Shapiro free(g->a_ctx->ctx_mac_ptr[i]); 94406f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_mac_buf[i] != NULL) 94506f25ae9SGregory Neil Shapiro free(g->a_ctx->ctx_mac_buf[i]); 94606f25ae9SGregory Neil Shapiro g->a_ctx->ctx_mac_ptr[i] = argv; 94706f25ae9SGregory Neil Shapiro g->a_ctx->ctx_mac_buf[i] = g->a_buf; 94806f25ae9SGregory Neil Shapiro return _SMFIS_KEEP; 94906f25ae9SGregory Neil Shapiro } 95040266059SGregory Neil Shapiro /* 95106f25ae9SGregory Neil Shapiro ** ST_QUIT -- quit command 95206f25ae9SGregory Neil Shapiro ** 95306f25ae9SGregory Neil Shapiro ** Parameters: 95406f25ae9SGregory Neil Shapiro ** g -- generic argument structure 95506f25ae9SGregory Neil Shapiro ** 95606f25ae9SGregory Neil Shapiro ** Returns: 95706f25ae9SGregory Neil Shapiro ** noreply 95806f25ae9SGregory Neil Shapiro */ 95906f25ae9SGregory Neil Shapiro 960a7ec597cSGregory Neil Shapiro /* ARGSUSED */ 96106f25ae9SGregory Neil Shapiro static int 96206f25ae9SGregory Neil Shapiro st_quit(g) 96306f25ae9SGregory Neil Shapiro genarg *g; 96406f25ae9SGregory Neil Shapiro { 96506f25ae9SGregory Neil Shapiro return _SMFIS_NOREPLY; 96606f25ae9SGregory Neil Shapiro } 96740266059SGregory Neil Shapiro /* 96806f25ae9SGregory Neil Shapiro ** ST_BODYCHUNK -- deal with a piece of the mail body 96906f25ae9SGregory Neil Shapiro ** 97006f25ae9SGregory Neil Shapiro ** Parameters: 97106f25ae9SGregory Neil Shapiro ** g -- generic argument structure 97206f25ae9SGregory Neil Shapiro ** 97306f25ae9SGregory Neil Shapiro ** Returns: 97406f25ae9SGregory Neil Shapiro ** continue or filter-specified value 97506f25ae9SGregory Neil Shapiro */ 97606f25ae9SGregory Neil Shapiro 97706f25ae9SGregory Neil Shapiro static int 97806f25ae9SGregory Neil Shapiro st_bodychunk(g) 97906f25ae9SGregory Neil Shapiro genarg *g; 98006f25ae9SGregory Neil Shapiro { 98140266059SGregory Neil Shapiro sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t)); 98206f25ae9SGregory Neil Shapiro 98306f25ae9SGregory Neil Shapiro if (g == NULL) 98406f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 98506f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 98606f25ae9SGregory Neil Shapiro (fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL) 98740266059SGregory Neil Shapiro return (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf, 98840266059SGregory Neil Shapiro g->a_len); 98906f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 99006f25ae9SGregory Neil Shapiro } 99140266059SGregory Neil Shapiro /* 99206f25ae9SGregory Neil Shapiro ** ST_BODYEND -- deal with the last piece of the mail body 99306f25ae9SGregory Neil Shapiro ** 99406f25ae9SGregory Neil Shapiro ** Parameters: 99506f25ae9SGregory Neil Shapiro ** g -- generic argument structure 99606f25ae9SGregory Neil Shapiro ** 99706f25ae9SGregory Neil Shapiro ** Returns: 99806f25ae9SGregory Neil Shapiro ** continue or filter-specified value 99906f25ae9SGregory Neil Shapiro ** 100006f25ae9SGregory Neil Shapiro ** Side effects: 100106f25ae9SGregory Neil Shapiro ** sends a reply for the body part (if non-empty). 100206f25ae9SGregory Neil Shapiro */ 100306f25ae9SGregory Neil Shapiro 100406f25ae9SGregory Neil Shapiro static int 100506f25ae9SGregory Neil Shapiro st_bodyend(g) 100606f25ae9SGregory Neil Shapiro genarg *g; 100706f25ae9SGregory Neil Shapiro { 100806f25ae9SGregory Neil Shapiro sfsistat r; 100940266059SGregory Neil Shapiro sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t)); 101006f25ae9SGregory Neil Shapiro sfsistat (*fi_eom) __P((SMFICTX *)); 101106f25ae9SGregory Neil Shapiro 101206f25ae9SGregory Neil Shapiro if (g == NULL) 101306f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 101406f25ae9SGregory Neil Shapiro r = SMFIS_CONTINUE; 101506f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL) 101606f25ae9SGregory Neil Shapiro { 101706f25ae9SGregory Neil Shapiro if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL && 101806f25ae9SGregory Neil Shapiro g->a_len > 0) 101906f25ae9SGregory Neil Shapiro { 102006f25ae9SGregory Neil Shapiro socket_t sd; 102106f25ae9SGregory Neil Shapiro struct timeval timeout; 102206f25ae9SGregory Neil Shapiro 102306f25ae9SGregory Neil Shapiro timeout.tv_sec = g->a_ctx->ctx_timeout; 102406f25ae9SGregory Neil Shapiro timeout.tv_usec = 0; 102506f25ae9SGregory Neil Shapiro sd = g->a_ctx->ctx_sd; 102640266059SGregory Neil Shapiro r = (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf, 102740266059SGregory Neil Shapiro g->a_len); 102806f25ae9SGregory Neil Shapiro if (r != SMFIS_CONTINUE && 102906f25ae9SGregory Neil Shapiro sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS) 103006f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 103106f25ae9SGregory Neil Shapiro } 103206f25ae9SGregory Neil Shapiro } 103306f25ae9SGregory Neil Shapiro if (r == SMFIS_CONTINUE && 103406f25ae9SGregory Neil Shapiro (fi_eom = g->a_ctx->ctx_smfi->xxfi_eom) != NULL) 103506f25ae9SGregory Neil Shapiro return (*fi_eom)(g->a_ctx); 103606f25ae9SGregory Neil Shapiro return r; 103706f25ae9SGregory Neil Shapiro } 103840266059SGregory Neil Shapiro /* 103906f25ae9SGregory Neil Shapiro ** ST_ABORTFCT -- deal with aborts 104006f25ae9SGregory Neil Shapiro ** 104106f25ae9SGregory Neil Shapiro ** Parameters: 104206f25ae9SGregory Neil Shapiro ** g -- generic argument structure 104306f25ae9SGregory Neil Shapiro ** 104406f25ae9SGregory Neil Shapiro ** Returns: 104506f25ae9SGregory Neil Shapiro ** abort or filter-specified value 104606f25ae9SGregory Neil Shapiro */ 104706f25ae9SGregory Neil Shapiro 104806f25ae9SGregory Neil Shapiro static int 104906f25ae9SGregory Neil Shapiro st_abortfct(g) 105006f25ae9SGregory Neil Shapiro genarg *g; 105106f25ae9SGregory Neil Shapiro { 105206f25ae9SGregory Neil Shapiro sfsistat (*fi_abort) __P((SMFICTX *)); 105306f25ae9SGregory Neil Shapiro 105406f25ae9SGregory Neil Shapiro if (g == NULL) 105506f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 105606f25ae9SGregory Neil Shapiro if (g != NULL && g->a_ctx->ctx_smfi != NULL && 105706f25ae9SGregory Neil Shapiro (fi_abort = g->a_ctx->ctx_smfi->xxfi_abort) != NULL) 105806f25ae9SGregory Neil Shapiro (void) (*fi_abort)(g->a_ctx); 105906f25ae9SGregory Neil Shapiro return _SMFIS_NOREPLY; 106006f25ae9SGregory Neil Shapiro } 106140266059SGregory Neil Shapiro /* 106206f25ae9SGregory Neil Shapiro ** TRANS_OK -- is the state transition ok? 106306f25ae9SGregory Neil Shapiro ** 106406f25ae9SGregory Neil Shapiro ** Parameters: 106506f25ae9SGregory Neil Shapiro ** old -- old state 106606f25ae9SGregory Neil Shapiro ** new -- new state 106706f25ae9SGregory Neil Shapiro ** 106806f25ae9SGregory Neil Shapiro ** Returns: 106906f25ae9SGregory Neil Shapiro ** state transition ok 107006f25ae9SGregory Neil Shapiro */ 107106f25ae9SGregory Neil Shapiro 107206f25ae9SGregory Neil Shapiro static bool 107306f25ae9SGregory Neil Shapiro trans_ok(old, new) 107406f25ae9SGregory Neil Shapiro int old, new; 107506f25ae9SGregory Neil Shapiro { 107606f25ae9SGregory Neil Shapiro int s, n; 107706f25ae9SGregory Neil Shapiro 107806f25ae9SGregory Neil Shapiro s = old; 107942e5d165SGregory Neil Shapiro do 108042e5d165SGregory Neil Shapiro { 108106f25ae9SGregory Neil Shapiro /* is this state transition allowed? */ 108213bd1963SGregory Neil Shapiro if ((MI_MASK(new) & next_states[s]) != 0) 108340266059SGregory Neil Shapiro return true; 108406f25ae9SGregory Neil Shapiro 108506f25ae9SGregory Neil Shapiro /* 108606f25ae9SGregory Neil Shapiro ** no: try next state; 108706f25ae9SGregory Neil Shapiro ** this works since the relevant states are ordered 108806f25ae9SGregory Neil Shapiro ** strict sequentially 108906f25ae9SGregory Neil Shapiro */ 109040266059SGregory Neil Shapiro 109106f25ae9SGregory Neil Shapiro n = s + 1; 109206f25ae9SGregory Neil Shapiro 109306f25ae9SGregory Neil Shapiro /* 109406f25ae9SGregory Neil Shapiro ** can we actually "skip" this state? 109506f25ae9SGregory Neil Shapiro ** see fix_stm() which sets this bit for those 109606f25ae9SGregory Neil Shapiro ** states which the filter program is not interested in 109706f25ae9SGregory Neil Shapiro */ 109840266059SGregory Neil Shapiro 109906f25ae9SGregory Neil Shapiro if (bitset(NX_SKIP, next_states[n])) 110006f25ae9SGregory Neil Shapiro s = n; 110106f25ae9SGregory Neil Shapiro else 110240266059SGregory Neil Shapiro return false; 110306f25ae9SGregory Neil Shapiro } while (s <= ST_LAST); 110440266059SGregory Neil Shapiro return false; 110506f25ae9SGregory Neil Shapiro } 110640266059SGregory Neil Shapiro /* 110706f25ae9SGregory Neil Shapiro ** FIX_STM -- add "skip" bits to the state transition table 110806f25ae9SGregory Neil Shapiro ** 110906f25ae9SGregory Neil Shapiro ** Parameters: 111006f25ae9SGregory Neil Shapiro ** ctx -- context structure 111106f25ae9SGregory Neil Shapiro ** 111206f25ae9SGregory Neil Shapiro ** Returns: 111306f25ae9SGregory Neil Shapiro ** None. 111406f25ae9SGregory Neil Shapiro ** 111506f25ae9SGregory Neil Shapiro ** Side effects: 111606f25ae9SGregory Neil Shapiro ** may change state transition table. 111706f25ae9SGregory Neil Shapiro */ 111806f25ae9SGregory Neil Shapiro 111906f25ae9SGregory Neil Shapiro static void 112006f25ae9SGregory Neil Shapiro fix_stm(ctx) 112106f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 112206f25ae9SGregory Neil Shapiro { 112340266059SGregory Neil Shapiro unsigned long fl; 112406f25ae9SGregory Neil Shapiro 112506f25ae9SGregory Neil Shapiro if (ctx == NULL || ctx->ctx_smfi == NULL) 112606f25ae9SGregory Neil Shapiro return; 112706f25ae9SGregory Neil Shapiro fl = ctx->ctx_pflags; 112806f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOCONNECT, fl)) 112906f25ae9SGregory Neil Shapiro next_states[ST_CONN] |= NX_SKIP; 113006f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOHELO, fl)) 113106f25ae9SGregory Neil Shapiro next_states[ST_HELO] |= NX_SKIP; 113206f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOMAIL, fl)) 113306f25ae9SGregory Neil Shapiro next_states[ST_MAIL] |= NX_SKIP; 113406f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NORCPT, fl)) 113506f25ae9SGregory Neil Shapiro next_states[ST_RCPT] |= NX_SKIP; 113606f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOHDRS, fl)) 113706f25ae9SGregory Neil Shapiro next_states[ST_HDRS] |= NX_SKIP; 113806f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOEOH, fl)) 113906f25ae9SGregory Neil Shapiro next_states[ST_EOHS] |= NX_SKIP; 114006f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOBODY, fl)) 114106f25ae9SGregory Neil Shapiro next_states[ST_BODY] |= NX_SKIP; 114206f25ae9SGregory Neil Shapiro } 114340266059SGregory Neil Shapiro /* 114406f25ae9SGregory Neil Shapiro ** DEC_ARGV -- split a buffer into a list of strings, NULL terminated 114506f25ae9SGregory Neil Shapiro ** 114606f25ae9SGregory Neil Shapiro ** Parameters: 114706f25ae9SGregory Neil Shapiro ** buf -- buffer with several strings 114806f25ae9SGregory Neil Shapiro ** len -- length of buffer 114906f25ae9SGregory Neil Shapiro ** 115006f25ae9SGregory Neil Shapiro ** Returns: 115106f25ae9SGregory Neil Shapiro ** array of pointers to the individual strings 115206f25ae9SGregory Neil Shapiro */ 115306f25ae9SGregory Neil Shapiro 115406f25ae9SGregory Neil Shapiro static char ** 115506f25ae9SGregory Neil Shapiro dec_argv(buf, len) 115606f25ae9SGregory Neil Shapiro char *buf; 115706f25ae9SGregory Neil Shapiro size_t len; 115806f25ae9SGregory Neil Shapiro { 115906f25ae9SGregory Neil Shapiro char **s; 116006f25ae9SGregory Neil Shapiro size_t i; 116106f25ae9SGregory Neil Shapiro int elem, nelem; 116206f25ae9SGregory Neil Shapiro 116306f25ae9SGregory Neil Shapiro nelem = 0; 116406f25ae9SGregory Neil Shapiro for (i = 0; i < len; i++) 116506f25ae9SGregory Neil Shapiro { 116606f25ae9SGregory Neil Shapiro if (buf[i] == '\0') 116706f25ae9SGregory Neil Shapiro ++nelem; 116806f25ae9SGregory Neil Shapiro } 116906f25ae9SGregory Neil Shapiro if (nelem == 0) 117006f25ae9SGregory Neil Shapiro return NULL; 117106f25ae9SGregory Neil Shapiro 117206f25ae9SGregory Neil Shapiro /* last entry is only for the name */ 117306f25ae9SGregory Neil Shapiro s = (char **)malloc((nelem + 1) * (sizeof *s)); 117406f25ae9SGregory Neil Shapiro if (s == NULL) 117506f25ae9SGregory Neil Shapiro return NULL; 117606f25ae9SGregory Neil Shapiro s[0] = buf; 117706f25ae9SGregory Neil Shapiro for (i = 0, elem = 0; i < len && elem < nelem; i++) 117806f25ae9SGregory Neil Shapiro { 117906f25ae9SGregory Neil Shapiro if (buf[i] == '\0') 1180323f6dcbSGregory Neil Shapiro { 1181323f6dcbSGregory Neil Shapiro ++elem; 1182323f6dcbSGregory Neil Shapiro if (i + 1 >= len) 1183323f6dcbSGregory Neil Shapiro s[elem] = NULL; 1184323f6dcbSGregory Neil Shapiro else 1185323f6dcbSGregory Neil Shapiro s[elem] = &(buf[i + 1]); 1186323f6dcbSGregory Neil Shapiro } 118706f25ae9SGregory Neil Shapiro } 118806f25ae9SGregory Neil Shapiro 1189323f6dcbSGregory Neil Shapiro /* overwrite last entry (already done above, just paranoia) */ 119006f25ae9SGregory Neil Shapiro s[elem] = NULL; 119106f25ae9SGregory Neil Shapiro return s; 119206f25ae9SGregory Neil Shapiro } 119340266059SGregory Neil Shapiro /* 119406f25ae9SGregory Neil Shapiro ** DEC_ARG2 -- split a buffer into two strings 119506f25ae9SGregory Neil Shapiro ** 119606f25ae9SGregory Neil Shapiro ** Parameters: 119706f25ae9SGregory Neil Shapiro ** buf -- buffer with two strings 119806f25ae9SGregory Neil Shapiro ** len -- length of buffer 119906f25ae9SGregory Neil Shapiro ** s1,s2 -- pointer to result strings 120006f25ae9SGregory Neil Shapiro ** 120106f25ae9SGregory Neil Shapiro ** Returns: 120206f25ae9SGregory Neil Shapiro ** MI_FAILURE/MI_SUCCESS 120306f25ae9SGregory Neil Shapiro */ 120406f25ae9SGregory Neil Shapiro 120506f25ae9SGregory Neil Shapiro static int 120606f25ae9SGregory Neil Shapiro dec_arg2(buf, len, s1, s2) 120706f25ae9SGregory Neil Shapiro char *buf; 120806f25ae9SGregory Neil Shapiro size_t len; 120906f25ae9SGregory Neil Shapiro char **s1; 121006f25ae9SGregory Neil Shapiro char **s2; 121106f25ae9SGregory Neil Shapiro { 121206f25ae9SGregory Neil Shapiro size_t i; 121306f25ae9SGregory Neil Shapiro 1214323f6dcbSGregory Neil Shapiro /* paranoia: check for terminating '\0' */ 1215323f6dcbSGregory Neil Shapiro if (len == 0 || buf[len - 1] != '\0') 1216323f6dcbSGregory Neil Shapiro return MI_FAILURE; 121706f25ae9SGregory Neil Shapiro *s1 = buf; 121806f25ae9SGregory Neil Shapiro for (i = 1; i < len && buf[i] != '\0'; i++) 121906f25ae9SGregory Neil Shapiro continue; 122006f25ae9SGregory Neil Shapiro if (i >= len - 1) 122106f25ae9SGregory Neil Shapiro return MI_FAILURE; 122206f25ae9SGregory Neil Shapiro *s2 = buf + i + 1; 122306f25ae9SGregory Neil Shapiro return MI_SUCCESS; 122406f25ae9SGregory Neil Shapiro } 122540266059SGregory Neil Shapiro /* 122606f25ae9SGregory Neil Shapiro ** SENDOK -- is it ok for the filter to send stuff to the MTA? 122706f25ae9SGregory Neil Shapiro ** 122806f25ae9SGregory Neil Shapiro ** Parameters: 122906f25ae9SGregory Neil Shapiro ** ctx -- context structure 123006f25ae9SGregory Neil Shapiro ** flag -- flag to check 123106f25ae9SGregory Neil Shapiro ** 123206f25ae9SGregory Neil Shapiro ** Returns: 123306f25ae9SGregory Neil Shapiro ** sending allowed (in current state) 123406f25ae9SGregory Neil Shapiro */ 123506f25ae9SGregory Neil Shapiro 123606f25ae9SGregory Neil Shapiro bool 123706f25ae9SGregory Neil Shapiro mi_sendok(ctx, flag) 123806f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 123906f25ae9SGregory Neil Shapiro int flag; 124006f25ae9SGregory Neil Shapiro { 124106f25ae9SGregory Neil Shapiro if (ctx == NULL || ctx->ctx_smfi == NULL) 124240266059SGregory Neil Shapiro return false; 124340266059SGregory Neil Shapiro 124440266059SGregory Neil Shapiro /* did the milter request this operation? */ 124506f25ae9SGregory Neil Shapiro if (flag != 0 && !bitset(flag, ctx->ctx_smfi->xxfi_flags)) 124640266059SGregory Neil Shapiro return false; 124740266059SGregory Neil Shapiro 124840266059SGregory Neil Shapiro /* are we in the correct state? It must be "End of Message". */ 124906f25ae9SGregory Neil Shapiro return ctx->ctx_state == ST_ENDM; 125006f25ae9SGregory Neil Shapiro } 1251