Fix smtp proto

We enable readcb for srvdst to relay the 220 smtp greeting from the
server to the client, otherwise the conn stalls.
Related with issue #18 too.
This commit is contained in:
Soner Tari 2020-04-13 15:35:09 +03:00
parent 1a0d46587b
commit 1445a5cdf8
6 changed files with 86 additions and 5 deletions

View File

@ -128,7 +128,7 @@ protoautossl_conn_connect(pxy_conn_ctx_t *ctx)
/* initiate connection */
if (bufferevent_socket_connect(ctx->srvdst.bev, (struct sockaddr *)&ctx->dstaddr, ctx->dstaddrlen) == -1) {
log_err_level_printf(LOG_CRIT, "bufferevent_socket_connect for srvdst failed\n");
log_err_level_printf(LOG_CRIT, "protoautossl_conn_connect: bufferevent_socket_connect for srvdst failed\n");
log_fine("bufferevent_socket_connect for srvdst failed");
// @attention Do not try to term/close conns or do anything else with conn ctx on the thrmgr thread after setting event callbacks and/or socket connect. Just return 0.
}

View File

@ -26,6 +26,7 @@
*/
#include "protosmtp.h"
#include "prototcp.h"
#include "protossl.h"
#include <string.h>
@ -91,11 +92,86 @@ protosmtp_validate(pxy_conn_ctx_t *ctx, char *packet
return 0;
}
static int NONNULL(1) WUNRES
protosmtp_conn_connect(pxy_conn_ctx_t *ctx)
{
log_finest("ENTER");
/* create server-side socket and eventbuffer */
if (ctx->protoctx->proto == PROTO_SMTP) {
if (prototcp_setup_srvdst(ctx) == -1) {
return -1;
}
} else {
if (protossl_setup_srvdst(ctx) == -1) {
return -1;
}
}
// Conn setup is successful, so add the conn to the conn list of its thread now
pxy_thrmgr_add_conn(ctx);
// We enable readcb for srvdst to relay the 220 smtp greeting from the server to the client, otherwise the conn stalls
bufferevent_setcb(ctx->srvdst.bev, pxy_bev_readcb, pxy_bev_writecb, pxy_bev_eventcb, ctx);
bufferevent_enable(ctx->srvdst.bev, EV_READ|EV_WRITE);
/* initiate connection */
if (bufferevent_socket_connect(ctx->srvdst.bev, (struct sockaddr *)&ctx->dstaddr, ctx->dstaddrlen) == -1) {
log_err_level_printf(LOG_CRIT, "protosmtp_conn_connect: bufferevent_socket_connect for srvdst failed\n");
log_fine("bufferevent_socket_connect for srvdst failed");
// @attention Do not try to term/close conns or do anything else with conn ctx on the thrmgr thread after setting event callbacks and/or socket connect.
}
return 0;
}
static void NONNULL(1)
protosmtp_bev_readcb_srvdst(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));
// Make sure src.bev exists
if (ctx->src.bev) {
if (prototcp_try_send_userauth_msg(ctx->src.bev, ctx)) {
return;
}
}
if (ctx->src.closed) {
pxy_discard_inbuf(bev);
return;
}
struct evbuffer *inbuf = bufferevent_get_input(bev);
struct evbuffer *outbuf = bufferevent_get_output(ctx->src.bev);
evbuffer_add_buffer(outbuf, inbuf);
pxy_try_set_watermark(bev, ctx, ctx->src.bev);
}
static void NONNULL(1)
protosmtp_bev_readcb(struct bufferevent *bev, void *arg)
{
pxy_conn_ctx_t *ctx = arg;
if (bev == ctx->src.bev) {
prototcp_bev_readcb_src(bev, ctx);
} else if (bev == ctx->dst.bev) {
prototcp_bev_readcb_dst(bev, ctx);
} else if (bev == ctx->srvdst.bev) {
protosmtp_bev_readcb_srvdst(bev, ctx);
} else {
log_err_printf("protosmtp_bev_readcb: UNKWN conn end\n");
}
}
protocol_t
protosmtp_setup(pxy_conn_ctx_t *ctx)
{
ctx->protoctx->proto = PROTO_SMTP;
ctx->protoctx->connectcb = protosmtp_conn_connect;
ctx->protoctx->bev_readcb = protosmtp_bev_readcb;
ctx->protoctx->validatecb = protosmtp_validate;
ctx->protoctx->arg = malloc(sizeof(protosmtp_ctx_t));
@ -112,9 +188,10 @@ protosmtps_setup(pxy_conn_ctx_t *ctx)
{
ctx->protoctx->proto = PROTO_SMTPS;
ctx->protoctx->connectcb = protossl_conn_connect;
ctx->protoctx->connectcb = protosmtp_conn_connect;
ctx->protoctx->fd_readcb = protossl_fd_readcb;
ctx->protoctx->bev_readcb = protosmtp_bev_readcb;
ctx->protoctx->bev_eventcb = protossl_bev_eventcb;
ctx->protoctx->proto_free = protossl_free;

View File

@ -1256,7 +1256,7 @@ protossl_setup_srvdst_ssl(pxy_conn_ctx_t *ctx)
return 0;
}
static int NONNULL(1)
int
protossl_setup_srvdst(pxy_conn_ctx_t *ctx)
{
if (protossl_setup_srvdst_ssl(ctx) == -1) {

View File

@ -52,6 +52,7 @@ int protossl_setup_dst_ssl_child(pxy_conn_child_ctx_t *) NONNULL(1);
int protossl_setup_dst_new_bev_ssl_connecting_child(pxy_conn_child_ctx_t *) NONNULL(1);
int protossl_setup_dst_child(pxy_conn_child_ctx_t *) NONNULL(1);
int protossl_setup_srvdst(pxy_conn_ctx_t *ctx) NONNULL(1);
int protossl_setup_srvdst_ssl(pxy_conn_ctx_t *) NONNULL(1);
int protossl_setup_srvdst_new_bev_ssl_connecting(pxy_conn_ctx_t *) NONNULL(1);

View File

@ -267,7 +267,7 @@ prototcp_try_validate_proto(struct bufferevent *bev, pxy_conn_ctx_t *ctx, struct
return 0;
}
static void NONNULL(1,2)
void
prototcp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));
@ -313,7 +313,7 @@ prototcp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
pxy_try_set_watermark(bev, ctx, ctx->dst.bev);
}
static void NONNULL(1)
void
prototcp_bev_readcb_dst(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));

View File

@ -38,6 +38,9 @@ int prototcp_try_send_userauth_msg(struct bufferevent *, pxy_conn_ctx_t *) NONNU
int prototcp_try_close_unauth_conn(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1,2);
int prototcp_try_close_protoerror_conn(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1,2);
void prototcp_bev_readcb_src(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1,2);
void prototcp_bev_readcb_dst(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1);
void prototcp_bev_writecb_dst(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1);
void prototcp_bev_writecb_srvdst(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1);