engine.c revision 203004
1184610Salfred/* 2184610Salfred * Copyright (c) 1999-2004, 2006-2008 Sendmail, Inc. and its suppliers. 3184610Salfred * All rights reserved. 4184610Salfred * 5184610Salfred * By using this file, you agree to the terms and conditions set 6187494Semax * forth in the LICENSE file which can be found at the top level of 7184610Salfred * the sendmail distribution. 8184610Salfred * 9184610Salfred */ 10184610Salfred 11184610Salfred#include <sm/gen.h> 12184610SalfredSM_RCSID("@(#)$Id: engine.c,v 8.166 2009/11/06 00:57:07 ca Exp $") 13184610Salfred 14184610Salfred#include "libmilter.h" 15184610Salfred 16184610Salfred#if NETINET || NETINET6 17184610Salfred# include <arpa/inet.h> 18184610Salfred#endif /* NETINET || NETINET6 */ 19184610Salfred 20184610Salfred/* generic argument for functions in the command table */ 21184610Salfredstruct arg_struct 22184610Salfred{ 23184610Salfred size_t a_len; /* length of buffer */ 24184610Salfred char *a_buf; /* argument string */ 25184610Salfred int a_idx; /* index for macro array */ 26184610Salfred SMFICTX_PTR a_ctx; /* context */ 27184610Salfred}; 28184610Salfred 29184610Salfredtypedef struct arg_struct genarg; 30184610Salfred 31184610Salfred/* structure for commands received from MTA */ 32184610Salfredstruct cmdfct_t 33184610Salfred{ 34187494Semax char cm_cmd; /* command */ 35187494Semax int cm_argt; /* type of arguments expected */ 36187741Semax int cm_next; /* next state */ 37187494Semax int cm_todo; /* what to do next */ 38187494Semax int cm_macros; /* index for macros */ 39187494Semax int (*cm_fct) __P((genarg *)); /* function to execute */ 40187741Semax}; 41187494Semax 42187741Semaxtypedef struct cmdfct_t cmdfct; 43187741Semax 44187741Semax/* possible values for cm_argt */ 45187494Semax#define CM_ARG0 0 /* no args */ 46187741Semax#define CM_ARG1 1 /* one arg (string) */ 47187741Semax#define CM_ARG2 2 /* two args (strings) */ 48187741Semax#define CM_ARGA 4 /* one string and _SOCK_ADDR */ 49187741Semax#define CM_ARGO 5 /* two integers */ 50187494Semax#define CM_ARGV 8 /* \0 separated list of args, NULL-terminated */ 51187494Semax#define CM_ARGN 9 /* \0 separated list of args (strings) */ 52187494Semax 53187494Semax/* possible values for cm_todo */ 54187741Semax#define CT_CONT 0x0000 /* continue reading commands */ 55187494Semax#define CT_IGNO 0x0001 /* continue even when error */ 56187494Semax 57187494Semax/* not needed right now, done via return code instead */ 58187494Semax#define CT_KEEP 0x0004 /* keep buffer (contains symbols) */ 59187494Semax#define CT_END 0x0008 /* last command of session, stop replying */ 60187494Semax 61187494Semax/* index in macro array: macros only for these commands */ 62187741Semax#define CI_NONE (-1) 63187741Semax#define CI_CONN 0 64187741Semax#define CI_HELO 1 65187741Semax#define CI_MAIL 2 66187741Semax#define CI_RCPT 3 67187741Semax#define CI_DATA 4 68187494Semax#define CI_EOM 5 69187741Semax#define CI_EOH 6 70187741Semax#define CI_LAST CI_EOH 71187741Semax#if CI_LAST < CI_DATA 72187741SemaxERROR: do not compile with CI_LAST < CI_DATA 73187741Semax#endif 74187494Semax#if CI_LAST < CI_EOM 75187494SemaxERROR: do not compile with CI_LAST < CI_EOM 76187494Semax#endif 77187494Semax#if CI_LAST < CI_EOH 78187494SemaxERROR: do not compile with CI_LAST < CI_EOH 79187494Semax#endif 80187741Semax#if CI_LAST < CI_ENVRCPT 81187741SemaxERROR: do not compile with CI_LAST < CI_ENVRCPT 82187741Semax#endif 83187741Semax#if CI_LAST < CI_ENVFROM 84187494SemaxERROR: do not compile with CI_LAST < CI_ENVFROM 85187494Semax#endif 86187741Semax#if CI_LAST < CI_HELO 87187741SemaxERROR: do not compile with CI_LAST < CI_HELO 88187741Semax#endif 89187741Semax#if CI_LAST < CI_CONNECT 90189002SedERROR: do not compile with CI_LAST < CI_CONNECT 91187741Semax#endif 92187741Semax#if CI_LAST >= MAX_MACROS_ENTRIES 93187494SemaxERROR: do not compile with CI_LAST >= MAX_MACROS_ENTRIES 94187494Semax#endif 95188746Sthompsa 96188942Sthompsa/* function prototypes */ 97188942Sthompsastatic int st_abortfct __P((genarg *)); 98188942Sthompsastatic int st_macros __P((genarg *)); 99184610Salfredstatic int st_optionneg __P((genarg *)); 100184610Salfredstatic int st_bodychunk __P((genarg *)); 101184610Salfredstatic int st_connectinfo __P((genarg *)); 102188942Sthompsastatic int st_bodyend __P((genarg *)); 103188942Sthompsastatic int st_helo __P((genarg *)); 104188942Sthompsastatic int st_header __P((genarg *)); 105188942Sthompsastatic int st_sender __P((genarg *)); 106188942Sthompsastatic int st_rcpt __P((genarg *)); 107188942Sthompsastatic int st_unknown __P((genarg *)); 108188942Sthompsastatic int st_data __P((genarg *)); 109188942Sthompsastatic int st_eoh __P((genarg *)); 110184610Salfredstatic int st_quit __P((genarg *)); 111184610Salfredstatic int sendreply __P((sfsistat, socket_t, struct timeval *, SMFICTX_PTR)); 112187494Semaxstatic void fix_stm __P((SMFICTX_PTR)); 113184610Salfredstatic bool trans_ok __P((int, int)); 114184610Salfredstatic char **dec_argv __P((char *, size_t)); 115184610Salfredstatic int dec_arg2 __P((char *, size_t, char **, char **)); 116184610Salfredstatic void mi_clr_symlist __P((SMFICTX_PTR)); 117184610Salfred 118184610Salfred#if _FFR_WORKERS_POOL 119184610Salfredstatic bool mi_rd_socket_ready __P((int)); 120184610Salfred#endif /* _FFR_WORKERS_POOL */ 121188942Sthompsa 122184610Salfred/* states */ 123187494Semax#define ST_NONE (-1) 124187494Semax#define ST_INIT 0 /* initial state */ 125187494Semax#define ST_OPTS 1 /* option negotiation */ 126187494Semax#define ST_CONN 2 /* connection info */ 127184610Salfred#define ST_HELO 3 /* helo */ 128187741Semax#define ST_MAIL 4 /* mail from */ 129187494Semax#define ST_RCPT 5 /* rcpt to */ 130184610Salfred#define ST_DATA 6 /* data */ 131187741Semax#define ST_HDRS 7 /* headers */ 132187741Semax#define ST_EOHS 8 /* end of headers */ 133187494Semax#define ST_BODY 9 /* body */ 134187494Semax#define ST_ENDM 10 /* end of message */ 135187494Semax#define ST_QUIT 11 /* quit */ 136187494Semax#define ST_ABRT 12 /* abort */ 137187494Semax#define ST_UNKN 13 /* unknown SMTP command */ 138187494Semax#define ST_Q_NC 14 /* quit, new connection follows */ 139187494Semax#define ST_LAST ST_Q_NC /* last valid state */ 140187494Semax#define ST_SKIP 16 /* not a state but required for the state table */ 141184610Salfred 142184610Salfred/* in a mail transaction? must be before eom according to spec. */ 143187494Semax#define ST_IN_MAIL(st) ((st) >= ST_MAIL && (st) < ST_ENDM) 144184610Salfred 145187494Semax/* 146187494Semax** set of next states 147187494Semax** each state (ST_*) corresponds to bit in an int value (1 << state) 148184610Salfred** each state has a set of allowed transitions ('or' of bits of states) 149187494Semax** so a state transition is valid if the mask of the next state 150187494Semax** is set in the NX_* value 151184610Salfred** this function is coded in trans_ok(), see below. 152184610Salfred*/ 153184610Salfred 154184610Salfred#define MI_MASK(x) (0x0001 << (x)) /* generate a bit "mask" for a state */ 155184610Salfred#define NX_INIT (MI_MASK(ST_OPTS)) 156187494Semax#define NX_OPTS (MI_MASK(ST_CONN) | MI_MASK(ST_UNKN)) 157184610Salfred#define NX_CONN (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN)) 158187494Semax#define NX_HELO (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN)) 159187494Semax#define NX_MAIL (MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | MI_MASK(ST_UNKN)) 160187494Semax#define NX_RCPT (MI_MASK(ST_HDRS) | MI_MASK(ST_EOHS) | MI_MASK(ST_DATA) | \ 161187494Semax MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | \ 162187494Semax MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | MI_MASK(ST_UNKN)) 163187494Semax#define NX_DATA (MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT)) 164187494Semax#define NX_HDRS (MI_MASK(ST_EOHS) | MI_MASK(ST_HDRS) | MI_MASK(ST_ABRT)) 165184610Salfred#define NX_EOHS (MI_MASK(ST_BODY) | MI_MASK(ST_ENDM) | MI_MASK(ST_ABRT)) 166187494Semax#define NX_BODY (MI_MASK(ST_ENDM) | MI_MASK(ST_BODY) | MI_MASK(ST_ABRT)) 167187494Semax#define NX_ENDM (MI_MASK(ST_QUIT) | MI_MASK(ST_MAIL) | MI_MASK(ST_UNKN) | \ 168184610Salfred MI_MASK(ST_Q_NC)) 169184610Salfred#define NX_QUIT 0 170184610Salfred#define NX_ABRT 0 171184610Salfred#define NX_UNKN (MI_MASK(ST_HELO) | MI_MASK(ST_MAIL) | \ 172184610Salfred MI_MASK(ST_RCPT) | MI_MASK(ST_ABRT) | \ 173187494Semax MI_MASK(ST_DATA) | \ 174187494Semax MI_MASK(ST_BODY) | MI_MASK(ST_UNKN) | \ 175184610Salfred MI_MASK(ST_ABRT) | MI_MASK(ST_QUIT) | MI_MASK(ST_Q_NC)) 176184610Salfred#define NX_Q_NC (MI_MASK(ST_CONN) | MI_MASK(ST_UNKN)) 177184610Salfred#define NX_SKIP MI_MASK(ST_SKIP) 178184610Salfred 179184610Salfredstatic int next_states[] = 180184610Salfred{ 181184610Salfred NX_INIT 182184610Salfred , NX_OPTS 183184610Salfred , NX_CONN 184184610Salfred , NX_HELO 185184610Salfred , NX_MAIL 186184610Salfred , NX_RCPT 187184610Salfred , NX_DATA 188184610Salfred , NX_HDRS 189184610Salfred , NX_EOHS 190184610Salfred , NX_BODY 191184610Salfred , NX_ENDM 192184610Salfred , NX_QUIT 193184610Salfred , NX_ABRT 194184610Salfred , NX_UNKN 195184610Salfred , NX_Q_NC 196184610Salfred}; 197184610Salfred 198184610Salfred#define SIZE_NEXT_STATES (sizeof(next_states) / sizeof(next_states[0])) 199184610Salfred 200184610Salfred/* commands received by milter */ 201184610Salfredstatic cmdfct cmds[] = 202184610Salfred{ 203184610Salfred {SMFIC_ABORT, CM_ARG0, ST_ABRT, CT_CONT, CI_NONE, st_abortfct } 204184610Salfred, {SMFIC_MACRO, CM_ARGV, ST_NONE, CT_KEEP, CI_NONE, st_macros } 205184610Salfred, {SMFIC_BODY, CM_ARG1, ST_BODY, CT_CONT, CI_NONE, st_bodychunk } 206184610Salfred, {SMFIC_CONNECT, CM_ARG2, ST_CONN, CT_CONT, CI_CONN, st_connectinfo } 207184610Salfred, {SMFIC_BODYEOB, CM_ARG1, ST_ENDM, CT_CONT, CI_EOM, st_bodyend } 208184610Salfred, {SMFIC_HELO, CM_ARG1, ST_HELO, CT_CONT, CI_HELO, st_helo } 209184610Salfred, {SMFIC_HEADER, CM_ARG2, ST_HDRS, CT_CONT, CI_NONE, st_header } 210184610Salfred, {SMFIC_MAIL, CM_ARGV, ST_MAIL, CT_CONT, CI_MAIL, st_sender } 211184610Salfred, {SMFIC_OPTNEG, CM_ARGO, ST_OPTS, CT_CONT, CI_NONE, st_optionneg } 212184610Salfred, {SMFIC_EOH, CM_ARG0, ST_EOHS, CT_CONT, CI_EOH, st_eoh } 213184610Salfred, {SMFIC_QUIT, CM_ARG0, ST_QUIT, CT_END, CI_NONE, st_quit } 214184610Salfred, {SMFIC_DATA, CM_ARG0, ST_DATA, CT_CONT, CI_DATA, st_data } 215184610Salfred, {SMFIC_RCPT, CM_ARGV, ST_RCPT, CT_IGNO, CI_RCPT, st_rcpt } 216184610Salfred, {SMFIC_UNKNOWN, CM_ARG1, ST_UNKN, CT_IGNO, CI_NONE, st_unknown } 217187494Semax, {SMFIC_QUIT_NC, CM_ARG0, ST_Q_NC, CT_CONT, CI_NONE, st_quit } 218184610Salfred}; 219184610Salfred 220184610Salfred/* 221187494Semax** Additional (internal) reply codes; 222187494Semax** must be coordinated wit libmilter/mfapi.h 223187494Semax*/ 224187494Semax 225187494Semax#define _SMFIS_KEEP 20 226187494Semax#define _SMFIS_ABORT 21 227187494Semax#define _SMFIS_OPTIONS 22 228187494Semax#define _SMFIS_NOREPLY SMFIS_NOREPLY 229187494Semax#define _SMFIS_FAIL (-1) 230187494Semax#define _SMFIS_NONE (-2) 231187494Semax 232187494Semax/* 233184610Salfred** MI_ENGINE -- receive commands and process them 234184610Salfred** 235187494Semax** Parameters: 236187494Semax** ctx -- context structure 237187494Semax** 238187494Semax** Returns: 239187494Semax** MI_FAILURE/MI_SUCCESS 240187494Semax*/ 241184610Salfred 242187494Semaxint 243187494Semaxmi_engine(ctx) 244187494Semax SMFICTX_PTR ctx; 245187494Semax{ 246187494Semax size_t len; 247187494Semax int i; 248184610Salfred socket_t sd; 249187741Semax int ret = MI_SUCCESS; 250187741Semax int ncmds = sizeof(cmds) / sizeof(cmdfct); 251184610Salfred int curstate = ST_INIT; 252187494Semax int newstate; 253187494Semax bool call_abort; 254187494Semax sfsistat r; 255187494Semax char cmd; 256187494Semax char *buf = NULL; 257187494Semax genarg arg; 258187494Semax struct timeval timeout; 259187494Semax int (*f) __P((genarg *)); 260187494Semax sfsistat (*fi_abort) __P((SMFICTX *)); 261187494Semax sfsistat (*fi_close) __P((SMFICTX *)); 262187494Semax 263187494Semax arg.a_ctx = ctx; 264187494Semax sd = ctx->ctx_sd; 265187494Semax fi_abort = ctx->ctx_smfi->xxfi_abort; 266184610Salfred#if _FFR_WORKERS_POOL 267187494Semax curstate = ctx->ctx_state; 268187494Semax if (curstate == ST_INIT) 269187494Semax { 270187494Semax mi_clr_macros(ctx, 0); 271187494Semax fix_stm(ctx); 272184610Salfred } 273187494Semax#else /* _FFR_WORKERS_POOL */ 274187494Semax mi_clr_macros(ctx, 0); 275187494Semax fix_stm(ctx); 276187494Semax#endif /* _FFR_WORKERS_POOL */ 277187494Semax r = _SMFIS_NONE; 278187741Semax do 279187494Semax { 280187741Semax /* call abort only if in a mail transaction */ 281187494Semax call_abort = ST_IN_MAIL(curstate); 282184610Salfred timeout.tv_sec = ctx->ctx_timeout; 283187494Semax timeout.tv_usec = 0; 284187494Semax if (mi_stop() == MILTER_ABRT) 285187494Semax { 286187494Semax if (ctx->ctx_dbg > 3) 287187494Semax sm_dprintf("[%ld] milter_abort\n", 288187741Semax (long) ctx->ctx_id); 289187494Semax ret = MI_FAILURE; 290187494Semax break; 291187494Semax } 292184610Salfred 293187494Semax /* 294187494Semax ** Notice: buf is allocated by mi_rd_cmd() and it will 295187494Semax ** usually be free()d after it has been used in f(). 296187494Semax ** However, if the function returns _SMFIS_KEEP then buf 297187494Semax ** contains macros and will not be free()d. 298187741Semax ** Hence r must be set to _SMFIS_NONE if a new buf is 299187494Semax ** allocated to avoid problem with housekeeping, esp. 300187494Semax ** if the code "break"s out of the loop. 301187494Semax */ 302184610Salfred 303187494Semax#if _FFR_WORKERS_POOL 304187494Semax /* Is the socket ready to be read ??? */ 305187494Semax if (!mi_rd_socket_ready(sd)) 306187494Semax { 307187494Semax ret = MI_CONTINUE; 308187741Semax break; 309187494Semax } 310187494Semax#endif /* _FFR_WORKERS_POOL */ 311187494Semax 312184610Salfred r = _SMFIS_NONE; 313184610Salfred if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len, 314187494Semax ctx->ctx_smfi->xxfi_name)) == NULL && 315187494Semax cmd < SMFIC_VALIDCMD) 316187494Semax { 317184610Salfred if (ctx->ctx_dbg > 5) 318187494Semax sm_dprintf("[%ld] mi_engine: mi_rd_cmd error (%x)\n", 319187494Semax (long) ctx->ctx_id, (int) cmd); 320187494Semax 321187494Semax /* 322187494Semax ** eof is currently treated as failure -> 323187741Semax ** abort() instead of close(), otherwise use: 324187494Semax ** if (cmd != SMFIC_EOF) 325187494Semax */ 326187494Semax 327187494Semax ret = MI_FAILURE; 328184610Salfred break; 329187494Semax } 330187494Semax if (ctx->ctx_dbg > 4) 331187494Semax sm_dprintf("[%ld] got cmd '%c' len %d\n", 332187494Semax (long) ctx->ctx_id, cmd, (int) len); 333187494Semax for (i = 0; i < ncmds; i++) 334187741Semax { 335187494Semax if (cmd == cmds[i].cm_cmd) 336187494Semax break; 337187494Semax } 338187494Semax if (i >= ncmds) 339184610Salfred { 340187494Semax /* unknown command */ 341187494Semax if (ctx->ctx_dbg > 1) 342187494Semax sm_dprintf("[%ld] cmd '%c' unknown\n", 343187494Semax (long) ctx->ctx_id, cmd); 344187494Semax ret = MI_FAILURE; 345187741Semax break; 346187494Semax } 347187494Semax if ((f = cmds[i].cm_fct) == NULL) 348187494Semax { 349187494Semax /* stop for now */ 350184610Salfred if (ctx->ctx_dbg > 1) 351187494Semax sm_dprintf("[%ld] cmd '%c' not impl\n", 352187494Semax (long) ctx->ctx_id, cmd); 353187494Semax ret = MI_FAILURE; 354187494Semax break; 355187494Semax } 356187741Semax 357187494Semax /* is new state ok? */ 358187494Semax newstate = cmds[i].cm_next; 359187494Semax if (ctx->ctx_dbg > 5) 360187494Semax sm_dprintf("[%ld] cur %x new %x nextmask %x\n", 361184610Salfred (long) ctx->ctx_id, 362184610Salfred curstate, newstate, next_states[curstate]); 363184610Salfred 364184610Salfred if (newstate != ST_NONE && !trans_ok(curstate, newstate)) 365184610Salfred { 366184610Salfred if (ctx->ctx_dbg > 1) 367184610Salfred sm_dprintf("[%ld] abort: cur %d (%x) new %d (%x) next %x\n", 368184610Salfred (long) ctx->ctx_id, 369187494Semax curstate, MI_MASK(curstate), 370184610Salfred newstate, MI_MASK(newstate), 371184610Salfred next_states[curstate]); 372184610Salfred 373187741Semax /* call abort only if in a mail transaction */ 374187741Semax if (fi_abort != NULL && call_abort) 375187741Semax (void) (*fi_abort)(ctx); 376184610Salfred 377187494Semax /* 378184610Salfred ** try to reach the new state from HELO 379184610Salfred ** if it can't be reached, ignore the command. 380184610Salfred */ 381187741Semax 382187741Semax curstate = ST_HELO; 383187494Semax if (!trans_ok(curstate, newstate)) 384187494Semax { 385187494Semax if (buf != NULL) 386187494Semax { 387184610Salfred free(buf); 388184610Salfred buf = NULL; 389187494Semax } 390184610Salfred continue; 391184610Salfred } 392184610Salfred } 393187494Semax arg.a_len = len; 394187494Semax arg.a_buf = buf; 395184610Salfred if (newstate != ST_NONE) 396184610Salfred { 397184610Salfred curstate = newstate; 398184610Salfred ctx->ctx_state = curstate; 399184610Salfred } 400187494Semax arg.a_idx = cmds[i].cm_macros; 401184610Salfred call_abort = ST_IN_MAIL(curstate); 402187494Semax 403184610Salfred /* call function to deal with command */ 404187494Semax MI_MONITOR_BEGIN(ctx, cmd); 405187494Semax r = (*f)(&arg); 406184610Salfred MI_MONITOR_END(ctx, cmd); 407187494Semax if (r != _SMFIS_KEEP && buf != NULL) 408187865Semax { 409187865Semax free(buf); 410187865Semax buf = NULL; 411184610Salfred } 412187494Semax if (sendreply(r, sd, &timeout, ctx) != MI_SUCCESS) 413184610Salfred { 414187494Semax ret = MI_FAILURE; 415184610Salfred break; 416187494Semax } 417184610Salfred 418184610Salfred if (r == SMFIS_ACCEPT) 419187494Semax { 420187494Semax /* accept mail, no further actions taken */ 421184610Salfred curstate = ST_HELO; 422184610Salfred } 423184610Salfred else if (r == SMFIS_REJECT || r == SMFIS_DISCARD || 424184610Salfred r == SMFIS_TEMPFAIL) 425184610Salfred { 426187494Semax /* 427187494Semax ** further actions depend on current state 428187494Semax ** if the IGNO bit is set: "ignore" the error, 429190728Sthompsa ** i.e., stay in the current state 430187494Semax */ 431187741Semax if (!bitset(CT_IGNO, cmds[i].cm_todo)) 432187741Semax curstate = ST_HELO; 433184610Salfred } 434184610Salfred else if (r == _SMFIS_ABORT) 435184610Salfred { 436187741Semax if (ctx->ctx_dbg > 5) 437187741Semax sm_dprintf("[%ld] function returned abort\n", 438184610Salfred (long) ctx->ctx_id); 439187494Semax ret = MI_FAILURE; 440187494Semax break; 441187494Semax } 442187494Semax } while (!bitset(CT_END, cmds[i].cm_todo)); 443187494Semax 444187741Semax ctx->ctx_state = curstate; 445187494Semax 446187494Semax if (ret == MI_FAILURE) 447187494Semax { 448187494Semax /* call abort only if in a mail transaction */ 449187741Semax if (fi_abort != NULL && call_abort) 450187741Semax (void) (*fi_abort)(ctx); 451187494Semax } 452187494Semax 453187494Semax /* has close been called? */ 454187494Semax if (ctx->ctx_state != ST_QUIT 455187494Semax#if _FFR_WORKERS_POOL 456187494Semax && ret != MI_CONTINUE 457184610Salfred#endif /* _FFR_WORKERS_POOL */ 458184610Salfred ) 459184610Salfred { 460184610Salfred if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) 461187494Semax (void) (*fi_close)(ctx); 462187741Semax } 463187741Semax if (r != _SMFIS_KEEP && buf != NULL) 464187494Semax free(buf); 465187494Semax#if !_FFR_WORKERS_POOL 466184610Salfred mi_clr_macros(ctx, 0); 467184610Salfred#endif /* _FFR_WORKERS_POOL */ 468187494Semax return ret; 469184610Salfred} 470187494Semax 471187741Semaxstatic size_t milter_addsymlist __P((SMFICTX_PTR, char *, char **)); 472184610Salfred 473184610Salfredstatic size_t 474184610Salfredmilter_addsymlist(ctx, buf, newbuf) 475184610Salfred SMFICTX_PTR ctx; 476184610Salfred char *buf; 477184610Salfred char **newbuf; 478184610Salfred{ 479184610Salfred size_t len; 480184610Salfred int i; 481184610Salfred mi_int32 v; 482184610Salfred char *buffer; 483184610Salfred 484184610Salfred SM_ASSERT(ctx != NULL); 485184610Salfred SM_ASSERT(buf != NULL); 486184610Salfred SM_ASSERT(newbuf != NULL); 487184610Salfred len = 0; 488184610Salfred for (i = 0; i < MAX_MACROS_ENTRIES; i++) 489184610Salfred { 490184610Salfred if (ctx->ctx_mac_list[i] != NULL) 491184610Salfred { 492187741Semax len += strlen(ctx->ctx_mac_list[i]) + 1 + 493187741Semax MILTER_LEN_BYTES; 494184610Salfred } 495184610Salfred } 496184610Salfred if (len > 0) 497187494Semax { 498184610Salfred size_t offset; 499184610Salfred 500190728Sthompsa SM_ASSERT(len + MILTER_OPTLEN > len); 501187494Semax len += MILTER_OPTLEN; 502190728Sthompsa buffer = malloc(len); 503190728Sthompsa if (buffer != NULL) 504190728Sthompsa { 505190728Sthompsa (void) memcpy(buffer, buf, MILTER_OPTLEN); 506190728Sthompsa offset = MILTER_OPTLEN; 507190728Sthompsa for (i = 0; i < MAX_MACROS_ENTRIES; i++) 508190728Sthompsa { 509184610Salfred size_t l; 510190728Sthompsa 511190728Sthompsa if (ctx->ctx_mac_list[i] == NULL) 512190728Sthompsa continue; 513190728Sthompsa 514190728Sthompsa SM_ASSERT(offset + MILTER_LEN_BYTES < len); 515184610Salfred v = htonl(i); 516187494Semax (void) memcpy(buffer + offset, (void *) &v, 517190728Sthompsa MILTER_LEN_BYTES); 518190728Sthompsa offset += MILTER_LEN_BYTES; 519190728Sthompsa l = strlen(ctx->ctx_mac_list[i]) + 1; 520190728Sthompsa SM_ASSERT(offset + l <= len); 521190728Sthompsa (void) memcpy(buffer + offset, 522190728Sthompsa ctx->ctx_mac_list[i], l); 523190728Sthompsa offset += l; 524190728Sthompsa } 525190728Sthompsa } 526190728Sthompsa else 527184610Salfred { 528184610Salfred /* oops ... */ 529184610Salfred } 530187741Semax } 531187494Semax else 532187494Semax { 533187741Semax len = MILTER_OPTLEN; 534187494Semax buffer = buf; 535184610Salfred } 536184610Salfred *newbuf = buffer; 537184610Salfred return len; 538187741Semax} 539187741Semax 540187741Semax/* 541187741Semax** GET_NR_BIT -- get "no reply" bit matching state 542184610Salfred** 543184610Salfred** Parameters: 544184610Salfred** state -- current protocol stage 545187494Semax** 546187494Semax** Returns: 547184610Salfred** 0: no matching bit 548184610Salfred** >0: the matching "no reply" bit 549187494Semax*/ 550184610Salfred 551184610Salfredstatic unsigned long get_nr_bit __P((int)); 552184610Salfred 553184610Salfredstatic unsigned long 554184610Salfredget_nr_bit(state) 555187494Semax int state; 556184610Salfred{ 557184610Salfred unsigned long bit; 558187494Semax 559187494Semax switch (state) 560184610Salfred { 561184610Salfred case ST_CONN: 562184610Salfred bit = SMFIP_NR_CONN; 563184610Salfred break; 564184610Salfred case ST_HELO: 565187494Semax bit = SMFIP_NR_HELO; 566187494Semax break; 567184610Salfred case ST_MAIL: 568187494Semax bit = SMFIP_NR_MAIL; 569187494Semax break; 570187494Semax case ST_RCPT: 571187494Semax bit = SMFIP_NR_RCPT; 572187494Semax break; 573184610Salfred case ST_DATA: 574184610Salfred bit = SMFIP_NR_DATA; 575187741Semax break; 576187741Semax case ST_UNKN: 577187741Semax bit = SMFIP_NR_UNKN; 578187494Semax break; 579187494Semax case ST_HDRS: 580184610Salfred bit = SMFIP_NR_HDR; 581187494Semax break; 582187741Semax case ST_EOHS: 583184610Salfred bit = SMFIP_NR_EOH; 584184610Salfred break; 585184610Salfred case ST_BODY: 586187741Semax bit = SMFIP_NR_BODY; 587184610Salfred break; 588187741Semax default: 589187741Semax bit = 0; 590187494Semax break; 591184610Salfred } 592187494Semax return bit; 593184610Salfred} 594187494Semax 595187494Semax/* 596187494Semax** SENDREPLY -- send a reply to the MTA 597187494Semax** 598187494Semax** Parameters: 599187494Semax** r -- reply code 600184610Salfred** sd -- socket descriptor 601184610Salfred** timeout_ptr -- (ptr to) timeout to use for sending 602184610Salfred** ctx -- context structure 603187741Semax** 604187494Semax** Returns: 605187494Semax** MI_SUCCESS/MI_FAILURE 606184610Salfred*/ 607184610Salfred 608184610Salfredstatic int 609187741Semaxsendreply(r, sd, timeout_ptr, ctx) 610187741Semax sfsistat r; 611187741Semax socket_t sd; 612187494Semax struct timeval *timeout_ptr; 613184610Salfred SMFICTX_PTR ctx; 614184610Salfred{ 615187494Semax int ret; 616187494Semax unsigned long bit; 617187741Semax 618184610Salfred ret = MI_SUCCESS; 619187741Semax 620184610Salfred bit = get_nr_bit(ctx->ctx_state); 621184610Salfred if (bit != 0 && (ctx->ctx_pflags & bit) != 0 && r != SMFIS_NOREPLY) 622187494Semax { 623187741Semax if (r >= SMFIS_CONTINUE && r < _SMFIS_KEEP) 624184610Salfred { 625184610Salfred /* milter said it wouldn't reply, but it lied... */ 626187494Semax smi_log(SMI_LOG_ERR, 627184610Salfred "%s: milter claimed not to reply in state %d but did anyway %d\n", 628184610Salfred ctx->ctx_smfi->xxfi_name, 629184610Salfred ctx->ctx_state, r); 630184610Salfred 631187494Semax } 632187494Semax 633187494Semax /* 634184610Salfred ** Force specified behavior, otherwise libmilter 635184610Salfred ** and MTA will fail to communicate properly. 636184610Salfred */ 637184610Salfred 638184610Salfred switch (r) 639184610Salfred { 640187494Semax case SMFIS_CONTINUE: 641184610Salfred case SMFIS_TEMPFAIL: 642184610Salfred case SMFIS_REJECT: 643184610Salfred case SMFIS_DISCARD: 644184610Salfred case SMFIS_ACCEPT: 645187494Semax case SMFIS_SKIP: 646184610Salfred case _SMFIS_OPTIONS: 647187494Semax r = SMFIS_NOREPLY; 648187494Semax break; 649187494Semax } 650187494Semax } 651187494Semax 652187494Semax switch (r) 653187494Semax { 654184610Salfred case SMFIS_CONTINUE: 655187494Semax ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 0); 656187741Semax break; 657187494Semax case SMFIS_TEMPFAIL: 658184610Salfred case SMFIS_REJECT: 659187494Semax if (ctx->ctx_reply != NULL && 660184610Salfred ((r == SMFIS_TEMPFAIL && *ctx->ctx_reply == '4') || 661187494Semax (r == SMFIS_REJECT && *ctx->ctx_reply == '5'))) 662187494Semax { 663187494Semax ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_REPLYCODE, 664187494Semax ctx->ctx_reply, 665187494Semax strlen(ctx->ctx_reply) + 1); 666187494Semax free(ctx->ctx_reply); 667184610Salfred ctx->ctx_reply = NULL; 668184610Salfred } 669184610Salfred else 670187741Semax { 671187494Semax ret = mi_wr_cmd(sd, timeout_ptr, r == SMFIS_REJECT ? 672187494Semax SMFIR_REJECT : SMFIR_TEMPFAIL, NULL, 0); 673184610Salfred } 674187494Semax break; 675187494Semax case SMFIS_DISCARD: 676184610Salfred ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_DISCARD, NULL, 0); 677184610Salfred break; 678187494Semax case SMFIS_ACCEPT: 679184610Salfred ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_ACCEPT, NULL, 0); 680184610Salfred break; 681187494Semax case SMFIS_SKIP: 682187494Semax ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_SKIP, NULL, 0); 683184610Salfred break; 684187494Semax case _SMFIS_OPTIONS: 685184610Salfred { 686184610Salfred mi_int32 v; 687187494Semax size_t len; 688187494Semax char *buffer; 689184610Salfred char buf[MILTER_OPTLEN]; 690187494Semax 691187494Semax v = htonl(ctx->ctx_prot_vers2mta); 692187494Semax (void) memcpy(&(buf[0]), (void *) &v, 693187494Semax MILTER_LEN_BYTES); 694187494Semax v = htonl(ctx->ctx_aflags); 695187494Semax (void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v, 696187494Semax MILTER_LEN_BYTES); 697187494Semax v = htonl(ctx->ctx_pflags2mta); 698187494Semax (void) memcpy(&(buf[MILTER_LEN_BYTES * 2]), 699187494Semax (void *) &v, MILTER_LEN_BYTES); 700187494Semax len = milter_addsymlist(ctx, buf, &buffer); 701187494Semax if (buffer != NULL) 702187494Semax ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG, 703187494Semax buffer, len); 704187494Semax else 705187494Semax ret = MI_FAILURE; 706187494Semax } 707187494Semax break; 708187494Semax case SMFIS_NOREPLY: 709187494Semax if (bit != 0 && 710187494Semax (ctx->ctx_pflags & bit) != 0 && 711187494Semax (ctx->ctx_mta_pflags & bit) == 0) 712184610Salfred { 713184610Salfred /* 714187494Semax ** milter doesn't want to send a reply, 715187494Semax ** but the MTA doesn't have that feature: fake it. 716187494Semax */ 717187494Semax 718187494Semax ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 719184610Salfred 0); 720187494Semax } 721187494Semax break; 722184610Salfred default: /* don't send a reply */ 723184610Salfred break; 724187494Semax } 725187494Semax return ret; 726184610Salfred} 727187494Semax 728187494Semax/* 729184610Salfred** CLR_MACROS -- clear set of macros starting from a given index 730187741Semax** 731187494Semax** Parameters: 732187494Semax** ctx -- context structure 733184610Salfred** m -- index from which to clear all macros 734184610Salfred** 735187494Semax** Returns: 736187494Semax** None. 737184610Salfred*/ 738187741Semax 739187741Semaxvoid 740187494Semaxmi_clr_macros(ctx, m) 741184610Salfred SMFICTX_PTR ctx; 742187494Semax int m; 743187494Semax{ 744187494Semax int i; 745187494Semax 746184610Salfred for (i = m; i < MAX_MACROS_ENTRIES; i++) 747187494Semax { 748187741Semax if (ctx->ctx_mac_ptr[i] != NULL) 749187741Semax { 750187741Semax free(ctx->ctx_mac_ptr[i]); 751187741Semax ctx->ctx_mac_ptr[i] = NULL; 752187494Semax } 753184610Salfred if (ctx->ctx_mac_buf[i] != NULL) 754187494Semax { 755184610Salfred free(ctx->ctx_mac_buf[i]); 756187494Semax ctx->ctx_mac_buf[i] = NULL; 757187494Semax } 758187494Semax } 759187494Semax} 760187494Semax 761187494Semax/* 762184610Salfred** MI_CLR_SYMLIST -- clear list of macros 763187494Semax** 764184610Salfred** Parameters: 765187741Semax** ctx -- context structure 766187494Semax** 767187494Semax** Returns: 768187494Semax** None. 769184610Salfred*/ 770187494Semax 771184610Salfredstatic void 772184610Salfredmi_clr_symlist(ctx) 773184610Salfred SMFICTX *ctx; 774187494Semax{ 775184610Salfred int i; 776184610Salfred 777187494Semax SM_ASSERT(ctx != NULL); 778187494Semax for (i = SMFIM_FIRST; i <= SMFIM_LAST; i++) 779184610Salfred { 780187494Semax if (ctx->ctx_mac_list[i] != NULL) 781184610Salfred { 782184610Salfred free(ctx->ctx_mac_list[i]); 783187494Semax ctx->ctx_mac_list[i] = NULL; 784187494Semax } 785184610Salfred } 786184610Salfred} 787187494Semax 788187494Semax/* 789187494Semax** MI_CLR_CTX -- clear context 790184610Salfred** 791187494Semax** Parameters: 792187494Semax** ctx -- context structure 793184610Salfred** 794187494Semax** Returns: 795187494Semax** None. 796184610Salfred*/ 797184610Salfred 798184610Salfredvoid 799187494Semaxmi_clr_ctx(ctx) 800187494Semax SMFICTX *ctx; 801184610Salfred{ 802187494Semax SM_ASSERT(ctx != NULL); 803187494Semax if (ValidSocket(ctx->ctx_sd)) 804187494Semax { 805184610Salfred (void) closesocket(ctx->ctx_sd); 806187494Semax ctx->ctx_sd = INVALID_SOCKET; 807187494Semax } 808184610Salfred if (ctx->ctx_reply != NULL) 809184610Salfred { 810187494Semax free(ctx->ctx_reply); 811187494Semax ctx->ctx_reply = NULL; 812187494Semax } 813187494Semax if (ctx->ctx_privdata != NULL) 814187494Semax { 815184610Salfred smi_log(SMI_LOG_WARN, 816187494Semax "%s: private data not NULL", 817187494Semax ctx->ctx_smfi->xxfi_name); 818184610Salfred } 819184610Salfred mi_clr_macros(ctx, 0); 820187494Semax mi_clr_symlist(ctx); 821187494Semax free(ctx); 822184610Salfred} 823187494Semax 824187494Semax/* 825184610Salfred** ST_OPTIONNEG -- negotiate options 826187741Semax** 827187494Semax** Parameters: 828187494Semax** g -- generic argument structure 829184610Salfred** 830187494Semax** Returns: 831187494Semax** abort/send options/continue 832187494Semax*/ 833184610Salfred 834187741Semaxstatic int 835187741Semaxst_optionneg(g) 836187494Semax genarg *g; 837184610Salfred{ 838187494Semax mi_int32 i, v, fake_pflags, internal_pflags; 839187494Semax SMFICTX_PTR ctx; 840187494Semax#if _FFR_MILTER_CHECK 841187494Semax bool testmode = false; 842184610Salfred#endif /* _FFR_MILTER_CHECK */ 843187494Semax int (*fi_negotiate) __P((SMFICTX *, 844187741Semax unsigned long, unsigned long, 845187741Semax unsigned long, unsigned long, 846187741Semax unsigned long *, unsigned long *, 847187741Semax unsigned long *, unsigned long *)); 848187494Semax 849187494Semax if (g == NULL || g->a_ctx->ctx_smfi == NULL) 850187494Semax return SMFIS_CONTINUE; 851184610Salfred ctx = g->a_ctx; 852187494Semax mi_clr_macros(ctx, g->a_idx + 1); 853187494Semax ctx->ctx_prot_vers = SMFI_PROT_VERSION; 854187494Semax 855187494Semax /* check for minimum length */ 856187494Semax if (g->a_len < MILTER_OPTLEN) 857184610Salfred { 858184610Salfred smi_log(SMI_LOG_ERR, 859184610Salfred "%s: st_optionneg[%ld]: len too short %d < %d", 860184610Salfred ctx->ctx_smfi->xxfi_name, 861187741Semax (long) ctx->ctx_id, (int) g->a_len, 862187494Semax MILTER_OPTLEN); 863184610Salfred return _SMFIS_ABORT; 864184610Salfred } 865184610Salfred 866187741Semax /* protocol version */ 867187741Semax (void) memcpy((void *) &i, (void *) &(g->a_buf[0]), MILTER_LEN_BYTES); 868187741Semax v = ntohl(i); 869187494Semax 870184610Salfred#define SMFI_PROT_VERSION_MIN 2 871187494Semax 872187741Semax /* check for minimum version */ 873187494Semax if (v < SMFI_PROT_VERSION_MIN) 874187741Semax { 875184610Salfred smi_log(SMI_LOG_ERR, 876187741Semax "%s: st_optionneg[%ld]: protocol version too old %d < %d", 877184610Salfred ctx->ctx_smfi->xxfi_name, 878184610Salfred (long) ctx->ctx_id, v, SMFI_PROT_VERSION_MIN); 879187494Semax return _SMFIS_ABORT; 880187741Semax } 881184610Salfred ctx->ctx_mta_prot_vers = v; 882187494Semax if (ctx->ctx_prot_vers < ctx->ctx_mta_prot_vers) 883184610Salfred ctx->ctx_prot_vers2mta = ctx->ctx_prot_vers; 884187494Semax else 885187494Semax ctx->ctx_prot_vers2mta = ctx->ctx_mta_prot_vers; 886184610Salfred 887184610Salfred (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]), 888184610Salfred MILTER_LEN_BYTES); 889187494Semax v = ntohl(i); 890184610Salfred 891187494Semax /* no flags? set to default value for V1 actions */ 892187494Semax if (v == 0) 893184610Salfred v = SMFI_V1_ACTS; 894184610Salfred ctx->ctx_mta_aflags = v; /* MTA action flags */ 895184610Salfred 896184610Salfred internal_pflags = 0; 897187494Semax (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES * 2]), 898184610Salfred MILTER_LEN_BYTES); 899187494Semax v = ntohl(i); 900184610Salfred 901187494Semax /* no flags? set to default value for V1 protocol */ 902187494Semax if (v == 0) 903184610Salfred v = SMFI_V1_PROT; 904187494Semax#if _FFR_MDS_NEGOTIATE 905184610Salfred else if (ctx->ctx_smfi->xxfi_version >= SMFI_VERSION_MDS) 906184610Salfred { 907187741Semax /* 908187741Semax ** Allow changing the size only if milter is compiled 909187741Semax ** against a version that supports this. 910187741Semax ** If a milter is dynamically linked against a newer 911187494Semax ** libmilter version, we don't want to "surprise" 912184610Salfred ** it with a larger buffer as it may rely on it 913187494Semax ** even though it is not documented as a limit. 914184610Salfred */ 915187494Semax 916187494Semax if (bitset(SMFIP_MDS_1M, v)) 917187494Semax { 918187494Semax internal_pflags |= SMFIP_MDS_1M; 919187494Semax (void) smfi_setmaxdatasize(MILTER_MDS_1M); 920187494Semax } 921184610Salfred else if (bitset(SMFIP_MDS_256K, v)) 922184610Salfred { 923184610Salfred internal_pflags |= SMFIP_MDS_256K; 924187741Semax (void) smfi_setmaxdatasize(MILTER_MDS_256K); 925187494Semax } 926184610Salfred } 927187494Semax# if 0 928187494Semax /* don't log this for now... */ 929187494Semax else if (ctx->ctx_smfi->xxfi_version < SMFI_VERSION_MDS && 930187494Semax bitset(SMFIP_MDS_1M|SMFIP_MDS_256K, v)) 931187494Semax { 932187494Semax smi_log(SMI_LOG_WARN, 933184610Salfred "%s: st_optionneg[%ld]: milter version=%X, trying flags=%X", 934187494Semax ctx->ctx_smfi->xxfi_name, 935187494Semax (long) ctx->ctx_id, ctx->ctx_smfi->xxfi_version, v); 936187494Semax } 937187494Semax# endif /* 0 */ 938184610Salfred#endif /* _FFR_MDS_NEGOTIATE */ 939187494Semax 940187494Semax /* 941184610Salfred ** MTA protocol flags. 942187494Semax ** We pass the internal flags to the milter as "read only", 943187494Semax ** i.e., a milter can read them so it knows which size 944187494Semax ** will be used, but any changes by a milter will be ignored 945187494Semax ** (see below, search for SMFI_INTERNAL). 946187494Semax */ 947184610Salfred 948187741Semax ctx->ctx_mta_pflags = (v & ~SMFI_INTERNAL) | internal_pflags; 949187494Semax 950187494Semax /* 951187494Semax ** Copy flags from milter struct into libmilter context; 952184610Salfred ** this variable will be used later on to check whether 953187494Semax ** the MTA "actions" can fulfill the milter requirements, 954187494Semax ** but it may be overwritten by the negotiate callback. 955187494Semax */ 956187494Semax 957187494Semax ctx->ctx_aflags = ctx->ctx_smfi->xxfi_flags; 958184610Salfred fake_pflags = SMFIP_NR_CONN 959187494Semax |SMFIP_NR_HELO 960187494Semax |SMFIP_NR_MAIL 961187494Semax |SMFIP_NR_RCPT 962187494Semax |SMFIP_NR_DATA 963187494Semax |SMFIP_NR_UNKN 964187741Semax |SMFIP_NR_HDR 965184610Salfred |SMFIP_NR_EOH 966187494Semax |SMFIP_NR_BODY 967187494Semax ; 968187494Semax 969184610Salfred if (g->a_ctx->ctx_smfi != NULL && 970187494Semax g->a_ctx->ctx_smfi->xxfi_version > 4 && 971187494Semax (fi_negotiate = g->a_ctx->ctx_smfi->xxfi_negotiate) != NULL) 972187494Semax { 973187494Semax int r; 974187494Semax unsigned long m_aflags, m_pflags, m_f2, m_f3; 975187494Semax 976187494Semax /* 977187494Semax ** let milter decide whether the features offered by the 978187494Semax ** MTA are "good enough". 979184610Salfred ** Notes: 980187494Semax ** - libmilter can "fake" some features (e.g., SMFIP_NR_HDR) 981187494Semax ** - m_f2, m_f3 are for future extensions 982187494Semax */ 983187494Semax 984187494Semax m_f2 = m_f3 = 0; 985184610Salfred m_aflags = ctx->ctx_mta_aflags; 986184610Salfred m_pflags = ctx->ctx_pflags; 987187494Semax if ((SMFIP_SKIP & ctx->ctx_mta_pflags) != 0) 988187494Semax m_pflags |= SMFIP_SKIP; 989187494Semax r = fi_negotiate(g->a_ctx, 990187494Semax ctx->ctx_mta_aflags, 991187494Semax ctx->ctx_mta_pflags|fake_pflags, 992187494Semax 0, 0, 993187494Semax &m_aflags, &m_pflags, &m_f2, &m_f3); 994187494Semax 995187494Semax#if _FFR_MILTER_CHECK 996187494Semax testmode = bitset(SMFIP_TEST, m_pflags); 997187494Semax if (testmode) 998184610Salfred m_pflags &= ~SMFIP_TEST; 999187494Semax#endif /* _FFR_MILTER_CHECK */ 1000187494Semax 1001184610Salfred /* 1002184610Salfred ** Types of protocol flags (pflags): 1003187494Semax ** 1. do NOT send protocol step X 1004187494Semax ** 2. MTA can do/understand something extra (SKIP, 1005187494Semax ** send unknown RCPTs) 1006184610Salfred ** 3. MTA can deal with "no reply" for various protocol steps 1007187494Semax ** Note: this mean that it isn't possible to simply set all 1008187494Semax ** flags to get "everything": 1009184610Salfred ** setting a flag of type 1 turns off a step 1010187494Semax ** (it should be the other way around: 1011187494Semax ** a flag means a protocol step can be sent) 1012187494Semax ** setting a flag of type 3 requires that milter 1013184610Salfred ** never sends a reply for the corresponding step. 1014187494Semax ** Summary: the "negation" of protocol flags is causing 1015187494Semax ** problems, but at least for type 3 there is no simple 1016187494Semax ** solution. 1017184610Salfred ** 1018187494Semax ** What should "all options" mean? 1019187494Semax ** send all protocol steps _except_ those for which there is 1020187494Semax ** no callback (currently registered in ctx_pflags) 1021187494Semax ** expect SKIP as return code? Yes 1022184610Salfred ** send unknown RCPTs? No, 1023187494Semax ** must be explicitly requested? 1024187494Semax ** "no reply" for some protocol steps? No, 1025184610Salfred ** must be explicitly requested. 1026187741Semax */ 1027187494Semax 1028187494Semax if (SMFIS_ALL_OPTS == r) 1029184610Salfred { 1030187494Semax ctx->ctx_aflags = ctx->ctx_mta_aflags; 1031187494Semax ctx->ctx_pflags2mta = ctx->ctx_pflags; 1032184610Salfred if ((SMFIP_SKIP & ctx->ctx_mta_pflags) != 0) 1033187494Semax ctx->ctx_pflags2mta |= SMFIP_SKIP; 1034187494Semax } 1035184610Salfred else if (r != SMFIS_CONTINUE) 1036187494Semax { 1037187494Semax smi_log(SMI_LOG_ERR, 1038187494Semax "%s: st_optionneg[%ld]: xxfi_negotiate returned %d (protocol options=0x%lx, actions=0x%lx)", 1039187494Semax ctx->ctx_smfi->xxfi_name, 1040187494Semax (long) ctx->ctx_id, r, ctx->ctx_mta_pflags, 1041184610Salfred ctx->ctx_mta_aflags); 1042184610Salfred return _SMFIS_ABORT; 1043184610Salfred } 1044184610Salfred else 1045187741Semax { 1046187494Semax ctx->ctx_aflags = m_aflags; 1047187494Semax ctx->ctx_pflags = m_pflags; 1048184610Salfred ctx->ctx_pflags2mta = m_pflags; 1049184610Salfred } 1050184610Salfred 1051187741Semax /* check whether some flags need to be "faked" */ 1052187741Semax i = ctx->ctx_pflags2mta; 1053187741Semax if ((ctx->ctx_mta_pflags & i) != i) 1054187494Semax { 1055184610Salfred unsigned int idx; 1056184610Salfred unsigned long b; 1057187494Semax 1058184610Salfred /* 1059187494Semax ** If some behavior can be faked (set in fake_pflags), 1060187494Semax ** but the MTA doesn't support it, then unset 1061184610Salfred ** that flag in the value that is sent to the MTA. 1062187494Semax */ 1063187494Semax 1064187741Semax for (idx = 0; idx < 32; idx++) 1065187494Semax { 1066187741Semax b = 1 << idx; 1067184610Salfred if ((ctx->ctx_mta_pflags & b) != b && 1068187494Semax (fake_pflags & b) == b) 1069187494Semax ctx->ctx_pflags2mta &= ~b; 1070187494Semax } 1071184610Salfred } 1072187494Semax } 1073187494Semax else 1074187494Semax { 1075187494Semax /* 1076184610Salfred ** Set the protocol flags based on the values determined 1077187494Semax ** in mi_listener() which checked the defined callbacks. 1078187494Semax */ 1079187494Semax 1080184610Salfred ctx->ctx_pflags2mta = ctx->ctx_pflags; 1081187494Semax } 1082187494Semax 1083187494Semax /* check whether actions and protocol requirements can be satisfied */ 1084184610Salfred i = ctx->ctx_aflags; 1085187494Semax if ((i & ctx->ctx_mta_aflags) != i) 1086187494Semax { 1087187741Semax smi_log(SMI_LOG_ERR, 1088187494Semax "%s: st_optionneg[%ld]: 0x%lx does not fulfill action requirements 0x%x", 1089187741Semax ctx->ctx_smfi->xxfi_name, 1090184610Salfred (long) ctx->ctx_id, ctx->ctx_mta_aflags, i); 1091184610Salfred return _SMFIS_ABORT; 1092187494Semax } 1093187494Semax 1094187494Semax i = ctx->ctx_pflags2mta; 1095187494Semax if ((ctx->ctx_mta_pflags & i) != i) 1096187494Semax { 1097187494Semax /* 1098187494Semax ** Older MTAs do not support some protocol steps. 1099187494Semax ** As this protocol is a bit "wierd" (it asks for steps 1100187494Semax ** NOT to be taken/sent) we have to check whether we 1101187494Semax ** should turn off those "negative" requests. 1102187494Semax ** Currently these are only SMFIP_NODATA and SMFIP_NOUNKNOWN. 1103187494Semax */ 1104187494Semax 1105184610Salfred if (bitset(SMFIP_NODATA, ctx->ctx_pflags2mta) && 1106187494Semax !bitset(SMFIP_NODATA, ctx->ctx_mta_pflags)) 1107184610Salfred ctx->ctx_pflags2mta &= ~SMFIP_NODATA; 1108187494Semax if (bitset(SMFIP_NOUNKNOWN, ctx->ctx_pflags2mta) && 1109187494Semax !bitset(SMFIP_NOUNKNOWN, ctx->ctx_mta_pflags)) 1110187494Semax ctx->ctx_pflags2mta &= ~SMFIP_NOUNKNOWN; 1111187494Semax i = ctx->ctx_pflags2mta; 1112184610Salfred } 1113187494Semax 1114187741Semax if ((ctx->ctx_mta_pflags & i) != i) 1115187494Semax { 1116184610Salfred smi_log(SMI_LOG_ERR, 1117184610Salfred "%s: st_optionneg[%ld]: 0x%lx does not fulfill protocol requirements 0x%x", 1118184610Salfred ctx->ctx_smfi->xxfi_name, 1119187741Semax (long) ctx->ctx_id, ctx->ctx_mta_pflags, i); 1120187741Semax return _SMFIS_ABORT; 1121187741Semax } 1122187741Semax fix_stm(ctx); 1123187741Semax 1124187741Semax if (ctx->ctx_dbg > 3) 1125187741Semax sm_dprintf("[%ld] milter_negotiate:" 1126187741Semax " mta_actions=0x%lx, mta_flags=0x%lx" 1127187741Semax " actions=0x%lx, flags=0x%lx\n" 1128187741Semax , (long) ctx->ctx_id 1129187741Semax , ctx->ctx_mta_aflags, ctx->ctx_mta_pflags 1130187741Semax , ctx->ctx_aflags, ctx->ctx_pflags); 1131187741Semax 1132187741Semax#if _FFR_MILTER_CHECK 1133187741Semax if (ctx->ctx_dbg > 3) 1134187741Semax sm_dprintf("[%ld] milter_negotiate:" 1135187741Semax " testmode=%d, pflags2mta=%X, internal_pflags=%X\n" 1136187741Semax , (long) ctx->ctx_id, testmode 1137187741Semax , ctx->ctx_pflags2mta, internal_pflags); 1138187741Semax 1139187741Semax /* in test mode: take flags without further modifications */ 1140187741Semax if (!testmode) 1141187741Semax /* Warning: check statement below! */ 1142187741Semax#endif /* _FFR_MILTER_CHECK */ 1143187741Semax 1144187741Semax /* 1145187741Semax ** Remove the internal flags that might have been set by a milter 1146187741Semax ** and set only those determined above. 1147187741Semax */ 1148187741Semax 1149187741Semax ctx->ctx_pflags2mta = (ctx->ctx_pflags2mta & ~SMFI_INTERNAL) 1150187741Semax | internal_pflags; 1151187741Semax return _SMFIS_OPTIONS; 1152187741Semax} 1153187741Semax 1154187741Semax/* 1155187741Semax** ST_CONNECTINFO -- receive connection information 1156187741Semax** 1157187741Semax** Parameters: 1158187741Semax** g -- generic argument structure 1159187741Semax** 1160187741Semax** Returns: 1161187741Semax** continue or filter-specified value 1162187741Semax*/ 1163187741Semax 1164187741Semaxstatic int 1165187741Semaxst_connectinfo(g) 1166184610Salfred genarg *g; 1167184610Salfred{ 1168187494Semax size_t l; 1169184610Salfred size_t i; 1170184610Salfred char *s, family; 1171184610Salfred unsigned short port = 0; 1172184610Salfred _SOCK_ADDR sockaddr; 1173187741Semax sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *)); 1174187494Semax 1175184610Salfred if (g == NULL) 1176184610Salfred return _SMFIS_ABORT; 1177187741Semax mi_clr_macros(g->a_ctx, g->a_idx + 1); 1178187494Semax if (g->a_ctx->ctx_smfi == NULL || 1179184610Salfred (fi_connect = g->a_ctx->ctx_smfi->xxfi_connect) == NULL) 1180187741Semax return SMFIS_CONTINUE; 1181184610Salfred 1182187741Semax s = g->a_buf; 1183187741Semax i = 0; 1184187741Semax l = g->a_len; 1185187741Semax while (s[i] != '\0' && i <= l) 1186187741Semax ++i; 1187187741Semax if (i + 1 >= l) 1188187741Semax return _SMFIS_ABORT; 1189187741Semax 1190187741Semax /* Move past trailing \0 in host string */ 1191187741Semax i++; 1192187741Semax family = s[i++]; 1193187741Semax (void) memset(&sockaddr, '\0', sizeof sockaddr); 1194187741Semax if (family != SMFIA_UNKNOWN) 1195187741Semax { 1196187741Semax if (i + sizeof port >= l) 1197187741Semax { 1198187741Semax smi_log(SMI_LOG_ERR, 1199187494Semax "%s: connect[%ld]: wrong len %d >= %d", 1200187741Semax g->a_ctx->ctx_smfi->xxfi_name, 1201187741Semax (long) g->a_ctx->ctx_id, (int) i, (int) l); 1202187494Semax return _SMFIS_ABORT; 1203187494Semax } 1204187494Semax (void) memcpy((void *) &port, (void *) (s + i), 1205187494Semax sizeof port); 1206187494Semax i += sizeof port; 1207187494Semax 1208187741Semax /* make sure string is terminated */ 1209187494Semax if (s[l - 1] != '\0') 1210187494Semax return _SMFIS_ABORT; 1211187494Semax# if NETINET 1212187741Semax if (family == SMFIA_INET) 1213187494Semax { 1214187494Semax if (inet_aton(s + i, (struct in_addr *) &sockaddr.sin.sin_addr) 1215187494Semax != 1) 1216187494Semax { 1217187494Semax smi_log(SMI_LOG_ERR, 1218184610Salfred "%s: connect[%ld]: inet_aton failed", 1219187494Semax g->a_ctx->ctx_smfi->xxfi_name, 1220187494Semax (long) g->a_ctx->ctx_id); 1221184610Salfred return _SMFIS_ABORT; 1222184610Salfred } 1223187494Semax sockaddr.sa.sa_family = AF_INET; 1224187494Semax if (port > 0) 1225184610Salfred sockaddr.sin.sin_port = port; 1226187741Semax } 1227187741Semax else 1228184610Salfred# endif /* NETINET */ 1229187741Semax# if NETINET6 1230187494Semax if (family == SMFIA_INET6) 1231187494Semax { 1232187741Semax if (mi_inet_pton(AF_INET6, s + i, 1233187494Semax &sockaddr.sin6.sin6_addr) != 1) 1234187741Semax { 1235187741Semax smi_log(SMI_LOG_ERR, 1236187741Semax "%s: connect[%ld]: mi_inet_pton failed", 1237187741Semax g->a_ctx->ctx_smfi->xxfi_name, 1238187741Semax (long) g->a_ctx->ctx_id); 1239187494Semax return _SMFIS_ABORT; 1240187741Semax } 1241187741Semax sockaddr.sa.sa_family = AF_INET6; 1242187741Semax if (port > 0) 1243187494Semax sockaddr.sin6.sin6_port = port; 1244187741Semax } 1245187494Semax else 1246187494Semax# endif /* NETINET6 */ 1247187494Semax# if NETUNIX 1248187494Semax if (family == SMFIA_UNIX) 1249187494Semax { 1250187741Semax if (sm_strlcpy(sockaddr.sunix.sun_path, s + i, 1251187741Semax sizeof sockaddr.sunix.sun_path) >= 1252187494Semax sizeof sockaddr.sunix.sun_path) 1253187494Semax { 1254187494Semax smi_log(SMI_LOG_ERR, 1255187494Semax "%s: connect[%ld]: path too long", 1256187494Semax g->a_ctx->ctx_smfi->xxfi_name, 1257187494Semax (long) g->a_ctx->ctx_id); 1258187494Semax return _SMFIS_ABORT; 1259187494Semax } 1260187494Semax sockaddr.sunix.sun_family = AF_UNIX; 1261187494Semax } 1262187494Semax else 1263187494Semax# endif /* NETUNIX */ 1264187494Semax { 1265187494Semax smi_log(SMI_LOG_ERR, 1266187741Semax "%s: connect[%ld]: unknown family %d", 1267187741Semax g->a_ctx->ctx_smfi->xxfi_name, 1268184610Salfred (long) g->a_ctx->ctx_id, family); 1269187494Semax return _SMFIS_ABORT; 1270187494Semax } 1271187494Semax } 1272187741Semax return (*fi_connect)(g->a_ctx, g->a_buf, 1273187494Semax family != SMFIA_UNKNOWN ? &sockaddr : NULL); 1274187741Semax} 1275184610Salfred 1276184610Salfred/* 1277187494Semax** ST_EOH -- end of headers 1278187494Semax** 1279187741Semax** Parameters: 1280187494Semax** g -- generic argument structure 1281187741Semax** 1282184610Salfred** Returns: 1283187494Semax** continue or filter-specified value 1284187494Semax*/ 1285187494Semax 1286187494Semaxstatic int 1287187494Semaxst_eoh(g) 1288187494Semax genarg *g; 1289187494Semax{ 1290184610Salfred sfsistat (*fi_eoh) __P((SMFICTX *)); 1291187494Semax 1292187494Semax if (g == NULL) 1293187494Semax return _SMFIS_ABORT; 1294187494Semax if (g->a_ctx->ctx_smfi != NULL && 1295184610Salfred (fi_eoh = g->a_ctx->ctx_smfi->xxfi_eoh) != NULL) 1296187494Semax return (*fi_eoh)(g->a_ctx); 1297187494Semax return SMFIS_CONTINUE; 1298187494Semax} 1299187494Semax 1300187494Semax/* 1301184610Salfred** ST_DATA -- DATA command 1302184610Salfred** 1303187494Semax** Parameters: 1304187494Semax** g -- generic argument structure 1305184610Salfred** 1306184610Salfred** Returns: 1307184610Salfred** continue or filter-specified value 1308187494Semax*/ 1309184610Salfred 1310187494Semaxstatic int 1311187494Semaxst_data(g) 1312187494Semax genarg *g; 1313187494Semax{ 1314187494Semax sfsistat (*fi_data) __P((SMFICTX *)); 1315187494Semax 1316187494Semax if (g == NULL) 1317187494Semax return _SMFIS_ABORT; 1318187494Semax if (g->a_ctx->ctx_smfi != NULL && 1319184610Salfred g->a_ctx->ctx_smfi->xxfi_version > 3 && 1320187494Semax (fi_data = g->a_ctx->ctx_smfi->xxfi_data) != NULL) 1321187494Semax return (*fi_data)(g->a_ctx); 1322184610Salfred return SMFIS_CONTINUE; 1323187494Semax} 1324187494Semax 1325187494Semax/* 1326187494Semax** ST_HELO -- helo/ehlo command 1327184610Salfred** 1328187494Semax** Parameters: 1329187494Semax** g -- generic argument structure 1330187494Semax** 1331187494Semax** Returns: 1332184610Salfred** continue or filter-specified value 1333187494Semax*/ 1334187494Semax 1335184610Salfredstatic int 1336187741Semaxst_helo(g) 1337187741Semax genarg *g; 1338187741Semax{ 1339187741Semax sfsistat (*fi_helo) __P((SMFICTX *, char *)); 1340187494Semax 1341187741Semax if (g == NULL) 1342184610Salfred return _SMFIS_ABORT; 1343187494Semax mi_clr_macros(g->a_ctx, g->a_idx + 1); 1344187741Semax if (g->a_ctx->ctx_smfi != NULL && 1345184610Salfred (fi_helo = g->a_ctx->ctx_smfi->xxfi_helo) != NULL) 1346187494Semax { 1347187494Semax /* paranoia: check for terminating '\0' */ 1348184610Salfred if (g->a_len == 0 || g->a_buf[g->a_len - 1] != '\0') 1349187494Semax return MI_FAILURE; 1350187494Semax return (*fi_helo)(g->a_ctx, g->a_buf); 1351187494Semax } 1352187494Semax return SMFIS_CONTINUE; 1353184610Salfred} 1354187494Semax 1355187494Semax/* 1356187494Semax** ST_HEADER -- header line 1357187494Semax** 1358184610Salfred** Parameters: 1359187494Semax** g -- generic argument structure 1360184610Salfred** 1361187741Semax** Returns: 1362187494Semax** continue or filter-specified value 1363187741Semax*/ 1364184610Salfred 1365184610Salfredstatic int 1366187494Semaxst_header(g) 1367184610Salfred genarg *g; 1368184610Salfred{ 1369187494Semax char *hf, *hv; 1370187494Semax sfsistat (*fi_header) __P((SMFICTX *, char *, char *)); 1371184610Salfred 1372184610Salfred if (g == NULL) 1373184610Salfred return _SMFIS_ABORT; 1374184610Salfred if (g->a_ctx->ctx_smfi == NULL || 1375184610Salfred (fi_header = g->a_ctx->ctx_smfi->xxfi_header) == NULL) 1376187741Semax return SMFIS_CONTINUE; 1377184610Salfred if (dec_arg2(g->a_buf, g->a_len, &hf, &hv) == MI_SUCCESS) 1378187741Semax return (*fi_header)(g->a_ctx, hf, hv); 1379184610Salfred else 1380187741Semax return _SMFIS_ABORT; 1381187741Semax} 1382184610Salfred 1383187494Semax#define ARGV_FCT(lf, rf, idx) \ 1384187741Semax char **argv; \ 1385184610Salfred sfsistat (*lf) __P((SMFICTX *, char **)); \ 1386187494Semax int r; \ 1387184610Salfred \ 1388187741Semax if (g == NULL) \ 1389187741Semax return _SMFIS_ABORT; \ 1390184610Salfred mi_clr_macros(g->a_ctx, g->a_idx + 1); \ 1391187494Semax if (g->a_ctx->ctx_smfi == NULL || \ 1392187494Semax (lf = g->a_ctx->ctx_smfi->rf) == NULL) \ 1393187494Semax return SMFIS_CONTINUE; \ 1394187494Semax if ((argv = dec_argv(g->a_buf, g->a_len)) == NULL) \ 1395184610Salfred return _SMFIS_ABORT; \ 1396187741Semax r = (*lf)(g->a_ctx, argv); \ 1397184610Salfred free(argv); \ 1398187494Semax return r; 1399187494Semax 1400187494Semax/* 1401184610Salfred** ST_SENDER -- MAIL FROM command 1402187494Semax** 1403187494Semax** Parameters: 1404184610Salfred** g -- generic argument structure 1405184610Salfred** 1406184610Salfred** Returns: 1407184610Salfred** continue or filter-specified value 1408184610Salfred*/ 1409187494Semax 1410187494Semaxstatic int 1411187494Semaxst_sender(g) 1412187494Semax genarg *g; 1413184610Salfred{ 1414184610Salfred ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL) 1415184610Salfred} 1416184610Salfred 1417184610Salfred/* 1418184610Salfred** ST_RCPT -- RCPT TO command 1419184610Salfred** 1420184610Salfred** Parameters: 1421187494Semax** g -- generic argument structure 1422184610Salfred** 1423187494Semax** Returns: 1424187494Semax** continue or filter-specified value 1425187494Semax*/ 1426187494Semax 1427187494Semaxstatic int 1428187494Semaxst_rcpt(g) 1429187494Semax genarg *g; 1430187494Semax{ 1431187494Semax ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT) 1432187494Semax} 1433187741Semax 1434187494Semax/* 1435187494Semax** ST_UNKNOWN -- unrecognized or unimplemented command 1436187494Semax** 1437187494Semax** Parameters: 1438187494Semax** g -- generic argument structure 1439187494Semax** 1440187494Semax** Returns: 1441187494Semax** continue or filter-specified value 1442184610Salfred*/ 1443184610Salfred 1444184610Salfredstatic int 1445184610Salfredst_unknown(g) 1446184610Salfred genarg *g; 1447184610Salfred{ 1448184610Salfred sfsistat (*fi_unknown) __P((SMFICTX *, const char *)); 1449184610Salfred 1450184610Salfred if (g == NULL) 1451184610Salfred return _SMFIS_ABORT; 1452184610Salfred if (g->a_ctx->ctx_smfi != NULL && 1453187494Semax g->a_ctx->ctx_smfi->xxfi_version > 2 && 1454184610Salfred (fi_unknown = g->a_ctx->ctx_smfi->xxfi_unknown) != NULL) 1455187494Semax return (*fi_unknown)(g->a_ctx, (const char *) g->a_buf); 1456187494Semax return SMFIS_CONTINUE; 1457187494Semax} 1458187494Semax 1459184610Salfred/* 1460184610Salfred** ST_MACROS -- deal with macros received from the MTA 1461184610Salfred** 1462184610Salfred** Parameters: 1463184610Salfred** g -- generic argument structure 1464187494Semax** 1465184610Salfred** Returns: 1466187494Semax** continue/keep 1467187494Semax** 1468187494Semax** Side effects: 1469187494Semax** set pointer in macro array to current values. 1470184610Salfred*/ 1471184610Salfred 1472184610Salfredstatic int 1473187494Semaxst_macros(g) 1474184610Salfred genarg *g; 1475187494Semax{ 1476187494Semax int i; 1477184610Salfred char **argv; 1478187494Semax 1479187494Semax if (g == NULL || g->a_len < 1) 1480184610Salfred return _SMFIS_FAIL; 1481187494Semax if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL) 1482187494Semax return _SMFIS_FAIL; 1483187494Semax switch (g->a_buf[0]) 1484187494Semax { 1485184610Salfred case SMFIC_CONNECT: 1486187494Semax i = CI_CONN; 1487187494Semax break; 1488187494Semax case SMFIC_HELO: 1489184610Salfred i = CI_HELO; 1490187494Semax break; 1491187494Semax case SMFIC_MAIL: 1492187494Semax i = CI_MAIL; 1493184610Salfred break; 1494187494Semax case SMFIC_RCPT: 1495187494Semax i = CI_RCPT; 1496187494Semax break; 1497187494Semax case SMFIC_DATA: 1498184610Salfred i = CI_DATA; 1499187494Semax break; 1500187494Semax case SMFIC_BODYEOB: 1501184610Salfred i = CI_EOM; 1502184610Salfred break; 1503184610Salfred case SMFIC_EOH: 1504184610Salfred i = CI_EOH; 1505184610Salfred break; 1506184610Salfred default: 1507184610Salfred free(argv); 1508187494Semax return _SMFIS_FAIL; 1509184610Salfred } 1510187494Semax if (g->a_ctx->ctx_mac_ptr[i] != NULL) 1511184610Salfred free(g->a_ctx->ctx_mac_ptr[i]); 1512184610Salfred if (g->a_ctx->ctx_mac_buf[i] != NULL) 1513184610Salfred free(g->a_ctx->ctx_mac_buf[i]); 1514184610Salfred g->a_ctx->ctx_mac_ptr[i] = argv; 1515184610Salfred g->a_ctx->ctx_mac_buf[i] = g->a_buf; 1516184610Salfred return _SMFIS_KEEP; 1517184610Salfred} 1518184610Salfred 1519184610Salfred/* 1520184610Salfred** ST_QUIT -- quit command 1521184610Salfred** 1522184610Salfred** Parameters: 1523184610Salfred** g -- generic argument structure 1524184610Salfred** 1525184610Salfred** Returns: 1526187494Semax** noreply 1527187494Semax*/ 1528187494Semax 1529187494Semax/* ARGSUSED */ 1530187494Semaxstatic int 1531187494Semaxst_quit(g) 1532187494Semax genarg *g; 1533187494Semax{ 1534184610Salfred sfsistat (*fi_close) __P((SMFICTX *)); 1535184610Salfred 1536184610Salfred if (g == NULL) 1537187494Semax return _SMFIS_ABORT; 1538187494Semax if (g->a_ctx->ctx_smfi != NULL && 1539184610Salfred (fi_close = g->a_ctx->ctx_smfi->xxfi_close) != NULL) 1540184610Salfred (void) (*fi_close)(g->a_ctx); 1541184610Salfred mi_clr_macros(g->a_ctx, 0); 1542184610Salfred return _SMFIS_NOREPLY; 1543184610Salfred} 1544187494Semax 1545184610Salfred/* 1546187494Semax** ST_BODYCHUNK -- deal with a piece of the mail body 1547184610Salfred** 1548187494Semax** Parameters: 1549187494Semax** g -- generic argument structure 1550187494Semax** 1551184610Salfred** Returns: 1552184610Salfred** continue or filter-specified value 1553184610Salfred*/ 1554187494Semax 1555184610Salfredstatic int 1556184610Salfredst_bodychunk(g) 1557184610Salfred genarg *g; 1558184610Salfred{ 1559184610Salfred sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t)); 1560184610Salfred 1561184610Salfred if (g == NULL) 1562184610Salfred return _SMFIS_ABORT; 1563184610Salfred if (g->a_ctx->ctx_smfi != NULL && 1564184610Salfred (fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL) 1565184610Salfred return (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf, 1566184610Salfred g->a_len); 1567187494Semax return SMFIS_CONTINUE; 1568184610Salfred} 1569184610Salfred 1570184610Salfred/* 1571184610Salfred** ST_BODYEND -- deal with the last piece of the mail body 1572187494Semax** 1573184610Salfred** Parameters: 1574184610Salfred** g -- generic argument structure 1575187494Semax** 1576187494Semax** Returns: 1577184610Salfred** continue or filter-specified value 1578184610Salfred** 1579184610Salfred** Side effects: 1580184610Salfred** sends a reply for the body part (if non-empty). 1581184610Salfred*/ 1582187494Semax 1583187494Semaxstatic int 1584187494Semaxst_bodyend(g) 1585187494Semax genarg *g; 1586184610Salfred{ 1587184610Salfred sfsistat r; 1588184610Salfred sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t)); 1589184610Salfred sfsistat (*fi_eom) __P((SMFICTX *)); 1590184610Salfred 1591187494Semax if (g == NULL) 1592187494Semax return _SMFIS_ABORT; 1593184610Salfred r = SMFIS_CONTINUE; 1594184610Salfred if (g->a_ctx->ctx_smfi != NULL) 1595187494Semax { 1596187494Semax if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL && 1597187494Semax g->a_len > 0) 1598187494Semax { 1599187494Semax socket_t sd; 1600187494Semax struct timeval timeout; 1601187494Semax 1602187494Semax timeout.tv_sec = g->a_ctx->ctx_timeout; 1603187494Semax timeout.tv_usec = 0; 1604187494Semax sd = g->a_ctx->ctx_sd; 1605187494Semax r = (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf, 1606187494Semax g->a_len); 1607184610Salfred if (r != SMFIS_CONTINUE && 1608184610Salfred sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS) 1609187494Semax return _SMFIS_ABORT; 1610187494Semax } 1611187494Semax } 1612187494Semax if (r == SMFIS_CONTINUE && 1613187494Semax (fi_eom = g->a_ctx->ctx_smfi->xxfi_eom) != NULL) 1614184610Salfred return (*fi_eom)(g->a_ctx); 1615187494Semax return r; 1616184610Salfred} 1617184610Salfred 1618184610Salfred/* 1619187494Semax** ST_ABORTFCT -- deal with aborts 1620187494Semax** 1621187494Semax** Parameters: 1622187494Semax** g -- generic argument structure 1623187494Semax** 1624184610Salfred** Returns: 1625187494Semax** abort or filter-specified value 1626184610Salfred*/ 1627184610Salfred 1628184610Salfredstatic int 1629184610Salfredst_abortfct(g) 1630187494Semax genarg *g; 1631184610Salfred{ 1632184610Salfred sfsistat (*fi_abort) __P((SMFICTX *)); 1633184610Salfred 1634187494Semax if (g == NULL) 1635187494Semax return _SMFIS_ABORT; 1636184610Salfred if (g != NULL && g->a_ctx->ctx_smfi != NULL && 1637184610Salfred (fi_abort = g->a_ctx->ctx_smfi->xxfi_abort) != NULL) 1638184610Salfred (void) (*fi_abort)(g->a_ctx); 1639184610Salfred return _SMFIS_NOREPLY; 1640187494Semax} 1641184610Salfred 1642184610Salfred/* 1643187741Semax** TRANS_OK -- is the state transition ok? 1644184610Salfred** 1645187494Semax** Parameters: 1646187741Semax** old -- old state 1647187494Semax** new -- new state 1648187494Semax** 1649187494Semax** Returns: 1650187494Semax** state transition ok 1651184610Salfred*/ 1652184610Salfred 1653187494Semaxstatic bool 1654187494Semaxtrans_ok(old, new) 1655184610Salfred int old, new; 1656187494Semax{ 1657187741Semax int s, n; 1658184610Salfred 1659184610Salfred s = old; 1660184610Salfred if (s >= SIZE_NEXT_STATES) 1661184610Salfred return false; 1662187494Semax do 1663187494Semax { 1664187494Semax /* is this state transition allowed? */ 1665187494Semax if ((MI_MASK(new) & next_states[s]) != 0) 1666187494Semax return true; 1667187494Semax 1668187494Semax /* 1669187494Semax ** no: try next state; 1670187494Semax ** this works since the relevant states are ordered 1671187494Semax ** strict sequentially 1672187494Semax */ 1673187494Semax 1674187494Semax n = s + 1; 1675187494Semax if (n >= SIZE_NEXT_STATES) 1676187494Semax return false; 1677187494Semax 1678187494Semax /* 1679187494Semax ** can we actually "skip" this state? 1680187494Semax ** see fix_stm() which sets this bit for those 1681187494Semax ** states which the filter program is not interested in 1682187494Semax */ 1683187494Semax 1684187494Semax if (bitset(NX_SKIP, next_states[n])) 1685187494Semax s = n; 1686187494Semax else 1687187494Semax return false; 1688187494Semax } while (s < SIZE_NEXT_STATES); 1689187494Semax return false; 1690187494Semax} 1691187494Semax 1692187494Semax/* 1693187494Semax** FIX_STM -- add "skip" bits to the state transition table 1694187494Semax** 1695184610Salfred** Parameters: 1696187494Semax** ctx -- context structure 1697184610Salfred** 1698187494Semax** Returns: 1699187494Semax** None. 1700187494Semax** 1701187494Semax** Side effects: 1702187494Semax** may change state transition table. 1703187494Semax*/ 1704187494Semax 1705187494Semaxstatic void 1706187494Semaxfix_stm(ctx) 1707187494Semax SMFICTX_PTR ctx; 1708187494Semax{ 1709187494Semax unsigned long fl; 1710187494Semax 1711187494Semax if (ctx == NULL || ctx->ctx_smfi == NULL) 1712187494Semax return; 1713187494Semax fl = ctx->ctx_pflags; 1714187494Semax if (bitset(SMFIP_NOCONNECT, fl)) 1715187494Semax next_states[ST_CONN] |= NX_SKIP; 1716187494Semax if (bitset(SMFIP_NOHELO, fl)) 1717189275Sthompsa next_states[ST_HELO] |= NX_SKIP; 1718187494Semax if (bitset(SMFIP_NOMAIL, fl)) 1719187494Semax next_states[ST_MAIL] |= NX_SKIP; 1720187494Semax if (bitset(SMFIP_NORCPT, fl)) 1721188942Sthompsa next_states[ST_RCPT] |= NX_SKIP; 1722187494Semax if (bitset(SMFIP_NOHDRS, fl)) 1723 next_states[ST_HDRS] |= NX_SKIP; 1724 if (bitset(SMFIP_NOEOH, fl)) 1725 next_states[ST_EOHS] |= NX_SKIP; 1726 if (bitset(SMFIP_NOBODY, fl)) 1727 next_states[ST_BODY] |= NX_SKIP; 1728 if (bitset(SMFIP_NODATA, fl)) 1729 next_states[ST_DATA] |= NX_SKIP; 1730 if (bitset(SMFIP_NOUNKNOWN, fl)) 1731 next_states[ST_UNKN] |= NX_SKIP; 1732} 1733 1734/* 1735** DEC_ARGV -- split a buffer into a list of strings, NULL terminated 1736** 1737** Parameters: 1738** buf -- buffer with several strings 1739** len -- length of buffer 1740** 1741** Returns: 1742** array of pointers to the individual strings 1743*/ 1744 1745static char ** 1746dec_argv(buf, len) 1747 char *buf; 1748 size_t len; 1749{ 1750 char **s; 1751 size_t i; 1752 int elem, nelem; 1753 1754 nelem = 0; 1755 for (i = 0; i < len; i++) 1756 { 1757 if (buf[i] == '\0') 1758 ++nelem; 1759 } 1760 if (nelem == 0) 1761 return NULL; 1762 1763 /* last entry is only for the name */ 1764 s = (char **)malloc((nelem + 1) * (sizeof *s)); 1765 if (s == NULL) 1766 return NULL; 1767 s[0] = buf; 1768 for (i = 0, elem = 0; i < len && elem < nelem; i++) 1769 { 1770 if (buf[i] == '\0') 1771 { 1772 ++elem; 1773 if (i + 1 >= len) 1774 s[elem] = NULL; 1775 else 1776 s[elem] = &(buf[i + 1]); 1777 } 1778 } 1779 1780 /* overwrite last entry (already done above, just paranoia) */ 1781 s[elem] = NULL; 1782 return s; 1783} 1784 1785/* 1786** DEC_ARG2 -- split a buffer into two strings 1787** 1788** Parameters: 1789** buf -- buffer with two strings 1790** len -- length of buffer 1791** s1,s2 -- pointer to result strings 1792** 1793** Returns: 1794** MI_FAILURE/MI_SUCCESS 1795*/ 1796 1797static int 1798dec_arg2(buf, len, s1, s2) 1799 char *buf; 1800 size_t len; 1801 char **s1; 1802 char **s2; 1803{ 1804 size_t i; 1805 1806 /* paranoia: check for terminating '\0' */ 1807 if (len == 0 || buf[len - 1] != '\0') 1808 return MI_FAILURE; 1809 *s1 = buf; 1810 for (i = 1; i < len && buf[i] != '\0'; i++) 1811 continue; 1812 if (i >= len - 1) 1813 return MI_FAILURE; 1814 *s2 = buf + i + 1; 1815 return MI_SUCCESS; 1816} 1817 1818/* 1819** SENDOK -- is it ok for the filter to send stuff to the MTA? 1820** 1821** Parameters: 1822** ctx -- context structure 1823** flag -- flag to check 1824** 1825** Returns: 1826** sending allowed (in current state) 1827*/ 1828 1829bool 1830mi_sendok(ctx, flag) 1831 SMFICTX_PTR ctx; 1832 int flag; 1833{ 1834 if (ctx == NULL || ctx->ctx_smfi == NULL) 1835 return false; 1836 1837 /* did the milter request this operation? */ 1838 if (flag != 0 && !bitset(flag, ctx->ctx_aflags)) 1839 return false; 1840 1841 /* are we in the correct state? It must be "End of Message". */ 1842 return ctx->ctx_state == ST_ENDM; 1843} 1844 1845#if _FFR_WORKERS_POOL 1846/* 1847** MI_RD_SOCKET_READY - checks if the socket is ready for read(2) 1848** 1849** Parameters: 1850** sd -- socket_t 1851** 1852** Returns: 1853** true iff socket is ready for read(2) 1854*/ 1855 1856#define MI_RD_CMD_TO 1 1857#define MI_RD_MAX_ERR 16 1858 1859static bool 1860mi_rd_socket_ready (sd) 1861 socket_t sd; 1862{ 1863 int n; 1864 int nerr = 0; 1865#if SM_CONF_POLL 1866 struct pollfd pfd; 1867#else /* SM_CONF_POLL */ 1868 fd_set rd_set, exc_set; 1869#endif /* SM_CONF_POLL */ 1870 1871 do 1872 { 1873#if SM_CONF_POLL 1874 pfd.fd = sd; 1875 pfd.events = POLLIN; 1876 pfd.revents = 0; 1877 1878 n = poll(&pfd, 1, MI_RD_CMD_TO); 1879#else /* SM_CONF_POLL */ 1880 struct timeval timeout; 1881 1882 FD_ZERO(&rd_set); 1883 FD_ZERO(&exc_set); 1884 FD_SET(sd, &rd_set); 1885 FD_SET(sd, &exc_set); 1886 1887 timeout.tv_sec = MI_RD_CMD_TO / 1000; 1888 timeout.tv_usec = 0; 1889 n = select(sd + 1, &rd_set, NULL, &exc_set, &timeout); 1890#endif /* SM_CONF_POLL */ 1891 1892 if (n < 0) 1893 { 1894 if (errno == EINTR) 1895 { 1896 nerr++; 1897 continue; 1898 } 1899 return true; 1900 } 1901 1902 if (n == 0) 1903 return false; 1904 break; 1905 } while (nerr < MI_RD_MAX_ERR); 1906 if (nerr >= MI_RD_MAX_ERR) 1907 return false; 1908 1909#if SM_CONF_POLL 1910 return (pfd.revents != 0); 1911#else /* SM_CONF_POLL */ 1912 return FD_ISSET(sd, &rd_set) || FD_ISSET(sd, &exc_set); 1913#endif /* SM_CONF_POLL */ 1914} 1915#endif /* _FFR_WORKERS_POOL */ 1916