/* * Copyright (c) 2002-2006 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: pmilter.h,v 1.40 2007/02/13 03:58:18 ca Exp $ */ #ifndef PMILTER_H #define PMILTER_H 1 #include "sm/generic.h" #include "sm/magic.h" #include "sm/common.h" #include "sm/pthread.h" #include "sm/heap.h" #include "sm/net.h" #include "sm/sockcnf.h" #include "sm/socket.h" #include "sm/io.h" #include "sm/evthr.h" #include "sm/queue.h" #include "sm/rcb.h" #include "sm/rcbl.h" #include "sm/rcbcomm.h" #include "sm/mta.h" #include "sm/queue.h" #include "sm/pmfdef.h" #include "sm/hdrmod.h" #ifndef PMILTER_DEBUG #define PMILTER_DEBUG 1 #endif #ifndef MTA_USE_RSAD #define MTA_USE_RSAD 1 #endif #ifndef PM_SE_TA_ID_LOCAL #define PM_SE_TA_ID_LOCAL 1 #endif #if SM_HEAP_CHECK extern SM_DEBUG_T SmHeapCheck; # define HEAP_CHECK (SmHeapCheck > 0) #else # define HEAP_CHECK 0 #endif /* HACK .... */ #define MAX_SMTPS_FD 32 /* must <= 32, see pmg_csused */ #define SM_PMG_CTX_MAGIC SM_MAGIC('P', 'M', 'I', 'C') #define SM_PMSS_CTX_MAGIC SM_MAGIC('P', 'M', 'S', 'S') #define SM_PMSE_CTX_MAGIC SM_MAGIC('P', 'M', 'S', 'E') #define SM_IS_PMG_CTX(pmg_ctx) SM_REQUIRE_ISA((pmg_ctx), SM_PMG_CTX_MAGIC) #define SM_IS_PMSS_CTX(pmss_ctx) SM_REQUIRE_ISA((pmss_ctx), SM_PMSS_CTX_MAGIC) #define SM_IS_PMSE_CTX(pmse_ctx) SM_REQUIRE_ISA((pmse_ctx), SM_PMSE_CTX_MAGIC) /* ** pmilter (library) context */ struct pmg_ctx_S { sm_magic_T sm_magic; pthread_mutex_t pmg_mutex; uint pmg_state; char *pmg_sockname; sockspec_T pmg_sockspec; /* what does libpmilter provide? */ uint32_t pmg_cap; uint32_t pmg_fct; uint32_t pmg_feat; uint32_t pmg_misc; int pmg_sslfd; /* listen fd */ uint pmg_ssnfd; /* number of used fds */ uint32_t pmg_sused; /* bitmask for used elements */ pmss_ctx_P pmg_sctx[MAX_SMTPS_FD]; sm_evthr_ctx_P pmg_ev_ctx; /* event thread context */ pmilter_P pmg_pmilter; /* pmilter (application) description */ void *pmg_appl_ctx; /* application context */ }; #define PMILT_ST_NONE 0 #define PMILT_ST_INIT0 1 #define PMILT_ST_RDCF 2 #define PMILT_ST_INIT1 3 #define PMILT_ST_RUN 4 #define PMILT_ST_STOPPING 5 #define PMILT_ST_STOPPED 6 typedef struct pm_rcpt_S pm_rcpt_T, *pm_rcpt_P; typedef struct pm_rcpts_S pm_rcpts_T, *pm_rcpts_P; struct pm_rcpt_S { sm_str_P pmr_pa; /* rcpt */ rcpt_idx_T pmr_idx; SIMPLEQ_ENTRY(pm_rcpt_S) pmr_link; /* link */ ushort pmr_type; }; SIMPLEQ_HEAD(pm_rcpts_S, pm_rcpt_S); /* operations on rcpt lists */ #define PM_RCPTS_INIT(pm_rcpt_hd) SIMPLEQ_INIT(pm_rcpt_hd) #define PM_RCPTS_EMPTY(pm_rcpt_hd) SIMPLEQ_EMPTY(pm_rcpt_hd) #define PM_RCPTS_FIRST(pm_rcpt_hd) SIMPLEQ_FIRST(pm_rcpt_hd) #define PM_RCPTS_END(pm_rcpt_hd) SIMPLEQ_END(pm_rcpt_hd) #define PM_RCPTS_NEXT(rcpt) SIMPLEQ_NEXT(rcpt, pmr_link) #define PM_RCPTS_INSERT_TAIL(pm_rcpt_hd, rcpt) SIMPLEQ_INSERT_TAIL(pm_rcpt_hd, rcpt, pmr_link) #define PM_RCPTS_REMOVE_HEAD(pm_rcpt_hd) SIMPLEQ_REMOVE_HEAD(pm_rcpt_hd, pmr_link) /* ** Session context in pmilter ** These are currently organized in a list; a hash table is more efficient ** if there are many concurrent sessions. ENHANCE ** Note: we don't need to keep an entire SMTP session context around, ** this is just for pmilter calls which can take only a few arguments. */ struct pmse_ctx_S { sm_magic_T sm_magic; pmg_ctx_P pmse_pmg_ctx; /* pointer back to main ctx */ pmss_ctx_P pmse_pmss_ctx; /* pointer back to SMTPS ctx */ void *pmse_appl_ctx; /* application ctx */ uint pmse_state; ipv4_T pmse_cltipv4; smtp_id_T pmse_se_id; /* SMTPS session id */ smtp_id_T pmse_ta_id; /* SMTPS transaction id */ sm_str_P pmse_reply_text; /* reply text */ sm_str_P pmse_arg1; sm_str_P pmse_arg2; /* status of current SMTP command (only RCPT right now) */ sm_ret_T pmse_cmd_status; rcpt_idx_T pmse_rcpt_idx; sm_str_P pmse_mac_values[PM_SMST_MAX][PM_MAX_MACROS]; TAILQ_ENTRY(pmse_ctx_S) pmse_link; /* link to next elem */ sm_hdrmodhd_P pmse_hdrmodhd; pm_rcpts_T pmse_rcpts_hd; sm_str_P pmse_mail_new; #if MTA_USE_RSAD uint pmse_nreplies; /* number of replies */ int *pmse_rcodes; sm_str_P *pmse_replies; /* replies */ #endif }; #define PMSE_ST_NONE 0x00000000 #define PMSE_ST_CNNCT 0x00000001 #define PMSE_ST_EHLO 0x00000002 #define PMSE_ST_STTLS 0x00000004 #define PMSE_ST_AUTH 0x00000008 #define PMSE_ST_MAIL 0x00000010 #define PMSE_ST_RCPT 0x00000020 #define PMSE_ST_DATA 0x00000040 #define PMSE_ST_MSG 0x00000080 #define PMSE_ST_DOT 0x00000100 #define PMSE_ST_MSG_RPLC 0x00000200 #define PMSE_ST_MSG_RPLC_STAT 0x00000400 #define PMSE_ST_DONE 0x00000800 #define PMSEL_INIT(pmss_ss_hd) TAILQ_INIT(pmss_ss_hd) #define PMSEL_FIRST(pmss_ss_hd) TAILQ_FIRST(pmss_ss_hd) #define PMSEL_END(pmss_ss_hd) TAILQ_END(pmss_ss_hd) #define PMSEL_EMPTY(pmss_ss_hd) TAILQ_EMPTY(pmss_ss_hd) #define PMSEL_NEXT(pmse_ctx) TAILQ_NEXT(pmse_ctx, pmse_link) #define PMSEL_PRE(pmss_ss_hd, pmse_ctx) TAILQ_INSERT_HEAD(pmss_ss_hd, pmse_ctx, pmse_link) #define PMSEL_APP(pmss_ss_hd, pmse_ctx) TAILQ_INSERT_TAIL(pmss_ss_hd, pmse_ctx, pmse_link) #define PMSEL_REMOVE(pmss_ss_hd, pmse_ctx) TAILQ_REMOVE(pmss_ss_hd, pmse_ctx, pmse_link) /* ** Task context pmilter/SMTP server ** Generally access to this structure is restricted since it is associated ** with exactly one fd and hence one (evthr) task. ** However, see below for details which parts are protected by mutexes. */ struct pmss_ctx_S { sm_magic_T sm_magic; rcbcom_ctx_T pmss_com; pmg_ctx_P pmss_pmg_ctx; /* pointer back to main ctx */ int pmss_id; /* SMTPS id */ void *pmss_appl_ctx; /* application ctx */ uint pmss_status; uint32_t pmss_bit; /* bit for pmg_ssctx */ /* what does the server offer? */ uint32_t pmss_cap; /* SMTP protocol capabilities */ uint32_t pmss_fct; /* callback functions */ uint32_t pmss_feat; /* features */ uint32_t pmss_misc; /* misc. */ /* what does the pmilter want? */ uint32_t pmss_pmcap; uint32_t pmss_pmfct; uint32_t pmss_pmfeat; uint32_t pmss_pmmisc; uint pmss_max_thrs; /* upper limit for threads */ uint pmss_cur_session; /* current # of sessions */ uint32_t pmss_mac_names[PM_SMST_MAX][PM_MAX_MACROS]; /* head of session list */ TAILQ_HEAD(, pmse_ctx_S) pmss_ss_hd; }; /* SMTPS status */ #define PMSS_ST_NONE 0x00 /* not yet OK */ #define PMSS_ST_START 0x01 /* started */ #define PMSS_ST_OK 0x10 /* initialized, running normal */ #define PMSS_ST_SH_DOWN 0x80 /* shutting down */ #define PMSS_ST_STOPPED 0x81 /* stopped: almost terminated */ sm_ret_T sm_pmilt_init0(pmg_ctx_P *_ppmg_ctx); sm_ret_T sm_pmilt_init1(pmg_ctx_P _pmg_ctx); sm_ret_T sm_pmilt_start(pmg_ctx_P _pmg_ctx); sm_ret_T sm_pmilt_stop(pmg_ctx_P _pmg_ctx); sm_ret_T sm_pmss_new(pmg_ctx_P _pmg_ctx, pmss_ctx_P *_ppmss_ctx); sm_ret_T sm_pmss_free(pmss_ctx_P _pmss_ctx); sm_ret_T sm_pmss_close(pmss_ctx_P _pmss_ctx); sm_ret_T sm_pmse_new(pmg_ctx_P _pmg_ctx, pmss_ctx_P _pmss_ctx, pmse_ctx_P *_ppmse_ctx); sm_ret_T sm_pmse_free(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx); sm_ret_T sm_pmse_find(pmss_ctx_P _pmss_ctx, smtp_id_P _se_id, pmse_ctx_P *_ppmse_ctx); sm_ret_T sm_pmilt_smtpsli(sm_evthr_task_P _tsk); sm_ret_T sm_smtps2pmilt(sm_evthr_task_P _tsk); sm_ret_T sm_pmilt_nseid(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx, sm_rcbe_P _rcbe); sm_ret_T sm_pmilt_cseid(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx); sm_ret_T sm_pmilt_helo(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx, sm_rcbe_P _rcbe, bool _ehlo); sm_ret_T sm_pmilt_mail(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx, sm_rcbe_P _rcbe); sm_ret_T sm_pmilt_rcpt(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx, sm_rcbe_P _rcbe); sm_ret_T sm_pmilt_data(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx, sm_rcbe_P _rcbe); sm_ret_T sm_pmilt_msg(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx, uchar *_buf, size_t _len, sm_rcbe_P _rcbe); sm_ret_T sm_pmilt_dot(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx, uchar *_buf, size_t _len, sm_rcbe_P _rcbe); sm_ret_T sm_pmilt_msg_rplc_stat(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx, sm_ret_T _status); sm_ret_T sm_pmilt_abort_ta(pmss_ctx_P _pmss_ctx, pmse_ctx_P _pmse_ctx); sm_ret_T sm_pmilt_setmacro(pmse_ctx_P _pmse_ctx, uint _stage, uint32_t _macro, sm_str_P _value); sm_ret_T sm_pmilt_rdmacros(pmse_ctx_P _pmse_ctx, uint _stage, sm_rcb_P _rcb); sm_ret_T sm_pmilt_rdmacro(pmse_ctx_P _pmse_ctx, uint _stage, sm_rcb_P _rcb); sm_ret_T sm_pmilt_freemacros(pmse_ctx_P _pmse_ctx, uint _where); sm_ret_T sm_pmilt_msg_rplc(void *_ctx); sm_ret_T pm_rcpts_free(pmse_ctx_P _pmse_ctx); #if MTA_USE_RSAD sm_ret_T pm_clrreplies(pmse_ctx_P _pmse_ctx); #else #define pm_clrreplies(pmse_ctx) #endif #define PMSS_ID_NONE (-1) /* no id (yet) */ #define PMILT_R_WAITQ SM_SUCCESS /* default: put back in waitq */ #define PMILT_R_ASYNC 1 /* do nothing, task has been put in waitq */ #if PMILTER_DEBUG #if PMILTER_DEBUG_DEFINE uint pm_debug; #else extern uint pm_debug; #endif # define PM_DEBFP smioerr # define PM_LEV_DPRINTF(lev, x) do { \ if ((lev) < pm_debug) \ sm_io_fprintf x; \ } while (0) # define PM_DPRINTF(x) sm_io_fprintf x #else /* PMILTER_DEBUG */ # define PM_DPRINTF(x) # define PM_LEV_DPRINTF(lev, x) #endif /* PMILTER_DEBUG */ #endif /* ! PMILTER_H */