From e05f51a8ae279f99323c7ebf8a5bac88a47b5c40 Mon Sep 17 00:00:00 2001
From: Sean Bright <sean@seanbright.com>
Date: Wed, 2 Aug 2023 09:56:49 -0400
Subject: [PATCH] res_pjsip: Enable TLS v1.3 if present.

Fixes #221

UserNote: res_pjsip now allows TLS v1.3 to be enabled if supported by
the underlying PJSIP library. The bundled version of PJSIP supports
TLS v1.3.

(cherry picked from commit b5762cd54e8c169646f3c52f522512f4bed53ac1)
---
 configure                          | 177 +++++++++++++++++++++++++++++
 configure.ac                       |   6 +
 include/asterisk/autoconfig.h.in   |   9 ++
 res/res_pjsip/config_transport.c   |  15 ++-
 res/res_pjsip/pjsip_config.xml     |   3 +
 third-party/pjproject/configure.m4 |   3 +
 6 files changed, 211 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 0b328219ef..de576d0bc4 100755
--- a/configure
+++ b/configure
@@ -950,6 +950,18 @@ PBX_PJSIP_EVSUB_GRP_LOCK
 PJSIP_EVSUB_GRP_LOCK_DIR
 PJSIP_EVSUB_GRP_LOCK_INCLUDE
 PJSIP_EVSUB_GRP_LOCK_LIB
+PBX_PJSIP_TLS_1_3
+PJSIP_TLS_1_3_DIR
+PJSIP_TLS_1_3_INCLUDE
+PJSIP_TLS_1_3_LIB
+PBX_PJSIP_TLS_1_2
+PJSIP_TLS_1_2_DIR
+PJSIP_TLS_1_2_INCLUDE
+PJSIP_TLS_1_2_LIB
+PBX_PJSIP_TLS_1_1
+PJSIP_TLS_1_1_DIR
+PJSIP_TLS_1_1_INCLUDE
+PJSIP_TLS_1_1_LIB
 PBX_PJSIP_TLS_TRANSPORT_PROTO
 PJSIP_TLS_TRANSPORT_PROTO_DIR
 PJSIP_TLS_TRANSPORT_PROTO_INCLUDE
@@ -10262,6 +10274,15 @@ $as_echo "#define HAVE_PJSIP_EXTERNAL_RESOLVER 1" >>confdefs.h
 $as_echo "#define HAVE_PJSIP_TLS_TRANSPORT_PROTO 1" >>confdefs.h
 
 
+$as_echo "#define HAVE_PJSIP_TLS_1_1 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_PJSIP_TLS_1_2 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_PJSIP_TLS_1_3 1" >>confdefs.h
+
+
 $as_echo "#define HAVE_PJSIP_EVSUB_GRP_LOCK 1" >>confdefs.h
 
 
@@ -12208,6 +12229,42 @@ PBX_PJSIP_TLS_TRANSPORT_PROTO=0
 
 
 
+PJSIP_TLS_1_1_DESCRIP="PJSIP TLS 1.1 Support"
+PJSIP_TLS_1_1_OPTION=pjsip
+PJSIP_TLS_1_1_DIR=${PJPROJECT_DIR}
+
+PBX_PJSIP_TLS_1_1=0
+
+
+
+
+
+
+
+PJSIP_TLS_1_2_DESCRIP="PJSIP TLS 1.2 Support"
+PJSIP_TLS_1_2_OPTION=pjsip
+PJSIP_TLS_1_2_DIR=${PJPROJECT_DIR}
+
+PBX_PJSIP_TLS_1_2=0
+
+
+
+
+
+
+
+PJSIP_TLS_1_3_DESCRIP="PJSIP TLS 1.3 Support"
+PJSIP_TLS_1_3_OPTION=pjsip
+PJSIP_TLS_1_3_DIR=${PJPROJECT_DIR}
+
+PBX_PJSIP_TLS_1_3=0
+
+
+
+
+
+
+
 PJSIP_EVSUB_GRP_LOCK_DESCRIP="PJSIP EVSUB Group Lock support"
 PJSIP_EVSUB_GRP_LOCK_OPTION=pjsip
 PJSIP_EVSUB_GRP_LOCK_DIR=${PJPROJECT_DIR}
@@ -25418,6 +25475,126 @@ $as_echo "#define HAVE_PJSIP_TLS_TRANSPORT_PROTO 1" >>confdefs.h
 
 
 
+else
+         { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	CPPFLAGS="${saved_cppflags}"
+    fi
+
+
+    if test "x${PBX_PJSIP_TLS_1_1}" != "x1" -a "${USE_PJSIP_TLS_1_1}" != "no"; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if \"enum pjsip_ssl_method method = PJSIP_TLSV1_1_METHOD;\" compiles using pjsip.h" >&5
+$as_echo_n "checking if \"enum pjsip_ssl_method method = PJSIP_TLSV1_1_METHOD;\" compiles using pjsip.h... " >&6; }
+	saved_cppflags="${CPPFLAGS}"
+	if test "x${PJSIP_TLS_1_1_DIR}" != "x"; then
+	    PJSIP_TLS_1_1_INCLUDE="-I${PJSIP_TLS_1_1_DIR}/include"
+	fi
+	CPPFLAGS="${CPPFLAGS} ${PJSIP_TLS_1_1_INCLUDE}"
+
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <pjsip.h>
+int
+main ()
+{
+ enum pjsip_ssl_method method = PJSIP_TLSV1_1_METHOD;;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+     { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		PBX_PJSIP_TLS_1_1=1
+
+$as_echo "#define HAVE_PJSIP_TLS_1_1 1" >>confdefs.h
+
+
+
+else
+         { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	CPPFLAGS="${saved_cppflags}"
+    fi
+
+
+    if test "x${PBX_PJSIP_TLS_1_2}" != "x1" -a "${USE_PJSIP_TLS_1_2}" != "no"; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if \"enum pjsip_ssl_method method = PJSIP_TLSV1_2_METHOD;\" compiles using pjsip.h" >&5
+$as_echo_n "checking if \"enum pjsip_ssl_method method = PJSIP_TLSV1_2_METHOD;\" compiles using pjsip.h... " >&6; }
+	saved_cppflags="${CPPFLAGS}"
+	if test "x${PJSIP_TLS_1_2_DIR}" != "x"; then
+	    PJSIP_TLS_1_2_INCLUDE="-I${PJSIP_TLS_1_2_DIR}/include"
+	fi
+	CPPFLAGS="${CPPFLAGS} ${PJSIP_TLS_1_2_INCLUDE}"
+
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <pjsip.h>
+int
+main ()
+{
+ enum pjsip_ssl_method method = PJSIP_TLSV1_2_METHOD;;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+     { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		PBX_PJSIP_TLS_1_2=1
+
+$as_echo "#define HAVE_PJSIP_TLS_1_2 1" >>confdefs.h
+
+
+
+else
+         { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	CPPFLAGS="${saved_cppflags}"
+    fi
+
+
+    if test "x${PBX_PJSIP_TLS_1_3}" != "x1" -a "${USE_PJSIP_TLS_1_3}" != "no"; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if \"enum pjsip_ssl_method method = PJSIP_TLSV1_3_METHOD;\" compiles using pjsip.h" >&5
+$as_echo_n "checking if \"enum pjsip_ssl_method method = PJSIP_TLSV1_3_METHOD;\" compiles using pjsip.h... " >&6; }
+	saved_cppflags="${CPPFLAGS}"
+	if test "x${PJSIP_TLS_1_3_DIR}" != "x"; then
+	    PJSIP_TLS_1_3_INCLUDE="-I${PJSIP_TLS_1_3_DIR}/include"
+	fi
+	CPPFLAGS="${CPPFLAGS} ${PJSIP_TLS_1_3_INCLUDE}"
+
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <pjsip.h>
+int
+main ()
+{
+ enum pjsip_ssl_method method = PJSIP_TLSV1_3_METHOD;;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+     { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		PBX_PJSIP_TLS_1_3=1
+
+$as_echo "#define HAVE_PJSIP_TLS_1_3 1" >>confdefs.h
+
+
+
 else
          { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
diff --git a/configure.ac b/configure.ac
index 9e5e54668d..458ea41ff9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -581,6 +581,9 @@ AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_GET_DEST_INFO], [pjsip_get_dest_info support],
 AST_EXT_LIB_SETUP_OPTIONAL([PJ_SSL_CERT_LOAD_FROM_FILES2], [pj_ssl_cert_load_from_files2 support], [PJPROJECT], [pjsip])
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EXTERNAL_RESOLVER], [PJSIP External Resolver Support], [PJPROJECT], [pjsip])
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_TRANSPORT_PROTO], [PJSIP TLS Transport proto field support], [PJPROJECT], [pjsip])
+AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_1_1], [PJSIP TLS 1.1 Support], [PJPROJECT], [pjsip])
+AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_1_2], [PJSIP TLS 1.2 Support], [PJPROJECT], [pjsip])
+AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_1_3], [PJSIP TLS 1.3 Support], [PJPROJECT], [pjsip])
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EVSUB_GRP_LOCK], [PJSIP EVSUB Group Lock support], [PJPROJECT], [pjsip])
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_INV_SESSION_REF], [PJSIP INVITE Session Reference Count support], [PJPROJECT], [pjsip])
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_AUTH_CLT_DEINIT], [pjsip_auth_clt_deinit support], [PJPROJECT], [pjsip])
@@ -2478,6 +2481,9 @@ if test "$USE_PJPROJECT" != "no" ; then
          CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
          LIBS="${LIBS} ${PJPROJECT_LIB}"
          AST_C_COMPILE_CHECK([PJSIP_TLS_TRANSPORT_PROTO], [struct pjsip_tls_setting setting; int proto; proto = setting.proto;], [pjsip.h])
+         AST_C_COMPILE_CHECK([PJSIP_TLS_1_1], [enum pjsip_ssl_method method = PJSIP_TLSV1_1_METHOD;], [pjsip.h])
+         AST_C_COMPILE_CHECK([PJSIP_TLS_1_2], [enum pjsip_ssl_method method = PJSIP_TLSV1_2_METHOD;], [pjsip.h])
+         AST_C_COMPILE_CHECK([PJSIP_TLS_1_3], [enum pjsip_ssl_method method = PJSIP_TLSV1_3_METHOD;], [pjsip.h])
          AST_C_COMPILE_CHECK([PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS], [pjsip_cfg()->endpt.accept_multiple_sdp_answers = 0;], [pjsip.h])
          AST_C_COMPILE_CHECK([PJSIP_ENDPOINT_COMPACT_FORM], [pjsip_cfg()->endpt.use_compact_form = PJ_TRUE;], [pjsip.h])
          AST_C_COMPILE_CHECK([PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE], [struct pjsip_tpselector sel; sel.disable_connection_reuse = PJ_TRUE;], [pjsip.h])
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index 6f643fa6e5..d8408cf5e3 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -653,6 +653,15 @@
 /* Define if your system has the PJSIP_REPLACE_MEDIA_STREAM headers. */
 #undef HAVE_PJSIP_REPLACE_MEDIA_STREAM
 
+/* Define if your system has the PJSIP_TLS_1_1 headers. */
+#undef HAVE_PJSIP_TLS_1_1
+
+/* Define if your system has the PJSIP_TLS_1_2 headers. */
+#undef HAVE_PJSIP_TLS_1_2
+
+/* Define if your system has the PJSIP_TLS_1_3 headers. */
+#undef HAVE_PJSIP_TLS_1_3
+
 /* Define if your system has the PJSIP_TLS_TRANSPORT_PROTO headers. */
 #undef HAVE_PJSIP_TLS_TRANSPORT_PROTO
 
diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c
index c8655c2eea..f4f6efc5cd 100644
--- a/res/res_pjsip/config_transport.c
+++ b/res/res_pjsip/config_transport.c
@@ -1221,11 +1221,17 @@ static int transport_tls_method_handler(const struct aco_option *opt, struct ast
 		state->tls.method = PJSIP_SSL_UNSPECIFIED_METHOD;
 	} else if (!strcasecmp(var->value, "tlsv1")) {
 		state->tls.method = PJSIP_TLSV1_METHOD;
-#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
+#ifdef HAVE_PJSIP_TLS_1_1
 	} else if (!strcasecmp(var->value, "tlsv1_1")) {
 		state->tls.method = PJSIP_TLSV1_1_METHOD;
+#endif
+#ifdef HAVE_PJSIP_TLS_1_2
 	} else if (!strcasecmp(var->value, "tlsv1_2")) {
 		state->tls.method = PJSIP_TLSV1_2_METHOD;
+#endif
+#ifdef HAVE_PJSIP_TLS_1_3
+	} else if (!strcasecmp(var->value, "tlsv1_3")) {
+		state->tls.method = PJSIP_TLSV1_3_METHOD;
 #endif
 	} else if (!strcasecmp(var->value, "sslv2")) {
 		state->tls.method = PJSIP_SSLV2_METHOD;
@@ -1243,9 +1249,14 @@ static int transport_tls_method_handler(const struct aco_option *opt, struct ast
 static const char *tls_method_map[] = {
 	[PJSIP_SSL_UNSPECIFIED_METHOD] = "unspecified",
 	[PJSIP_TLSV1_METHOD] = "tlsv1",
-#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
+#ifdef HAVE_PJSIP_TLS_1_1
 	[PJSIP_TLSV1_1_METHOD] = "tlsv1_1",
+#endif
+#ifdef HAVE_PJSIP_TLS_1_2
 	[PJSIP_TLSV1_2_METHOD] = "tlsv1_2",
+#endif
+#ifdef HAVE_PJSIP_TLS_1_3
+	[PJSIP_TLSV1_3_METHOD] = "tlsv1_3",
 #endif
 	[PJSIP_SSLV2_METHOD] = "sslv2",
 	[PJSIP_SSLV3_METHOD] = "sslv3",
diff --git a/res/res_pjsip/pjsip_config.xml b/res/res_pjsip/pjsip_config.xml
index bbbdd12670..2f4a090f8f 100644
--- a/res/res_pjsip/pjsip_config.xml
+++ b/res/res_pjsip/pjsip_config.xml
@@ -1749,6 +1749,8 @@
 				<configOption name="method">
 					<synopsis>Method of SSL transport (TLS ONLY, not WSS)</synopsis>
 					<description>
+						<para>The availability of each of these options is dependent on the
+						version and configuration of the underlying PJSIP library.</para>
 						<enumlist>
 							<enum name="default">
 								<para>The default as defined by PJSIP. This is currently TLSv1, but may change with future releases.</para>
@@ -1759,6 +1761,7 @@
 							<enum name="tlsv1" />
 							<enum name="tlsv1_1" />
 							<enum name="tlsv1_2" />
+							<enum name="tlsv1_3" />
 							<enum name="sslv2" />
 							<enum name="sslv3" />
 							<enum name="sslv23" />
diff --git a/third-party/pjproject/configure.m4 b/third-party/pjproject/configure.m4
index 0995cfc992..eb768731c0 100644
--- a/third-party/pjproject/configure.m4
+++ b/third-party/pjproject/configure.m4
@@ -126,6 +126,9 @@ AC_DEFUN([_PJPROJECT_CONFIGURE],
 		AC_DEFINE([HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2], 1, [Define if your system has pj_ssl_cert_load_from_files2 declared.])
 		AC_DEFINE([HAVE_PJSIP_EXTERNAL_RESOLVER], 1, [Define if your system has pjsip_endpt_set_ext_resolver declared.])
 		AC_DEFINE([HAVE_PJSIP_TLS_TRANSPORT_PROTO], 1, [Define if your system has PJSIP_TLS_TRANSPORT_PROTO])
+		AC_DEFINE([HAVE_PJSIP_TLS_1_1], 1, [Define if your system has PJSIP with TLSv1.1 support.])
+		AC_DEFINE([HAVE_PJSIP_TLS_1_2], 1, [Define if your system has PJSIP with TLSv1.2 support.])
+		AC_DEFINE([HAVE_PJSIP_TLS_1_3], 1, [Define if your system has PJSIP with TLSv1.3 support.])
 		AC_DEFINE([HAVE_PJSIP_EVSUB_GRP_LOCK], 1, [Define if your system has PJSIP_EVSUB_GRP_LOCK])
 		AC_DEFINE([HAVE_PJSIP_INV_SESSION_REF], 1, [Define if your system has PJSIP_INV_SESSION_REF])
 		AC_DEFINE([HAVE_PJSIP_AUTH_CLT_DEINIT], 1, [Define if your system has pjsip_auth_clt_deinit declared.])