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; }