/* * Copyright (c) 2004-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. */ /* ** SMTPS - policy milter communication module */ #include "sm/generic.h" SM_RCSID("@(#)$Id: s2m.c,v 1.32 2007/10/23 03:57:40 ca Exp $") #include "sm/assert.h" #include "sm/error.h" #include "sm/memops.h" #include "sm/reccom.h" #include "sm/smar.h" #include "statethreads/st.h" #include "sm/str.h" #include "sm/rcbst.h" #include "sm/stthreads.h" #include "smtps-str.h" #include "s2q.h" #include "smtps.h" #include "s2m.h" #if MTA_USE_PMILTER /* ** SM_NEW_MACV -- create string for macro ** ** Parameters: ** ss_sess -- session context ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_new_macv(ss_sess_P ss_sess) { SM_REQUIRE(ss_sess != NULL); if (NULL == ss_sess->ssse_macv) ss_sess->ssse_macv = sm_str_new(NULL, 32, 256); if (NULL != ss_sess->ssse_macv) { sm_str_clr(ss_sess->ssse_macv); return SM_SUCCESS; } return sm_err_temp(ENOMEM); } /* ** SM_SS_GETMACRO -- get value of macro ** ** Parameters: ** ss_sess -- session context ** stage -- stage of the SMTP dialogue ** macm -- name of macro ** pmacv -- (pointer to) value of macro (output) ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_ss_getmacro(ss_sess_P ss_sess, uint stage, uint32_t macm, sm_str_P *pmacv) { sm_ret_T ret; ss_ctx_P ss_ctx; ss_ta_P ss_ta; SM_REQUIRE(pmacv != NULL); SM_IS_SS_SESS(ss_sess); ss_ctx = ss_sess->ssse_sctx; SM_IS_SS_CTX(ss_ctx); *pmacv = NULL; ret = SM_SUCCESS; ss_ta = ss_sess->ssse_ta; switch (macm) { case PMM_SRVHOSTNAME: *pmacv = ss_ctx->ssc_hostname; break; case PMM_SEID: /* could be "resolved" in libpmilter */ break; case PMM_CLIENT_RESOLVE: if (ss_sess != NULL) { ret = sm_new_macv(ss_sess); if (sm_is_err(ret)) return ret; sm_str_scat(ss_sess->ssse_macv, sm_rslv2txt(ss_sess->ssse_cltrslv)); *pmacv = ss_sess->ssse_macv; } break; #if MTA_USE_TLS case PMM_TLS_VERSION: if (ss_sess != NULL && ss_sess->ssse_tlsi != NULL) *pmacv = ss_sess->ssse_tlsi->tlsi_version; break; case PMM_TLS_CIPHER_SUITE: if (ss_sess != NULL) *pmacv = ss_sess->ssse_tlsi->tlsi_cipher; break; case PMM_TLS_CIPHER_BITS: if (ss_sess != NULL && ss_sess->ssse_tlsi != NULL) { ret = sm_new_macv(ss_sess); if (sm_is_err(ret)) return ret; sm_strprintf(ss_sess->ssse_macv, "%d", ss_sess->ssse_tlsi->tlsi_cipher_bits); *pmacv = ss_sess->ssse_macv; } break; case PMM_TLS_ALG_BITS: if (ss_sess != NULL && ss_sess->ssse_tlsi != NULL) { ret = sm_new_macv(ss_sess); if (sm_is_err(ret)) return ret; sm_strprintf(ss_sess->ssse_macv, "%d", ss_sess->ssse_tlsi->tlsi_algs_bits); *pmacv = ss_sess->ssse_macv; } break; case PMM_TLS_VRFY: if (ss_sess != NULL && ss_sess->ssse_tlsi != NULL) { ret = sm_new_macv(ss_sess); if (sm_is_err(ret)) return ret; sm_str_scat(ss_sess->ssse_macv, tls_vrfy2txt(ss_sess->ssse_tlsi->tlsi_vrfy)); *pmacv = ss_sess->ssse_macv; } break; case PMM_TLS_CERT_SUBJECT: if (ss_sess != NULL && ss_sess->ssse_tlsi != NULL) *pmacv = ss_sess->ssse_tlsi->tlsi_cert_subject; break; case PMM_TLS_CERT_ISSUER: if (ss_sess != NULL && ss_sess->ssse_tlsi != NULL) *pmacv = ss_sess->ssse_tlsi->tlsi_cert_issuer; break; case PMM_TLS_CN_SUBJECT: if (ss_sess != NULL && ss_sess->ssse_tlsi != NULL) *pmacv = ss_sess->ssse_tlsi->tlsi_cn_subject; break; case PMM_TLS_CN_ISSUER: if (ss_sess != NULL && ss_sess->ssse_tlsi != NULL) *pmacv = ss_sess->ssse_tlsi->tlsi_cn_issuer; break; #endif /* MTA_USE_TLS */ #if MTA_USE_SASL case PMM_AUTH_TYPE: if (ss_sess != NULL) *pmacv = ss_sess->ssse_sasl_mech; break; case PMM_AUTH_AUTHEN: if (ss_sess != NULL) *pmacv = ss_sess->ssse_sasl_authen; break; case PMM_AUTH_AUTHOR: if (ss_sess != NULL) *pmacv = ss_sess->ssse_sasl_author; break; #endif /* MTA_USE_SASL */ case PMM_MAIL_TAID: /* could be "resolved" in libpmilter? */ break; case PMM_DOT_HOPS: if (ss_ta != NULL) { ret = sm_new_macv(ss_sess); if (sm_is_err(ret)) return ret; sm_strprintf(ss_sess->ssse_macv, "%u", ss_ta->ssta_hops); *pmacv = ss_sess->ssse_macv; } break; case PMM_DOT_MSGID: if (ss_ta != NULL) *pmacv = ss_ta->ssta_msgid; break; default: /* ignore errors for now */ /* ret = sm_err_perm(SM_E_NOTFOUND); */ break; } return ret; } /* ** SM_S2M_MACROS -- send macros to PMILTER ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** stage -- which stage of the SMTP dialogue? ** rcb -- RCB to fill in ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_s2m_macros(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, uint stage, sm_rcb_P rcb) { sm_ret_T ret; uint j; uint32_t macm; sm_str_P macv; ss_ctx_P ss_ctx; ss_ctx = ss_sess->ssse_sctx; SM_ASSERT(stage < PM_MAX_MACROS); SSQ_DPRINTF((smioerr, "sev=DBG, func=sm_s2m_macros, stage=%u, mac=%#X\n", stage, ss_ctx->ssc_mac_names[stage][0])); if (ss_ctx->ssc_mac_names[stage][0] == PMM_END) return SM_SUCCESS; ret = SM_SUCCESS; for (j = 0; !sm_is_err(ret) && j < PM_MAX_MACROS && (macm = ss_ctx->ssc_mac_names[stage][j]) != PMM_END; j++) { ret = sm_ss_getmacro(ss_sess, stage, macm, &macv); if (sm_is_err(ret)) return ret; if (macv != NULL) { SSQ_DPRINTF((smioerr, "sev=DBG, func=sm_s2m_macros, macm=%#X, macv=%S\n", macm, macv)); ret = sm_rcb_putv(rcb, 0, SM_RCBV_INT, RT_S2M_MACM, macm, SM_RCBV_STR, RT_S2M_MACV, macv, SM_RCBV_END); if (sm_is_err(ret)) return ret; } } return ret; } /* ** SM_S2M_CLT -- send client address to PMILTER ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** sid -- session id ** cltipv4 -- client IPv4 address ** port -- port of server ** ** Returns: ** usual sm_error code */ sm_ret_T sm_s2m_clt(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, sessta_id_P sid, uint32_t cltipv4, ushort port) { sm_ret_T ret; sm_rcb_P rcb; SM_REQUIRE(s2m_ctx != NULL); SM_IS_SS_SESS(ss_sess); S2Q_CHK_CONN_R(ss_sess, s2m_ctx); rcb = ss_sess->ssse_rcb; ret = sm_rcb_putrec(rcb, RCB_PUTR_FIRST|RCB_PUTR_OPEN, 0, -1, SM_RCBV_INT, RT_PROT_VER, PROT_VER_RT, SM_RCBV_INT, RT_S2M_ID, s2m_ctx->s2q_ss_ctx->ssc_id, SM_RCBV_BUF, RT_S2M_NSEID, sid, SMTP_STID_SIZE, SM_RCBV_INT, RT_S2M_IPV4, cltipv4, SM_RCBV_INT, RT_S2M_PORT, port, SM_RCBV_CSTR, RT_S2M_HOST, ss_sess->ssse_cltname, SM_RCBV_END); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_clt, sess=%p, sm_rcb_putrec=%m\n", ss_sess, ret)); goto error; } ret = sm_s2m_macros(ss_sess, s2m_ctx, PM_SMST_CONNECT, rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_clt, sess=%p, sm_s2m_macros=%m\n", ss_sess, ret)); goto error; } ret = sm_rcb_close_enc(rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_clt, sess=%p, sm_rcb_close_enc=%m\n", ss_sess, ret)); goto error; } ret = ss_send_rq(ss_sess, sid, s2m_ctx, rcb, true); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_clt, sess=%p, ss_send_rq=%m\n", ss_sess, ret)); goto error; } return SM_SUCCESS; error: return ret; } /* ** SM_S2M_HELO -- send HELO string to PMILTER ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** sid -- session id ** ehlo -- was EHLO used? ** ** Returns: ** usual sm_error code */ sm_ret_T sm_s2m_helo(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, sessta_id_P sid, bool ehlo) { sm_ret_T ret; sm_rcb_P rcb; SM_REQUIRE(s2m_ctx != NULL); SM_IS_SS_SESS(ss_sess); S2Q_CHK_CONN_R(ss_sess, s2m_ctx); rcb = ss_sess->ssse_rcb; ret = sm_rcb_putrec(rcb, RCB_PUTR_FIRST|RCB_PUTR_OPEN, 0, -1, SM_RCBV_INT, RT_PROT_VER, PROT_VER_RT, SM_RCBV_INT, RT_S2M_ID, s2m_ctx->s2q_ss_ctx->ssc_id, SM_RCBV_BUF, RT_S2M_SEID, sid, SMTP_STID_SIZE, SM_RCBV_STR, ehlo ? RT_S2M_EHLO : RT_S2M_HELO, ss_sess->ssse_helo, SM_RCBV_END); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_helo, sess=%p, sm_rcb_putrec=%m\n", ss_sess, ret)); goto error; } ret = sm_s2m_macros(ss_sess, s2m_ctx, PM_SMST_EHLO, rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_helo, sess=%p, sm_s2m_macros=%m\n", ss_sess, ret)); goto error; } ret = sm_rcb_close_enc(rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_helo, sess=%p, sm_rcb_close_enc=%m\n", ss_sess, ret)); goto error; } ret = ss_send_rq(ss_sess, sid, s2m_ctx, rcb, true); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_help, sess=%p, ss_send_rq=%m\n", ss_sess, ret)); goto error; } return SM_SUCCESS; error: return ret; } /* ** SM_S2M_MAIL -- send mail address to PMILTER ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** sid -- session id ** tid -- transaction id ** mail -- mail from address ** argoffset -- offset of arguments in sess_rd (0: no args) ** ** Returns: ** usual sm_error code */ sm_ret_T sm_s2m_mail(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, sessta_id_P sid, sessta_id_P tid, sm_str_P mail, uint argoffset) { sm_ret_T ret; sm_rcb_P rcb; SM_REQUIRE(s2m_ctx != NULL); SM_IS_SS_SESS(ss_sess); S2Q_CHK_CONN_R(ss_sess, s2m_ctx); if (argoffset > 0) SM_REQUIRE(sm_str_getlen(ss_sess->ssse_rd) > argoffset); rcb = ss_sess->ssse_rcb; ret = sm_rcb_putrec(rcb, RCB_PUTR_FIRST|RCB_PUTR_OPEN, 0, -1, SM_RCBV_INT, RT_PROT_VER, PROT_VER_RT, SM_RCBV_INT, RT_S2M_ID, s2m_ctx->s2q_ss_ctx->ssc_id, SM_RCBV_BUF, RT_S2M_SEID, sid, SMTP_STID_SIZE, SM_RCBV_BUF, RT_S2M_NTAID, tid, SMTP_STID_SIZE, SM_RCBV_STR, RT_S2M_MAIL, mail, SM_RCBV_BUF, (argoffset > 0) ? RT_S2M_ARG : RT_NOSEND, sm_str_getdata(ss_sess->ssse_rd) + argoffset, sm_str_getlen(ss_sess->ssse_rd) - argoffset, SM_RCBV_END); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_mail, sess=%p, sm_rcb_putrec=%m\n", ss_sess, ret)); goto error; } ret = sm_s2m_macros(ss_sess, s2m_ctx, PM_SMST_MAIL, rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_mail, sess=%p, sm_s2m_macros=%m\n", ss_sess, ret)); goto error; } ret = sm_rcb_close_enc(rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_mail, sess=%p, sm_rcb_close_enc=%m\n", ss_sess, ret)); goto error; } ret = ss_send_rq(ss_sess, sid, s2m_ctx, rcb, true); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_mail, sess=%p, ss_send_rq=%m\n", ss_sess, ret)); goto error; } return SM_SUCCESS; error: return ret; } /* ** SM_S2M_RCPT -- send recipient to PMILTER ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** sid -- session id ** rcpt_idx -- rcpt idx ** rcpt -- rcpt to address ** cur_status -- current status while dealing with RCPT ** ** Returns: ** usual sm_error code */ sm_ret_T sm_s2m_rcpt(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, sessta_id_P sid, int rcpt_idx, sm_str_P rcpt, sm_ret_T cur_status) { sm_ret_T ret; sm_rcb_P rcb; SM_REQUIRE(s2m_ctx != NULL); SM_IS_SS_SESS(ss_sess); S2Q_CHK_CONN_R(ss_sess, s2m_ctx); rcb = ss_sess->ssse_rcb; ret = sm_rcb_putrec(rcb, RCB_PUTR_FIRST|RCB_PUTR_OPEN, 0, -1, SM_RCBV_INT, RT_PROT_VER, PROT_VER_RT, SM_RCBV_INT, RT_S2M_ID, (uint32_t) s2m_ctx->s2q_ss_ctx->ssc_id, SM_RCBV_BUF, RT_S2M_SEID, sid, SMTP_STID_SIZE, SM_RCBV_INT, RT_S2M_RCPT_IDX, (uint32_t) rcpt_idx, SM_RCBV_STR, RT_S2M_RCPT, rcpt, SM_RCBV_INT, RT_S2M_RCPT_ST, (uint32_t) cur_status, SM_RCBV_END); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_rcpt, sess=%p, sm_rcb_putrec=%m\n", ss_sess, ret)); goto error; } ret = sm_s2m_macros(ss_sess, s2m_ctx, PM_SMST_RCPT, rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_rcpt, sess=%p, sm_s2m_macros=%m\n", ss_sess, ret)); goto error; } ret = sm_rcb_close_enc(rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_rcpt, sess=%p, sm_rcb_close_enc=%m\n", ss_sess, ret)); goto error; } ret = ss_send_rq(ss_sess, sid, s2m_ctx, rcb, true); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_rcpt, sess=%p, ss_send_rq=%m\n", ss_sess, ret)); goto error; } return SM_SUCCESS; error: return ret; } /* ** SM_S2M_DATA -- inform PMILTER about DATA command ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** sid -- session id ** ** Returns: ** usual sm_error code */ sm_ret_T sm_s2m_data(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, sessta_id_P sid) { sm_ret_T ret; sm_rcb_P rcb; SM_REQUIRE(s2m_ctx != NULL); SM_IS_SS_SESS(ss_sess); S2Q_CHK_CONN_R(ss_sess, s2m_ctx); rcb = ss_sess->ssse_rcb; ret = sm_rcb_putrec(rcb, RCB_PUTR_FIRST|RCB_PUTR_OPEN, 0, -1, SM_RCBV_INT, RT_PROT_VER, PROT_VER_RT, SM_RCBV_INT, RT_S2M_ID, (uint32_t) s2m_ctx->s2q_ss_ctx->ssc_id, SM_RCBV_BUF, RT_S2M_SEID, sid, SMTP_STID_SIZE, SM_RCBV_INT, RT_S2M_DATA, 0, SM_RCBV_END); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_data, sess=%p, sm_rcb_putrec=%m\n", ss_sess, ret)); goto error; } ret = sm_s2m_macros(ss_sess, s2m_ctx, PM_SMST_DATA, rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_data, sess=%p, sm_s2m_macros=%m\n", ss_sess, ret)); goto error; } ret = sm_rcb_close_enc(rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_data, sess=%p, sm_rcb_close_enc=%m\n", ss_sess, ret)); goto error; } ret = ss_send_rq(ss_sess, sid, s2m_ctx, rcb, true); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_data, sess=%p, ss_send_rq=%m\n", ss_sess, ret)); goto error; } return SM_SUCCESS; error: return ret; } /* ** SM_S2M_MSG -- send message chunk to PMILTER ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** sid -- session id ** buf -- message chunk ** len -- length of message chunk ** flags -- some flags ** ** Returns: ** usual sm_error code */ sm_ret_T sm_s2m_msg(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, sessta_id_P sid, uchar *buf, size_t len, uint flags) { sm_ret_T ret; sm_rcb_P rcb; if (len == 0) return SM_SUCCESS; SM_REQUIRE(s2m_ctx != NULL); SM_IS_SS_SESS(ss_sess); S2Q_CHK_CONN_R(ss_sess, s2m_ctx); SM_REQUIRE(buf != NULL); rcb = ss_sess->ssse_rcb; ret = sm_rcb_putrec(rcb, SM_IS_FLAG(flags, SM_S2M_MSG_LAST) ? (RCB_PUTR_FIRST|RCB_PUTR_OPEN) : RCB_PUTR_DFLT, 0, -1, SM_RCBV_INT, RT_PROT_VER, PROT_VER_RT, SM_RCBV_INT, RT_S2M_ID, (uint32_t) s2m_ctx->s2q_ss_ctx->ssc_id, SM_RCBV_BUF, RT_S2M_SEID, sid, SMTP_STID_SIZE, SM_RCBV_BUF, SM_IS_FLAG(flags, SM_S2M_MSG_LAST) ? RT_S2M_DOT : RT_S2M_MSG, buf, len, SM_RCBV_END); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_msg, sess=%p, sm_rcb_putrec=%m\n", ss_sess, ret)); goto error; } if (SM_IS_FLAG(flags, SM_S2M_MSG_LAST)) { ret = sm_s2m_macros(ss_sess, s2m_ctx, PM_SMST_DOT, rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_msg, sess=%p, sm_s2m_macros=%m\n", ss_sess, ret)); goto error; } ret = sm_rcb_close_enc(rcb); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_msg, sess=%p, sm_rcb_close_enc=%m\n", ss_sess, ret)); goto error; } } ret = ss_send_rq(ss_sess, sid, s2m_ctx, rcb, SM_IS_FLAG(flags, SM_S2M_MSG_REPLY)); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_msg, sess=%p, ss_send_rq=%m\n", ss_sess, ret)); goto error; } return SM_SUCCESS; error: return ret; } /* ** SM_S2M_MSG_RPLC_STAT -- tell PMILTER about status of message replacement ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** sid -- session id ** cur_status -- status of message replacement ** ** Returns: ** usual sm_error code */ sm_ret_T sm_s2m_msg_rplc_stat(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, sessta_id_P sid, sm_ret_T cur_status) { sm_ret_T ret; sm_rcb_P rcb; SM_REQUIRE(s2m_ctx != NULL); SM_IS_SS_SESS(ss_sess); S2Q_CHK_CONN_R(ss_sess, s2m_ctx); rcb = ss_sess->ssse_rcb; ret = sm_rcb_putrec(rcb, RCB_PUTR_DFLT, 0, -1, SM_RCBV_INT, RT_PROT_VER, PROT_VER_RT, SM_RCBV_INT, RT_S2M_ID, (uint32_t) s2m_ctx->s2q_ss_ctx->ssc_id, SM_RCBV_BUF, RT_S2M_SEID, sid, SMTP_STID_SIZE, SM_RCBV_INT, RT_S2M_MSG_RPLC_STAT, cur_status, SM_RCBV_END); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_msg_rplc_stat, sess=%p, sm_rcb_putrec=%m\n", ss_sess, ret)); goto error; } ret = ss_send_rq(ss_sess, sid, s2m_ctx, rcb, false); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_msg_rplc_stat, sess=%p, ss_send_rq=%m\n", ss_sess, ret)); goto error; } return SM_SUCCESS; error: return ret; } /* ** SM_S2M_ABORT -- tell PMILTER to abort current transaction ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** sid -- session id ** ** Returns: ** usual sm_error code */ sm_ret_T sm_s2m_abort(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, sessta_id_P sid) { sm_ret_T ret; sm_rcb_P rcb; SM_REQUIRE(s2m_ctx != NULL); SM_IS_SS_SESS(ss_sess); S2Q_CHK_CONN_R(ss_sess, s2m_ctx); rcb = ss_sess->ssse_rcb; ret = sm_rcb_putrec(rcb, RCB_PUTR_DFLT, 0, -1, SM_RCBV_INT, RT_PROT_VER, PROT_VER_RT, SM_RCBV_INT, RT_S2M_ID, (uint32_t) s2m_ctx->s2q_ss_ctx->ssc_id, SM_RCBV_BUF, RT_S2M_SEID, sid, SMTP_STID_SIZE, SM_RCBV_INT, RT_S2M_ABORT_TA, 0, SM_RCBV_END); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_abort, sess=%p, sm_rcb_putrec=%m\n", ss_sess, ret)); goto error; } ret = ss_send_rq(ss_sess, sid, s2m_ctx, rcb, false); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_abort, sess=%p, ss_send_rq=%m\n", ss_sess, ret)); goto error; } return SM_SUCCESS; error: return ret; } /* ** SM_S2M_CSEID -- inform PMILTER that session is closed ** ** Parameters: ** ss_sess -- session context ** s2m_ctx -- S2M context ** sid -- session id ** ** Returns: ** usual sm_error code */ sm_ret_T sm_s2m_cseid(ss_sess_P ss_sess, s2q_ctx_P s2m_ctx, sessta_id_P sid) { sm_ret_T ret; sm_rcb_P rcb; SM_REQUIRE(s2m_ctx != NULL); SM_IS_SS_SESS(ss_sess); S2Q_CHK_CONN_R(ss_sess, s2m_ctx); rcb = ss_sess->ssse_rcb; ret = sm_rcb_putrec(rcb, RCB_PUTR_DFLT, 0, -1, SM_RCBV_INT, RT_PROT_VER, PROT_VER_RT, SM_RCBV_INT, RT_S2M_ID, s2m_ctx->s2q_ss_ctx->ssc_id, SM_RCBV_BUF, RT_S2M_CSEID, sid, SMTP_STID_SIZE, SM_RCBV_END); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_cseid, sess=%p, sm_rcb_putrec=%m\n", ss_sess, ret)); goto error; } ret = ss_send_rq(ss_sess, sid, s2m_ctx, rcb, false); if (sm_is_err(ret)) { SSQ_DPRINTF((smioerr, "sev=ERROR, func=sm_s2m_cseid, sess=%p, ss_send_rq=%m\n", ss_sess, ret)); goto error; } return SM_SUCCESS; error: return ret; } #endif /* MTA_USE_PMILTER */