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> 12d0cef73dSGregory Neil Shapiro SM_RCSID("@(#)$Id: engine.c,v 8.157 2007/03/26 18:10:04 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) */ 59d0cef73dSGregory Neil Shapiro #define CT_END 0x0008 /* last command of session, stop 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 67d0cef73dSGregory Neil Shapiro #define CI_DATA 4 68d0cef73dSGregory Neil Shapiro #define CI_EOM 5 69d0cef73dSGregory Neil Shapiro #define CI_EOH 6 70d0cef73dSGregory Neil Shapiro #define CI_LAST CI_EOH 71d0cef73dSGregory Neil Shapiro #if CI_LAST < CI_DATA 72d0cef73dSGregory Neil Shapiro ERROR: do not compile with CI_LAST < CI_DATA 73d0cef73dSGregory Neil Shapiro #endif 74d0cef73dSGregory Neil Shapiro #if CI_LAST < CI_EOM 75d0cef73dSGregory Neil Shapiro ERROR: do not compile with CI_LAST < CI_EOM 76d0cef73dSGregory Neil Shapiro #endif 77d0cef73dSGregory Neil Shapiro #if CI_LAST < CI_EOH 78d0cef73dSGregory Neil Shapiro ERROR: do not compile with CI_LAST < CI_EOH 79d0cef73dSGregory Neil Shapiro #endif 80d0cef73dSGregory Neil Shapiro #if CI_LAST < CI_ENVRCPT 81d0cef73dSGregory Neil Shapiro ERROR: do not compile with CI_LAST < CI_ENVRCPT 82d0cef73dSGregory Neil Shapiro #endif 83d0cef73dSGregory Neil Shapiro #if CI_LAST < CI_ENVFROM 84d0cef73dSGregory Neil Shapiro ERROR: do not compile with CI_LAST < CI_ENVFROM 85d0cef73dSGregory Neil Shapiro #endif 86d0cef73dSGregory Neil Shapiro #if CI_LAST < CI_HELO 87d0cef73dSGregory Neil Shapiro ERROR: do not compile with CI_LAST < CI_HELO 88d0cef73dSGregory Neil Shapiro #endif 89d0cef73dSGregory Neil Shapiro #if CI_LAST < CI_CONNECT 90d0cef73dSGregory Neil Shapiro ERROR: do not compile with CI_LAST < CI_CONNECT 91d0cef73dSGregory Neil Shapiro #endif 92d0cef73dSGregory Neil Shapiro #if CI_LAST >= MAX_MACROS_ENTRIES 93d0cef73dSGregory Neil Shapiro ERROR: do not compile with CI_LAST >= MAX_MACROS_ENTRIES 94323f6dcbSGregory Neil Shapiro #endif 9506f25ae9SGregory Neil Shapiro 9606f25ae9SGregory Neil Shapiro /* function prototypes */ 9706f25ae9SGregory Neil Shapiro static int st_abortfct __P((genarg *)); 9806f25ae9SGregory Neil Shapiro static int st_macros __P((genarg *)); 9906f25ae9SGregory Neil Shapiro static int st_optionneg __P((genarg *)); 10006f25ae9SGregory Neil Shapiro static int st_bodychunk __P((genarg *)); 10106f25ae9SGregory Neil Shapiro static int st_connectinfo __P((genarg *)); 10206f25ae9SGregory Neil Shapiro static int st_bodyend __P((genarg *)); 10306f25ae9SGregory Neil Shapiro static int st_helo __P((genarg *)); 10406f25ae9SGregory Neil Shapiro static int st_header __P((genarg *)); 10506f25ae9SGregory Neil Shapiro static int st_sender __P((genarg *)); 10606f25ae9SGregory Neil Shapiro static int st_rcpt __P((genarg *)); 107e92d3f3fSGregory Neil Shapiro static int st_unknown __P((genarg *)); 108e92d3f3fSGregory Neil Shapiro static int st_data __P((genarg *)); 10906f25ae9SGregory Neil Shapiro static int st_eoh __P((genarg *)); 11006f25ae9SGregory Neil Shapiro static int st_quit __P((genarg *)); 11106f25ae9SGregory Neil Shapiro static int sendreply __P((sfsistat, socket_t, struct timeval *, SMFICTX_PTR)); 11206f25ae9SGregory Neil Shapiro static void fix_stm __P((SMFICTX_PTR)); 11306f25ae9SGregory Neil Shapiro static bool trans_ok __P((int, int)); 11406f25ae9SGregory Neil Shapiro static char **dec_argv __P((char *, size_t)); 11506f25ae9SGregory Neil Shapiro static int dec_arg2 __P((char *, size_t, char **, char **)); 11606f25ae9SGregory Neil Shapiro 117d0cef73dSGregory Neil Shapiro #if _FFR_WORKERS_POOL 118d0cef73dSGregory Neil Shapiro static bool mi_rd_socket_ready __P((int)); 119d0cef73dSGregory Neil Shapiro #endif /* _FFR_WORKERS_POOL */ 120d0cef73dSGregory Neil Shapiro 12106f25ae9SGregory Neil Shapiro /* states */ 12206f25ae9SGregory Neil Shapiro #define ST_NONE (-1) 12306f25ae9SGregory Neil Shapiro #define ST_INIT 0 /* initial state */ 12406f25ae9SGregory Neil Shapiro #define ST_OPTS 1 /* option negotiation */ 12506f25ae9SGregory Neil Shapiro #define ST_CONN 2 /* connection info */ 12606f25ae9SGregory Neil Shapiro #define ST_HELO 3 /* helo */ 12706f25ae9SGregory Neil Shapiro #define ST_MAIL 4 /* mail from */ 12806f25ae9SGregory Neil Shapiro #define ST_RCPT 5 /* rcpt to */ 129e92d3f3fSGregory Neil Shapiro #define ST_DATA 6 /* data */ 130e92d3f3fSGregory Neil Shapiro #define ST_HDRS 7 /* headers */ 131e92d3f3fSGregory Neil Shapiro #define ST_EOHS 8 /* end of headers */ 132e92d3f3fSGregory Neil Shapiro #define ST_BODY 9 /* body */ 133e92d3f3fSGregory Neil Shapiro #define ST_ENDM 10 /* end of message */ 134e92d3f3fSGregory Neil Shapiro #define ST_QUIT 11 /* quit */ 135e92d3f3fSGregory Neil Shapiro #define ST_ABRT 12 /* abort */ 136e92d3f3fSGregory Neil Shapiro #define ST_UNKN 13 /* unknown SMTP command */ 137d0cef73dSGregory Neil Shapiro #define ST_Q_NC 14 /* quit, new connection follows */ 138d0cef73dSGregory Neil Shapiro #define ST_LAST ST_Q_NC /* last valid state */ 139d0cef73dSGregory Neil Shapiro #define ST_SKIP 16 /* not a state but required for the state table */ 14006f25ae9SGregory Neil Shapiro 14106f25ae9SGregory Neil Shapiro /* in a mail transaction? must be before eom according to spec. */ 14206f25ae9SGregory Neil Shapiro #define ST_IN_MAIL(st) ((st) >= ST_MAIL && (st) < ST_ENDM) 14306f25ae9SGregory Neil Shapiro 14406f25ae9SGregory Neil Shapiro /* 14506f25ae9SGregory Neil Shapiro ** set of next states 14606f25ae9SGregory Neil Shapiro ** each state (ST_*) corresponds to bit in an int value (1 << state) 14706f25ae9SGregory Neil Shapiro ** each state has a set of allowed transitions ('or' of bits of states) 14806f25ae9SGregory Neil Shapiro ** so a state transition is valid if the mask of the next state 14906f25ae9SGregory Neil Shapiro ** is set in the NX_* value 15006f25ae9SGregory Neil Shapiro ** this function is coded in trans_ok(), see below. 15106f25ae9SGregory Neil Shapiro */ 15240266059SGregory Neil Shapiro 15313bd1963SGregory Neil Shapiro #define MI_MASK(x) (0x0001 << (x)) /* generate a bit "mask" for a state */ 15413bd1963SGregory Neil Shapiro #define NX_INIT (MI_MASK(ST_OPTS)) 155e92d3f3fSGregory Neil Shapiro #define NX_OPTS (MI_MASK(ST_CONN) | MI_MASK(ST_UNKN)) 156e92d3f3fSGregory Neil Shapiro #define NX_CONN (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN)) 157e92d3f3fSGregory Neil Shapiro #define NX_HELO (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN)) 158e92d3f3fSGregory Neil Shapiro #define NX_MAIL (MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | MI_MASK(ST_UNKN)) 159e92d3f3fSGregory Neil Shapiro #define NX_RCPT (MI_MASK(ST_HDRS) | MI_MASK(ST_EOHS) | MI_MASK(ST_DATA) | \ 16013bd1963SGregory Neil Shapiro MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | \ 161e92d3f3fSGregory Neil Shapiro MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | MI_MASK(ST_UNKN)) 162e92d3f3fSGregory Neil Shapiro #define NX_DATA (MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT)) 16313bd1963SGregory Neil Shapiro #define NX_HDRS (MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT)) 16413bd1963SGregory Neil Shapiro #define NX_EOHS (MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | MI_MASK(ST_ABRT)) 16513bd1963SGregory Neil Shapiro #define NX_BODY (MI_MASK(ST_ENDM) | MI_MASK(ST_BODY) | MI_MASK(ST_ABRT)) 166d0cef73dSGregory Neil Shapiro #define NX_ENDM (MI_MASK(ST_QUIT) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN) | \ 167d0cef73dSGregory Neil Shapiro MI_MASK(ST_Q_NC)) 16806f25ae9SGregory Neil Shapiro #define NX_QUIT 0 16906f25ae9SGregory Neil Shapiro #define NX_ABRT 0 170e92d3f3fSGregory Neil Shapiro #define NX_UNKN (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | \ 171e92d3f3fSGregory Neil Shapiro MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | \ 172e92d3f3fSGregory Neil Shapiro MI_MASK(ST_DATA) | \ 173e92d3f3fSGregory Neil Shapiro MI_MASK(ST_BODY) | MI_MASK(ST_UNKN) | \ 174d0cef73dSGregory Neil Shapiro MI_MASK(ST_ABRT) | MI_MASK(ST_QUIT) | MI_MASK(ST_Q_NC)) 175d0cef73dSGregory Neil Shapiro #define NX_Q_NC (MI_MASK(ST_CONN) | MI_MASK(ST_UNKN)) 17613bd1963SGregory Neil Shapiro #define NX_SKIP MI_MASK(ST_SKIP) 17706f25ae9SGregory Neil Shapiro 17806f25ae9SGregory Neil Shapiro static int next_states[] = 17906f25ae9SGregory Neil Shapiro { 180d0cef73dSGregory Neil Shapiro NX_INIT 181d0cef73dSGregory Neil Shapiro , NX_OPTS 182d0cef73dSGregory Neil Shapiro , NX_CONN 183d0cef73dSGregory Neil Shapiro , NX_HELO 184d0cef73dSGregory Neil Shapiro , NX_MAIL 185d0cef73dSGregory Neil Shapiro , NX_RCPT 186d0cef73dSGregory Neil Shapiro , NX_DATA 187d0cef73dSGregory Neil Shapiro , NX_HDRS 188d0cef73dSGregory Neil Shapiro , NX_EOHS 189d0cef73dSGregory Neil Shapiro , NX_BODY 190d0cef73dSGregory Neil Shapiro , NX_ENDM 191d0cef73dSGregory Neil Shapiro , NX_QUIT 192d0cef73dSGregory Neil Shapiro , NX_ABRT 193d0cef73dSGregory Neil Shapiro , NX_UNKN 194d0cef73dSGregory Neil Shapiro , NX_Q_NC 19506f25ae9SGregory Neil Shapiro }; 19606f25ae9SGregory Neil Shapiro 197af9557fdSGregory Neil Shapiro #define SIZE_NEXT_STATES (sizeof(next_states) / sizeof(next_states[0])) 198af9557fdSGregory Neil Shapiro 19906f25ae9SGregory Neil Shapiro /* commands received by milter */ 20006f25ae9SGregory Neil Shapiro static cmdfct cmds[] = 20106f25ae9SGregory Neil Shapiro { 202d0cef73dSGregory Neil Shapiro {SMFIC_ABORT, CM_ARG0, ST_ABRT, CT_CONT, CI_NONE, st_abortfct } 203d0cef73dSGregory Neil Shapiro , {SMFIC_MACRO, CM_ARGV, ST_NONE, CT_KEEP, CI_NONE, st_macros } 204d0cef73dSGregory Neil Shapiro , {SMFIC_BODY, CM_ARG1, ST_BODY, CT_CONT, CI_NONE, st_bodychunk } 205d0cef73dSGregory Neil Shapiro , {SMFIC_CONNECT, CM_ARG2, ST_CONN, CT_CONT, CI_CONN, st_connectinfo } 206d0cef73dSGregory Neil Shapiro , {SMFIC_BODYEOB, CM_ARG1, ST_ENDM, CT_CONT, CI_EOM, st_bodyend } 207d0cef73dSGregory Neil Shapiro , {SMFIC_HELO, CM_ARG1, ST_HELO, CT_CONT, CI_HELO, st_helo } 208d0cef73dSGregory Neil Shapiro , {SMFIC_HEADER, CM_ARG2, ST_HDRS, CT_CONT, CI_NONE, st_header } 209d0cef73dSGregory Neil Shapiro , {SMFIC_MAIL, CM_ARGV, ST_MAIL, CT_CONT, CI_MAIL, st_sender } 210d0cef73dSGregory Neil Shapiro , {SMFIC_OPTNEG, CM_ARGO, ST_OPTS, CT_CONT, CI_NONE, st_optionneg } 211d0cef73dSGregory Neil Shapiro , {SMFIC_EOH, CM_ARG0, ST_EOHS, CT_CONT, CI_EOH, st_eoh } 212d0cef73dSGregory Neil Shapiro , {SMFIC_QUIT, CM_ARG0, ST_QUIT, CT_END, CI_NONE, st_quit } 213d0cef73dSGregory Neil Shapiro , {SMFIC_DATA, CM_ARG0, ST_DATA, CT_CONT, CI_DATA, st_data } 214d0cef73dSGregory Neil Shapiro , {SMFIC_RCPT, CM_ARGV, ST_RCPT, CT_IGNO, CI_RCPT, st_rcpt } 215e92d3f3fSGregory Neil Shapiro , {SMFIC_UNKNOWN, CM_ARG1, ST_UNKN, CT_IGNO, CI_NONE, st_unknown } 216d0cef73dSGregory Neil Shapiro , {SMFIC_QUIT_NC, CM_ARG0, ST_Q_NC, CT_CONT, CI_NONE, st_quit } 21706f25ae9SGregory Neil Shapiro }; 21806f25ae9SGregory Neil Shapiro 219d0cef73dSGregory Neil Shapiro /* 220d0cef73dSGregory Neil Shapiro ** Additional (internal) reply codes; 221d0cef73dSGregory Neil Shapiro ** must be coordinated wit libmilter/mfapi.h 222d0cef73dSGregory Neil Shapiro */ 223d0cef73dSGregory Neil Shapiro 22406f25ae9SGregory Neil Shapiro #define _SMFIS_KEEP 20 22506f25ae9SGregory Neil Shapiro #define _SMFIS_ABORT 21 22606f25ae9SGregory Neil Shapiro #define _SMFIS_OPTIONS 22 227d0cef73dSGregory Neil Shapiro #define _SMFIS_NOREPLY SMFIS_NOREPLY 22806f25ae9SGregory Neil Shapiro #define _SMFIS_FAIL (-1) 22940266059SGregory Neil Shapiro #define _SMFIS_NONE (-2) 23006f25ae9SGregory Neil Shapiro 23140266059SGregory Neil Shapiro /* 23206f25ae9SGregory Neil Shapiro ** MI_ENGINE -- receive commands and process them 23306f25ae9SGregory Neil Shapiro ** 23406f25ae9SGregory Neil Shapiro ** Parameters: 23506f25ae9SGregory Neil Shapiro ** ctx -- context structure 23606f25ae9SGregory Neil Shapiro ** 23706f25ae9SGregory Neil Shapiro ** Returns: 23806f25ae9SGregory Neil Shapiro ** MI_FAILURE/MI_SUCCESS 23906f25ae9SGregory Neil Shapiro */ 240d0cef73dSGregory Neil Shapiro 24106f25ae9SGregory Neil Shapiro int 24206f25ae9SGregory Neil Shapiro mi_engine(ctx) 24306f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 24406f25ae9SGregory Neil Shapiro { 24506f25ae9SGregory Neil Shapiro size_t len; 24606f25ae9SGregory Neil Shapiro int i; 24706f25ae9SGregory Neil Shapiro socket_t sd; 24806f25ae9SGregory Neil Shapiro int ret = MI_SUCCESS; 24906f25ae9SGregory Neil Shapiro int ncmds = sizeof(cmds) / sizeof(cmdfct); 25006f25ae9SGregory Neil Shapiro int curstate = ST_INIT; 25106f25ae9SGregory Neil Shapiro int newstate; 25206f25ae9SGregory Neil Shapiro bool call_abort; 25306f25ae9SGregory Neil Shapiro sfsistat r; 25406f25ae9SGregory Neil Shapiro char cmd; 25506f25ae9SGregory Neil Shapiro char *buf = NULL; 25606f25ae9SGregory Neil Shapiro genarg arg; 25706f25ae9SGregory Neil Shapiro struct timeval timeout; 25806f25ae9SGregory Neil Shapiro int (*f) __P((genarg *)); 25906f25ae9SGregory Neil Shapiro sfsistat (*fi_abort) __P((SMFICTX *)); 26006f25ae9SGregory Neil Shapiro sfsistat (*fi_close) __P((SMFICTX *)); 26106f25ae9SGregory Neil Shapiro 26206f25ae9SGregory Neil Shapiro arg.a_ctx = ctx; 26306f25ae9SGregory Neil Shapiro sd = ctx->ctx_sd; 26406f25ae9SGregory Neil Shapiro fi_abort = ctx->ctx_smfi->xxfi_abort; 265d0cef73dSGregory Neil Shapiro #if _FFR_WORKERS_POOL 266d0cef73dSGregory Neil Shapiro curstate = ctx->ctx_state; 267d0cef73dSGregory Neil Shapiro if (curstate == ST_INIT) 268d0cef73dSGregory Neil Shapiro { 26906f25ae9SGregory Neil Shapiro mi_clr_macros(ctx, 0); 27006f25ae9SGregory Neil Shapiro fix_stm(ctx); 271d0cef73dSGregory Neil Shapiro } 272d0cef73dSGregory Neil Shapiro #else /* _FFR_WORKERS_POOL */ 273d0cef73dSGregory Neil Shapiro mi_clr_macros(ctx, 0); 274d0cef73dSGregory Neil Shapiro fix_stm(ctx); 275d0cef73dSGregory Neil Shapiro #endif /* _FFR_WORKERS_POOL */ 27640266059SGregory Neil Shapiro r = _SMFIS_NONE; 27742e5d165SGregory Neil Shapiro do 27842e5d165SGregory Neil Shapiro { 27906f25ae9SGregory Neil Shapiro /* call abort only if in a mail transaction */ 28006f25ae9SGregory Neil Shapiro call_abort = ST_IN_MAIL(curstate); 28106f25ae9SGregory Neil Shapiro timeout.tv_sec = ctx->ctx_timeout; 28206f25ae9SGregory Neil Shapiro timeout.tv_usec = 0; 28306f25ae9SGregory Neil Shapiro if (mi_stop() == MILTER_ABRT) 28406f25ae9SGregory Neil Shapiro { 28506f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 3) 286d0cef73dSGregory Neil Shapiro sm_dprintf("[%ld] milter_abort\n", 287d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id); 28806f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 28906f25ae9SGregory Neil Shapiro break; 29006f25ae9SGregory Neil Shapiro } 29140266059SGregory Neil Shapiro 29240266059SGregory Neil Shapiro /* 29340266059SGregory Neil Shapiro ** Notice: buf is allocated by mi_rd_cmd() and it will 29440266059SGregory Neil Shapiro ** usually be free()d after it has been used in f(). 29540266059SGregory Neil Shapiro ** However, if the function returns _SMFIS_KEEP then buf 29640266059SGregory Neil Shapiro ** contains macros and will not be free()d. 29740266059SGregory Neil Shapiro ** Hence r must be set to _SMFIS_NONE if a new buf is 29840266059SGregory Neil Shapiro ** allocated to avoid problem with housekeeping, esp. 29940266059SGregory Neil Shapiro ** if the code "break"s out of the loop. 30040266059SGregory Neil Shapiro */ 30140266059SGregory Neil Shapiro 302d0cef73dSGregory Neil Shapiro #if _FFR_WORKERS_POOL 303d0cef73dSGregory Neil Shapiro /* Is the socket ready to be read ??? */ 304d0cef73dSGregory Neil Shapiro if (!mi_rd_socket_ready(sd)) 305d0cef73dSGregory Neil Shapiro { 306d0cef73dSGregory Neil Shapiro ret = MI_CONTINUE; 307d0cef73dSGregory Neil Shapiro break; 308d0cef73dSGregory Neil Shapiro } 309d0cef73dSGregory Neil Shapiro #endif /* _FFR_WORKERS_POOL */ 310d0cef73dSGregory Neil Shapiro 31140266059SGregory Neil Shapiro r = _SMFIS_NONE; 31206f25ae9SGregory Neil Shapiro if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len, 31306f25ae9SGregory Neil Shapiro ctx->ctx_smfi->xxfi_name)) == NULL && 31406f25ae9SGregory Neil Shapiro cmd < SMFIC_VALIDCMD) 31506f25ae9SGregory Neil Shapiro { 31606f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 5) 317d0cef73dSGregory Neil Shapiro sm_dprintf("[%ld] mi_engine: mi_rd_cmd error (%x)\n", 318d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, (int) cmd); 31906f25ae9SGregory Neil Shapiro 32006f25ae9SGregory Neil Shapiro /* 32106f25ae9SGregory Neil Shapiro ** eof is currently treated as failure -> 32206f25ae9SGregory Neil Shapiro ** abort() instead of close(), otherwise use: 32306f25ae9SGregory Neil Shapiro ** if (cmd != SMFIC_EOF) 32406f25ae9SGregory Neil Shapiro */ 32506f25ae9SGregory Neil Shapiro 32606f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 32706f25ae9SGregory Neil Shapiro break; 32806f25ae9SGregory Neil Shapiro } 32906f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 4) 330d0cef73dSGregory Neil Shapiro sm_dprintf("[%ld] got cmd '%c' len %d\n", 331d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, cmd, (int) len); 33206f25ae9SGregory Neil Shapiro for (i = 0; i < ncmds; i++) 33306f25ae9SGregory Neil Shapiro { 33406f25ae9SGregory Neil Shapiro if (cmd == cmds[i].cm_cmd) 33506f25ae9SGregory Neil Shapiro break; 33606f25ae9SGregory Neil Shapiro } 33706f25ae9SGregory Neil Shapiro if (i >= ncmds) 33806f25ae9SGregory Neil Shapiro { 33906f25ae9SGregory Neil Shapiro /* unknown command */ 34006f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 1) 341d0cef73dSGregory Neil Shapiro sm_dprintf("[%ld] cmd '%c' unknown\n", 342d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, cmd); 34306f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 34406f25ae9SGregory Neil Shapiro break; 34506f25ae9SGregory Neil Shapiro } 34606f25ae9SGregory Neil Shapiro if ((f = cmds[i].cm_fct) == NULL) 34706f25ae9SGregory Neil Shapiro { 34806f25ae9SGregory Neil Shapiro /* stop for now */ 34906f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 1) 350d0cef73dSGregory Neil Shapiro sm_dprintf("[%ld] cmd '%c' not impl\n", 351d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, cmd); 35206f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 35306f25ae9SGregory Neil Shapiro break; 35406f25ae9SGregory Neil Shapiro } 35506f25ae9SGregory Neil Shapiro 35606f25ae9SGregory Neil Shapiro /* is new state ok? */ 35706f25ae9SGregory Neil Shapiro newstate = cmds[i].cm_next; 35806f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 5) 359d0cef73dSGregory Neil Shapiro sm_dprintf("[%ld] cur %x new %x nextmask %x\n", 360d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, 36106f25ae9SGregory Neil Shapiro curstate, newstate, next_states[curstate]); 36206f25ae9SGregory Neil Shapiro 36306f25ae9SGregory Neil Shapiro if (newstate != ST_NONE && !trans_ok(curstate, newstate)) 36406f25ae9SGregory Neil Shapiro { 36506f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 1) 366d0cef73dSGregory Neil Shapiro sm_dprintf("[%ld] abort: cur %d (%x) new %d (%x) next %x\n", 367d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, 36813bd1963SGregory Neil Shapiro curstate, MI_MASK(curstate), 36913bd1963SGregory Neil Shapiro newstate, MI_MASK(newstate), 37006f25ae9SGregory Neil Shapiro next_states[curstate]); 37106f25ae9SGregory Neil Shapiro 37206f25ae9SGregory Neil Shapiro /* call abort only if in a mail transaction */ 37306f25ae9SGregory Neil Shapiro if (fi_abort != NULL && call_abort) 37406f25ae9SGregory Neil Shapiro (void) (*fi_abort)(ctx); 37506f25ae9SGregory Neil Shapiro 37606f25ae9SGregory Neil Shapiro /* 37706f25ae9SGregory Neil Shapiro ** try to reach the new state from HELO 37806f25ae9SGregory Neil Shapiro ** if it can't be reached, ignore the command. 37906f25ae9SGregory Neil Shapiro */ 38006f25ae9SGregory Neil Shapiro 38106f25ae9SGregory Neil Shapiro curstate = ST_HELO; 38206f25ae9SGregory Neil Shapiro if (!trans_ok(curstate, newstate)) 38340266059SGregory Neil Shapiro { 384959366dcSGregory Neil Shapiro if (buf != NULL) 385959366dcSGregory Neil Shapiro { 38640266059SGregory Neil Shapiro free(buf); 38740266059SGregory Neil Shapiro buf = NULL; 388959366dcSGregory Neil Shapiro } 38906f25ae9SGregory Neil Shapiro continue; 39006f25ae9SGregory Neil Shapiro } 39140266059SGregory Neil Shapiro } 39206f25ae9SGregory Neil Shapiro arg.a_len = len; 39306f25ae9SGregory Neil Shapiro arg.a_buf = buf; 39406f25ae9SGregory Neil Shapiro if (newstate != ST_NONE) 39506f25ae9SGregory Neil Shapiro { 39606f25ae9SGregory Neil Shapiro curstate = newstate; 39706f25ae9SGregory Neil Shapiro ctx->ctx_state = curstate; 39806f25ae9SGregory Neil Shapiro } 39906f25ae9SGregory Neil Shapiro arg.a_idx = cmds[i].cm_macros; 400b6bacd31SGregory Neil Shapiro call_abort = ST_IN_MAIL(curstate); 40106f25ae9SGregory Neil Shapiro 40206f25ae9SGregory Neil Shapiro /* call function to deal with command */ 403d0cef73dSGregory Neil Shapiro MI_MONITOR_BEGIN(ctx, cmd); 40406f25ae9SGregory Neil Shapiro r = (*f)(&arg); 405d0cef73dSGregory Neil Shapiro MI_MONITOR_END(ctx, cmd); 40606f25ae9SGregory Neil Shapiro if (r != _SMFIS_KEEP && buf != NULL) 40706f25ae9SGregory Neil Shapiro { 40806f25ae9SGregory Neil Shapiro free(buf); 40906f25ae9SGregory Neil Shapiro buf = NULL; 41006f25ae9SGregory Neil Shapiro } 41106f25ae9SGregory Neil Shapiro if (sendreply(r, sd, &timeout, ctx) != MI_SUCCESS) 41206f25ae9SGregory Neil Shapiro { 41306f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 41406f25ae9SGregory Neil Shapiro break; 41506f25ae9SGregory Neil Shapiro } 41606f25ae9SGregory Neil Shapiro 41706f25ae9SGregory Neil Shapiro if (r == SMFIS_ACCEPT) 41806f25ae9SGregory Neil Shapiro { 41906f25ae9SGregory Neil Shapiro /* accept mail, no further actions taken */ 42006f25ae9SGregory Neil Shapiro curstate = ST_HELO; 42106f25ae9SGregory Neil Shapiro } 42206f25ae9SGregory Neil Shapiro else if (r == SMFIS_REJECT || r == SMFIS_DISCARD || 42306f25ae9SGregory Neil Shapiro r == SMFIS_TEMPFAIL) 42406f25ae9SGregory Neil Shapiro { 42506f25ae9SGregory Neil Shapiro /* 42606f25ae9SGregory Neil Shapiro ** further actions depend on current state 42706f25ae9SGregory Neil Shapiro ** if the IGNO bit is set: "ignore" the error, 42806f25ae9SGregory Neil Shapiro ** i.e., stay in the current state 42906f25ae9SGregory Neil Shapiro */ 43006f25ae9SGregory Neil Shapiro if (!bitset(CT_IGNO, cmds[i].cm_todo)) 43106f25ae9SGregory Neil Shapiro curstate = ST_HELO; 43206f25ae9SGregory Neil Shapiro } 43306f25ae9SGregory Neil Shapiro else if (r == _SMFIS_ABORT) 43406f25ae9SGregory Neil Shapiro { 43506f25ae9SGregory Neil Shapiro if (ctx->ctx_dbg > 5) 436d0cef73dSGregory Neil Shapiro sm_dprintf("[%ld] function returned abort\n", 437d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id); 43806f25ae9SGregory Neil Shapiro ret = MI_FAILURE; 43906f25ae9SGregory Neil Shapiro break; 44006f25ae9SGregory Neil Shapiro } 44106f25ae9SGregory Neil Shapiro } while (!bitset(CT_END, cmds[i].cm_todo)); 44206f25ae9SGregory Neil Shapiro 443d0cef73dSGregory Neil Shapiro ctx->ctx_state = curstate; 444d0cef73dSGregory Neil Shapiro 445d0cef73dSGregory Neil Shapiro if (ret == MI_FAILURE) 44606f25ae9SGregory Neil Shapiro { 44706f25ae9SGregory Neil Shapiro /* call abort only if in a mail transaction */ 44806f25ae9SGregory Neil Shapiro if (fi_abort != NULL && call_abort) 44906f25ae9SGregory Neil Shapiro (void) (*fi_abort)(ctx); 45006f25ae9SGregory Neil Shapiro } 45106f25ae9SGregory Neil Shapiro 452d0cef73dSGregory Neil Shapiro /* has close been called? */ 453d0cef73dSGregory Neil Shapiro if (ctx->ctx_state != ST_QUIT 454d0cef73dSGregory Neil Shapiro #if _FFR_WORKERS_POOL 455d0cef73dSGregory Neil Shapiro && ret != MI_CONTINUE 456d0cef73dSGregory Neil Shapiro #endif /* _FFR_WORKERS_POOL */ 457d0cef73dSGregory Neil Shapiro ) 458d0cef73dSGregory Neil Shapiro { 45906f25ae9SGregory Neil Shapiro if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) 46006f25ae9SGregory Neil Shapiro (void) (*fi_close)(ctx); 461d0cef73dSGregory Neil Shapiro } 46240266059SGregory Neil Shapiro if (r != _SMFIS_KEEP && buf != NULL) 46306f25ae9SGregory Neil Shapiro free(buf); 464d0cef73dSGregory Neil Shapiro #if !_FFR_WORKERS_POOL 46506f25ae9SGregory Neil Shapiro mi_clr_macros(ctx, 0); 466d0cef73dSGregory Neil Shapiro #endif /* _FFR_WORKERS_POOL */ 46706f25ae9SGregory Neil Shapiro return ret; 46806f25ae9SGregory Neil Shapiro } 469d0cef73dSGregory Neil Shapiro 470d0cef73dSGregory Neil Shapiro static size_t milter_addsymlist __P((SMFICTX_PTR, char *, char **)); 471d0cef73dSGregory Neil Shapiro 472d0cef73dSGregory Neil Shapiro static size_t 473d0cef73dSGregory Neil Shapiro milter_addsymlist(ctx, buf, newbuf) 474d0cef73dSGregory Neil Shapiro SMFICTX_PTR ctx; 475d0cef73dSGregory Neil Shapiro char *buf; 476d0cef73dSGregory Neil Shapiro char **newbuf; 477d0cef73dSGregory Neil Shapiro { 478d0cef73dSGregory Neil Shapiro size_t len; 479d0cef73dSGregory Neil Shapiro int i; 480d0cef73dSGregory Neil Shapiro mi_int32 v; 481d0cef73dSGregory Neil Shapiro char *buffer; 482d0cef73dSGregory Neil Shapiro 483d0cef73dSGregory Neil Shapiro SM_ASSERT(ctx != NULL); 484d0cef73dSGregory Neil Shapiro SM_ASSERT(buf != NULL); 485d0cef73dSGregory Neil Shapiro SM_ASSERT(newbuf != NULL); 486d0cef73dSGregory Neil Shapiro len = 0; 487d0cef73dSGregory Neil Shapiro for (i = 0; i < MAX_MACROS_ENTRIES; i++) 488d0cef73dSGregory Neil Shapiro { 489d0cef73dSGregory Neil Shapiro if (ctx->ctx_mac_list[i] != NULL) 490d0cef73dSGregory Neil Shapiro { 491d0cef73dSGregory Neil Shapiro len += strlen(ctx->ctx_mac_list[i]) + 1 + 492d0cef73dSGregory Neil Shapiro MILTER_LEN_BYTES; 493d0cef73dSGregory Neil Shapiro } 494d0cef73dSGregory Neil Shapiro } 495d0cef73dSGregory Neil Shapiro if (len > 0) 496d0cef73dSGregory Neil Shapiro { 497d0cef73dSGregory Neil Shapiro size_t offset; 498d0cef73dSGregory Neil Shapiro 499d0cef73dSGregory Neil Shapiro SM_ASSERT(len + MILTER_OPTLEN > len); 500d0cef73dSGregory Neil Shapiro len += MILTER_OPTLEN; 501d0cef73dSGregory Neil Shapiro buffer = malloc(len); 502d0cef73dSGregory Neil Shapiro if (buffer != NULL) 503d0cef73dSGregory Neil Shapiro { 504d0cef73dSGregory Neil Shapiro (void) memcpy(buffer, buf, MILTER_OPTLEN); 505d0cef73dSGregory Neil Shapiro offset = MILTER_OPTLEN; 506d0cef73dSGregory Neil Shapiro for (i = 0; i < MAX_MACROS_ENTRIES; i++) 507d0cef73dSGregory Neil Shapiro { 508d0cef73dSGregory Neil Shapiro size_t l; 509d0cef73dSGregory Neil Shapiro 510d0cef73dSGregory Neil Shapiro if (ctx->ctx_mac_list[i] == NULL) 511d0cef73dSGregory Neil Shapiro continue; 512d0cef73dSGregory Neil Shapiro 513d0cef73dSGregory Neil Shapiro SM_ASSERT(offset + MILTER_LEN_BYTES < len); 514d0cef73dSGregory Neil Shapiro v = htonl(i); 515d0cef73dSGregory Neil Shapiro (void) memcpy(buffer + offset, (void *) &v, 516d0cef73dSGregory Neil Shapiro MILTER_LEN_BYTES); 517d0cef73dSGregory Neil Shapiro offset += MILTER_LEN_BYTES; 518d0cef73dSGregory Neil Shapiro l = strlen(ctx->ctx_mac_list[i]) + 1; 519d0cef73dSGregory Neil Shapiro SM_ASSERT(offset + l <= len); 520d0cef73dSGregory Neil Shapiro (void) memcpy(buffer + offset, 521d0cef73dSGregory Neil Shapiro ctx->ctx_mac_list[i], l); 522d0cef73dSGregory Neil Shapiro offset += l; 523d0cef73dSGregory Neil Shapiro } 524d0cef73dSGregory Neil Shapiro } 525d0cef73dSGregory Neil Shapiro else 526d0cef73dSGregory Neil Shapiro { 527d0cef73dSGregory Neil Shapiro /* oops ... */ 528d0cef73dSGregory Neil Shapiro } 529d0cef73dSGregory Neil Shapiro } 530d0cef73dSGregory Neil Shapiro else 531d0cef73dSGregory Neil Shapiro { 532d0cef73dSGregory Neil Shapiro len = MILTER_OPTLEN; 533d0cef73dSGregory Neil Shapiro buffer = buf; 534d0cef73dSGregory Neil Shapiro } 535d0cef73dSGregory Neil Shapiro *newbuf = buffer; 536d0cef73dSGregory Neil Shapiro return len; 537d0cef73dSGregory Neil Shapiro } 538d0cef73dSGregory Neil Shapiro 539d0cef73dSGregory Neil Shapiro /* 540d0cef73dSGregory Neil Shapiro ** GET_NR_BIT -- get "no reply" bit matching state 541d0cef73dSGregory Neil Shapiro ** 542d0cef73dSGregory Neil Shapiro ** Parameters: 543d0cef73dSGregory Neil Shapiro ** state -- current protocol stage 544d0cef73dSGregory Neil Shapiro ** 545d0cef73dSGregory Neil Shapiro ** Returns: 546d0cef73dSGregory Neil Shapiro ** 0: no matching bit 547d0cef73dSGregory Neil Shapiro ** >0: the matching "no reply" bit 548d0cef73dSGregory Neil Shapiro */ 549d0cef73dSGregory Neil Shapiro 550d0cef73dSGregory Neil Shapiro static unsigned long get_nr_bit __P((int)); 551d0cef73dSGregory Neil Shapiro 552d0cef73dSGregory Neil Shapiro static unsigned long 553d0cef73dSGregory Neil Shapiro get_nr_bit(state) 554d0cef73dSGregory Neil Shapiro int state; 555d0cef73dSGregory Neil Shapiro { 556d0cef73dSGregory Neil Shapiro unsigned long bit; 557d0cef73dSGregory Neil Shapiro 558d0cef73dSGregory Neil Shapiro switch (state) 559d0cef73dSGregory Neil Shapiro { 560d0cef73dSGregory Neil Shapiro case ST_CONN: 561d0cef73dSGregory Neil Shapiro bit = SMFIP_NR_CONN; 562d0cef73dSGregory Neil Shapiro break; 563d0cef73dSGregory Neil Shapiro case ST_HELO: 564d0cef73dSGregory Neil Shapiro bit = SMFIP_NR_HELO; 565d0cef73dSGregory Neil Shapiro break; 566d0cef73dSGregory Neil Shapiro case ST_MAIL: 567d0cef73dSGregory Neil Shapiro bit = SMFIP_NR_MAIL; 568d0cef73dSGregory Neil Shapiro break; 569d0cef73dSGregory Neil Shapiro case ST_RCPT: 570d0cef73dSGregory Neil Shapiro bit = SMFIP_NR_RCPT; 571d0cef73dSGregory Neil Shapiro break; 572d0cef73dSGregory Neil Shapiro case ST_DATA: 573d0cef73dSGregory Neil Shapiro bit = SMFIP_NR_DATA; 574d0cef73dSGregory Neil Shapiro break; 575d0cef73dSGregory Neil Shapiro case ST_UNKN: 576d0cef73dSGregory Neil Shapiro bit = SMFIP_NR_UNKN; 577d0cef73dSGregory Neil Shapiro break; 578d0cef73dSGregory Neil Shapiro case ST_HDRS: 579d0cef73dSGregory Neil Shapiro bit = SMFIP_NR_HDR; 580d0cef73dSGregory Neil Shapiro break; 581d0cef73dSGregory Neil Shapiro case ST_EOHS: 582d0cef73dSGregory Neil Shapiro bit = SMFIP_NR_EOH; 583d0cef73dSGregory Neil Shapiro break; 584d0cef73dSGregory Neil Shapiro case ST_BODY: 585d0cef73dSGregory Neil Shapiro bit = SMFIP_NR_BODY; 586d0cef73dSGregory Neil Shapiro break; 587d0cef73dSGregory Neil Shapiro default: 588d0cef73dSGregory Neil Shapiro bit = 0; 589d0cef73dSGregory Neil Shapiro break; 590d0cef73dSGregory Neil Shapiro } 591d0cef73dSGregory Neil Shapiro return bit; 592d0cef73dSGregory Neil Shapiro } 593d0cef73dSGregory Neil Shapiro 59440266059SGregory Neil Shapiro /* 59506f25ae9SGregory Neil Shapiro ** SENDREPLY -- send a reply to the MTA 59606f25ae9SGregory Neil Shapiro ** 59706f25ae9SGregory Neil Shapiro ** Parameters: 59806f25ae9SGregory Neil Shapiro ** r -- reply code 59906f25ae9SGregory Neil Shapiro ** sd -- socket descriptor 60006f25ae9SGregory Neil Shapiro ** timeout_ptr -- (ptr to) timeout to use for sending 60106f25ae9SGregory Neil Shapiro ** ctx -- context structure 60206f25ae9SGregory Neil Shapiro ** 60306f25ae9SGregory Neil Shapiro ** Returns: 60406f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE 60506f25ae9SGregory Neil Shapiro */ 60606f25ae9SGregory Neil Shapiro 60706f25ae9SGregory Neil Shapiro static int 60806f25ae9SGregory Neil Shapiro sendreply(r, sd, timeout_ptr, ctx) 60906f25ae9SGregory Neil Shapiro sfsistat r; 61006f25ae9SGregory Neil Shapiro socket_t sd; 61106f25ae9SGregory Neil Shapiro struct timeval *timeout_ptr; 61206f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 61306f25ae9SGregory Neil Shapiro { 614d0cef73dSGregory Neil Shapiro int ret; 615d0cef73dSGregory Neil Shapiro unsigned long bit; 616d0cef73dSGregory Neil Shapiro 617d0cef73dSGregory Neil Shapiro ret = MI_SUCCESS; 618d0cef73dSGregory Neil Shapiro 619d0cef73dSGregory Neil Shapiro bit = get_nr_bit(ctx->ctx_state); 620d0cef73dSGregory Neil Shapiro if (bit != 0 && (ctx->ctx_pflags & bit) != 0 && r != SMFIS_NOREPLY) 621d0cef73dSGregory Neil Shapiro { 622d0cef73dSGregory Neil Shapiro if (r >= SMFIS_CONTINUE && r < _SMFIS_KEEP) 623d0cef73dSGregory Neil Shapiro { 624d0cef73dSGregory Neil Shapiro /* milter said it wouldn't reply, but it lied... */ 625d0cef73dSGregory Neil Shapiro smi_log(SMI_LOG_ERR, 626d0cef73dSGregory Neil Shapiro "%s: milter claimed not to reply in state %d but did anyway %d\n", 627d0cef73dSGregory Neil Shapiro ctx->ctx_smfi->xxfi_name, 628d0cef73dSGregory Neil Shapiro ctx->ctx_state, r); 629d0cef73dSGregory Neil Shapiro 630d0cef73dSGregory Neil Shapiro } 631d0cef73dSGregory Neil Shapiro 632d0cef73dSGregory Neil Shapiro /* 633d0cef73dSGregory Neil Shapiro ** Force specified behavior, otherwise libmilter 634d0cef73dSGregory Neil Shapiro ** and MTA will fail to communicate properly. 635d0cef73dSGregory Neil Shapiro */ 636d0cef73dSGregory Neil Shapiro 637d0cef73dSGregory Neil Shapiro switch (r) 638d0cef73dSGregory Neil Shapiro { 639d0cef73dSGregory Neil Shapiro case SMFIS_CONTINUE: 640d0cef73dSGregory Neil Shapiro case SMFIS_TEMPFAIL: 641d0cef73dSGregory Neil Shapiro case SMFIS_REJECT: 642d0cef73dSGregory Neil Shapiro case SMFIS_DISCARD: 643d0cef73dSGregory Neil Shapiro case SMFIS_ACCEPT: 644d0cef73dSGregory Neil Shapiro case SMFIS_SKIP: 645d0cef73dSGregory Neil Shapiro case _SMFIS_OPTIONS: 646d0cef73dSGregory Neil Shapiro r = SMFIS_NOREPLY; 647d0cef73dSGregory Neil Shapiro break; 648d0cef73dSGregory Neil Shapiro } 649d0cef73dSGregory Neil Shapiro } 65006f25ae9SGregory Neil Shapiro 65106f25ae9SGregory Neil Shapiro switch (r) 65206f25ae9SGregory Neil Shapiro { 65306f25ae9SGregory Neil Shapiro case SMFIS_CONTINUE: 65406f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 0); 65506f25ae9SGregory Neil Shapiro break; 65606f25ae9SGregory Neil Shapiro case SMFIS_TEMPFAIL: 65706f25ae9SGregory Neil Shapiro case SMFIS_REJECT: 658605302a5SGregory Neil Shapiro if (ctx->ctx_reply != NULL && 659605302a5SGregory Neil Shapiro ((r == SMFIS_TEMPFAIL && *ctx->ctx_reply == '4') || 660605302a5SGregory Neil Shapiro (r == SMFIS_REJECT && *ctx->ctx_reply == '5'))) 66106f25ae9SGregory Neil Shapiro { 66206f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_REPLYCODE, 66306f25ae9SGregory Neil Shapiro ctx->ctx_reply, 66406f25ae9SGregory Neil Shapiro strlen(ctx->ctx_reply) + 1); 66506f25ae9SGregory Neil Shapiro free(ctx->ctx_reply); 66606f25ae9SGregory Neil Shapiro ctx->ctx_reply = NULL; 66706f25ae9SGregory Neil Shapiro } 66806f25ae9SGregory Neil Shapiro else 66906f25ae9SGregory Neil Shapiro { 67006f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, r == SMFIS_REJECT ? 67106f25ae9SGregory Neil Shapiro SMFIR_REJECT : SMFIR_TEMPFAIL, NULL, 0); 67206f25ae9SGregory Neil Shapiro } 67306f25ae9SGregory Neil Shapiro break; 67406f25ae9SGregory Neil Shapiro case SMFIS_DISCARD: 67506f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_DISCARD, NULL, 0); 67606f25ae9SGregory Neil Shapiro break; 67706f25ae9SGregory Neil Shapiro case SMFIS_ACCEPT: 67806f25ae9SGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_ACCEPT, NULL, 0); 67906f25ae9SGregory Neil Shapiro break; 680d0cef73dSGregory Neil Shapiro case SMFIS_SKIP: 681d0cef73dSGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_SKIP, NULL, 0); 682d0cef73dSGregory Neil Shapiro break; 68306f25ae9SGregory Neil Shapiro case _SMFIS_OPTIONS: 68406f25ae9SGregory Neil Shapiro { 68506f25ae9SGregory Neil Shapiro mi_int32 v; 686d0cef73dSGregory Neil Shapiro size_t len; 687d0cef73dSGregory Neil Shapiro char *buffer; 688d0cef73dSGregory Neil Shapiro char buf[MILTER_OPTLEN]; 68906f25ae9SGregory Neil Shapiro 690d0cef73dSGregory Neil Shapiro v = htonl(ctx->ctx_prot_vers2mta); 691d0cef73dSGregory Neil Shapiro (void) memcpy(&(buf[0]), (void *) &v, 692d0cef73dSGregory Neil Shapiro MILTER_LEN_BYTES); 693d0cef73dSGregory Neil Shapiro v = htonl(ctx->ctx_aflags); 69406f25ae9SGregory Neil Shapiro (void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v, 69506f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 696d0cef73dSGregory Neil Shapiro v = htonl(ctx->ctx_pflags2mta); 697d0cef73dSGregory Neil Shapiro (void) memcpy(&(buf[MILTER_LEN_BYTES * 2]), 698d0cef73dSGregory Neil Shapiro (void *) &v, MILTER_LEN_BYTES); 699d0cef73dSGregory Neil Shapiro len = milter_addsymlist(ctx, buf, &buffer); 700d0cef73dSGregory Neil Shapiro if (buffer != NULL) 701d0cef73dSGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG, 702d0cef73dSGregory Neil Shapiro buffer, len); 703d0cef73dSGregory Neil Shapiro else 704d0cef73dSGregory Neil Shapiro ret = MI_FAILURE; 705d0cef73dSGregory Neil Shapiro } 706d0cef73dSGregory Neil Shapiro break; 707d0cef73dSGregory Neil Shapiro case SMFIS_NOREPLY: 708d0cef73dSGregory Neil Shapiro if (bit != 0 && 709d0cef73dSGregory Neil Shapiro (ctx->ctx_pflags & bit) != 0 && 710d0cef73dSGregory Neil Shapiro (ctx->ctx_mta_pflags & bit) == 0) 711d0cef73dSGregory Neil Shapiro { 712d0cef73dSGregory Neil Shapiro /* 713d0cef73dSGregory Neil Shapiro ** milter doesn't want to send a reply, 714d0cef73dSGregory Neil Shapiro ** but the MTA doesn't have that feature: fake it. 715d0cef73dSGregory Neil Shapiro */ 716d0cef73dSGregory Neil Shapiro 717d0cef73dSGregory Neil Shapiro ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 718d0cef73dSGregory Neil Shapiro 0); 71906f25ae9SGregory Neil Shapiro } 72006f25ae9SGregory Neil Shapiro break; 72106f25ae9SGregory Neil Shapiro default: /* don't send a reply */ 72206f25ae9SGregory Neil Shapiro break; 72306f25ae9SGregory Neil Shapiro } 72406f25ae9SGregory Neil Shapiro return ret; 72506f25ae9SGregory Neil Shapiro } 72606f25ae9SGregory Neil Shapiro 72706f25ae9SGregory Neil Shapiro /* 72806f25ae9SGregory Neil Shapiro ** CLR_MACROS -- clear set of macros starting from a given index 72906f25ae9SGregory Neil Shapiro ** 73006f25ae9SGregory Neil Shapiro ** Parameters: 73106f25ae9SGregory Neil Shapiro ** ctx -- context structure 73206f25ae9SGregory Neil Shapiro ** m -- index from which to clear all macros 73306f25ae9SGregory Neil Shapiro ** 73406f25ae9SGregory Neil Shapiro ** Returns: 73506f25ae9SGregory Neil Shapiro ** None. 73606f25ae9SGregory Neil Shapiro */ 737d0cef73dSGregory Neil Shapiro 73806f25ae9SGregory Neil Shapiro void 73906f25ae9SGregory Neil Shapiro mi_clr_macros(ctx, m) 74006f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 74106f25ae9SGregory Neil Shapiro int m; 74206f25ae9SGregory Neil Shapiro { 74306f25ae9SGregory Neil Shapiro int i; 74406f25ae9SGregory Neil Shapiro 74506f25ae9SGregory Neil Shapiro for (i = m; i < MAX_MACROS_ENTRIES; i++) 74606f25ae9SGregory Neil Shapiro { 74706f25ae9SGregory Neil Shapiro if (ctx->ctx_mac_ptr[i] != NULL) 74806f25ae9SGregory Neil Shapiro { 74906f25ae9SGregory Neil Shapiro free(ctx->ctx_mac_ptr[i]); 75006f25ae9SGregory Neil Shapiro ctx->ctx_mac_ptr[i] = NULL; 75106f25ae9SGregory Neil Shapiro } 75206f25ae9SGregory Neil Shapiro if (ctx->ctx_mac_buf[i] != NULL) 75306f25ae9SGregory Neil Shapiro { 75406f25ae9SGregory Neil Shapiro free(ctx->ctx_mac_buf[i]); 75506f25ae9SGregory Neil Shapiro ctx->ctx_mac_buf[i] = NULL; 75606f25ae9SGregory Neil Shapiro } 75706f25ae9SGregory Neil Shapiro } 75806f25ae9SGregory Neil Shapiro } 759d0cef73dSGregory Neil Shapiro 76040266059SGregory Neil Shapiro /* 76106f25ae9SGregory Neil Shapiro ** ST_OPTIONNEG -- negotiate options 76206f25ae9SGregory Neil Shapiro ** 76306f25ae9SGregory Neil Shapiro ** Parameters: 76406f25ae9SGregory Neil Shapiro ** g -- generic argument structure 76506f25ae9SGregory Neil Shapiro ** 76606f25ae9SGregory Neil Shapiro ** Returns: 76706f25ae9SGregory Neil Shapiro ** abort/send options/continue 76806f25ae9SGregory Neil Shapiro */ 76906f25ae9SGregory Neil Shapiro 77006f25ae9SGregory Neil Shapiro static int 77106f25ae9SGregory Neil Shapiro st_optionneg(g) 77206f25ae9SGregory Neil Shapiro genarg *g; 77306f25ae9SGregory Neil Shapiro { 774d0cef73dSGregory Neil Shapiro mi_int32 i, v, fake_pflags; 775d0cef73dSGregory Neil Shapiro SMFICTX_PTR ctx; 776d0cef73dSGregory Neil Shapiro int (*fi_negotiate) __P((SMFICTX *, 777d0cef73dSGregory Neil Shapiro unsigned long, unsigned long, 778d0cef73dSGregory Neil Shapiro unsigned long, unsigned long, 779d0cef73dSGregory Neil Shapiro unsigned long *, unsigned long *, 780d0cef73dSGregory Neil Shapiro unsigned long *, unsigned long *)); 78106f25ae9SGregory Neil Shapiro 78206f25ae9SGregory Neil Shapiro if (g == NULL || g->a_ctx->ctx_smfi == NULL) 78306f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 784d0cef73dSGregory Neil Shapiro ctx = g->a_ctx; 785d0cef73dSGregory Neil Shapiro mi_clr_macros(ctx, g->a_idx + 1); 786d0cef73dSGregory Neil Shapiro ctx->ctx_prot_vers = SMFI_PROT_VERSION; 78706f25ae9SGregory Neil Shapiro 78806f25ae9SGregory Neil Shapiro /* check for minimum length */ 78906f25ae9SGregory Neil Shapiro if (g->a_len < MILTER_OPTLEN) 79006f25ae9SGregory Neil Shapiro { 79106f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 792d0cef73dSGregory Neil Shapiro "%s: st_optionneg[%ld]: len too short %d < %d", 793d0cef73dSGregory Neil Shapiro ctx->ctx_smfi->xxfi_name, 794d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, (int) g->a_len, 79506f25ae9SGregory Neil Shapiro MILTER_OPTLEN); 79606f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 79706f25ae9SGregory Neil Shapiro } 79806f25ae9SGregory Neil Shapiro 799d0cef73dSGregory Neil Shapiro /* protocol version */ 800d0cef73dSGregory Neil Shapiro (void) memcpy((void *) &i, (void *) &(g->a_buf[0]), MILTER_LEN_BYTES); 80106f25ae9SGregory Neil Shapiro v = ntohl(i); 802d0cef73dSGregory Neil Shapiro 803d0cef73dSGregory Neil Shapiro #define SMFI_PROT_VERSION_MIN 2 804d0cef73dSGregory Neil Shapiro 805d0cef73dSGregory Neil Shapiro /* check for minimum version */ 806d0cef73dSGregory Neil Shapiro if (v < SMFI_PROT_VERSION_MIN) 80706f25ae9SGregory Neil Shapiro { 80806f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 809d0cef73dSGregory Neil Shapiro "%s: st_optionneg[%ld]: protocol version too old %d < %d", 810d0cef73dSGregory Neil Shapiro ctx->ctx_smfi->xxfi_name, 811d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, v, SMFI_PROT_VERSION_MIN); 81206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 81306f25ae9SGregory Neil Shapiro } 814d0cef73dSGregory Neil Shapiro ctx->ctx_mta_prot_vers = v; 815d0cef73dSGregory Neil Shapiro if (ctx->ctx_prot_vers < ctx->ctx_mta_prot_vers) 816d0cef73dSGregory Neil Shapiro ctx->ctx_prot_vers2mta = ctx->ctx_prot_vers; 817d0cef73dSGregory Neil Shapiro else 818d0cef73dSGregory Neil Shapiro ctx->ctx_prot_vers2mta = ctx->ctx_mta_prot_vers; 81906f25ae9SGregory Neil Shapiro 82006f25ae9SGregory Neil Shapiro (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]), 82106f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 82206f25ae9SGregory Neil Shapiro v = ntohl(i); 82306f25ae9SGregory Neil Shapiro 82406f25ae9SGregory Neil Shapiro /* no flags? set to default value for V1 actions */ 82506f25ae9SGregory Neil Shapiro if (v == 0) 82606f25ae9SGregory Neil Shapiro v = SMFI_V1_ACTS; 827d0cef73dSGregory Neil Shapiro ctx->ctx_mta_aflags = v; /* MTA action flags */ 82806f25ae9SGregory Neil Shapiro 82906f25ae9SGregory Neil Shapiro (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES * 2]), 83006f25ae9SGregory Neil Shapiro MILTER_LEN_BYTES); 83106f25ae9SGregory Neil Shapiro v = ntohl(i); 83206f25ae9SGregory Neil Shapiro 83306f25ae9SGregory Neil Shapiro /* no flags? set to default value for V1 protocol */ 83406f25ae9SGregory Neil Shapiro if (v == 0) 83506f25ae9SGregory Neil Shapiro v = SMFI_V1_PROT; 836d0cef73dSGregory Neil Shapiro ctx->ctx_mta_pflags = v; /* MTA protocol flags */ 837d0cef73dSGregory Neil Shapiro 838d0cef73dSGregory Neil Shapiro /* 839d0cef73dSGregory Neil Shapiro ** Copy flags from milter struct into libmilter context; 840d0cef73dSGregory Neil Shapiro ** this variable will be used later on to check whether 841d0cef73dSGregory Neil Shapiro ** the MTA "actions" can fulfill the milter requirements, 842d0cef73dSGregory Neil Shapiro ** but it may be overwritten by the negotiate callback. 843d0cef73dSGregory Neil Shapiro */ 844d0cef73dSGregory Neil Shapiro 845d0cef73dSGregory Neil Shapiro ctx->ctx_aflags = ctx->ctx_smfi->xxfi_flags; 846d0cef73dSGregory Neil Shapiro fake_pflags = SMFIP_NR_CONN 847d0cef73dSGregory Neil Shapiro |SMFIP_NR_HELO 848d0cef73dSGregory Neil Shapiro |SMFIP_NR_MAIL 849d0cef73dSGregory Neil Shapiro |SMFIP_NR_RCPT 850d0cef73dSGregory Neil Shapiro |SMFIP_NR_DATA 851d0cef73dSGregory Neil Shapiro |SMFIP_NR_UNKN 852d0cef73dSGregory Neil Shapiro |SMFIP_NR_HDR 853d0cef73dSGregory Neil Shapiro |SMFIP_NR_EOH 854d0cef73dSGregory Neil Shapiro |SMFIP_NR_BODY 855d0cef73dSGregory Neil Shapiro ; 856d0cef73dSGregory Neil Shapiro 857d0cef73dSGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 858d0cef73dSGregory Neil Shapiro (fi_negotiate = g->a_ctx->ctx_smfi->xxfi_negotiate) != NULL) 859d0cef73dSGregory Neil Shapiro { 860d0cef73dSGregory Neil Shapiro int r; 861d0cef73dSGregory Neil Shapiro unsigned long m_aflags, m_pflags, m_f2, m_f3; 862d0cef73dSGregory Neil Shapiro 863d0cef73dSGregory Neil Shapiro /* 864d0cef73dSGregory Neil Shapiro ** let milter decide whether the features offered by the 865d0cef73dSGregory Neil Shapiro ** MTA are "good enough". 866d0cef73dSGregory Neil Shapiro ** Notes: 867d0cef73dSGregory Neil Shapiro ** - libmilter can "fake" some features (e.g., SMFIP_NR_HDR) 868d0cef73dSGregory Neil Shapiro ** - m_f2, m_f3 are for future extensions 869d0cef73dSGregory Neil Shapiro */ 870d0cef73dSGregory Neil Shapiro 871d0cef73dSGregory Neil Shapiro m_f2 = m_f3 = 0; 872d0cef73dSGregory Neil Shapiro m_aflags = ctx->ctx_mta_aflags; 873d0cef73dSGregory Neil Shapiro m_pflags = ctx->ctx_pflags; 874d0cef73dSGregory Neil Shapiro if ((SMFIP_SKIP & ctx->ctx_mta_pflags) != 0) 875d0cef73dSGregory Neil Shapiro m_pflags |= SMFIP_SKIP; 876d0cef73dSGregory Neil Shapiro r = fi_negotiate(g->a_ctx, 877d0cef73dSGregory Neil Shapiro ctx->ctx_mta_aflags, 878d0cef73dSGregory Neil Shapiro ctx->ctx_mta_pflags|fake_pflags, 879d0cef73dSGregory Neil Shapiro 0, 0, 880d0cef73dSGregory Neil Shapiro &m_aflags, &m_pflags, &m_f2, &m_f3); 881d0cef73dSGregory Neil Shapiro 882d0cef73dSGregory Neil Shapiro /* 883d0cef73dSGregory Neil Shapiro ** Types of protocol flags (pflags): 884d0cef73dSGregory Neil Shapiro ** 1. do NOT send protocol step X 885d0cef73dSGregory Neil Shapiro ** 2. MTA can do/understand something extra (SKIP, 886d0cef73dSGregory Neil Shapiro ** send unknown RCPTs) 887d0cef73dSGregory Neil Shapiro ** 3. MTA can deal with "no reply" for various protocol steps 888d0cef73dSGregory Neil Shapiro ** Note: this mean that it isn't possible to simply set all 889d0cef73dSGregory Neil Shapiro ** flags to get "everything": 890d0cef73dSGregory Neil Shapiro ** setting a flag of type 1 turns off a step 891d0cef73dSGregory Neil Shapiro ** (it should be the other way around: 892d0cef73dSGregory Neil Shapiro ** a flag means a protocol step can be sent) 893d0cef73dSGregory Neil Shapiro ** setting a flag of type 3 requires that milter 894d0cef73dSGregory Neil Shapiro ** never sends a reply for the corresponding step. 895d0cef73dSGregory Neil Shapiro ** Summary: the "negation" of protocol flags is causing 896d0cef73dSGregory Neil Shapiro ** problems, but at least for type 3 there is no simple 897d0cef73dSGregory Neil Shapiro ** solution. 898d0cef73dSGregory Neil Shapiro ** 899d0cef73dSGregory Neil Shapiro ** What should "all options" mean? 900d0cef73dSGregory Neil Shapiro ** send all protocol steps _except_ those for which there is 901d0cef73dSGregory Neil Shapiro ** no callback (currently registered in ctx_pflags) 902d0cef73dSGregory Neil Shapiro ** expect SKIP as return code? Yes 903d0cef73dSGregory Neil Shapiro ** send unknown RCPTs? No, 904d0cef73dSGregory Neil Shapiro ** must be explicitly requested? 905d0cef73dSGregory Neil Shapiro ** "no reply" for some protocol steps? No, 906d0cef73dSGregory Neil Shapiro ** must be explicitly requested. 907d0cef73dSGregory Neil Shapiro */ 908d0cef73dSGregory Neil Shapiro 909d0cef73dSGregory Neil Shapiro if (SMFIS_ALL_OPTS == r) 910d0cef73dSGregory Neil Shapiro { 911d0cef73dSGregory Neil Shapiro ctx->ctx_aflags = ctx->ctx_mta_aflags; 912d0cef73dSGregory Neil Shapiro ctx->ctx_pflags2mta = ctx->ctx_pflags; 913d0cef73dSGregory Neil Shapiro if ((SMFIP_SKIP & ctx->ctx_mta_pflags) != 0) 914d0cef73dSGregory Neil Shapiro ctx->ctx_pflags2mta |= SMFIP_SKIP; 915d0cef73dSGregory Neil Shapiro } 916d0cef73dSGregory Neil Shapiro else if (r != SMFIS_CONTINUE) 91706f25ae9SGregory Neil Shapiro { 91806f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 919d0cef73dSGregory Neil Shapiro "%s: st_optionneg[%ld]: xxfi_negotiate returned %d (protocol options=0x%lx, actions=0x%lx)", 920d0cef73dSGregory Neil Shapiro ctx->ctx_smfi->xxfi_name, 921d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, r, ctx->ctx_mta_pflags, 922d0cef73dSGregory Neil Shapiro ctx->ctx_mta_aflags); 923d0cef73dSGregory Neil Shapiro return _SMFIS_ABORT; 924d0cef73dSGregory Neil Shapiro } 925d0cef73dSGregory Neil Shapiro else 926d0cef73dSGregory Neil Shapiro { 927d0cef73dSGregory Neil Shapiro ctx->ctx_aflags = m_aflags; 928d0cef73dSGregory Neil Shapiro ctx->ctx_pflags = m_pflags; 929d0cef73dSGregory Neil Shapiro ctx->ctx_pflags2mta = m_pflags; 930d0cef73dSGregory Neil Shapiro } 931d0cef73dSGregory Neil Shapiro 932d0cef73dSGregory Neil Shapiro /* check whether some flags need to be "faked" */ 933d0cef73dSGregory Neil Shapiro i = ctx->ctx_pflags2mta; 934d0cef73dSGregory Neil Shapiro if ((ctx->ctx_mta_pflags & i) != i) 935d0cef73dSGregory Neil Shapiro { 936d0cef73dSGregory Neil Shapiro unsigned int idx; 937d0cef73dSGregory Neil Shapiro unsigned long b; 938d0cef73dSGregory Neil Shapiro 939d0cef73dSGregory Neil Shapiro /* 940d0cef73dSGregory Neil Shapiro ** If some behavior can be faked (set in fake_pflags), 941d0cef73dSGregory Neil Shapiro ** but the MTA doesn't support it, then unset 942d0cef73dSGregory Neil Shapiro ** that flag in the value that is sent to the MTA. 943d0cef73dSGregory Neil Shapiro */ 944d0cef73dSGregory Neil Shapiro 945d0cef73dSGregory Neil Shapiro for (idx = 0; idx < 32; idx++) 946d0cef73dSGregory Neil Shapiro { 947d0cef73dSGregory Neil Shapiro b = 1 << idx; 948d0cef73dSGregory Neil Shapiro if ((ctx->ctx_mta_pflags & b) != b && 949d0cef73dSGregory Neil Shapiro (fake_pflags & b) == b) 950d0cef73dSGregory Neil Shapiro ctx->ctx_pflags2mta &= ~b; 951d0cef73dSGregory Neil Shapiro } 952d0cef73dSGregory Neil Shapiro } 953d0cef73dSGregory Neil Shapiro } 954d0cef73dSGregory Neil Shapiro else 955d0cef73dSGregory Neil Shapiro { 956d0cef73dSGregory Neil Shapiro /* 957d0cef73dSGregory Neil Shapiro ** Set the protocol flags based on the values determined 958d0cef73dSGregory Neil Shapiro ** in mi_listener() which checked the defined callbacks. 959d0cef73dSGregory Neil Shapiro */ 960d0cef73dSGregory Neil Shapiro 961d0cef73dSGregory Neil Shapiro ctx->ctx_pflags2mta = ctx->ctx_pflags; 962d0cef73dSGregory Neil Shapiro } 963d0cef73dSGregory Neil Shapiro 964d0cef73dSGregory Neil Shapiro /* check whether actions and protocol requirements can be satisfied */ 965d0cef73dSGregory Neil Shapiro i = ctx->ctx_aflags; 966d0cef73dSGregory Neil Shapiro if ((i & ctx->ctx_mta_aflags) != i) 967d0cef73dSGregory Neil Shapiro { 968d0cef73dSGregory Neil Shapiro smi_log(SMI_LOG_ERR, 969d0cef73dSGregory Neil Shapiro "%s: st_optionneg[%ld]: 0x%lx does not fulfill action requirements 0x%x", 970d0cef73dSGregory Neil Shapiro ctx->ctx_smfi->xxfi_name, 971d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, ctx->ctx_mta_aflags, i); 97206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 97306f25ae9SGregory Neil Shapiro } 97406f25ae9SGregory Neil Shapiro 975d0cef73dSGregory Neil Shapiro i = ctx->ctx_pflags2mta; 976d0cef73dSGregory Neil Shapiro if ((ctx->ctx_mta_pflags & i) != i) 977d0cef73dSGregory Neil Shapiro { 978d0cef73dSGregory Neil Shapiro /* 979d0cef73dSGregory Neil Shapiro ** Older MTAs do not support some protocol steps. 980d0cef73dSGregory Neil Shapiro ** As this protocol is a bit "wierd" (it asks for steps 981d0cef73dSGregory Neil Shapiro ** NOT to be taken/sent) we have to check whether we 982d0cef73dSGregory Neil Shapiro ** should turn off those "negative" requests. 983d0cef73dSGregory Neil Shapiro ** Currently these are only SMFIP_NODATA and SMFIP_NOUNKNOWN. 984d0cef73dSGregory Neil Shapiro */ 985d0cef73dSGregory Neil Shapiro 986d0cef73dSGregory Neil Shapiro if (bitset(SMFIP_NODATA, ctx->ctx_pflags2mta) && 987d0cef73dSGregory Neil Shapiro !bitset(SMFIP_NODATA, ctx->ctx_mta_pflags)) 988d0cef73dSGregory Neil Shapiro ctx->ctx_pflags2mta &= ~SMFIP_NODATA; 989d0cef73dSGregory Neil Shapiro if (bitset(SMFIP_NOUNKNOWN, ctx->ctx_pflags2mta) && 990d0cef73dSGregory Neil Shapiro !bitset(SMFIP_NOUNKNOWN, ctx->ctx_mta_pflags)) 991d0cef73dSGregory Neil Shapiro ctx->ctx_pflags2mta &= ~SMFIP_NOUNKNOWN; 992d0cef73dSGregory Neil Shapiro i = ctx->ctx_pflags2mta; 993d0cef73dSGregory Neil Shapiro } 994d0cef73dSGregory Neil Shapiro 995d0cef73dSGregory Neil Shapiro if ((ctx->ctx_mta_pflags & i) != i) 996d0cef73dSGregory Neil Shapiro { 997d0cef73dSGregory Neil Shapiro smi_log(SMI_LOG_ERR, 998d0cef73dSGregory Neil Shapiro "%s: st_optionneg[%ld]: 0x%lx does not fulfill protocol requirements 0x%x", 999d0cef73dSGregory Neil Shapiro ctx->ctx_smfi->xxfi_name, 1000d0cef73dSGregory Neil Shapiro (long) ctx->ctx_id, ctx->ctx_mta_pflags, i); 1001d0cef73dSGregory Neil Shapiro return _SMFIS_ABORT; 1002d0cef73dSGregory Neil Shapiro } 1003d0cef73dSGregory Neil Shapiro 1004d0cef73dSGregory Neil Shapiro if (ctx->ctx_dbg > 3) 1005d0cef73dSGregory Neil Shapiro sm_dprintf("[%ld] milter_negotiate:" 1006d0cef73dSGregory Neil Shapiro " mta_actions=0x%lx, mta_flags=0x%lx" 1007d0cef73dSGregory Neil Shapiro " actions=0x%lx, flags=0x%lx\n" 1008d0cef73dSGregory Neil Shapiro , (long) ctx->ctx_id 1009d0cef73dSGregory Neil Shapiro , ctx->ctx_mta_aflags, ctx->ctx_mta_pflags 1010d0cef73dSGregory Neil Shapiro , ctx->ctx_aflags, ctx->ctx_pflags); 1011d0cef73dSGregory Neil Shapiro 101206f25ae9SGregory Neil Shapiro return _SMFIS_OPTIONS; 101306f25ae9SGregory Neil Shapiro } 1014d0cef73dSGregory Neil Shapiro 101540266059SGregory Neil Shapiro /* 101606f25ae9SGregory Neil Shapiro ** ST_CONNECTINFO -- receive connection information 101706f25ae9SGregory Neil Shapiro ** 101806f25ae9SGregory Neil Shapiro ** Parameters: 101906f25ae9SGregory Neil Shapiro ** g -- generic argument structure 102006f25ae9SGregory Neil Shapiro ** 102106f25ae9SGregory Neil Shapiro ** Returns: 102206f25ae9SGregory Neil Shapiro ** continue or filter-specified value 102306f25ae9SGregory Neil Shapiro */ 102406f25ae9SGregory Neil Shapiro 102506f25ae9SGregory Neil Shapiro static int 102606f25ae9SGregory Neil Shapiro st_connectinfo(g) 102706f25ae9SGregory Neil Shapiro genarg *g; 102806f25ae9SGregory Neil Shapiro { 102906f25ae9SGregory Neil Shapiro size_t l; 103006f25ae9SGregory Neil Shapiro size_t i; 103106f25ae9SGregory Neil Shapiro char *s, family; 103240266059SGregory Neil Shapiro unsigned short port = 0; 103306f25ae9SGregory Neil Shapiro _SOCK_ADDR sockaddr; 103406f25ae9SGregory Neil Shapiro sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *)); 103506f25ae9SGregory Neil Shapiro 103606f25ae9SGregory Neil Shapiro if (g == NULL) 103706f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 103806f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 103906f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi == NULL || 104006f25ae9SGregory Neil Shapiro (fi_connect = g->a_ctx->ctx_smfi->xxfi_connect) == NULL) 104106f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 104206f25ae9SGregory Neil Shapiro 104306f25ae9SGregory Neil Shapiro s = g->a_buf; 104406f25ae9SGregory Neil Shapiro i = 0; 104506f25ae9SGregory Neil Shapiro l = g->a_len; 104606f25ae9SGregory Neil Shapiro while (s[i] != '\0' && i <= l) 104706f25ae9SGregory Neil Shapiro ++i; 1048323f6dcbSGregory Neil Shapiro if (i + 1 >= l) 104906f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 105006f25ae9SGregory Neil Shapiro 105106f25ae9SGregory Neil Shapiro /* Move past trailing \0 in host string */ 105206f25ae9SGregory Neil Shapiro i++; 105306f25ae9SGregory Neil Shapiro family = s[i++]; 1054a7ec597cSGregory Neil Shapiro (void) memset(&sockaddr, '\0', sizeof sockaddr); 105506f25ae9SGregory Neil Shapiro if (family != SMFIA_UNKNOWN) 105606f25ae9SGregory Neil Shapiro { 1057323f6dcbSGregory Neil Shapiro if (i + sizeof port >= l) 105806f25ae9SGregory Neil Shapiro { 105906f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 1060d0cef73dSGregory Neil Shapiro "%s: connect[%ld]: wrong len %d >= %d", 106106f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 1062d0cef73dSGregory Neil Shapiro (long) g->a_ctx->ctx_id, (int) i, (int) l); 106306f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 106406f25ae9SGregory Neil Shapiro } 1065323f6dcbSGregory Neil Shapiro (void) memcpy((void *) &port, (void *) (s + i), 1066323f6dcbSGregory Neil Shapiro sizeof port); 1067323f6dcbSGregory Neil Shapiro i += sizeof port; 1068605302a5SGregory Neil Shapiro 1069605302a5SGregory Neil Shapiro /* make sure string is terminated */ 1070605302a5SGregory Neil Shapiro if (s[l - 1] != '\0') 1071605302a5SGregory Neil Shapiro return _SMFIS_ABORT; 107206f25ae9SGregory Neil Shapiro # if NETINET 107306f25ae9SGregory Neil Shapiro if (family == SMFIA_INET) 107406f25ae9SGregory Neil Shapiro { 107506f25ae9SGregory Neil Shapiro if (inet_aton(s + i, (struct in_addr *) &sockaddr.sin.sin_addr) 1076605302a5SGregory Neil Shapiro != 1) 107706f25ae9SGregory Neil Shapiro { 107806f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 1079d0cef73dSGregory Neil Shapiro "%s: connect[%ld]: inet_aton failed", 108006f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 1081d0cef73dSGregory Neil Shapiro (long) g->a_ctx->ctx_id); 108206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 108306f25ae9SGregory Neil Shapiro } 108406f25ae9SGregory Neil Shapiro sockaddr.sa.sa_family = AF_INET; 108506f25ae9SGregory Neil Shapiro if (port > 0) 108606f25ae9SGregory Neil Shapiro sockaddr.sin.sin_port = port; 108706f25ae9SGregory Neil Shapiro } 108806f25ae9SGregory Neil Shapiro else 108906f25ae9SGregory Neil Shapiro # endif /* NETINET */ 109006f25ae9SGregory Neil Shapiro # if NETINET6 109106f25ae9SGregory Neil Shapiro if (family == SMFIA_INET6) 109206f25ae9SGregory Neil Shapiro { 109340266059SGregory Neil Shapiro if (mi_inet_pton(AF_INET6, s + i, 109406f25ae9SGregory Neil Shapiro &sockaddr.sin6.sin6_addr) != 1) 109506f25ae9SGregory Neil Shapiro { 109606f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 1097d0cef73dSGregory Neil Shapiro "%s: connect[%ld]: mi_inet_pton failed", 109806f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 1099d0cef73dSGregory Neil Shapiro (long) g->a_ctx->ctx_id); 110006f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 110106f25ae9SGregory Neil Shapiro } 110206f25ae9SGregory Neil Shapiro sockaddr.sa.sa_family = AF_INET6; 110306f25ae9SGregory Neil Shapiro if (port > 0) 110406f25ae9SGregory Neil Shapiro sockaddr.sin6.sin6_port = port; 110506f25ae9SGregory Neil Shapiro } 110606f25ae9SGregory Neil Shapiro else 110706f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 110806f25ae9SGregory Neil Shapiro # if NETUNIX 110906f25ae9SGregory Neil Shapiro if (family == SMFIA_UNIX) 111006f25ae9SGregory Neil Shapiro { 111140266059SGregory Neil Shapiro if (sm_strlcpy(sockaddr.sunix.sun_path, s + i, 111206f25ae9SGregory Neil Shapiro sizeof sockaddr.sunix.sun_path) >= 111306f25ae9SGregory Neil Shapiro sizeof sockaddr.sunix.sun_path) 111406f25ae9SGregory Neil Shapiro { 111506f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 1116d0cef73dSGregory Neil Shapiro "%s: connect[%ld]: path too long", 111706f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 1118d0cef73dSGregory Neil Shapiro (long) g->a_ctx->ctx_id); 111906f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 112006f25ae9SGregory Neil Shapiro } 112106f25ae9SGregory Neil Shapiro sockaddr.sunix.sun_family = AF_UNIX; 112206f25ae9SGregory Neil Shapiro } 112306f25ae9SGregory Neil Shapiro else 112406f25ae9SGregory Neil Shapiro # endif /* NETUNIX */ 112506f25ae9SGregory Neil Shapiro { 112606f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR, 1127d0cef73dSGregory Neil Shapiro "%s: connect[%ld]: unknown family %d", 112806f25ae9SGregory Neil Shapiro g->a_ctx->ctx_smfi->xxfi_name, 1129d0cef73dSGregory Neil Shapiro (long) g->a_ctx->ctx_id, family); 113006f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 113106f25ae9SGregory Neil Shapiro } 113206f25ae9SGregory Neil Shapiro } 113306f25ae9SGregory Neil Shapiro return (*fi_connect)(g->a_ctx, g->a_buf, 113406f25ae9SGregory Neil Shapiro family != SMFIA_UNKNOWN ? &sockaddr : NULL); 113506f25ae9SGregory Neil Shapiro } 1136e92d3f3fSGregory Neil Shapiro 113740266059SGregory Neil Shapiro /* 113806f25ae9SGregory Neil Shapiro ** ST_EOH -- end of headers 113906f25ae9SGregory Neil Shapiro ** 114006f25ae9SGregory Neil Shapiro ** Parameters: 114106f25ae9SGregory Neil Shapiro ** g -- generic argument structure 114206f25ae9SGregory Neil Shapiro ** 114306f25ae9SGregory Neil Shapiro ** Returns: 114406f25ae9SGregory Neil Shapiro ** continue or filter-specified value 114506f25ae9SGregory Neil Shapiro */ 114606f25ae9SGregory Neil Shapiro 114706f25ae9SGregory Neil Shapiro static int 114806f25ae9SGregory Neil Shapiro st_eoh(g) 114906f25ae9SGregory Neil Shapiro genarg *g; 115006f25ae9SGregory Neil Shapiro { 115106f25ae9SGregory Neil Shapiro sfsistat (*fi_eoh) __P((SMFICTX *)); 115206f25ae9SGregory Neil Shapiro 115306f25ae9SGregory Neil Shapiro if (g == NULL) 115406f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 115506f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 115606f25ae9SGregory Neil Shapiro (fi_eoh = g->a_ctx->ctx_smfi->xxfi_eoh) != NULL) 115706f25ae9SGregory Neil Shapiro return (*fi_eoh)(g->a_ctx); 115806f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 115906f25ae9SGregory Neil Shapiro } 1160e92d3f3fSGregory Neil Shapiro 1161e92d3f3fSGregory Neil Shapiro /* 1162e92d3f3fSGregory Neil Shapiro ** ST_DATA -- DATA command 1163e92d3f3fSGregory Neil Shapiro ** 1164e92d3f3fSGregory Neil Shapiro ** Parameters: 1165e92d3f3fSGregory Neil Shapiro ** g -- generic argument structure 1166e92d3f3fSGregory Neil Shapiro ** 1167e92d3f3fSGregory Neil Shapiro ** Returns: 1168e92d3f3fSGregory Neil Shapiro ** continue or filter-specified value 1169e92d3f3fSGregory Neil Shapiro */ 1170e92d3f3fSGregory Neil Shapiro 1171e92d3f3fSGregory Neil Shapiro static int 1172e92d3f3fSGregory Neil Shapiro st_data(g) 1173e92d3f3fSGregory Neil Shapiro genarg *g; 1174e92d3f3fSGregory Neil Shapiro { 1175e92d3f3fSGregory Neil Shapiro sfsistat (*fi_data) __P((SMFICTX *)); 1176e92d3f3fSGregory Neil Shapiro 1177e92d3f3fSGregory Neil Shapiro if (g == NULL) 1178e92d3f3fSGregory Neil Shapiro return _SMFIS_ABORT; 1179e92d3f3fSGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 1180e92d3f3fSGregory Neil Shapiro (fi_data = g->a_ctx->ctx_smfi->xxfi_data) != NULL) 1181e92d3f3fSGregory Neil Shapiro return (*fi_data)(g->a_ctx); 1182e92d3f3fSGregory Neil Shapiro return SMFIS_CONTINUE; 1183e92d3f3fSGregory Neil Shapiro } 1184e92d3f3fSGregory Neil Shapiro 118540266059SGregory Neil Shapiro /* 118606f25ae9SGregory Neil Shapiro ** ST_HELO -- helo/ehlo command 118706f25ae9SGregory Neil Shapiro ** 118806f25ae9SGregory Neil Shapiro ** Parameters: 118906f25ae9SGregory Neil Shapiro ** g -- generic argument structure 119006f25ae9SGregory Neil Shapiro ** 119106f25ae9SGregory Neil Shapiro ** Returns: 119206f25ae9SGregory Neil Shapiro ** continue or filter-specified value 119306f25ae9SGregory Neil Shapiro */ 1194d0cef73dSGregory Neil Shapiro 119506f25ae9SGregory Neil Shapiro static int 119606f25ae9SGregory Neil Shapiro st_helo(g) 119706f25ae9SGregory Neil Shapiro genarg *g; 119806f25ae9SGregory Neil Shapiro { 119906f25ae9SGregory Neil Shapiro sfsistat (*fi_helo) __P((SMFICTX *, char *)); 120006f25ae9SGregory Neil Shapiro 120106f25ae9SGregory Neil Shapiro if (g == NULL) 120206f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 120306f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); 120406f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 120506f25ae9SGregory Neil Shapiro (fi_helo = g->a_ctx->ctx_smfi->xxfi_helo) != NULL) 1206323f6dcbSGregory Neil Shapiro { 1207323f6dcbSGregory Neil Shapiro /* paranoia: check for terminating '\0' */ 1208323f6dcbSGregory Neil Shapiro if (g->a_len == 0 || g->a_buf[g->a_len - 1] != '\0') 1209323f6dcbSGregory Neil Shapiro return MI_FAILURE; 121006f25ae9SGregory Neil Shapiro return (*fi_helo)(g->a_ctx, g->a_buf); 1211323f6dcbSGregory Neil Shapiro } 121206f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 121306f25ae9SGregory Neil Shapiro } 1214d0cef73dSGregory Neil Shapiro 121540266059SGregory Neil Shapiro /* 121606f25ae9SGregory Neil Shapiro ** ST_HEADER -- header line 121706f25ae9SGregory Neil Shapiro ** 121806f25ae9SGregory Neil Shapiro ** Parameters: 121906f25ae9SGregory Neil Shapiro ** g -- generic argument structure 122006f25ae9SGregory Neil Shapiro ** 122106f25ae9SGregory Neil Shapiro ** Returns: 122206f25ae9SGregory Neil Shapiro ** continue or filter-specified value 122306f25ae9SGregory Neil Shapiro */ 122406f25ae9SGregory Neil Shapiro 122506f25ae9SGregory Neil Shapiro static int 122606f25ae9SGregory Neil Shapiro st_header(g) 122706f25ae9SGregory Neil Shapiro genarg *g; 122806f25ae9SGregory Neil Shapiro { 122906f25ae9SGregory Neil Shapiro char *hf, *hv; 123006f25ae9SGregory Neil Shapiro sfsistat (*fi_header) __P((SMFICTX *, char *, char *)); 123106f25ae9SGregory Neil Shapiro 123206f25ae9SGregory Neil Shapiro if (g == NULL) 123306f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 123406f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi == NULL || 123506f25ae9SGregory Neil Shapiro (fi_header = g->a_ctx->ctx_smfi->xxfi_header) == NULL) 123606f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 123706f25ae9SGregory Neil Shapiro if (dec_arg2(g->a_buf, g->a_len, &hf, &hv) == MI_SUCCESS) 123806f25ae9SGregory Neil Shapiro return (*fi_header)(g->a_ctx, hf, hv); 123906f25ae9SGregory Neil Shapiro else 124006f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 124106f25ae9SGregory Neil Shapiro } 124206f25ae9SGregory Neil Shapiro 124306f25ae9SGregory Neil Shapiro #define ARGV_FCT(lf, rf, idx) \ 124406f25ae9SGregory Neil Shapiro char **argv; \ 124506f25ae9SGregory Neil Shapiro sfsistat (*lf) __P((SMFICTX *, char **)); \ 124606f25ae9SGregory Neil Shapiro int r; \ 124706f25ae9SGregory Neil Shapiro \ 124806f25ae9SGregory Neil Shapiro if (g == NULL) \ 124906f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; \ 125006f25ae9SGregory Neil Shapiro mi_clr_macros(g->a_ctx, g->a_idx + 1); \ 125106f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi == NULL || \ 125206f25ae9SGregory Neil Shapiro (lf = g->a_ctx->ctx_smfi->rf) == NULL) \ 125306f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; \ 125406f25ae9SGregory Neil Shapiro if ((argv = dec_argv(g->a_buf, g->a_len)) == NULL) \ 125506f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; \ 125606f25ae9SGregory Neil Shapiro r = (*lf)(g->a_ctx, argv); \ 125706f25ae9SGregory Neil Shapiro free(argv); \ 125806f25ae9SGregory Neil Shapiro return r; 125906f25ae9SGregory Neil Shapiro 126040266059SGregory Neil Shapiro /* 126106f25ae9SGregory Neil Shapiro ** ST_SENDER -- MAIL FROM command 126206f25ae9SGregory Neil Shapiro ** 126306f25ae9SGregory Neil Shapiro ** Parameters: 126406f25ae9SGregory Neil Shapiro ** g -- generic argument structure 126506f25ae9SGregory Neil Shapiro ** 126606f25ae9SGregory Neil Shapiro ** Returns: 126706f25ae9SGregory Neil Shapiro ** continue or filter-specified value 126806f25ae9SGregory Neil Shapiro */ 126906f25ae9SGregory Neil Shapiro 127006f25ae9SGregory Neil Shapiro static int 127106f25ae9SGregory Neil Shapiro st_sender(g) 127206f25ae9SGregory Neil Shapiro genarg *g; 127306f25ae9SGregory Neil Shapiro { 127406f25ae9SGregory Neil Shapiro ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL) 127506f25ae9SGregory Neil Shapiro } 1276d0cef73dSGregory Neil Shapiro 127740266059SGregory Neil Shapiro /* 127806f25ae9SGregory Neil Shapiro ** ST_RCPT -- RCPT TO command 127906f25ae9SGregory Neil Shapiro ** 128006f25ae9SGregory Neil Shapiro ** Parameters: 128106f25ae9SGregory Neil Shapiro ** g -- generic argument structure 128206f25ae9SGregory Neil Shapiro ** 128306f25ae9SGregory Neil Shapiro ** Returns: 128406f25ae9SGregory Neil Shapiro ** continue or filter-specified value 128506f25ae9SGregory Neil Shapiro */ 128606f25ae9SGregory Neil Shapiro 128706f25ae9SGregory Neil Shapiro static int 128806f25ae9SGregory Neil Shapiro st_rcpt(g) 128906f25ae9SGregory Neil Shapiro genarg *g; 129006f25ae9SGregory Neil Shapiro { 129106f25ae9SGregory Neil Shapiro ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT) 129206f25ae9SGregory Neil Shapiro } 1293e92d3f3fSGregory Neil Shapiro 1294e92d3f3fSGregory Neil Shapiro /* 1295e92d3f3fSGregory Neil Shapiro ** ST_UNKNOWN -- unrecognized or unimplemented command 1296e92d3f3fSGregory Neil Shapiro ** 1297e92d3f3fSGregory Neil Shapiro ** Parameters: 1298e92d3f3fSGregory Neil Shapiro ** g -- generic argument structure 1299e92d3f3fSGregory Neil Shapiro ** 1300e92d3f3fSGregory Neil Shapiro ** Returns: 1301e92d3f3fSGregory Neil Shapiro ** continue or filter-specified value 1302e92d3f3fSGregory Neil Shapiro */ 1303e92d3f3fSGregory Neil Shapiro 1304e92d3f3fSGregory Neil Shapiro static int 1305e92d3f3fSGregory Neil Shapiro st_unknown(g) 1306e92d3f3fSGregory Neil Shapiro genarg *g; 1307e92d3f3fSGregory Neil Shapiro { 1308d0cef73dSGregory Neil Shapiro sfsistat (*fi_unknown) __P((SMFICTX *, const char *)); 1309e92d3f3fSGregory Neil Shapiro 1310e92d3f3fSGregory Neil Shapiro if (g == NULL) 1311e92d3f3fSGregory Neil Shapiro return _SMFIS_ABORT; 1312e92d3f3fSGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 1313e92d3f3fSGregory Neil Shapiro (fi_unknown = g->a_ctx->ctx_smfi->xxfi_unknown) != NULL) 1314d0cef73dSGregory Neil Shapiro return (*fi_unknown)(g->a_ctx, (const char *) g->a_buf); 1315e92d3f3fSGregory Neil Shapiro return SMFIS_CONTINUE; 1316e92d3f3fSGregory Neil Shapiro } 1317e92d3f3fSGregory Neil Shapiro 131840266059SGregory Neil Shapiro /* 131906f25ae9SGregory Neil Shapiro ** ST_MACROS -- deal with macros received from the MTA 132006f25ae9SGregory Neil Shapiro ** 132106f25ae9SGregory Neil Shapiro ** Parameters: 132206f25ae9SGregory Neil Shapiro ** g -- generic argument structure 132306f25ae9SGregory Neil Shapiro ** 132406f25ae9SGregory Neil Shapiro ** Returns: 132506f25ae9SGregory Neil Shapiro ** continue/keep 132606f25ae9SGregory Neil Shapiro ** 132706f25ae9SGregory Neil Shapiro ** Side effects: 132806f25ae9SGregory Neil Shapiro ** set pointer in macro array to current values. 132906f25ae9SGregory Neil Shapiro */ 133006f25ae9SGregory Neil Shapiro 133106f25ae9SGregory Neil Shapiro static int 133206f25ae9SGregory Neil Shapiro st_macros(g) 133306f25ae9SGregory Neil Shapiro genarg *g; 133406f25ae9SGregory Neil Shapiro { 133506f25ae9SGregory Neil Shapiro int i; 133606f25ae9SGregory Neil Shapiro char **argv; 133706f25ae9SGregory Neil Shapiro 133806f25ae9SGregory Neil Shapiro if (g == NULL || g->a_len < 1) 133906f25ae9SGregory Neil Shapiro return _SMFIS_FAIL; 134006f25ae9SGregory Neil Shapiro if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL) 134106f25ae9SGregory Neil Shapiro return _SMFIS_FAIL; 134206f25ae9SGregory Neil Shapiro switch (g->a_buf[0]) 134306f25ae9SGregory Neil Shapiro { 134406f25ae9SGregory Neil Shapiro case SMFIC_CONNECT: 134506f25ae9SGregory Neil Shapiro i = CI_CONN; 134606f25ae9SGregory Neil Shapiro break; 134706f25ae9SGregory Neil Shapiro case SMFIC_HELO: 134806f25ae9SGregory Neil Shapiro i = CI_HELO; 134906f25ae9SGregory Neil Shapiro break; 135006f25ae9SGregory Neil Shapiro case SMFIC_MAIL: 135106f25ae9SGregory Neil Shapiro i = CI_MAIL; 135206f25ae9SGregory Neil Shapiro break; 135306f25ae9SGregory Neil Shapiro case SMFIC_RCPT: 135406f25ae9SGregory Neil Shapiro i = CI_RCPT; 135506f25ae9SGregory Neil Shapiro break; 1356d0cef73dSGregory Neil Shapiro case SMFIC_DATA: 1357d0cef73dSGregory Neil Shapiro i = CI_DATA; 1358d0cef73dSGregory Neil Shapiro break; 1359323f6dcbSGregory Neil Shapiro case SMFIC_BODYEOB: 1360323f6dcbSGregory Neil Shapiro i = CI_EOM; 1361323f6dcbSGregory Neil Shapiro break; 1362d0cef73dSGregory Neil Shapiro case SMFIC_EOH: 1363d0cef73dSGregory Neil Shapiro i = CI_EOH; 1364d0cef73dSGregory Neil Shapiro break; 136506f25ae9SGregory Neil Shapiro default: 136606f25ae9SGregory Neil Shapiro free(argv); 136706f25ae9SGregory Neil Shapiro return _SMFIS_FAIL; 136806f25ae9SGregory Neil Shapiro } 136906f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_mac_ptr[i] != NULL) 137006f25ae9SGregory Neil Shapiro free(g->a_ctx->ctx_mac_ptr[i]); 137106f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_mac_buf[i] != NULL) 137206f25ae9SGregory Neil Shapiro free(g->a_ctx->ctx_mac_buf[i]); 137306f25ae9SGregory Neil Shapiro g->a_ctx->ctx_mac_ptr[i] = argv; 137406f25ae9SGregory Neil Shapiro g->a_ctx->ctx_mac_buf[i] = g->a_buf; 137506f25ae9SGregory Neil Shapiro return _SMFIS_KEEP; 137606f25ae9SGregory Neil Shapiro } 1377d0cef73dSGregory Neil Shapiro 137840266059SGregory Neil Shapiro /* 137906f25ae9SGregory Neil Shapiro ** ST_QUIT -- quit command 138006f25ae9SGregory Neil Shapiro ** 138106f25ae9SGregory Neil Shapiro ** Parameters: 138206f25ae9SGregory Neil Shapiro ** g -- generic argument structure 138306f25ae9SGregory Neil Shapiro ** 138406f25ae9SGregory Neil Shapiro ** Returns: 138506f25ae9SGregory Neil Shapiro ** noreply 138606f25ae9SGregory Neil Shapiro */ 138706f25ae9SGregory Neil Shapiro 1388a7ec597cSGregory Neil Shapiro /* ARGSUSED */ 138906f25ae9SGregory Neil Shapiro static int 139006f25ae9SGregory Neil Shapiro st_quit(g) 139106f25ae9SGregory Neil Shapiro genarg *g; 139206f25ae9SGregory Neil Shapiro { 1393d0cef73dSGregory Neil Shapiro sfsistat (*fi_close) __P((SMFICTX *)); 1394d0cef73dSGregory Neil Shapiro 1395d0cef73dSGregory Neil Shapiro if (g == NULL) 1396d0cef73dSGregory Neil Shapiro return _SMFIS_ABORT; 1397d0cef73dSGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 1398d0cef73dSGregory Neil Shapiro (fi_close = g->a_ctx->ctx_smfi->xxfi_close) != NULL) 1399d0cef73dSGregory Neil Shapiro (void) (*fi_close)(g->a_ctx); 1400d0cef73dSGregory Neil Shapiro mi_clr_macros(g->a_ctx, 0); 140106f25ae9SGregory Neil Shapiro return _SMFIS_NOREPLY; 140206f25ae9SGregory Neil Shapiro } 1403d0cef73dSGregory Neil Shapiro 140440266059SGregory Neil Shapiro /* 140506f25ae9SGregory Neil Shapiro ** ST_BODYCHUNK -- deal with a piece of the mail body 140606f25ae9SGregory Neil Shapiro ** 140706f25ae9SGregory Neil Shapiro ** Parameters: 140806f25ae9SGregory Neil Shapiro ** g -- generic argument structure 140906f25ae9SGregory Neil Shapiro ** 141006f25ae9SGregory Neil Shapiro ** Returns: 141106f25ae9SGregory Neil Shapiro ** continue or filter-specified value 141206f25ae9SGregory Neil Shapiro */ 141306f25ae9SGregory Neil Shapiro 141406f25ae9SGregory Neil Shapiro static int 141506f25ae9SGregory Neil Shapiro st_bodychunk(g) 141606f25ae9SGregory Neil Shapiro genarg *g; 141706f25ae9SGregory Neil Shapiro { 141840266059SGregory Neil Shapiro sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t)); 141906f25ae9SGregory Neil Shapiro 142006f25ae9SGregory Neil Shapiro if (g == NULL) 142106f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 142206f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL && 142306f25ae9SGregory Neil Shapiro (fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL) 142440266059SGregory Neil Shapiro return (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf, 142540266059SGregory Neil Shapiro g->a_len); 142606f25ae9SGregory Neil Shapiro return SMFIS_CONTINUE; 142706f25ae9SGregory Neil Shapiro } 1428d0cef73dSGregory Neil Shapiro 142940266059SGregory Neil Shapiro /* 143006f25ae9SGregory Neil Shapiro ** ST_BODYEND -- deal with the last piece of the mail body 143106f25ae9SGregory Neil Shapiro ** 143206f25ae9SGregory Neil Shapiro ** Parameters: 143306f25ae9SGregory Neil Shapiro ** g -- generic argument structure 143406f25ae9SGregory Neil Shapiro ** 143506f25ae9SGregory Neil Shapiro ** Returns: 143606f25ae9SGregory Neil Shapiro ** continue or filter-specified value 143706f25ae9SGregory Neil Shapiro ** 143806f25ae9SGregory Neil Shapiro ** Side effects: 143906f25ae9SGregory Neil Shapiro ** sends a reply for the body part (if non-empty). 144006f25ae9SGregory Neil Shapiro */ 144106f25ae9SGregory Neil Shapiro 144206f25ae9SGregory Neil Shapiro static int 144306f25ae9SGregory Neil Shapiro st_bodyend(g) 144406f25ae9SGregory Neil Shapiro genarg *g; 144506f25ae9SGregory Neil Shapiro { 144606f25ae9SGregory Neil Shapiro sfsistat r; 144740266059SGregory Neil Shapiro sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t)); 144806f25ae9SGregory Neil Shapiro sfsistat (*fi_eom) __P((SMFICTX *)); 144906f25ae9SGregory Neil Shapiro 145006f25ae9SGregory Neil Shapiro if (g == NULL) 145106f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 145206f25ae9SGregory Neil Shapiro r = SMFIS_CONTINUE; 145306f25ae9SGregory Neil Shapiro if (g->a_ctx->ctx_smfi != NULL) 145406f25ae9SGregory Neil Shapiro { 145506f25ae9SGregory Neil Shapiro if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL && 145606f25ae9SGregory Neil Shapiro g->a_len > 0) 145706f25ae9SGregory Neil Shapiro { 145806f25ae9SGregory Neil Shapiro socket_t sd; 145906f25ae9SGregory Neil Shapiro struct timeval timeout; 146006f25ae9SGregory Neil Shapiro 146106f25ae9SGregory Neil Shapiro timeout.tv_sec = g->a_ctx->ctx_timeout; 146206f25ae9SGregory Neil Shapiro timeout.tv_usec = 0; 146306f25ae9SGregory Neil Shapiro sd = g->a_ctx->ctx_sd; 146440266059SGregory Neil Shapiro r = (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf, 146540266059SGregory Neil Shapiro g->a_len); 146606f25ae9SGregory Neil Shapiro if (r != SMFIS_CONTINUE && 146706f25ae9SGregory Neil Shapiro sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS) 146806f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 146906f25ae9SGregory Neil Shapiro } 147006f25ae9SGregory Neil Shapiro } 147106f25ae9SGregory Neil Shapiro if (r == SMFIS_CONTINUE && 147206f25ae9SGregory Neil Shapiro (fi_eom = g->a_ctx->ctx_smfi->xxfi_eom) != NULL) 147306f25ae9SGregory Neil Shapiro return (*fi_eom)(g->a_ctx); 147406f25ae9SGregory Neil Shapiro return r; 147506f25ae9SGregory Neil Shapiro } 1476d0cef73dSGregory Neil Shapiro 147740266059SGregory Neil Shapiro /* 147806f25ae9SGregory Neil Shapiro ** ST_ABORTFCT -- deal with aborts 147906f25ae9SGregory Neil Shapiro ** 148006f25ae9SGregory Neil Shapiro ** Parameters: 148106f25ae9SGregory Neil Shapiro ** g -- generic argument structure 148206f25ae9SGregory Neil Shapiro ** 148306f25ae9SGregory Neil Shapiro ** Returns: 148406f25ae9SGregory Neil Shapiro ** abort or filter-specified value 148506f25ae9SGregory Neil Shapiro */ 148606f25ae9SGregory Neil Shapiro 148706f25ae9SGregory Neil Shapiro static int 148806f25ae9SGregory Neil Shapiro st_abortfct(g) 148906f25ae9SGregory Neil Shapiro genarg *g; 149006f25ae9SGregory Neil Shapiro { 149106f25ae9SGregory Neil Shapiro sfsistat (*fi_abort) __P((SMFICTX *)); 149206f25ae9SGregory Neil Shapiro 149306f25ae9SGregory Neil Shapiro if (g == NULL) 149406f25ae9SGregory Neil Shapiro return _SMFIS_ABORT; 149506f25ae9SGregory Neil Shapiro if (g != NULL && g->a_ctx->ctx_smfi != NULL && 149606f25ae9SGregory Neil Shapiro (fi_abort = g->a_ctx->ctx_smfi->xxfi_abort) != NULL) 149706f25ae9SGregory Neil Shapiro (void) (*fi_abort)(g->a_ctx); 149806f25ae9SGregory Neil Shapiro return _SMFIS_NOREPLY; 149906f25ae9SGregory Neil Shapiro } 1500d0cef73dSGregory Neil Shapiro 150140266059SGregory Neil Shapiro /* 150206f25ae9SGregory Neil Shapiro ** TRANS_OK -- is the state transition ok? 150306f25ae9SGregory Neil Shapiro ** 150406f25ae9SGregory Neil Shapiro ** Parameters: 150506f25ae9SGregory Neil Shapiro ** old -- old state 150606f25ae9SGregory Neil Shapiro ** new -- new state 150706f25ae9SGregory Neil Shapiro ** 150806f25ae9SGregory Neil Shapiro ** Returns: 150906f25ae9SGregory Neil Shapiro ** state transition ok 151006f25ae9SGregory Neil Shapiro */ 151106f25ae9SGregory Neil Shapiro 151206f25ae9SGregory Neil Shapiro static bool 151306f25ae9SGregory Neil Shapiro trans_ok(old, new) 151406f25ae9SGregory Neil Shapiro int old, new; 151506f25ae9SGregory Neil Shapiro { 151606f25ae9SGregory Neil Shapiro int s, n; 151706f25ae9SGregory Neil Shapiro 151806f25ae9SGregory Neil Shapiro s = old; 1519af9557fdSGregory Neil Shapiro if (s >= SIZE_NEXT_STATES) 1520af9557fdSGregory Neil Shapiro return false; 152142e5d165SGregory Neil Shapiro do 152242e5d165SGregory Neil Shapiro { 152306f25ae9SGregory Neil Shapiro /* is this state transition allowed? */ 152413bd1963SGregory Neil Shapiro if ((MI_MASK(new) & next_states[s]) != 0) 152540266059SGregory Neil Shapiro return true; 152606f25ae9SGregory Neil Shapiro 152706f25ae9SGregory Neil Shapiro /* 152806f25ae9SGregory Neil Shapiro ** no: try next state; 152906f25ae9SGregory Neil Shapiro ** this works since the relevant states are ordered 153006f25ae9SGregory Neil Shapiro ** strict sequentially 153106f25ae9SGregory Neil Shapiro */ 153240266059SGregory Neil Shapiro 153306f25ae9SGregory Neil Shapiro n = s + 1; 1534af9557fdSGregory Neil Shapiro if (n >= SIZE_NEXT_STATES) 1535af9557fdSGregory Neil Shapiro return false; 153606f25ae9SGregory Neil Shapiro 153706f25ae9SGregory Neil Shapiro /* 153806f25ae9SGregory Neil Shapiro ** can we actually "skip" this state? 153906f25ae9SGregory Neil Shapiro ** see fix_stm() which sets this bit for those 154006f25ae9SGregory Neil Shapiro ** states which the filter program is not interested in 154106f25ae9SGregory Neil Shapiro */ 154240266059SGregory Neil Shapiro 154306f25ae9SGregory Neil Shapiro if (bitset(NX_SKIP, next_states[n])) 154406f25ae9SGregory Neil Shapiro s = n; 154506f25ae9SGregory Neil Shapiro else 154640266059SGregory Neil Shapiro return false; 1547af9557fdSGregory Neil Shapiro } while (s < SIZE_NEXT_STATES); 154840266059SGregory Neil Shapiro return false; 154906f25ae9SGregory Neil Shapiro } 1550d0cef73dSGregory Neil Shapiro 155140266059SGregory Neil Shapiro /* 155206f25ae9SGregory Neil Shapiro ** FIX_STM -- add "skip" bits to the state transition table 155306f25ae9SGregory Neil Shapiro ** 155406f25ae9SGregory Neil Shapiro ** Parameters: 155506f25ae9SGregory Neil Shapiro ** ctx -- context structure 155606f25ae9SGregory Neil Shapiro ** 155706f25ae9SGregory Neil Shapiro ** Returns: 155806f25ae9SGregory Neil Shapiro ** None. 155906f25ae9SGregory Neil Shapiro ** 156006f25ae9SGregory Neil Shapiro ** Side effects: 156106f25ae9SGregory Neil Shapiro ** may change state transition table. 156206f25ae9SGregory Neil Shapiro */ 156306f25ae9SGregory Neil Shapiro 156406f25ae9SGregory Neil Shapiro static void 156506f25ae9SGregory Neil Shapiro fix_stm(ctx) 156606f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 156706f25ae9SGregory Neil Shapiro { 156840266059SGregory Neil Shapiro unsigned long fl; 156906f25ae9SGregory Neil Shapiro 157006f25ae9SGregory Neil Shapiro if (ctx == NULL || ctx->ctx_smfi == NULL) 157106f25ae9SGregory Neil Shapiro return; 157206f25ae9SGregory Neil Shapiro fl = ctx->ctx_pflags; 157306f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOCONNECT, fl)) 157406f25ae9SGregory Neil Shapiro next_states[ST_CONN] |= NX_SKIP; 157506f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOHELO, fl)) 157606f25ae9SGregory Neil Shapiro next_states[ST_HELO] |= NX_SKIP; 157706f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOMAIL, fl)) 157806f25ae9SGregory Neil Shapiro next_states[ST_MAIL] |= NX_SKIP; 157906f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NORCPT, fl)) 158006f25ae9SGregory Neil Shapiro next_states[ST_RCPT] |= NX_SKIP; 158106f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOHDRS, fl)) 158206f25ae9SGregory Neil Shapiro next_states[ST_HDRS] |= NX_SKIP; 158306f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOEOH, fl)) 158406f25ae9SGregory Neil Shapiro next_states[ST_EOHS] |= NX_SKIP; 158506f25ae9SGregory Neil Shapiro if (bitset(SMFIP_NOBODY, fl)) 158606f25ae9SGregory Neil Shapiro next_states[ST_BODY] |= NX_SKIP; 1587d0cef73dSGregory Neil Shapiro if (bitset(SMFIP_NODATA, fl)) 1588d0cef73dSGregory Neil Shapiro next_states[ST_DATA] |= NX_SKIP; 1589d0cef73dSGregory Neil Shapiro if (bitset(SMFIP_NOUNKNOWN, fl)) 1590d0cef73dSGregory Neil Shapiro next_states[ST_UNKN] |= NX_SKIP; 159106f25ae9SGregory Neil Shapiro } 1592d0cef73dSGregory Neil Shapiro 159340266059SGregory Neil Shapiro /* 159406f25ae9SGregory Neil Shapiro ** DEC_ARGV -- split a buffer into a list of strings, NULL terminated 159506f25ae9SGregory Neil Shapiro ** 159606f25ae9SGregory Neil Shapiro ** Parameters: 159706f25ae9SGregory Neil Shapiro ** buf -- buffer with several strings 159806f25ae9SGregory Neil Shapiro ** len -- length of buffer 159906f25ae9SGregory Neil Shapiro ** 160006f25ae9SGregory Neil Shapiro ** Returns: 160106f25ae9SGregory Neil Shapiro ** array of pointers to the individual strings 160206f25ae9SGregory Neil Shapiro */ 160306f25ae9SGregory Neil Shapiro 160406f25ae9SGregory Neil Shapiro static char ** 160506f25ae9SGregory Neil Shapiro dec_argv(buf, len) 160606f25ae9SGregory Neil Shapiro char *buf; 160706f25ae9SGregory Neil Shapiro size_t len; 160806f25ae9SGregory Neil Shapiro { 160906f25ae9SGregory Neil Shapiro char **s; 161006f25ae9SGregory Neil Shapiro size_t i; 161106f25ae9SGregory Neil Shapiro int elem, nelem; 161206f25ae9SGregory Neil Shapiro 161306f25ae9SGregory Neil Shapiro nelem = 0; 161406f25ae9SGregory Neil Shapiro for (i = 0; i < len; i++) 161506f25ae9SGregory Neil Shapiro { 161606f25ae9SGregory Neil Shapiro if (buf[i] == '\0') 161706f25ae9SGregory Neil Shapiro ++nelem; 161806f25ae9SGregory Neil Shapiro } 161906f25ae9SGregory Neil Shapiro if (nelem == 0) 162006f25ae9SGregory Neil Shapiro return NULL; 162106f25ae9SGregory Neil Shapiro 162206f25ae9SGregory Neil Shapiro /* last entry is only for the name */ 162306f25ae9SGregory Neil Shapiro s = (char **)malloc((nelem + 1) * (sizeof *s)); 162406f25ae9SGregory Neil Shapiro if (s == NULL) 162506f25ae9SGregory Neil Shapiro return NULL; 162606f25ae9SGregory Neil Shapiro s[0] = buf; 162706f25ae9SGregory Neil Shapiro for (i = 0, elem = 0; i < len && elem < nelem; i++) 162806f25ae9SGregory Neil Shapiro { 162906f25ae9SGregory Neil Shapiro if (buf[i] == '\0') 1630323f6dcbSGregory Neil Shapiro { 1631323f6dcbSGregory Neil Shapiro ++elem; 1632323f6dcbSGregory Neil Shapiro if (i + 1 >= len) 1633323f6dcbSGregory Neil Shapiro s[elem] = NULL; 1634323f6dcbSGregory Neil Shapiro else 1635323f6dcbSGregory Neil Shapiro s[elem] = &(buf[i + 1]); 1636323f6dcbSGregory Neil Shapiro } 163706f25ae9SGregory Neil Shapiro } 163806f25ae9SGregory Neil Shapiro 1639323f6dcbSGregory Neil Shapiro /* overwrite last entry (already done above, just paranoia) */ 164006f25ae9SGregory Neil Shapiro s[elem] = NULL; 164106f25ae9SGregory Neil Shapiro return s; 164206f25ae9SGregory Neil Shapiro } 1643d0cef73dSGregory Neil Shapiro 164440266059SGregory Neil Shapiro /* 164506f25ae9SGregory Neil Shapiro ** DEC_ARG2 -- split a buffer into two strings 164606f25ae9SGregory Neil Shapiro ** 164706f25ae9SGregory Neil Shapiro ** Parameters: 164806f25ae9SGregory Neil Shapiro ** buf -- buffer with two strings 164906f25ae9SGregory Neil Shapiro ** len -- length of buffer 165006f25ae9SGregory Neil Shapiro ** s1,s2 -- pointer to result strings 165106f25ae9SGregory Neil Shapiro ** 165206f25ae9SGregory Neil Shapiro ** Returns: 165306f25ae9SGregory Neil Shapiro ** MI_FAILURE/MI_SUCCESS 165406f25ae9SGregory Neil Shapiro */ 165506f25ae9SGregory Neil Shapiro 165606f25ae9SGregory Neil Shapiro static int 165706f25ae9SGregory Neil Shapiro dec_arg2(buf, len, s1, s2) 165806f25ae9SGregory Neil Shapiro char *buf; 165906f25ae9SGregory Neil Shapiro size_t len; 166006f25ae9SGregory Neil Shapiro char **s1; 166106f25ae9SGregory Neil Shapiro char **s2; 166206f25ae9SGregory Neil Shapiro { 166306f25ae9SGregory Neil Shapiro size_t i; 166406f25ae9SGregory Neil Shapiro 1665323f6dcbSGregory Neil Shapiro /* paranoia: check for terminating '\0' */ 1666323f6dcbSGregory Neil Shapiro if (len == 0 || buf[len - 1] != '\0') 1667323f6dcbSGregory Neil Shapiro return MI_FAILURE; 166806f25ae9SGregory Neil Shapiro *s1 = buf; 166906f25ae9SGregory Neil Shapiro for (i = 1; i < len && buf[i] != '\0'; i++) 167006f25ae9SGregory Neil Shapiro continue; 167106f25ae9SGregory Neil Shapiro if (i >= len - 1) 167206f25ae9SGregory Neil Shapiro return MI_FAILURE; 167306f25ae9SGregory Neil Shapiro *s2 = buf + i + 1; 167406f25ae9SGregory Neil Shapiro return MI_SUCCESS; 167506f25ae9SGregory Neil Shapiro } 1676d0cef73dSGregory Neil Shapiro 167740266059SGregory Neil Shapiro /* 167806f25ae9SGregory Neil Shapiro ** SENDOK -- is it ok for the filter to send stuff to the MTA? 167906f25ae9SGregory Neil Shapiro ** 168006f25ae9SGregory Neil Shapiro ** Parameters: 168106f25ae9SGregory Neil Shapiro ** ctx -- context structure 168206f25ae9SGregory Neil Shapiro ** flag -- flag to check 168306f25ae9SGregory Neil Shapiro ** 168406f25ae9SGregory Neil Shapiro ** Returns: 168506f25ae9SGregory Neil Shapiro ** sending allowed (in current state) 168606f25ae9SGregory Neil Shapiro */ 168706f25ae9SGregory Neil Shapiro 168806f25ae9SGregory Neil Shapiro bool 168906f25ae9SGregory Neil Shapiro mi_sendok(ctx, flag) 169006f25ae9SGregory Neil Shapiro SMFICTX_PTR ctx; 169106f25ae9SGregory Neil Shapiro int flag; 169206f25ae9SGregory Neil Shapiro { 169306f25ae9SGregory Neil Shapiro if (ctx == NULL || ctx->ctx_smfi == NULL) 169440266059SGregory Neil Shapiro return false; 169540266059SGregory Neil Shapiro 169640266059SGregory Neil Shapiro /* did the milter request this operation? */ 1697d0cef73dSGregory Neil Shapiro if (flag != 0 && !bitset(flag, ctx->ctx_aflags)) 169840266059SGregory Neil Shapiro return false; 169940266059SGregory Neil Shapiro 170040266059SGregory Neil Shapiro /* are we in the correct state? It must be "End of Message". */ 170106f25ae9SGregory Neil Shapiro return ctx->ctx_state == ST_ENDM; 170206f25ae9SGregory Neil Shapiro } 1703d0cef73dSGregory Neil Shapiro 1704d0cef73dSGregory Neil Shapiro #if _FFR_WORKERS_POOL 1705d0cef73dSGregory Neil Shapiro /* 1706d0cef73dSGregory Neil Shapiro ** MI_RD_SOCKET_READY - checks if the socket is ready for read(2) 1707d0cef73dSGregory Neil Shapiro ** 1708d0cef73dSGregory Neil Shapiro ** Parameters: 1709d0cef73dSGregory Neil Shapiro ** sd -- socket_t 1710d0cef73dSGregory Neil Shapiro ** 1711d0cef73dSGregory Neil Shapiro ** Returns: 1712d0cef73dSGregory Neil Shapiro ** true iff socket is ready for read(2) 1713d0cef73dSGregory Neil Shapiro */ 1714d0cef73dSGregory Neil Shapiro 1715d0cef73dSGregory Neil Shapiro #define MI_RD_CMD_TO 1 1716d0cef73dSGregory Neil Shapiro #define MI_RD_MAX_ERR 16 1717d0cef73dSGregory Neil Shapiro 1718d0cef73dSGregory Neil Shapiro static bool 1719d0cef73dSGregory Neil Shapiro mi_rd_socket_ready (sd) 1720d0cef73dSGregory Neil Shapiro socket_t sd; 1721d0cef73dSGregory Neil Shapiro { 1722d0cef73dSGregory Neil Shapiro int n; 1723d0cef73dSGregory Neil Shapiro int nerr = 0; 1724d0cef73dSGregory Neil Shapiro #if SM_CONF_POLL 1725d0cef73dSGregory Neil Shapiro struct pollfd pfd; 1726d0cef73dSGregory Neil Shapiro #else /* SM_CONF_POLL */ 1727d0cef73dSGregory Neil Shapiro fd_set rd_set, exc_set; 1728d0cef73dSGregory Neil Shapiro #endif /* SM_CONF_POLL */ 1729d0cef73dSGregory Neil Shapiro 1730d0cef73dSGregory Neil Shapiro do 1731d0cef73dSGregory Neil Shapiro { 1732d0cef73dSGregory Neil Shapiro #if SM_CONF_POLL 1733d0cef73dSGregory Neil Shapiro pfd.fd = sd; 1734d0cef73dSGregory Neil Shapiro pfd.events = POLLIN; 1735d0cef73dSGregory Neil Shapiro pfd.revents = 0; 1736d0cef73dSGregory Neil Shapiro 1737d0cef73dSGregory Neil Shapiro n = poll(&pfd, 1, MI_RD_CMD_TO); 1738d0cef73dSGregory Neil Shapiro #else /* SM_CONF_POLL */ 1739d0cef73dSGregory Neil Shapiro struct timeval timeout; 1740d0cef73dSGregory Neil Shapiro 1741d0cef73dSGregory Neil Shapiro FD_ZERO(&rd_set); 1742d0cef73dSGregory Neil Shapiro FD_ZERO(&exc_set); 1743d0cef73dSGregory Neil Shapiro FD_SET(sd, &rd_set); 1744d0cef73dSGregory Neil Shapiro FD_SET(sd, &exc_set); 1745d0cef73dSGregory Neil Shapiro 1746d0cef73dSGregory Neil Shapiro timeout.tv_sec = MI_RD_CMD_TO / 1000; 1747d0cef73dSGregory Neil Shapiro timeout.tv_usec = 0; 1748d0cef73dSGregory Neil Shapiro n = select(sd + 1, &rd_set, NULL, &exc_set, &timeout); 1749d0cef73dSGregory Neil Shapiro #endif /* SM_CONF_POLL */ 1750d0cef73dSGregory Neil Shapiro 1751d0cef73dSGregory Neil Shapiro if (n < 0) 1752d0cef73dSGregory Neil Shapiro { 1753d0cef73dSGregory Neil Shapiro if (errno == EINTR) 1754d0cef73dSGregory Neil Shapiro { 1755d0cef73dSGregory Neil Shapiro nerr++; 1756d0cef73dSGregory Neil Shapiro continue; 1757d0cef73dSGregory Neil Shapiro } 1758d0cef73dSGregory Neil Shapiro return true; 1759d0cef73dSGregory Neil Shapiro } 1760d0cef73dSGregory Neil Shapiro 1761d0cef73dSGregory Neil Shapiro if (n == 0) 1762d0cef73dSGregory Neil Shapiro return false; 1763d0cef73dSGregory Neil Shapiro break; 1764d0cef73dSGregory Neil Shapiro } while (nerr < MI_RD_MAX_ERR); 1765d0cef73dSGregory Neil Shapiro if (nerr >= MI_RD_MAX_ERR) 1766d0cef73dSGregory Neil Shapiro return false; 1767d0cef73dSGregory Neil Shapiro 1768d0cef73dSGregory Neil Shapiro #if SM_CONF_POLL 1769d0cef73dSGregory Neil Shapiro return (pfd.revents != 0); 1770d0cef73dSGregory Neil Shapiro #else /* SM_CONF_POLL */ 1771d0cef73dSGregory Neil Shapiro return FD_ISSET(sd, &rd_set) || FD_ISSET(sd, &exc_set); 1772d0cef73dSGregory Neil Shapiro #endif /* SM_CONF_POLL */ 1773d0cef73dSGregory Neil Shapiro } 1774d0cef73dSGregory Neil Shapiro #endif /* _FFR_WORKERS_POOL */ 1775