From 9ef45139166a93f2e26587a417285a693ea3a941 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 --- ...ls-with-direct-calls-to-TLS-and-HTTP.patch | 705 ++++++++++++++++++ fw/connection.c | 11 - fw/connection.h | 4 +- fw/gfsm.h | 3 +- fw/http.c | 44 +- fw/http.h | 2 +- fw/http_frame.c | 6 +- fw/http_frame.h | 4 +- fw/http_limits.c | 40 +- fw/http_limits.h | 4 +- fw/sock_clnt.c | 23 +- fw/sock_srv.c | 4 +- fw/tls.c | 42 +- fw/tls.h | 30 +- fw/tls_conf.c | 2 +- 15 files changed, 777 insertions(+), 147 deletions(-) create mode 100644 0001-Replace-GFSM-calls-with-direct-calls-to-TLS-and-HTTP.patch diff --git a/0001-Replace-GFSM-calls-with-direct-calls-to-TLS-and-HTTP.patch b/0001-Replace-GFSM-calls-with-direct-calls-to-TLS-and-HTTP.patch new file mode 100644 index 0000000000..0eb57da293 --- /dev/null +++ b/0001-Replace-GFSM-calls-with-direct-calls-to-TLS-and-HTTP.patch @@ -0,0 +1,705 @@ +From 2eae1dae4fc579043773ca61f709cf8ab910f10f Mon Sep 17 00:00:00 2001 +From: Alexander K +Date: Mon, 15 Nov 2021 02:09:33 +0300 +Subject: [PATCH] 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). +--- + fw/connection.c | 11 -------- + fw/connection.h | 2 -- + fw/gfsm.h | 3 +-- + fw/http.c | 65 ++++++++++++++++++------------------------------ + fw/http.h | 2 +- + fw/http_frame.c | 4 +-- + fw/http_limits.c | 40 ++++++----------------------- + fw/http_limits.h | 5 +++- + fw/sock_clnt.c | 27 ++++++++++++++------ + fw/sock_srv.c | 2 +- + fw/tls.c | 41 +++++++++++------------------- + fw/tls.h | 32 +++--------------------- + fw/tls_conf.c | 2 +- + 13 files changed, 79 insertions(+), 157 deletions(-) + +diff --git a/fw/connection.c b/fw/connection.c +index f73a5062..1b1e7c9c 100644 +--- a/fw/connection.c ++++ b/fw/connection.c +@@ -123,17 +123,6 @@ tfw_connection_send(TfwConn *conn, TfwMsg *msg) + return TFW_CONN_HOOK_CALL(conn, conn_send, msg); + } + +-int +-tfw_connection_recv(void *cdata, struct sk_buff *skb) +-{ +- TfwConn *conn = cdata; +- TfwFsmData fsm_data = { +- .skb = skb, +- }; +- +- return tfw_gfsm_dispatch(&conn->state, conn, &fsm_data); +-} +- + void + tfw_connection_hooks_register(TfwConnHooks *hooks, int type) + { +diff --git a/fw/connection.h b/fw/connection.h +index e7d35d02..6fd2e19d 100644 +--- a/fw/connection.h ++++ b/fw/connection.h +@@ -508,6 +508,4 @@ int tfw_connection_close(TfwConn *conn, bool sync); + void tfw_connection_drop(TfwConn *conn); + void tfw_connection_release(TfwConn *conn); + +-int tfw_connection_recv(void *cdata, struct sk_buff *skb); +- + #endif /* __TFW_CONNECTION_H__ */ +diff --git a/fw/gfsm.h b/fw/gfsm.h +index 57f9ceb4..3b3b1033 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-2021 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 */ + }; +diff --git a/fw/http.c b/fw/http.c +index c6f5c46b..03ddd79e 100644 +--- a/fw/http.c ++++ b/fw/http.c +@@ -121,7 +121,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; +@@ -5132,12 +5131,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; +@@ -5168,7 +5166,7 @@ next_msg: + 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. + */ +@@ -5339,8 +5337,7 @@ next_msg: + * 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; + +@@ -5710,11 +5707,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; +@@ -5749,7 +5745,7 @@ next_msg: + 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. + */ +@@ -5934,28 +5930,28 @@ bad_msg: + * @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, ++ struct sk_buff *skb) + { + if (WARN_ON_ONCE(!stream)) + return -EINVAL; + if (unlikely(!stream->msg)) { + stream->msg = tfw_http_conn_msg_alloc(conn, stream); + if (!stream->msg) { +- __kfree_skb(data->skb); ++ __kfree_skb(skb); + return TFW_BLOCK; + } +- tfw_http_mark_wl_new_msg(conn, (TfwHttpMsg *)stream->msg, +- data->skb); ++ tfw_http_mark_wl_new_msg(conn, (TfwHttpMsg *)stream->msg, skb); + T_DBG2("Link new msg %p with connection %p\n", + stream->msg, conn); + } + +- T_DBG2("Add skb %p to message %p\n", data->skb, stream->msg); +- ss_skb_queue_tail(&stream->msg->skb_head, data->skb); ++ T_DBG2("Add skb %p to message %p\n", skb, stream->msg); ++ ss_skb_queue_tail(&stream->msg->skb_head, 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, skb) ++ : tfw_http_resp_process(conn, stream, skb); + } + + /** +@@ -5967,24 +5963,25 @@ 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(void *conn, struct sk_buff *skb) + { + int r = T_OK; + TfwStream *stream = &((TfwConn *)conn)->stream; + struct sk_buff *next; + +- if (data->skb->prev) +- data->skb->prev->next = NULL; +- for (next = data->skb->next; data->skb; +- data->skb = next, next = next ? next->next : NULL) ++ if (skb->prev) ++ skb->prev->next = NULL; ++ for (next = skb->next; skb; ++ skb = next, next = next ? next->next : NULL) + { + if (likely(r == T_OK || r == T_POSTPONE)) { +- data->skb->next = data->skb->prev = NULL; ++ skb->next = 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, skb) ++ : tfw_http_msg_process_generic(conn, stream, ++ skb); + } else { +- __kfree_skb(data->skb); ++ __kfree_skb(skb); + } + } + +@@ -6737,28 +6734,15 @@ TfwMod tfw_http_mod = { + * init/exit + * ------------------------------------------------------------------------ + */ +- + int __init + 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; +@@ -6768,7 +6752,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 4da9bf10..2b15d007 100644 +--- a/fw/http.h ++++ b/fw/http.h +@@ -646,7 +646,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 04b70f3d..53d6f2f7 100644 +--- a/fw/http_frame.c ++++ b/fw/http_frame.c +@@ -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_limits.c b/fw/http_limits.c +index 2794a7be..6cdaf300 100644 +--- a/fw/http_limits.c ++++ b/fw/http_limits.c +@@ -856,13 +856,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) \ +@@ -1451,8 +1444,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; +@@ -1473,8 +1465,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) +@@ -1511,12 +1502,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; + +@@ -1525,7 +1515,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); + +@@ -1596,14 +1586,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 +@@ -1664,12 +1646,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; +@@ -1677,7 +1653,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: +@@ -1694,7 +1669,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 e3b30218..d851d2b2 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-2021 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 + #include + #include ++#include + + #include "tempesta_fw.h" + #include "connection.h" +@@ -238,4 +239,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 e9615d61..faa355d2 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-2021 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 +@@ -47,6 +47,9 @@ 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,10 +277,16 @@ 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, ++ .connection_recv = tfw_http_msg_process, ++}; ++ ++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 +@@ -387,10 +396,14 @@ tfw_listen_sock_add(const TfwAddr *addr, int type) + if (!ls) + return -ENOMEM; + +- if (type == TFW_FSM_HTTP) +- ss_proto_init(&ls->proto, &tfw_sock_clnt_ss_hooks, Conn_HttpClnt); +- else if (type == TFW_FSM_HTTPS) +- ss_proto_init(&ls->proto, &tfw_sock_clnt_ss_hooks, Conn_HttpsClnt); ++ if (type == TFW_FSM_HTTP) { ++ 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_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 b2a360ca..2a54f20d 100644 +--- a/fw/sock_srv.c ++++ b/fw/sock_srv.c +@@ -404,7 +404,7 @@ tfw_sock_srv_connect_drop(struct sock *sk) + static const SsHooks tfw_sock_srv_ss_hooks = { + .connection_new = tfw_sock_srv_connect_complete, + .connection_drop = tfw_sock_srv_connect_drop, +- .connection_recv = tfw_connection_recv, ++ .connection_recv = tfw_http_msg_process, + }; + + /** +diff --git a/fw/tls.c b/fw/tls.c +index bbd051c9..cf87d587 100644 +--- a/fw/tls.c ++++ b/fw/tls.c +@@ -30,6 +30,7 @@ + #include "msg.h" + #include "procfs.h" + #include "http_frame.h" ++#include "http_limits.h" + #include "tls.h" + #include "vhost.h" + #include "lib/hash.h" +@@ -98,15 +99,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 +@@ -117,19 +109,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, TFW_TLS_FSM_HS_DONE); + } + +-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 = {}; + + /* +@@ -152,7 +142,7 @@ next_msg: + 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: +@@ -212,7 +202,7 @@ next_msg: + 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; +@@ -714,7 +704,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; + +@@ -1079,22 +1073,16 @@ 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_mod_register(&tfw_tls_mod); + + return 0; +- +-err_fsm: +- tfw_h2_cleanup(); + err_h2: + tfw_tls_do_cleanup(); + +@@ -1106,7 +1094,6 @@ 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_h2_cleanup(); + tfw_tls_do_cleanup(); + } +diff --git a/fw/tls.h b/fw/tls.h +index 74200f0f..8ed99736 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-2021 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 +@@ -22,33 +22,6 @@ + + #include + +-#include "gfsm.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); +@@ -56,4 +29,7 @@ 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 6fb0e752..9d2d61ee 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; + } + +-- +2.30.2 + diff --git a/fw/connection.c b/fw/connection.c index f73a5062db..1b1e7c9cd5 100644 --- a/fw/connection.c +++ b/fw/connection.c @@ -123,17 +123,6 @@ tfw_connection_send(TfwConn *conn, TfwMsg *msg) return TFW_CONN_HOOK_CALL(conn, conn_send, msg); } -int -tfw_connection_recv(void *cdata, struct sk_buff *skb) -{ - TfwConn *conn = cdata; - TfwFsmData fsm_data = { - .skb = skb, - }; - - return tfw_gfsm_dispatch(&conn->state, conn, &fsm_data); -} - void tfw_connection_hooks_register(TfwConnHooks *hooks, int type) { diff --git a/fw/connection.h b/fw/connection.h index e7d35d020c..b65a6b52e6 100644 --- a/fw/connection.h +++ b/fw/connection.h @@ -100,7 +100,7 @@ enum { struct sock *sk; \ void (*destructor)(void *); -typedef struct { +typedef struct TfwConn { TFW_CONN_COMMON; } TfwConn; @@ -508,6 +508,4 @@ int tfw_connection_close(TfwConn *conn, bool sync); void tfw_connection_drop(TfwConn *conn); void tfw_connection_release(TfwConn *conn); -int tfw_connection_recv(void *cdata, struct sk_buff *skb); - #endif /* __TFW_CONNECTION_H__ */ diff --git a/fw/gfsm.h b/fw/gfsm.h index 57f9ceb4a2..154cb34907 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 */ }; diff --git a/fw/http.c b/fw/http.c index 6e604c8b2f..87d346041a 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; @@ -6117,13 +6114,14 @@ tfw_http_msg_process(void *conn, TfwFsmData *data) if (data->skb->prev) data->skb->prev->next = NULL; for (next = data->skb->next; data->skb; - data->skb = next, next = next ? next->next : NULL) + data->skb = next, next = next ? next->next : NULL) { 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_gfsm_handler_t) 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 545a42d158..6816aff4bc 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 6d08bcec72..1406aef8b3 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 ea83dde2b5..f28c18432e 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 3a555298db..674b36fa91 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) \ @@ -1450,8 +1443,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 +1464,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 +1501,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 +1514,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 +1585,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 +1645,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,7 +1652,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: @@ -1693,7 +1668,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 e3b302183c..58e2baf51b 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 e9615d61dc..06ac9b38e4 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 @@ -47,7 +47,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,10 +277,16 @@ 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_http_msg_process, +}; + +static const SsHooks tfw_sock_tls_clnt_ss_hooks = { .connection_new = tfw_sock_clnt_new, .connection_drop = tfw_sock_clnt_drop, - .connection_recv = tfw_connection_recv, + .connection_recv = tfw_tls_msg_process, }; static int @@ -388,9 +397,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 b2a360ca23..207ee4f33c 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 @@ -404,7 +404,7 @@ tfw_sock_srv_connect_drop(struct sock *sk) static const SsHooks tfw_sock_srv_ss_hooks = { .connection_new = tfw_sock_srv_connect_complete, .connection_drop = tfw_sock_srv_connect_drop, - .connection_recv = tfw_connection_recv, + .connection_recv = tfw_http_msg_process, }; /** diff --git a/fw/tls.c b/fw/tls.c index 35dccdc39a..7eff1fb8fb 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 @@ -30,6 +30,7 @@ #include "msg.h" #include "procfs.h" #include "http_frame.h" +#include "http_limits.h" #include "tls.h" #include "vhost.h" #include "lib/hash.h" @@ -59,15 +60,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 +70,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, TFW_TLS_FSM_HS_DONE); } -static int -tfw_tls_msg_process(void *conn, TfwFsmData *data) +int +tfw_tls_msg_process(TfwConn *conn, struct sk_buff *data) { 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 +103,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 +170,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 +672,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 +1041,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_mod_register(&tfw_tls_mod); return 0; -err_fsm: - tfw_h2_cleanup(); err_h2: tfw_tls_do_cleanup(); @@ -1074,7 +1063,6 @@ 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_h2_cleanup(); tfw_tls_do_cleanup(); } diff --git a/fw/tls.h b/fw/tls.h index a06be4652f..cd6088888a 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 6fb0e75278..9d2d61eecb 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; }