From 34095f59a3d54440bb1d5a79f19d3370380b20a2 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Wed, 12 Jul 2023 16:13:21 +0700 Subject: [PATCH] Add native SSL socket instance in TLS verification callback\ --- pjlib/include/pj/ssl_sock.h | 10 ++++++++++ pjlib/src/pj/ssl_sock_imp_common.c | 15 ++++++++++++--- pjlib/src/pj/ssl_sock_ossl.c | 25 +++++++++++++++---------- pjsip/include/pjsip/sip_transport_tls.h | 9 +++++++++ pjsip/src/pjsip/sip_transport_tls.c | 1 + 5 files changed, 47 insertions(+), 13 deletions(-) diff --git a/pjlib/include/pj/ssl_sock.h b/pjlib/include/pj/ssl_sock.h index 767e5032e..d12f4a0cd 100644 --- a/pjlib/include/pj/ssl_sock.h +++ b/pjlib/include/pj/ssl_sock.h @@ -682,6 +682,10 @@ typedef struct pj_ssl_sock_cb * Certification info can be obtained from #pj_ssl_sock_info. Currently * it's only implemented for OpenSSL backend. * + * If this is set, the callback will always be invoked, even when peer + * verification is disabled (pj_ssl_sock_param.verify_peer set to + * PJ_FALSE). + * * @param ssock The secure socket. * @param is_server PJ_TRUE to indicate an incoming connection. * @@ -809,6 +813,12 @@ typedef struct pj_ssl_sock_info */ pj_grp_lock_t *grp_lock; + /** + * Native TLS/SSL instance of the backend. Currently only available for + * OpenSSL backend (this will contain the OpenSSL "SSL" instance). + */ + void *native_ssl; + } pj_ssl_sock_info; diff --git a/pjlib/src/pj/ssl_sock_imp_common.c b/pjlib/src/pj/ssl_sock_imp_common.c index 3d6b24285..324720cd6 100644 --- a/pjlib/src/pj/ssl_sock_imp_common.c +++ b/pjlib/src/pj/ssl_sock_imp_common.c @@ -1574,17 +1574,26 @@ PJ_DEF(pj_status_t) pj_ssl_sock_get_info (pj_ssl_sock_t *ssock, if (info->established) { info->cipher = ssl_get_cipher(ssock); - - /* Verification status */ - info->verify_status = ssock->verify_status; } + /* Verification status */ + info->verify_status = ssock->verify_status; + /* Last known SSL error code */ info->last_native_err = ssock->last_err; /* Group lock */ info->grp_lock = ssock->param.grp_lock; + /* Native SSL object */ +#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0 && \ + (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_OPENSSL) + { + ossl_sock_t *ossock = (ossl_sock_t *)ssock; + info->native_ssl = ossock->ossl_ssl; + } +#endif + return PJ_SUCCESS; } diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c index d31cd5c82..a13e2a163 100644 --- a/pjlib/src/pj/ssl_sock_ossl.c +++ b/pjlib/src/pj/ssl_sock_ossl.c @@ -36,7 +36,7 @@ #if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0 && \ (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_OPENSSL) -#include "ssl_sock_imp_common.c" +#include "ssl_sock_imp_common.h" #define THIS_FILE "ssl_sock_ossl.c" @@ -230,6 +230,10 @@ typedef struct ossl_sock_t BIO *ossl_wbio; } ossl_sock_t; + +#include "ssl_sock_imp_common.c" + + /** * Mapping from OpenSSL error codes to pjlib error space. */ @@ -946,15 +950,6 @@ static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) goto on_return; } - if (ssock->param.cb.on_verify_cb) { - update_certs_info(ssock, x509_ctx, &ssock->local_cert_info, - &ssock->remote_cert_info, PJ_TRUE); - preverify_ok = (*ssock->param.cb.on_verify_cb)(ssock, - ssock->is_server); - - goto on_return; - } - /* Store verification status */ err = X509_STORE_CTX_get_error(x509_ctx); switch (err) { @@ -1025,6 +1020,16 @@ static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) break; } + /* Invoke app's verification callback */ + if (ssock->param.cb.on_verify_cb) { + update_certs_info(ssock, x509_ctx, &ssock->local_cert_info, + &ssock->remote_cert_info, PJ_TRUE); + preverify_ok = (*ssock->param.cb.on_verify_cb)(ssock, + ssock->is_server); + + goto on_return; + } + /* When verification is not requested just return ok here, however * application can still get the verification status. */ diff --git a/pjsip/include/pjsip/sip_transport_tls.h b/pjsip/include/pjsip/sip_transport_tls.h index 53062fac4..731b86b0e 100644 --- a/pjsip/include/pjsip/sip_transport_tls.h +++ b/pjsip/include/pjsip/sip_transport_tls.h @@ -132,6 +132,11 @@ typedef struct pjsip_tls_on_verify_param { */ pj_ssl_cert_info *remote_cert_info; + /** + * The SSL socket instance. + */ + pj_ssl_sock_t *ssock; + } pjsip_tls_on_verify_param; @@ -379,6 +384,10 @@ typedef struct pjsip_tls_setting * Callback to be called to verify a new connection. Currently it's only * implemented for OpenSSL backend. * + * If this is set, the callback will always be invoked, even when peer + * verification is disabled (pjsip_tls_setting.verify_server/verify_client + * set to PJ_FALSE). + * * @param param The parameter to the callback. * * @return Return PJ_TRUE if succesfully verified. diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c index 3c0a6ae92..b44b1cf8d 100644 --- a/pjsip/src/pjsip/sip_transport_tls.c +++ b/pjsip/src/pjsip/sip_transport_tls.c @@ -1621,6 +1621,7 @@ static pj_bool_t on_verify_cb(pj_ssl_sock_t* ssock, pj_bool_t is_server) param.local_cert_info = info.local_cert_info; param.remote_cert_info = info.remote_cert_info; param.tp_dir = is_server?PJSIP_TP_DIR_INCOMING:PJSIP_TP_DIR_OUTGOING; + param.ssock = ssock; return (*verify_cb)(¶m); }