From: Adrian Villin Date: Thu, 6 Mar 2025 12:25:50 +0000 (+0100) Subject: session: https parsing support X-Git-Tag: v25.10-rc0~82 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=7e323a363fe65241727d0b8316231e530338012f;p=vpp.git session: https parsing support Type: improvement Change-Id: I6ec29cda2cb841a70d6f5768f97666b2cc37febb Signed-off-by: Adrian Villin --- diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go index 93317bbf8d8..5fec25a1feb 100644 --- a/extras/hs-test/http_test.go +++ b/extras/hs-test/http_test.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "crypto/tls" "fmt" "io" "math/rand" @@ -33,7 +34,7 @@ func init() { HttpInvalidContentLengthTest, HttpInvalidTargetSyntaxTest, HttpStaticPathSanitizationTest, HttpUriDecodeTest, HttpHeadersTest, HttpStaticFileHandlerTest, HttpStaticFileHandlerDefaultMaxAgeTest, HttpClientTest, HttpClientErrRespTest, HttpClientPostFormTest, HttpClientGet128kbResponseTest, HttpClientGetResponseBodyTest, - HttpClientGetNoResponseBodyTest, HttpClientPostFileTest, HttpClientPostFilePtrTest, + HttpClientGetTlsNoRespBodyTest, HttpClientPostFileTest, HttpClientPostFilePtrTest, HttpUnitTest, HttpRequestLineTest, HttpClientGetTimeout, HttpStaticFileHandlerWrkTest, HttpStaticUrlHandlerWrkTest, HttpConnTimeoutTest, HttpClientGetRepeatTest, HttpClientPostRepeatTest, HttpIgnoreH2UpgradeTest, HttpInvalidAuthorityFormUriTest, HttpHeaderErrorConnectionDropTest) RegisterNoTopoSoloTests(HttpStaticPromTest, HttpGetTpsTest, HttpGetTpsInterruptModeTest, PromConcurrentConnectionsTest, @@ -365,26 +366,43 @@ func HttpClientPostFormTest(s *NoTopoSuite) { func HttpClientGetResponseBodyTest(s *NoTopoSuite) { response := "hello world" size := len(response) - httpClientGet(s, response, size) + httpClientGet(s, response, size, "http") } func HttpClientGet128kbResponseTest(s *NoTopoSuite) { response := strings.Repeat("a", 128*1024) size := len(response) - httpClientGet(s, response, size) + httpClientGet(s, response, size, "http") } -func HttpClientGetNoResponseBodyTest(s *NoTopoSuite) { +func HttpClientGetTlsNoRespBodyTest(s *NoTopoSuite) { response := "" - httpClientGet(s, response, 0) + httpClientGet(s, response, 0, "https") } -func httpClientGet(s *NoTopoSuite, response string, size int) { - serverAddress := s.HostAddr() +func httpClientGet(s *NoTopoSuite, response string, size int, proto string) { + var l net.Listener + var err error + var port string vpp := s.Containers.Vpp.VppInstance server := ghttp.NewUnstartedServer() - l, err := net.Listen("tcp", serverAddress+":80") + serverAddress := s.HostAddr() + + if proto == "https" { + certFile := "resources/cert/localhost.crt" + keyFile := "resources/cert/localhost.key" + cer, err := tls.LoadX509KeyPair(certFile, keyFile) + s.AssertNil(err) + tlsConfig := &tls.Config{Certificates: []tls.Certificate{cer}} + server.HTTPTestServer.TLS = tlsConfig + port = "443" + l, err = tls.Listen("tcp", serverAddress+":443", tlsConfig) + } else { + port = "80" + l, err = net.Listen("tcp", serverAddress+":80") + } s.AssertNil(err, fmt.Sprint(err)) + server.HTTPTestServer.Listener = l server.AppendHandlers( ghttp.CombineHandlers( @@ -397,7 +415,7 @@ func httpClientGet(s *NoTopoSuite, response string, size int) { server.Start() defer server.Close() - uri := "http://" + serverAddress + uri := proto + "://" + serverAddress + ":" + port cmd := "http client use-ptr verbose header Hello:World header Test-H2:Test-K2 save-to response.txt uri " + uri o := vpp.Vppctl(cmd) diff --git a/src/plugins/hs_apps/http_client.c b/src/plugins/hs_apps/http_client.c index 4701253bf59..1cf96cfa651 100644 --- a/src/plugins/hs_apps/http_client.c +++ b/src/plugins/hs_apps/http_client.c @@ -82,6 +82,7 @@ typedef struct u64 appns_secret; clib_spinlock_t lock; bool was_transport_closed; + u32 ckpair_index; } hc_main_t; typedef enum @@ -526,6 +527,7 @@ hc_attach () vnet_app_attach_args_t _a, *a = &_a; u64 options[18]; u32 segment_size = 128 << 20; + vnet_app_add_cert_key_pair_args_t _ck_pair, *ck_pair = &_ck_pair; int rv; if (hcm->private_segment_size) @@ -546,6 +548,7 @@ hc_attach () hcm->fifo_size ? hcm->fifo_size : 32 << 10; a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN; a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = hcm->prealloc_fifos; + a->options[APP_OPTIONS_TLS_ENGINE] = CRYPTO_ENGINE_OPENSSL; if (hcm->appns_id) { a->namespace_id = hcm->appns_id; @@ -560,6 +563,14 @@ hc_attach () vec_free (a->name); hcm->attached = 1; + clib_memset (ck_pair, 0, sizeof (*ck_pair)); + ck_pair->cert = (u8 *) test_srv_crt_rsa; + ck_pair->key = (u8 *) test_srv_key_rsa; + ck_pair->cert_len = test_srv_crt_rsa_len; + ck_pair->key_len = test_srv_key_rsa_len; + vnet_app_add_cert_key_pair (ck_pair); + hcm->ckpair_index = ck_pair->index; + return 0; } @@ -599,6 +610,14 @@ hc_connect () &a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_HTTP, sizeof (http_cfg)); clib_memcpy (ext_cfg->data, &http_cfg, sizeof (http_cfg)); + if (hcm->connect_sep.flags & SESSION_ENDPT_CFG_F_SECURE) + { + ext_cfg = session_endpoint_add_ext_cfg ( + &a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_CRYPTO, + sizeof (transport_endpt_crypto_cfg_t)); + ext_cfg->crypto.ckpair_index = hcm->ckpair_index; + } + session_send_rpc_evt_to_thread_force (transport_cl_thread (), hc_connect_rpc, a); } diff --git a/src/vnet/session/application_interface.c b/src/vnet/session/application_interface.c index e2f9a6883fe..c9aaceb330d 100644 --- a/src/vnet/session/application_interface.c +++ b/src/vnet/session/application_interface.c @@ -23,9 +23,11 @@ /** * unformat a vnet URI * - * transport-proto://[hostname]ip46-addr:port - * eg. tcp://ip46-addr:port - * tls://[testtsl.fd.io]ip46-addr:port + * transport-proto://[hostname]ip4-addr:port + * eg. tcp://ip4-addr:port + * https://[ip6]:port + * http://ip4:port + * tls://[testtsl.fd.io]ip4-addr:port * * u8 ip46_address[16]; * u16 port_in_host_byte_order; @@ -43,78 +45,70 @@ unformat_vnet_uri (unformat_input_t *input, va_list *args) session_endpoint_cfg_t *sep = va_arg (*args, session_endpoint_cfg_t *); u32 transport_proto = 0, port; - if (unformat (input, "%U://%U:%d", unformat_transport_proto, - &transport_proto, unformat_ip4_address, &sep->ip.ip4, &port)) + if (unformat (input, "%U:", unformat_transport_proto, &transport_proto)) { sep->transport_proto = transport_proto; - sep->port = clib_host_to_net_u16 (port); - sep->is_ip4 = 1; - return 1; } - else if (unformat (input, "%U://%U/%d", unformat_transport_proto, - &transport_proto, unformat_ip4_address, &sep->ip.ip4, - &port)) + else if (unformat (input, "%Us:", unformat_transport_proto, + &transport_proto)) { + sep->flags |= SESSION_ENDPT_CFG_F_SECURE; sep->transport_proto = transport_proto; - sep->port = clib_host_to_net_u16 (port); + } + + if (unformat (input, "//%U:", unformat_ip4_address, &sep->ip.ip4)) + { sep->is_ip4 = 1; - return 1; } - else if (unformat (input, "%U://%U", unformat_transport_proto, - &transport_proto, unformat_ip4_address, &sep->ip.ip4)) + /* deprecated */ + else if (unformat (input, "//%U/", unformat_ip4_address, &sep->ip.ip4)) { - sep->transport_proto = transport_proto; - if (sep->transport_proto == TRANSPORT_PROTO_HTTP) - port = 80; - else if (sep->transport_proto == TRANSPORT_PROTO_TLS) - port = 443; - else - return 0; - - sep->port = clib_host_to_net_u16 (port); sep->is_ip4 = 1; - return 1; } - else if (unformat (input, "%U://[%U]:%d", unformat_transport_proto, - &transport_proto, unformat_ip6_address, &sep->ip.ip6, - &port)) + else if (unformat (input, "//%U", unformat_ip4_address, &sep->ip.ip4)) + { + sep->is_ip4 = 1; + } + /* deprecated */ + else if (unformat (input, "//%U/", unformat_ip6_address, &sep->ip.ip6)) { - sep->transport_proto = transport_proto; - sep->port = clib_host_to_net_u16 (port); sep->is_ip4 = 0; - return 1; } - else if (unformat (input, "%U://[%U]", unformat_transport_proto, - &transport_proto, unformat_ip6_address, &sep->ip.ip6)) + else if (unformat (input, "//[%U]:", unformat_ip6_address, &sep->ip.ip6)) + { + sep->is_ip4 = 0; + } + /* deprecated */ + else if (unformat (input, "//[%U]/", unformat_ip6_address, &sep->ip.ip6)) { - sep->transport_proto = transport_proto; - if (sep->transport_proto == TRANSPORT_PROTO_HTTP) - port = 80; - else if (sep->transport_proto == TRANSPORT_PROTO_TLS) - port = 443; - else - return 0; - - sep->port = clib_host_to_net_u16 (port); sep->is_ip4 = 0; + } + else if (unformat (input, "//[%U]", unformat_ip6_address, &sep->ip.ip6)) + { + sep->is_ip4 = 0; + } + else if (unformat (input, "//session/%lu", &sep->parent_handle)) + { + sep->ip.ip4.as_u32 = 1; /* ip need to be non zero in vnet */ return 1; } - else if (unformat (input, "%U://%U/%d", unformat_transport_proto, - &transport_proto, unformat_ip6_address, &sep->ip.ip6, - &port)) + + if (unformat (input, "%d", &port)) { - sep->transport_proto = transport_proto; sep->port = clib_host_to_net_u16 (port); - sep->is_ip4 = 0; return 1; } - else if (unformat (input, "%U://session/%lu", unformat_transport_proto, - &transport_proto, &sep->parent_handle)) + else if (sep->transport_proto == TRANSPORT_PROTO_HTTP) { - sep->transport_proto = transport_proto; - sep->ip.ip4.as_u32 = 1; /* ip need to be non zero in vnet */ + sep->port = clib_host_to_net_u16 (80); return 1; } + else if (sep->transport_proto == TRANSPORT_PROTO_TLS) + { + sep->port = clib_host_to_net_u16 (443); + return 1; + } + return 0; } diff --git a/src/vnet/session/session_types.h b/src/vnet/session/session_types.h index 935f8f189ee..0c5afd40183 100644 --- a/src/vnet/session/session_types.h +++ b/src/vnet/session/session_types.h @@ -49,7 +49,9 @@ typedef struct _session_endpoint #undef _ } session_endpoint_t; -#define foreach_session_endpoint_cfg_flags _ (PROXY_LISTEN, "proxy listener") +#define foreach_session_endpoint_cfg_flags \ + _ (PROXY_LISTEN, "proxy listener") \ + _ (SECURE, "secure") typedef enum session_endpoint_cfg_flags_bits_ {