@@ -906,6 +906,88 @@ int test_tls_set_session_min_downgrade(void)
906906 return EXPECT_RESULT ();
907907}
908908
909+ #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
910+ !defined(WOLFSSL_NO_TLS12 ) && defined(HAVE_SNI ) && \
911+ defined(HAVE_SESSION_TICKET ) && !defined(NO_SESSION_CACHE )
912+ /* Accept-all SNI callback. */
913+ static int accept_any_sni_cb (WOLFSSL * ssl , int * ret , void * arg )
914+ {
915+ (void )ssl ; (void )ret ; (void )arg ;
916+ return 0 ; /* accept */
917+ }
918+ #endif
919+
920+ /* TLS resumption must proceed with full handshake to establish new session if
921+ * SNI/ALPN does not match previously established session. */
922+ int test_tls12_session_id_resumption_sni_mismatch (void )
923+ {
924+ EXPECT_DECLS ;
925+ #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES ) && \
926+ !defined(WOLFSSL_NO_TLS12 ) && defined(HAVE_SNI ) && \
927+ defined(HAVE_SESSION_TICKET ) && !defined(NO_SESSION_CACHE )
928+ WOLFSSL_CTX * ctx_c = NULL , * ctx_s = NULL ;
929+ WOLFSSL * ssl_c = NULL , * ssl_s = NULL ;
930+ WOLFSSL_SESSION * sess = NULL ;
931+ struct test_memio_ctx test_ctx ;
932+ const char * sniA = "public.example" ;
933+ const char * sniB = "admin.example" ;
934+
935+ /* Step 1: full TLS 1.2 handshake under SNI=public.example, with the
936+ * session ticket path disabled so resumption can only happen via the
937+ * server's session-ID cache. The server-side SNI callback ensures
938+ * ssl->extensions retains the client's SNI in builds that don't
939+ * compile in WOLFSSL_ALWAYS_KEEP_SNI. */
940+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
941+ ExpectIntEQ (test_memio_setup (& test_ctx , & ctx_c , & ctx_s , & ssl_c , & ssl_s ,
942+ wolfTLSv1_2_client_method , wolfTLSv1_2_server_method ), 0 );
943+ wolfSSL_CTX_set_servername_callback (ctx_s , accept_any_sni_cb );
944+ ExpectIntEQ (wolfSSL_NoTicketTLSv12 (ssl_c ), WOLFSSL_SUCCESS );
945+ ExpectIntEQ (wolfSSL_NoTicketTLSv12 (ssl_s ), WOLFSSL_SUCCESS );
946+ ExpectIntEQ (wolfSSL_UseSNI (ssl_c , WOLFSSL_SNI_HOST_NAME ,
947+ sniA , (word16 )XSTRLEN (sniA )), WOLFSSL_SUCCESS );
948+ ExpectIntEQ (test_memio_do_handshake (ssl_c , ssl_s , 10 , NULL ), 0 );
949+ /* Sanity: the first handshake was not a resumption. */
950+ ExpectIntEQ (wolfSSL_session_reused (ssl_s ), 0 );
951+ ExpectNotNull (sess = wolfSSL_get1_session (ssl_c ));
952+
953+ wolfSSL_free (ssl_c ); ssl_c = NULL ;
954+ wolfSSL_free (ssl_s ); ssl_s = NULL ;
955+
956+ /* Step 2: new SSL objects on the SAME WOLFSSL_CTX (so the server's
957+ * session cache still holds the entry from step 1). The client offers
958+ * the saved session but advertises a *different* SNI. The server's
959+ * cache lookup will match by session ID, but per RFC 6066 Section 3 the
960+ * server MUST NOT resume because the SNI differs from the original. */
961+ XMEMSET (& test_ctx , 0 , sizeof (test_ctx ));
962+ ExpectNotNull (ssl_c = wolfSSL_new (ctx_c ));
963+ wolfSSL_SetIOReadCtx (ssl_c , & test_ctx );
964+ wolfSSL_SetIOWriteCtx (ssl_c , & test_ctx );
965+ ExpectNotNull (ssl_s = wolfSSL_new (ctx_s ));
966+ wolfSSL_SetIOReadCtx (ssl_s , & test_ctx );
967+ wolfSSL_SetIOWriteCtx (ssl_s , & test_ctx );
968+ ExpectIntEQ (wolfSSL_NoTicketTLSv12 (ssl_c ), WOLFSSL_SUCCESS );
969+ ExpectIntEQ (wolfSSL_NoTicketTLSv12 (ssl_s ), WOLFSSL_SUCCESS );
970+ ExpectIntEQ (wolfSSL_UseSNI (ssl_c , WOLFSSL_SNI_HOST_NAME ,
971+ sniB , (word16 )XSTRLEN (sniB )), WOLFSSL_SUCCESS );
972+ ExpectIntEQ (wolfSSL_set_session (ssl_c , sess ), WOLFSSL_SUCCESS );
973+ ExpectIntEQ (test_memio_do_handshake (ssl_c , ssl_s , 10 , NULL ), 0 );
974+
975+ /* Post-fix expected behavior: server falls back to a full handshake
976+ * because the SNI in the ClientHello does not match the SNI bound to
977+ * the cached session. Pre-fix, the server silently resumes - which is
978+ * the bug. Both sides should report no resumption. */
979+ ExpectIntEQ (wolfSSL_session_reused (ssl_s ), 0 );
980+ ExpectIntEQ (wolfSSL_session_reused (ssl_c ), 0 );
981+
982+ wolfSSL_SESSION_free (sess );
983+ wolfSSL_free (ssl_c );
984+ wolfSSL_free (ssl_s );
985+ wolfSSL_CTX_free (ctx_c );
986+ wolfSSL_CTX_free (ctx_s );
987+ #endif
988+ return EXPECT_RESULT ();
989+ }
990+
909991int test_tls_set_curves_list_ecc_fallback (void )
910992{
911993 EXPECT_DECLS ;
0 commit comments