diff --git a/src/protoautossl.c b/src/protoautossl.c index 5774703..97a4c30 100644 --- a/src/protoautossl.c +++ b/src/protoautossl.c @@ -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. } diff --git a/src/protosmtp.c b/src/protosmtp.c index ca5da8d..69151a6 100644 --- a/src/protosmtp.c +++ b/src/protosmtp.c @@ -26,6 +26,7 @@ */ #include "protosmtp.h" +#include "prototcp.h" #include "protossl.h" #include @@ -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; diff --git a/src/protossl.c b/src/protossl.c index 3f350f7..4dca340 100644 --- a/src/protossl.c +++ b/src/protossl.c @@ -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) { diff --git a/src/protossl.h b/src/protossl.h index 8e0f3e6..0026132 100644 --- a/src/protossl.h +++ b/src/protossl.h @@ -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); diff --git a/src/prototcp.c b/src/prototcp.c index f7c473b..955daa8 100644 --- a/src/prototcp.c +++ b/src/prototcp.c @@ -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))); diff --git a/src/prototcp.h b/src/prototcp.h index 7e062da..b23bc95 100644 --- a/src/prototcp.h +++ b/src/prototcp.h @@ -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);