Commit 8ebf9a35 authored by Simon Morlat's avatar Simon Morlat

Add new property in [sip] section called "tls_certificate_subject_regexp"...

Add new property in [sip] section called "tls_certificate_subject_regexp" providing a regexp to match with TLS certificate subjects:
subjectAltNames.DNS subjectAltNames.URI and CN.
If nothing is matched the TLS connection is rejected.
parent b764d644
......@@ -42,8 +42,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <ortp/telephonyevents.h>
#include <mediastreamer2/zrtp.h>
#include <mediastreamer2/dtls_srtp.h>
#include <bctoolbox/defs.h>
#include <belr/grammarbuilder.h>
#include "bctoolbox/defs.h"
#include "bctoolbox/regex.h"
#include "belr/grammarbuilder.h"
#include "mediastreamer2/dtmfgen.h"
#include "mediastreamer2/mediastream.h"
......@@ -53,6 +54,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mediastreamer2/msjpegwriter.h"
#include "mediastreamer2/msogl.h"
#include "mediastreamer2/msvolume.h"
#include "bctoolbox/charconv.h"
#include "chat/chat-room/client-group-chat-room-p.h"
......@@ -69,6 +71,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "address/address-p.h"
#include "c-wrapper/c-wrapper.h"
#ifdef INET6
#ifndef _WIN32
#include <netdb.h>
......@@ -1274,6 +1277,34 @@ static void sound_config_read(LinphoneCore *lc)
_linphone_core_set_tone(lc,LinphoneReasonBusy,LinphoneToneBusy,NULL);
}
static int _linphone_core_tls_postcheck_callback(void *data, const bctbx_x509_certificate_t *peer_cert){
LinphoneCore *lc = (LinphoneCore *) data;
const char *tls_certificate_subject_regexp = lp_config_get_string(lc->config,"sip","tls_certificate_subject_regexp", NULL);
int ret = 0;
if (tls_certificate_subject_regexp){
ret = -1;
/*the purpose of this handling is to a peer certificate for which there is no single subject matching the regexp given
* in the "tls_certificate_subject_regexp" property.
*/
bctbx_list_t *subjects = bctbx_x509_certificate_get_subjects(peer_cert);
bctbx_list_t *elem;
for(elem = subjects; elem != NULL; elem = elem->next){
const char *subject = (const char *)elem->data;
ms_message("_linphone_core_tls_postcheck_callback: subject=%s", subject);
if (bctbx_is_matching_regex(subject, tls_certificate_subject_regexp)){
ret = 0;
ms_message("_linphone_core_tls_postcheck_callback(): successful by matching '%s'", subject);
break;
}
}
bctbx_list_free_with_data(subjects, bctbx_free);
}
if (ret == -1){
ms_message("_linphone_core_tls_postcheck_callback(): postcheck failed, nothing matched.");
}
return ret;
}
static void certificates_config_read(LinphoneCore *lc) {
LinphoneFactory *factory = linphone_factory_get();
const char *data_dir = linphone_factory_get_data_resources_dir(factory);
......@@ -1295,6 +1326,8 @@ static void certificates_config_read(LinphoneCore *lc) {
linphone_core_verify_server_certificates(lc, !!lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE));
linphone_core_verify_server_cn(lc, !!lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE));
bctbx_free(root_ca_path);
lc->sal->setTlsPostcheckCallback(_linphone_core_tls_postcheck_callback, lc);
}
static void sip_config_read(LinphoneCore *lc) {
......
......@@ -33,6 +33,7 @@
#include "mediastreamer2/mediastream.h"
#include "ortp/rtpsession.h"
#include "belle-sip/belle-sip.h"
#include "bctoolbox/crypto.h"
#ifndef LINPHONE_PUBLIC
#if defined(_MSC_VER)
......
......@@ -469,6 +469,7 @@ void Sal::setTlsProperties(){
if (!mRootCaData.empty())
belle_tls_crypto_config_set_root_ca_data(crypto_config, mRootCaData.c_str());
if (mSslConfig != NULL) belle_tls_crypto_config_set_ssl_config(crypto_config, mSslConfig);
if (mTlsPostcheckCb) belle_tls_crypto_config_set_postcheck_callback(crypto_config, mTlsPostcheckCb, mTlsPostcheckCbData);
belle_sip_tls_listening_point_set_crypto_config(tlp, crypto_config);
belle_sip_object_unref(crypto_config);
}
......@@ -707,6 +708,11 @@ void Sal::setSslConfig(void *ssl_config) {
setTlsProperties();
}
void Sal::setTlsPostcheckCallback(int (*cb)(void *, const bctbx_x509_certificate_t *), void *data){
mTlsPostcheckCb = cb;
mTlsPostcheckCbData = data;
}
int Sal::createUuid(char *uuid, size_t len) {
if (generateUuid(uuid, len) == 0) {
setUuid(uuid);
......
......@@ -224,7 +224,7 @@ public:
void verifyServerCertificates (bool value);
void verifyServerCn (bool value);
void setTlsPostcheckCallback(int (*cb)(void *, const bctbx_x509_certificate_t *), void *data);
// ---------------------------------------------------------------------------
// DNS resolution
......@@ -317,6 +317,8 @@ private:
void *mSslConfig = nullptr;
std::vector<std::string> mSupportedContentTypes;
std::string mLinphoneSpecs;
belle_tls_crypto_config_postcheck_callback_t mTlsPostcheckCb;
void *mTlsPostcheckCbData;
// Cache values
mutable std::string mDnsUserHostsFile;
......
......@@ -999,6 +999,36 @@ static void tls_certificate_failure(void){
}
}
static void tls_certificate_subject_check(void){
if (transport_supported(LinphoneTransportTls)) {
LinphoneCoreManager* lcm;
LinphoneCore *lc;
char *rootcapath = bc_tester_res("certificates/cn/cafile.pem");
lcm=linphone_core_manager_new2("pauline_alt_rc",FALSE);
lc=lcm->lc;
linphone_core_set_root_ca(lc, rootcapath);
/*let's search for a subject that is not in the certificate, it should fail*/
lp_config_set_string(linphone_core_get_config(lc), "sip", "tls_certificate_subject_regexp", "cotcotcot.org");
linphone_core_set_network_reachable(lc,TRUE);
BC_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&lcm->stat.number_of_LinphoneRegistrationFailed,1));
/*let's search for a subject (in subjectAltNames and CN) that exist in the certificate, it should pass*/
lp_config_set_string(linphone_core_get_config(lc), "sip", "tls_certificate_subject_regexp", "altname.linphone.org");
linphone_core_refresh_registers(lcm->lc);
BC_ASSERT_TRUE(wait_for(lc,lc,&lcm->stat.number_of_LinphoneRegistrationOk,1));
linphone_core_set_network_reachable(lc,FALSE);
/*let's search for a subject (in subjectAltNames and CN) that exist in the certificate, it should pass*/
lp_config_set_string(linphone_core_get_config(lc), "sip", "tls_certificate_subject_regexp", "Jehan Monnier");
linphone_core_set_network_reachable(lc,TRUE);
BC_ASSERT_TRUE(wait_for(lc,lc,&lcm->stat.number_of_LinphoneRegistrationOk,2));
BC_ASSERT_EQUAL(lcm->stat.number_of_LinphoneRegistrationFailed,1, int, "%d");
linphone_core_manager_destroy(lcm);
bc_free(rootcapath);
}
}
char *read_file(const char *path) {
long numbytes = 0;
size_t readbytes;
......@@ -1331,6 +1361,7 @@ test_t register_tests[] = {
TEST_NO_TAG("TLS register with alt. name certificate", tls_alt_name_register),
TEST_NO_TAG("TLS register with wildcard certificate", tls_wildcard_register),
TEST_NO_TAG("TLS certificate not verified",tls_certificate_failure),
TEST_NO_TAG("TLS certificate subjects check",tls_certificate_subject_check),
TEST_NO_TAG("TLS certificate given by string instead of file",tls_certificate_data),
TEST_NO_TAG("TLS with non tls server",tls_with_non_tls_server),
TEST_NO_TAG("Simple authenticated register", simple_authenticated_register),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment