/*
* 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 */
syntax highlighted by Code2HTML, v. 0.9.1