From 0a28e8ea100197d48684a5457185fd88b8225cc4 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhaylov Date: Mon, 21 Feb 2022 14:50:11 +0300 Subject: [PATCH] Replace GFSM calls with direct calls to TLS and HTTP Almost literaly follow ak patch from 2eae1dae4fc579043773ca61f709cf8ab910f10f Replace GFSM calls with direct calls to TLS and HTTP handlers on low level networking layers. GFSM was designed to build graphs of network protocols FSMs (this design was inspired by FreeBSD netgraph). However, during the years neither we nor external users have any requirements to introduce any modules which use GFSM to hook TLS or HTTP entry code. There are only 2 users of the mechanism for TLS and HTTP for now: 1. TLS -> HTTP protocols handling 2. HTTP limits (the frang module) This patch replaces GFSM calls with direct calls to tfw_http_req_process(), tfw_tls_msg_process() and frang_tls_handler() in following paths: 1. sync sockets -> TLS 2. sync sockets -> HTTP 3. TLS -> HTTP 4. TLS -> Frang As the result the function tfw_connection_recv() was eliminated. Now the code is simpler and has lower overhead. We still might need GFSM for the user-space requests handling (#77) and Tempesta Language (#102). Contributes to #755 Based-on-patch-by: Alexander K Signed-off-by: Aleksey Mikhaylov --- fw/connection.c | 5 +++-- fw/connection.h | 4 ++-- fw/gfsm.h | 12 ++++++------ fw/http.c | 42 ++++++++++++++---------------------------- fw/http.h | 2 +- fw/http_frame.c | 6 +++--- fw/http_frame.h | 4 +++- fw/http_limits.c | 47 +++++++++-------------------------------------- fw/http_limits.h | 4 +++- fw/sock_clnt.c | 22 +++++++++++++++++----- fw/sock_srv.c | 2 +- fw/tls.c | 47 ++++++++++++++++++----------------------------- fw/tls.h | 30 +++--------------------------- fw/tls_conf.c | 2 +- 14 files changed, 84 insertions(+), 145 deletions(-) diff --git a/fw/connection.c b/fw/connection.c index f73a5062d..0959160a2 100644 --- a/fw/connection.c +++ b/fw/connection.c @@ -4,7 +4,7 @@ * Generic connection management. * * Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com). - * Copyright (C) 2015-2021 Tempesta Technologies, Inc. + * Copyright (C) 2015-2022 Tempesta Technologies, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include "gfsm.h" #include "log.h" #include "sync_socket.h" +#include "http.h" TfwConnHooks *conn_hooks[TFW_CONN_MAX_PROTOS]; @@ -131,7 +132,7 @@ tfw_connection_recv(void *cdata, struct sk_buff *skb) .skb = skb, }; - return tfw_gfsm_dispatch(&conn->state, conn, &fsm_data); + return tfw_http_msg_process(conn, &fsm_data); } void diff --git a/fw/connection.h b/fw/connection.h index e7d35d020..60a4b1d2e 100644 --- a/fw/connection.h +++ b/fw/connection.h @@ -4,7 +4,7 @@ * Definitions for generic connection management at OSI level 6 (presentation). * * Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com). - * Copyright (C) 2015-2019 Tempesta Technologies, Inc. + * Copyright (C) 2015-2022 Tempesta Technologies, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -100,7 +100,7 @@ enum { struct sock *sk; \ void (*destructor)(void *); -typedef struct { +typedef struct TfwConn { TFW_CONN_COMMON; } TfwConn; diff --git a/fw/gfsm.h b/fw/gfsm.h index 57f9ceb4a..5894684ae 100644 --- a/fw/gfsm.h +++ b/fw/gfsm.h @@ -2,7 +2,7 @@ * Tempesta FW * * Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com). - * Copyright (C) 2015-2018 Tempesta Technologies, Inc. + * Copyright (C) 2015-2022 Tempesta Technologies, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -88,7 +88,6 @@ enum { /* Security rules enforcement. */ TFW_FSM_FRANG_REQ, TFW_FSM_FRANG_RESP, - TFW_FSM_FRANG_TLS, TFW_FSM_NUM /* Must be <= TFW_GFSM_FSM_N */ }; @@ -178,11 +177,12 @@ typedef struct { unsigned short states[TFW_GFSM_FSM_NUM]; } TfwGState; -#define TFW_GFSM_STATE(s) ((s)->states[(unsigned char)(s)->curr] \ - & ((TFW_GFSM_FSM_MASK << TFW_GFSM_FSM_SHIFT) \ - | TFW_GFSM_STATE_MASK)) +#define TFW_GFSM_STATE(s) ((s)->states[(unsigned char)(s)->curr] \ + & ((TFW_GFSM_FSM_MASK << TFW_GFSM_FSM_SHIFT) \ + | TFW_GFSM_STATE_MASK)) -typedef int (*tfw_gfsm_handler_t)(void *obj, TfwFsmData *data); +typedef struct TfwConn TfwConn; +typedef int (*tfw_gfsm_handler_t)(TfwConn *conn, TfwFsmData *data); void tfw_gfsm_state_init(TfwGState *st, void *obj, int st0); int tfw_gfsm_dispatch(TfwGState *st, void *obj, TfwFsmData *data); diff --git a/fw/http.c b/fw/http.c index 6e604c8b2..bcd2e3905 100644 --- a/fw/http.c +++ b/fw/http.c @@ -117,7 +117,6 @@ #define RESP_BUF_LEN 128 static DEFINE_PER_CPU(char[RESP_BUF_LEN], g_buf); -int ghprio; /* GFSM hook priority. */ #define TFW_CFG_BLK_DEF (TFW_BLK_ERR_REPLY) unsigned short tfw_blk_flags = TFW_CFG_BLK_DEF; @@ -5240,12 +5239,11 @@ tfw_h1_req_process(TfwStream *stream, struct sk_buff *skb) * TODO enter the function depending on current GFSM state. */ static int -tfw_http_req_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data) +tfw_http_req_process(TfwConn *conn, TfwStream *stream, struct sk_buff *skb) { bool block; ss_skb_actor_t *actor; unsigned int parsed; - struct sk_buff *skb = data->skb; TfwHttpReq *req; TfwHttpMsg *hmsib; TfwFsmData data_up; @@ -5276,7 +5274,7 @@ tfw_http_req_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data) skb->len, skb->next, parsed, req->msg.len, req->version, r); /* - * We have to keep @data the same to pass it as is to FSMs + * We have to keep @skb the same to pass it as is to FSMs * registered with lower priorities after us, but we must * feed the new data version to FSMs registered on our states. */ @@ -5455,8 +5453,7 @@ tfw_http_req_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data) * the quickest way to obtain target VHost and target backend server * connection since it allows to avoid expensive tables lookups. */ - switch (tfw_http_sess_obtain(req)) - { + switch (tfw_http_sess_obtain(req)) { case TFW_HTTP_SESS_SUCCESS: break; @@ -5851,11 +5848,10 @@ tfw_http_resp_terminate(TfwHttpMsg *hm) * TODO enter the function depending on current GFSM state. */ static int -tfw_http_resp_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data) +tfw_http_resp_process(TfwConn *conn, TfwStream *stream, struct sk_buff *skb) { int r = TFW_BLOCK; unsigned int chunks_unused, parsed; - struct sk_buff *skb = data->skb; TfwHttpReq *bad_req; TfwHttpMsg *hmresp, *hmsib; TfwFsmData data_up; @@ -5890,7 +5886,7 @@ tfw_http_resp_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data) skb->len, parsed, hmresp->msg.len, hmresp->version, r); /* - * We have to keep @data the same to pass it as is to FSMs + * We have to keep @skb the same to pass it as is to FSMs * registered with lower priorities after us, but we must * feed the new data version to FSMs registered on our states. */ @@ -6075,7 +6071,8 @@ tfw_http_resp_process(TfwConn *conn, TfwStream *stream, const TfwFsmData *data) * @return status (application logic decision) of the message processing. */ int -tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream, TfwFsmData *data) +tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream, + TfwFsmData *data) { if (WARN_ON_ONCE(!stream)) return -EINVAL; @@ -6095,8 +6092,8 @@ tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream, TfwFsmData *data) ss_skb_queue_tail(&stream->msg->skb_head, data->skb); return (TFW_CONN_TYPE(conn) & Conn_Clnt) - ? tfw_http_req_process(conn, stream, data) - : tfw_http_resp_process(conn, stream, data); + ? tfw_http_req_process(conn, stream, data->skb) + : tfw_http_resp_process(conn, stream, data->skb); } /** @@ -6108,7 +6105,7 @@ tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream, TfwFsmData *data) * returned an error code on. The rest of skbs are freed by us. */ int -tfw_http_msg_process(void *conn, TfwFsmData *data) +tfw_http_msg_process(TfwConn *conn, TfwFsmData *data) { int r = T_OK; TfwStream *stream = &((TfwConn *)conn)->stream; @@ -6122,8 +6119,9 @@ tfw_http_msg_process(void *conn, TfwFsmData *data) if (likely(r == T_OK || r == T_POSTPONE)) { data->skb->next = data->skb->prev = NULL; r = TFW_CONN_H2(conn) - ? tfw_h2_frame_process(conn, data) - : tfw_http_msg_process_generic(conn, stream, data); + ? tfw_h2_frame_process(conn, data->skb) + : tfw_http_msg_process_generic(conn, stream, + data); } else { __kfree_skb(data->skb); } @@ -6884,22 +6882,11 @@ tfw_http_init(void) { int r; - r = tfw_gfsm_register_fsm(TFW_FSM_HTTP, tfw_http_msg_process); - if (r) + if ((r = tfw_gfsm_register_fsm(TFW_FSM_HTTP, tfw_http_msg_process))) return r; tfw_connection_hooks_register(&http_conn_hooks, TFW_FSM_HTTP); - ghprio = tfw_gfsm_register_hook(TFW_FSM_TLS, - TFW_GFSM_HOOK_PRIORITY_ANY, - TFW_TLS_FSM_DATA_READY, - TFW_FSM_HTTP, TFW_HTTP_FSM_INIT); - if (ghprio < 0) { - tfw_connection_hooks_unregister(TFW_FSM_HTTP); - tfw_gfsm_unregister_fsm(TFW_FSM_HTTP); - return ghprio; - } - tfw_mod_register(&tfw_http_mod); return 0; @@ -6909,7 +6896,6 @@ void tfw_http_exit(void) { tfw_mod_unregister(&tfw_http_mod); - tfw_gfsm_unregister_hook(TFW_FSM_TLS, ghprio, TFW_TLS_FSM_DATA_READY); tfw_connection_hooks_unregister(TFW_FSM_HTTP); tfw_gfsm_unregister_fsm(TFW_FSM_HTTP); } diff --git a/fw/http.h b/fw/http.h index 545a42d15..6816aff4b 100644 --- a/fw/http.h +++ b/fw/http.h @@ -668,7 +668,7 @@ tfw_h2_pseudo_index(unsigned short status) typedef void (*tfw_http_cache_cb_t)(TfwHttpMsg *); /* External HTTP functions. */ -int tfw_http_msg_process(void *conn, TfwFsmData *data); +int tfw_http_msg_process(TfwConn *conn, TfwFsmData *data); int tfw_http_msg_process_generic(TfwConn *conn, TfwStream *stream, TfwFsmData *data); unsigned long tfw_http_req_key_calc(TfwHttpReq *req); diff --git a/fw/http_frame.c b/fw/http_frame.c index 6d08bcec7..1406aef8b 100644 --- a/fw/http_frame.c +++ b/fw/http_frame.c @@ -1,7 +1,7 @@ /** * Tempesta FW * - * Copyright (C) 2019-2021 Tempesta Technologies, Inc. + * Copyright (C) 2019-2022 Tempesta Technologies, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -1698,14 +1698,14 @@ tfw_h2_context_reinit(TfwH2Ctx *ctx, bool postponed) } int -tfw_h2_frame_process(void *c, TfwFsmData *data) +tfw_h2_frame_process(TfwConn *c, struct sk_buff *skb) { int r; bool postponed; unsigned int parsed, unused; TfwFsmData data_up = {}; TfwH2Ctx *h2 = tfw_h2_context(c); - struct sk_buff *nskb = NULL, *skb = data->skb; + struct sk_buff *nskb = NULL; next_msg: postponed = false; diff --git a/fw/http_frame.h b/fw/http_frame.h index ea83dde2b..f28c18432 100644 --- a/fw/http_frame.h +++ b/fw/http_frame.h @@ -200,11 +200,13 @@ typedef struct { unsigned char data_off; } TfwH2Ctx; +typedef struct TfwConn TfwConn; + int tfw_h2_init(void); void tfw_h2_cleanup(void); int tfw_h2_context_init(TfwH2Ctx *ctx); void tfw_h2_context_clear(TfwH2Ctx *ctx); -int tfw_h2_frame_process(void *c, TfwFsmData *data); +int tfw_h2_frame_process(TfwConn *c, struct sk_buff *skb); void tfw_h2_conn_streams_cleanup(TfwH2Ctx *ctx); unsigned int tfw_h2_stream_id(TfwHttpReq *req); unsigned int tfw_h2_stream_id_close(TfwHttpReq *req, unsigned char type, diff --git a/fw/http_limits.c b/fw/http_limits.c index 3a555298d..674836f41 100644 --- a/fw/http_limits.c +++ b/fw/http_limits.c @@ -855,13 +855,6 @@ enum { TFW_FRANG_RESP_FSM_DONE = TFW_GFSM_FRANG_RESP_STATE(TFW_GFSM_STATE_LAST) }; -#define TFW_GFSM_FRANG_TLS_STATE(s) \ - ((TFW_FSM_FRANG_TLS << TFW_GFSM_FSM_SHIFT) | (s)) -enum { - TFW_FRANG_TLS_FSM_INIT = TFW_GFSM_FRANG_TLS_STATE(0), - TFW_FRANG_TLS_FSM_DONE = TFW_GFSM_FRANG_TLS_STATE(TFW_GFSM_STATE_LAST) -}; - #define __FRANG_FSM_MOVE(st) T_FSM_MOVE(st, if (r) T_FSM_EXIT(); ) #define __FRANG_FSM_JUMP_EXIT(st) \ @@ -1245,10 +1238,9 @@ frang_http_req_process(FrangAcc *ra, TfwConn *conn, TfwFsmData *data, } static int -frang_http_req_handler(void *obj, TfwFsmData *data) +frang_http_req_handler(TfwConn *conn, TfwFsmData *data) { int r; - TfwConn *conn = (TfwConn *)obj; FrangAcc *ra = conn->sk->sk_security; TfwVhost *dvh = NULL; TfwHttpReq *req = (TfwHttpReq *)data->req; @@ -1411,10 +1403,9 @@ frang_resp_fwd_process(TfwHttpResp *resp) } static int -frang_resp_handler(void *obj, TfwFsmData *data) +frang_resp_handler(TfwConn *conn, TfwFsmData *data) { TfwHttpResp *resp = (TfwHttpResp *)data->resp; - TfwConn *conn = (TfwConn *)obj; int r = TFW_PASS; switch (TFW_GFSM_STATE(&conn->state)) { @@ -1450,8 +1441,7 @@ frang_tls_conn_limit(FrangAcc *ra, FrangGlobCfg *conf, int hs_state) ra->history[i].ts = ts; } - switch (hs_state) - { + switch (hs_state) { case TTLS_HS_CB_FINISHED_NEW: ra->history[i].tls_sess_new++; break; @@ -1472,8 +1462,7 @@ frang_tls_conn_limit(FrangAcc *ra, FrangGlobCfg *conf, int hs_state) sum_incomplete += ra->history[i].tls_sess_incomplete; } - switch (hs_state) - { + switch (hs_state) { case TTLS_HS_CB_FINISHED_NEW: if (conf->tls_new_conn_rate && sum_new > conf->tls_new_conn_rate) @@ -1510,12 +1499,11 @@ frang_tls_conn_limit(FrangAcc *ra, FrangGlobCfg *conf, int hs_state) return TFW_PASS; } -static int -frang_tls_handler(void *obj, TfwFsmData *data) +int +frang_tls_handler(TlsCtx *tls, int state) { - TfwCliConn *conn = (TfwCliConn *)obj; - FrangAcc *ra = conn->sk->sk_security; - int hs_state = -PTR_ERR(data->req); + TfwTlsConn *conn = container_of(tls, TfwTlsConn, tls); + FrangAcc *ra = conn->cli_conn.sk->sk_security; TfwVhost *dflt_vh = tfw_vhost_lookup_default(); int r; @@ -1524,7 +1512,7 @@ frang_tls_handler(void *obj, TfwFsmData *data) spin_lock(&ra->lock); - r = frang_tls_conn_limit(ra, dflt_vh->frang_gconf, hs_state); + r = frang_tls_conn_limit(ra, dflt_vh->frang_gconf, state); if (r == TFW_BLOCK && dflt_vh->frang_gconf->ip_block) tfw_filter_block_ip(&FRANG_ACC2CLI(ra)->addr); @@ -1595,14 +1583,6 @@ static FrangGfsmHook frang_gfsm_hooks[] = { .st0 = TFW_FRANG_RESP_FSM_FWD, .name = "response_fwd", }, - { - .prio = -1, - .hook_fsm = TFW_FSM_HTTPS, - .hook_state = TFW_TLS_FSM_HS_DONE, - .fsm_id = TFW_FSM_FRANG_TLS, - .st0 = TFW_FRANG_TLS_FSM_INIT, - .name = "tls_hs_done", - }, }; void @@ -1663,12 +1643,6 @@ tfw_http_limits_init(void) goto err_fsm_resp; } - r = tfw_gfsm_register_fsm(TFW_FSM_FRANG_TLS, frang_tls_handler); - if (r) { - T_ERR_NL("frang: can't register frang tls fsm\n"); - goto err_fsm_tls; - } - r = tfw_http_limits_hooks_register(); if (r) goto err_hooks; @@ -1676,8 +1650,6 @@ tfw_http_limits_init(void) return 0; err_hooks: tfw_http_limits_hooks_remove(); - tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_TLS); -err_fsm_tls: tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_RESP); err_fsm_resp: tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_REQ); @@ -1693,7 +1665,6 @@ tfw_http_limits_exit(void) T_DBG("frang exit\n"); tfw_http_limits_hooks_remove(); - tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_TLS); tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_RESP); tfw_gfsm_unregister_fsm(TFW_FSM_FRANG_REQ); tfw_classifier_unregister(); diff --git a/fw/http_limits.h b/fw/http_limits.h index e3b302183..58e2baf51 100644 --- a/fw/http_limits.h +++ b/fw/http_limits.h @@ -2,7 +2,7 @@ * Tempesta FW * * Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com). - * Copyright (C) 2015-2020 Tempesta Technologies, Inc. + * Copyright (C) 2015-2022 Tempesta Technologies, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -238,4 +238,6 @@ struct frang_vhost_cfg_t { bool http_method_override; }; +int frang_tls_handler(TlsCtx *tls, int state); + #endif /* __HTTP_LIMITS__ */ diff --git a/fw/sock_clnt.c b/fw/sock_clnt.c index e9615d61d..50c75b6df 100644 --- a/fw/sock_clnt.c +++ b/fw/sock_clnt.c @@ -4,7 +4,7 @@ * TCP/IP stack hooks and socket routines to handle client traffic. * * Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com). - * Copyright (C) 2015-2020 Tempesta Technologies, Inc. + * Copyright (C) 2015-2022 Tempesta Technologies, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include "cfg.h" #include "client.h" #include "connection.h" +#include "http.h" #include "http_limits.h" #include "log.h" #include "procfs.h" @@ -47,7 +48,10 @@ tfw_cli_cache(int type) /* * Currently any secure (TLS) connection is considered as HTTP/2 * connection, since we don't have any business with plain TLS. - */ + * + * FIXME #1422 this should be fixed since we still need HTTP/1 as + * more applicable protocol for service management. + */ return type & TFW_FSM_HTTPS ? tfw_h2_conn_cache : tfw_cli_conn_cache; } @@ -274,12 +278,18 @@ tfw_sock_clnt_drop(struct sock *sk) tfw_connection_put(conn); } -static const SsHooks tfw_sock_clnt_ss_hooks = { +static const SsHooks tfw_sock_http_clnt_ss_hooks = { .connection_new = tfw_sock_clnt_new, .connection_drop = tfw_sock_clnt_drop, .connection_recv = tfw_connection_recv, }; +static const SsHooks tfw_sock_tls_clnt_ss_hooks = { + .connection_new = tfw_sock_clnt_new, + .connection_drop = tfw_sock_clnt_drop, + .connection_recv = tfw_tls_msg_process, +}; + static int __cli_conn_close_cb(TfwConn *conn) { @@ -388,9 +398,11 @@ tfw_listen_sock_add(const TfwAddr *addr, int type) return -ENOMEM; if (type == TFW_FSM_HTTP) - ss_proto_init(&ls->proto, &tfw_sock_clnt_ss_hooks, Conn_HttpClnt); + ss_proto_init(&ls->proto, &tfw_sock_http_clnt_ss_hooks, + Conn_HttpClnt); else if (type == TFW_FSM_HTTPS) - ss_proto_init(&ls->proto, &tfw_sock_clnt_ss_hooks, Conn_HttpsClnt); + ss_proto_init(&ls->proto, &tfw_sock_tls_clnt_ss_hooks, + Conn_HttpsClnt); list_add(&ls->list, &tfw_listen_socks); ls->addr = *addr; diff --git a/fw/sock_srv.c b/fw/sock_srv.c index b2a360ca2..41bd87864 100644 --- a/fw/sock_srv.c +++ b/fw/sock_srv.c @@ -4,7 +4,7 @@ * Handling server connections. * * Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com). - * Copyright (C) 2015-2019 Tempesta Technologies, Inc. + * Copyright (C) 2015-2022 Tempesta Technologies, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by diff --git a/fw/tls.c b/fw/tls.c index 35dccdc39..fe5ca5b63 100644 --- a/fw/tls.c +++ b/fw/tls.c @@ -3,7 +3,7 @@ * * Transport Layer Security (TLS) interfaces to Tempesta TLS. * - * Copyright (C) 2015-2021 Tempesta Technologies, Inc. + * Copyright (C) 2015-2022 Tempesta Technologies, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -29,7 +29,9 @@ #include "client.h" #include "msg.h" #include "procfs.h" +#include "http.h" #include "http_frame.h" +#include "http_limits.h" #include "tls.h" #include "vhost.h" #include "lib/hash.h" @@ -59,15 +61,6 @@ tfw_tls_purge_io_ctx(TlsIOCtx *io) ttls_reset_io_ctx(io); } -static int -tfw_tls_hs_over(TlsCtx *ctx, int state) -{ - TfwCliConn *c = &container_of(ctx, TfwTlsConn, tls)->cli_conn; - TfwFsmData data_up = { .req = ERR_PTR(-state)}; - - return tfw_gfsm_move(&c->state, TFW_TLS_FSM_HS_DONE, &data_up); -} - /** * A connection has been lost during handshake processing, warn Frang. * It's relatively cheap to pass SYN cookie and then send previously captured @@ -78,19 +71,17 @@ void tfw_tls_connection_lost(TfwConn *conn) { TlsCtx *tls = &((TfwTlsConn *)conn)->tls; - TfwFsmData data_up = { .req = ERR_PTR(-TTLS_HS_CB_INCOMPLETE)}; if (!ttls_hs_done(tls)) - tfw_gfsm_move(&conn->state, TFW_TLS_FSM_HS_DONE, &data_up); + frang_tls_handler(tls, TTLS_HS_CB_FINISHED_RESUMED); } -static int -tfw_tls_msg_process(void *conn, TfwFsmData *data) +int +tfw_tls_msg_process(void *conn, struct sk_buff *skb) { int r, parsed; - struct sk_buff *nskb = NULL, *skb = data->skb; - TfwConn *c = conn; - TlsCtx *tls = tfw_tls_context(c); + struct sk_buff *nskb = NULL; + TlsCtx *tls = tfw_tls_context(conn); TfwFsmData data_up = {}; /* @@ -113,7 +104,7 @@ tfw_tls_msg_process(void *conn, TfwFsmData *data) case T_DROP: spin_unlock(&tls->lock); if (!ttls_hs_done(tls)) - tfw_tls_hs_over(tls, TTLS_HS_CB_INCOMPLETE); + frang_tls_handler(tls, TTLS_HS_CB_INCOMPLETE); /* The skb is freed in tfw_tls_conn_dtor(). */ return r; case T_POSTPONE: @@ -180,7 +171,7 @@ tfw_tls_msg_process(void *conn, TfwFsmData *data) ttls_reset_io_ctx(&tls->io_in); spin_unlock(&tls->lock); - r = tfw_gfsm_move(&c->state, TFW_TLS_FSM_DATA_READY, &data_up); + r = tfw_http_msg_process(conn, &data_up); if (r == TFW_BLOCK) { kfree_skb(nskb); return r; @@ -682,7 +673,11 @@ tfw_tls_conn_init(TfwConn *c) if ((r = tfw_h2_context_init(h2))) return r; - tfw_gfsm_state_init(&c->state, c, TFW_TLS_FSM_INIT); + /* + * We never hook TLS connections in GFSM, but initialize it with 0 state + * to keep the things safe. + */ + tfw_gfsm_state_init(&c->state, c, 0); c->destructor = tfw_tls_conn_dtor; @@ -1047,22 +1042,17 @@ tfw_tls_init(void) if (r) return -EINVAL; - ttls_register_callbacks(tfw_tls_send, tfw_tls_sni, tfw_tls_hs_over, + ttls_register_callbacks(tfw_tls_send, tfw_tls_sni, frang_tls_handler, ttls_cli_id); if ((r = tfw_h2_init())) goto err_h2; - if ((r = tfw_gfsm_register_fsm(TFW_FSM_TLS, tfw_tls_msg_process))) - goto err_fsm; - - tfw_connection_hooks_register(&tls_conn_hooks, TFW_FSM_TLS); + tfw_connection_hooks_register(&tls_conn_hooks, TFW_FSM_HTTPS); tfw_mod_register(&tfw_tls_mod); return 0; -err_fsm: - tfw_h2_cleanup(); err_h2: tfw_tls_do_cleanup(); @@ -1073,8 +1063,7 @@ void tfw_tls_exit(void) { tfw_mod_unregister(&tfw_tls_mod); - tfw_connection_hooks_unregister(TFW_FSM_TLS); - tfw_gfsm_unregister_fsm(TFW_FSM_TLS); + tfw_connection_hooks_unregister(TFW_FSM_HTTPS); tfw_h2_cleanup(); tfw_tls_do_cleanup(); } diff --git a/fw/tls.h b/fw/tls.h index a06be4652..cd6088888 100644 --- a/fw/tls.h +++ b/fw/tls.h @@ -1,7 +1,7 @@ /** * Tempesta FW * - * Copyright (C) 2015-2019 Tempesta Technologies, Inc. + * Copyright (C) 2015-2022 Tempesta Technologies, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -20,34 +20,8 @@ #ifndef __TFW_TLS_H__ #define __TFW_TLS_H__ -#include "gfsm.h" #include "ttls.h" -#define TFW_FSM_TLS TFW_FSM_HTTPS - -/** - * TLS states. - */ -#define TFW_GFSM_TLS_STATE(s) ((TFW_FSM_TLS << TFW_GFSM_FSM_SHIFT) | (s)) -enum { - /* TLS FSM initial state, not hookable. */ - TFW_TLS_FSM_INIT = TFW_GFSM_TLS_STATE(0), - /* - * A TLS Handshake has been completed on a connection. Client could - * either process a new full handshake or resume previous session. The - * state is also reached if the handshake process ended up with the - * error or never reached the final stage. - */ - TFW_TLS_FSM_HS_DONE = TFW_GFSM_TLS_STATE(1), - /* - * A new portion of data is decrypted and ready to be consumed by the - * upper layers. - */ - TFW_TLS_FSM_DATA_READY = TFW_GFSM_TLS_STATE(2), - - TFW_TLS_FSM_DONE = TFW_GFSM_TLS_STATE(TFW_GFSM_STATE_LAST) -}; - void tfw_tls_cfg_require(void); void tfw_tls_cfg_configured(bool global); void tfw_tls_match_any_sni_to_dflt(bool match); @@ -55,4 +29,6 @@ int tfw_tls_cfg_alpn_protos(const char *cfg_str, bool *deprecated); void tfw_tls_free_alpn_protos(void); int tfw_tls_encrypt(struct sock *sk, struct sk_buff *skb, unsigned int limit); +int tfw_tls_msg_process(void *conn, struct sk_buff *skb); + #endif /* __TFW_TLS_H__ */ diff --git a/fw/tls_conf.c b/fw/tls_conf.c index 6fb0e7527..9d2d61eec 100644 --- a/fw/tls_conf.c +++ b/fw/tls_conf.c @@ -224,7 +224,7 @@ tfw_tls_cert_cfg_finish(TfwVhost *vhost) curr_cert_conf = &conf->certs[conf->certs_num]; if (curr_cert_conf->conf_stage) { T_ERR_NL("TLS: certificate configuration is not done, " - "directive 'tls_certificate_key' is missing. \n"); + "directive 'tls_certificate_key' is missing.\n"); return -EINVAL; }