Discard underlying bufs while closing, sending errors, and denying ocsp

Also refactor for code reuse.
Since we are closing in all such cases, performance is not important.
pull/48/head
Soner Tari 2 years ago
parent 7143102efa
commit 2e8e677bac

@ -214,7 +214,7 @@ protoautossl_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
}
if (ctx->dst.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}
@ -245,7 +245,7 @@ protoautossl_bev_readcb_srvdst(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
// as we do with the smtp protocol, @see protosmtp_bev_readcb_srvdst()
if (ctx->src.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}

@ -229,7 +229,6 @@ protohttp_ocsp_is_valid_uri(const char *uri, pxy_conn_ctx_t *ctx)
static void NONNULL(1,2)
protohttp_ocsp_deny(pxy_conn_ctx_t *ctx, protohttp_ctx_t *http_ctx)
{
struct evbuffer *inbuf, *outbuf;
static const char ocspresp[] =
"HTTP/1.0 200 OK\r\n"
"Content-Type: application/ocsp-response\r\n"
@ -253,25 +252,17 @@ protohttp_ocsp_deny(pxy_conn_ctx_t *ctx, protohttp_ctx_t *http_ctx)
return;
deny:
inbuf = bufferevent_get_input(ctx->src.bev);
outbuf = bufferevent_get_output(ctx->src.bev);
if (evbuffer_get_length(inbuf) > 0) {
evbuffer_drain(inbuf, evbuffer_get_length(inbuf));
}
pxy_try_discard_inbuf(ctx->src.bev);
// Do not send anything to the child conns
struct evbuffer *dst_outbuf = bufferevent_get_output(ctx->dst.bev);
if (evbuffer_get_length(dst_outbuf) > 0) {
evbuffer_drain(dst_outbuf, evbuffer_get_length(dst_outbuf));
}
pxy_try_discard_outbuf(ctx->dst.bev);
// Do not send duplicate OCSP denied responses
if (http_ctx->ocsp_denied)
return;
log_finer("Sending OCSP denied response");
evbuffer_add_printf(outbuf, ocspresp);
evbuffer_add_printf(bufferevent_get_output(ctx->src.bev), ocspresp);
http_ctx->ocsp_denied = 1;
}
@ -801,7 +792,7 @@ protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));
if (ctx->dst.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}
@ -813,7 +804,7 @@ protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
if (ctx->conn_opts->user_auth && !ctx->user) {
log_finest("Redirecting conn");
char *url = protohttp_get_url(inbuf, ctx);
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
if (url) {
evbuffer_add_printf(bufferevent_get_output(bev), redirect_url, ctx->conn_opts->user_auth_url, url);
free(url);
@ -852,8 +843,8 @@ protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
if (protohttp_validate(ctx) == -1) {
evbuffer_add(bufferevent_get_output(bev), proto_error, strlen(proto_error));
ctx->sent_protoerror_msg = 1;
pxy_discard_inbuf(bev);
evbuffer_drain(outbuf, evbuffer_get_length(outbuf));
pxy_try_discard_inbuf(bev);
pxy_try_discard_outbuf(ctx->dst.bev);
return;
}
}
@ -983,7 +974,7 @@ protohttp_bev_readcb_dst(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));
if (ctx->src.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}
@ -1016,7 +1007,7 @@ protohttp_bev_readcb_src_child(struct bufferevent *bev, pxy_conn_child_ctx_t *ct
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));
if (ctx->dst.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}
@ -1043,7 +1034,7 @@ protohttp_bev_readcb_dst_child(struct bufferevent *bev, pxy_conn_child_ctx_t *ct
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));
if (ctx->src.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}

@ -139,7 +139,7 @@ protopassthrough_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
// Passthrough packets are transferred between src and srvdst
if (ctx->srvdst.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}
@ -164,7 +164,7 @@ protopassthrough_bev_readcb_srvdst(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
// Passthrough packets are transferred between src and srvdst
if (ctx->src.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}

@ -132,10 +132,13 @@ protosmtp_try_validate_response(struct bufferevent *bev, pxy_conn_ctx_t *ctx, st
// Send message to the client: outbuf of src
evbuffer_add(outbuf, PROTOERROR_MSG, PROTOERROR_MSG_LEN);
ctx->sent_protoerror_msg = 1;
// Discard packets from the client: inbuf of src
pxy_discard_inbuf(ctx->src.bev);
pxy_try_discard_inbuf(ctx->src.bev);
// Discard packets to the server: outbuf of srvdst
evbuffer_drain(bufferevent_get_output(bev), evbuffer_get_length(bufferevent_get_output(bev)));
pxy_try_discard_outbuf(bev);
free(packet);
return -1;
}
@ -204,7 +207,7 @@ protosmtp_bev_readcb_srvdst(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
}
if (ctx->src.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}

@ -284,7 +284,7 @@ prototcp_try_send_userauth_msg(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
if (ctx->conn_opts->user_auth && !ctx->user) {
log_finest("Sending userauth message");
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
evbuffer_add_printf(bufferevent_get_output(bev), USERAUTH_MSG, ctx->conn_opts->user_auth_url);
ctx->sent_userauth_msg = 1;
return 1;
@ -294,7 +294,7 @@ prototcp_try_send_userauth_msg(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
#endif /* !WITHOUT_USERAUTH */
static int NONNULL(1,2,3,4)
prototcp_try_validate_proto(struct bufferevent *bev, pxy_conn_ctx_t *ctx, struct evbuffer *inbuf, struct evbuffer *outbuf)
prototcp_try_validate_proto(struct bufferevent *bev, pxy_conn_ctx_t *ctx, struct evbuffer *inbuf, struct bufferevent *other)
{
if (ctx->conn_opts->validate_proto && ctx->protoctx->validatecb && !ctx->protoctx->is_valid) {
size_t packet_size = evbuffer_get_length(inbuf);
@ -310,10 +310,13 @@ prototcp_try_validate_proto(struct bufferevent *bev, pxy_conn_ctx_t *ctx, struct
// Send message to the client: outbuf of src
evbuffer_add(bufferevent_get_output(bev), PROTOERROR_MSG, PROTOERROR_MSG_LEN);
ctx->sent_protoerror_msg = 1;
// Discard packets from the client: inbuf of src
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
// Discard packets to the server: outbuf of dst
evbuffer_drain(outbuf, evbuffer_get_length(outbuf));
pxy_try_discard_outbuf(other);
free(packet);
return 1;
}
@ -328,7 +331,7 @@ 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)));
if (ctx->dst.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}
@ -343,12 +346,11 @@ prototcp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
}
struct evbuffer *inbuf = bufferevent_get_input(bev);
struct evbuffer *outbuf = bufferevent_get_output(ctx->dst.bev);
if (prototcp_try_validate_proto(bev, ctx, inbuf, outbuf) != 0) {
if (prototcp_try_validate_proto(bev, ctx, inbuf, ctx->dst.bev) != 0) {
return;
}
struct evbuffer *outbuf = bufferevent_get_output(ctx->dst.bev);
if (pxy_try_prepend_sslproxy_header(ctx, inbuf, outbuf) != 0) {
return;
}
@ -362,7 +364,7 @@ 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)));
if (ctx->src.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}
@ -382,7 +384,7 @@ prototcp_bev_readcb_src_child(struct bufferevent *bev, pxy_conn_child_ctx_t *ctx
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));
if (ctx->dst.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}
@ -415,7 +417,7 @@ prototcp_bev_readcb_dst_child(struct bufferevent *bev, pxy_conn_child_ctx_t *ctx
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));
if (ctx->src.closed) {
pxy_discard_inbuf(bev);
pxy_try_discard_inbuf(bev);
return;
}
@ -429,8 +431,10 @@ prototcp_try_close_unauth_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
if (ctx->conn_opts->user_auth && !ctx->user) {
size_t outbuflen = evbuffer_get_length(bufferevent_get_output(bev));
if (outbuflen > 0) {
log_finest_va("Not closing unauth conn, outbuflen=%zu", outbuflen);
struct bufferevent *ubev = bufferevent_get_underlying(bev);
if (outbuflen || (ubev && evbuffer_get_length(bufferevent_get_output(ubev)))) {
log_finest_va("Not closing unauth conn, outbuflen=%zu, ubev outbuflen=%zu",
outbuflen, ubev ? evbuffer_get_length(bufferevent_get_output(ubev)) : 0);
} else if (ctx->sent_userauth_msg) {
log_finest("Closing unauth conn");
pxy_conn_term(ctx, 1);
@ -448,8 +452,10 @@ prototcp_try_close_protoerror_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
if (ctx->conn_opts->validate_proto && ctx->sent_protoerror_msg) {
size_t outbuflen = evbuffer_get_length(bufferevent_get_output(bev));
if (outbuflen > 0) {
log_finest_va("Not closing protoerror conn, outbuflen=%zu", outbuflen);
struct bufferevent *ubev = bufferevent_get_underlying(bev);
if (outbuflen || (ubev && evbuffer_get_length(bufferevent_get_output(ubev)))) {
log_finest_va("Not closing protoerror conn, outbuflen=%zu, ubev outbuflen=%zu",
outbuflen, ubev ? evbuffer_get_length(bufferevent_get_output(ubev)) : 0);
} else {
log_finest("Closing protoerror conn");
pxy_conn_term(ctx, 1);

@ -793,6 +793,15 @@ pxy_log_dbg_evbuf_info(pxy_conn_ctx_t *ctx, pxy_conn_desc_t *this, pxy_conn_desc
evbuffer_get_length(bufferevent_get_output(this->bev)),
other->closed ? 0 : evbuffer_get_length(bufferevent_get_input(other->bev)),
other->closed ? 0 : evbuffer_get_length(bufferevent_get_output(other->bev)));
struct bufferevent *ubev = bufferevent_get_underlying(this->bev);
struct bufferevent *ubev_other = other->closed ? NULL : bufferevent_get_underlying(other->bev);
if (ubev || ubev_other)
log_dbg_printf("underlying evbuffer size at EOF: i:%zu o:%zu i:%zu o:%zu\n",
ubev ? evbuffer_get_length(bufferevent_get_input(ubev)) : 0,
ubev ? evbuffer_get_length(bufferevent_get_output(ubev)) : 0,
ubev_other ? evbuffer_get_length(bufferevent_get_input(ubev_other)) : 0,
ubev_other ? evbuffer_get_length(bufferevent_get_output(ubev_other)) : 0);
}
}
#endif /* DEBUG_PROXY */
@ -809,13 +818,45 @@ pxy_malloc_packet(size_t sz, pxy_conn_ctx_t *ctx)
}
void
pxy_discard_inbuf(struct bufferevent *bev)
pxy_try_discard_inbuf(struct bufferevent *bev)
{
struct evbuffer *inbuf = bufferevent_get_input(bev);
size_t inbuf_size = evbuffer_get_length(inbuf);
if (inbuf_size) {
log_dbg_printf("Warning: Drained %zu bytes from inbuf\n", inbuf_size);
evbuffer_drain(inbuf, inbuf_size);
}
struct bufferevent *ubev = bufferevent_get_underlying(bev);
if (ubev) {
struct evbuffer *ubev_inbuf = bufferevent_get_input(ubev);
size_t ubev_inbuf_size = evbuffer_get_length(ubev_inbuf);
if (ubev_inbuf_size) {
log_dbg_printf("Warning: Drained %zu bytes from inbuf underlying\n", ubev_inbuf_size);
evbuffer_drain(ubev_inbuf, ubev_inbuf_size);
}
}
}
log_dbg_printf("Warning: Drained %zu bytes (conn closed)\n", inbuf_size);
evbuffer_drain(inbuf, inbuf_size);
void
pxy_try_discard_outbuf(struct bufferevent *bev)
{
struct evbuffer *outbuf = bufferevent_get_output(bev);
size_t outbuf_size = evbuffer_get_length(outbuf);
if (outbuf_size) {
log_dbg_printf("Warning: Drained %zu bytes from outbuf\n", outbuf_size);
evbuffer_drain(outbuf, outbuf_size);
}
struct bufferevent *ubev = bufferevent_get_underlying(bev);
if (ubev) {
struct evbuffer *ubev_outbuf = bufferevent_get_output(ubev);
size_t ubev_outbuf_size = evbuffer_get_length(ubev_outbuf);
if (ubev_outbuf_size) {
log_dbg_printf("Warning: Drained %zu bytes from outbuf underlying\n", ubev_outbuf_size);
evbuffer_drain(ubev_outbuf, ubev_outbuf_size);
}
}
}
#ifdef DEBUG_PROXY
@ -1250,7 +1291,9 @@ pxy_try_close_conn_end(pxy_conn_desc_t *conn_end, pxy_conn_ctx_t *ctx)
/* if the other end is still open and doesn't have data
* to send, close it, otherwise its writecb will close
* it after writing what's left in the output buffer */
if (evbuffer_get_length(bufferevent_get_output(conn_end->bev)) == 0) {
struct bufferevent *ubev = bufferevent_get_underlying(conn_end->bev);
if (evbuffer_get_length(bufferevent_get_output(conn_end->bev)) == 0 &&
(!ubev || evbuffer_get_length(bufferevent_get_output(ubev)) == 0)) {
log_finest("evbuffer_get_length(outbuf) == 0, terminate conn");
conn_end->free(conn_end->bev, ctx);
conn_end->bev = NULL;

@ -427,7 +427,8 @@ void pxy_try_disconnect_child(pxy_conn_child_ctx_t *, pxy_conn_desc_t *, pxy_con
int pxy_try_consume_last_input(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1,2);
int pxy_try_consume_last_input_child(struct bufferevent *, pxy_conn_child_ctx_t *) NONNULL(1,2);
void pxy_discard_inbuf(struct bufferevent *) NONNULL(1);
void pxy_try_discard_inbuf(struct bufferevent *) NONNULL(1);
void pxy_try_discard_outbuf(struct bufferevent *) NONNULL(1);
int pxy_conn_init(pxy_conn_ctx_t *) NONNULL(1);
void pxy_conn_ctx_free(pxy_conn_ctx_t *, int) NONNULL(1);

Loading…
Cancel
Save