diff --git a/CMakeLists.txt b/CMakeLists.txt index 90f4cfe..a9160e0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,22 +200,17 @@ if(ASSERT_ON_WRONG_THREAD) endif() if(AUTH_ENABLED) - if(EXISTS ${CMAKE_SYSROOT}/usr/lib/libctrlm-hal-certificate.so) - add_compile_definitions(AUTH_ENABLED) - add_compile_definitions(AUTH_ACCOUNT_ID) - add_compile_definitions(AUTH_DEVICE_ID) - add_compile_definitions(AUTH_PARTNER_ID) - add_compile_definitions(AUTH_SAT_TOKEN) - if(AUTH_ACTIVATION_STATUS) - add_compile_definitions(AUTH_ACTIVATION_STATUS) - endif() - #By default disabled but can be enabled - #add_compile_definitions(AUTH_EXPERIENCE) - target_link_libraries(controlMgr ctrlm-hal-certificate) - else() - message(WARNING "ctrlm-hal-certificate library is not provided, disabling authentication") - unset(AUTH_ENABLED) + add_compile_definitions(AUTH_ENABLED) + add_compile_definitions(AUTH_ACCOUNT_ID) + add_compile_definitions(AUTH_DEVICE_ID) + add_compile_definitions(AUTH_PARTNER_ID) + add_compile_definitions(AUTH_SAT_TOKEN) + if(AUTH_ACTIVATION_STATUS) + add_compile_definitions(AUTH_ACTIVATION_STATUS) endif() + #By default disabled but can be enabled + #add_compile_definitions(AUTH_EXPERIENCE) + target_link_libraries(controlMgr RdkCertSelector) endif() if(BLE_ENABLED) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1959af7..ddb94a8 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -215,6 +215,7 @@ if(THUNDER) target_sources(controlMgr PRIVATE auth/ctrlm_auth.cpp auth/ctrlm_auth_thunder.cpp + auth/ctrlm_auth_certificate.cpp auth/ctrlm_thunder_plugin_authservice.cpp ) endif() diff --git a/src/auth/ctrlm_auth_certificate.cpp b/src/auth/ctrlm_auth_certificate.cpp new file mode 100644 index 0000000..63ff900 --- /dev/null +++ b/src/auth/ctrlm_auth_certificate.cpp @@ -0,0 +1,171 @@ +/* + * If not stated otherwise in this file or this component's license file the + * following copyright and licenses apply: + * + * Copyright 2015 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +#include +#include +#include +#include +#include +#include +#include +#include "rdkcertselector.h" +#include "ctrlm_auth_certificate.h" +#include "ctrlm_utils.h" +#include "ctrlm_log.h" + +#define CERT_FILENAME_PREFIX "file://" + +ctrlm_auth_certificate_t *ctrlm_auth_certificate_get() { + return(new(ctrlm_auth_certificate_t)); +} + +ctrlm_auth_certificate_t::ctrlm_auth_certificate_t() { + + this->device_cert.type = CTRLM_VOICE_CERT_TYPE_NONE; + this->ocsp_verify_stapling = false; + this->ocsp_verify_ca = false; + + char *cert_path = NULL; + char *cert_password = NULL; + rdkcertselector_h cert_selector = rdkcertselector_new( NULL, NULL, "MTLS" ); + + if(cert_selector == NULL){ + XLOGD_TELEMETRY("cert selector init failed"); + } else { + rdkcertselectorStatus_t cert_status = rdkcertselector_getCert(cert_selector, &cert_path, &cert_password); + + if(cert_status != certselectorOk) { + XLOGD_TELEMETRY("cert selector retrieval failed"); + } else { + if(cert_path == NULL || cert_password == NULL) { + XLOGD_TELEMETRY("cert selector get failed"); + } else { + + char *local_path = cert_path; + if(strncmp(local_path, CERT_FILENAME_PREFIX, strlen(CERT_FILENAME_PREFIX)) == 0) { + local_path += strlen(CERT_FILENAME_PREFIX); + } + if(!this->device_cert_p12_set(local_path, cert_password)) { + XLOGD_TELEMETRY("unable to set device certificate <%s>", local_path); + } else { + struct stat file_info; + // OCSP is a global setting that is enabled via RFC in systemd service ocsp-support + if(stat("/tmp/.EnableOCSPStapling", &file_info) == 0) { + XLOGD_TELEMETRY("OCSP verification enabled (stapling)"); + this->ocsp_verify_stapling = true; + } + if(stat("/tmp/.EnableOCSPCA", &file_info) == 0) { + XLOGD_TELEMETRY("OCSP verification enabled (CA)"); + this->ocsp_verify_ca = true; + } + if(!this->ocsp_verify_stapling && !this->ocsp_verify_ca) { + XLOGD_TELEMETRY("OCSP verification disabled"); + } + } + } + } + } + + if(cert_selector != NULL) { + rdkcertselector_free(&cert_selector); + } +} + +ctrlm_auth_certificate_t::~ctrlm_auth_certificate_t() { + if(this->device_cert.type == CTRLM_VOICE_CERT_TYPE_P12) { + if(this->device_cert.cert.p12.certificate != NULL) { + free((void *)this->device_cert.cert.p12.certificate); + } + if(this->device_cert.cert.p12.passphrase != NULL) { + free((void *)this->device_cert.cert.p12.passphrase); + } + } +} + +bool ctrlm_auth_certificate_t::device_cert_get(ctrlm_voice_cert_t &device_cert, bool &ocsp_verify_stapling, bool &ocsp_verify_ca) { + + device_cert = this->device_cert; + ocsp_verify_stapling = this->ocsp_verify_stapling; + ocsp_verify_ca = this->ocsp_verify_ca; + return(true); +} + +bool ctrlm_auth_certificate_t::device_cert_p12_set(const char *certificate, const char *passphrase) { + bool cert_valid = false; + + // Extract the certificate, private key and additional certificates + PKCS12 *p12_cert = NULL; + EVP_PKEY *pkey = NULL; + X509 *x509_cert = NULL; + STACK_OF(X509) *additional_certs = NULL; + + do { + FILE *fp = fopen(certificate, "rb"); + if(fp == NULL) { + XLOGD_ERROR("unable to open P12 certificate <%s>", certificate); + break; + } + + d2i_PKCS12_fp(fp, &p12_cert); + fclose(fp); + fp = NULL; + + if(p12_cert == NULL) { + XLOGD_ERROR("unable to read P12 certificate <%s>", certificate); + break; + } + + if(1 != PKCS12_parse(p12_cert, passphrase, &pkey, &x509_cert, &additional_certs)) { + XLOGD_ERROR("unable to parse P12 certificate <%s>", certificate); + break; + } + + this->device_cert.type = CTRLM_VOICE_CERT_TYPE_P12; + this->device_cert.cert.p12.certificate = strdup(certificate); + this->device_cert.cert.p12.passphrase = strdup(passphrase); + + // Ensure the strings were duplicated + if(this->device_cert.cert.p12.certificate == NULL || this->device_cert.cert.p12.passphrase == NULL) { + this->device_cert.type = CTRLM_VOICE_CERT_TYPE_NONE; + if(this->device_cert.cert.p12.certificate != NULL) { + free((void *)this->device_cert.cert.p12.certificate); + } + if(this->device_cert.cert.p12.passphrase != NULL) { + free((void *)this->device_cert.cert.p12.passphrase); + } + } else { + cert_valid = true; + } + + } while(0); + + if(p12_cert != NULL) { + PKCS12_free(p12_cert); + } + if(pkey != NULL) { + EVP_PKEY_free(pkey); + } + if(x509_cert != NULL) { + X509_free(x509_cert); + } + if(additional_certs != NULL) { + sk_X509_pop_free(additional_certs, X509_free); + } + + return(cert_valid); +} diff --git a/src/auth/ctrlm_hal_certificate.h b/src/auth/ctrlm_auth_certificate.h similarity index 89% rename from src/auth/ctrlm_hal_certificate.h rename to src/auth/ctrlm_auth_certificate.h index 93e6f03..cdf8719 100644 --- a/src/auth/ctrlm_hal_certificate.h +++ b/src/auth/ctrlm_auth_certificate.h @@ -17,8 +17,8 @@ * limitations under the License. */ -#ifndef __CTRLM_HAL_CERTIFICATE_H__ -#define __CTRLM_HAL_CERTIFICATE_H__ +#ifndef __CTRLM_AUTH_CERTIFICATE_H__ +#define __CTRLM_AUTH_CERTIFICATE_H__ #include #include @@ -62,10 +62,10 @@ typedef struct { } cert; } ctrlm_voice_cert_t; -class ctrlm_hal_certificate_t { +class ctrlm_auth_certificate_t { public: - ctrlm_hal_certificate_t(); - virtual ~ctrlm_hal_certificate_t(); + ctrlm_auth_certificate_t(); + virtual ~ctrlm_auth_certificate_t(); virtual bool device_cert_get(ctrlm_voice_cert_t &device_cert, bool &ocsp_verify_stapling, bool &ocsp_verify_ca); @@ -77,6 +77,6 @@ class ctrlm_hal_certificate_t { bool ocsp_verify_ca; }; -ctrlm_hal_certificate_t *ctrlm_hal_certificate_get(); +ctrlm_auth_certificate_t *ctrlm_auth_certificate_get(); #endif diff --git a/src/ctrlm.h b/src/ctrlm.h index 18d0f99..68fa181 100644 --- a/src/ctrlm.h +++ b/src/ctrlm.h @@ -29,7 +29,6 @@ #include "ctrlm_hal.h" #include "ctrlm_hal_rf4ce.h" #include "ctrlm_hal_ble.h" -#include "ctrlm_hal_certificate.h" #include "ctrlm_hal_ip.h" #include "ctrlm_ipc.h" #include "ctrlm_ipc_rcu.h" diff --git a/src/ctrlm_main.cpp b/src/ctrlm_main.cpp index f0be11e..b5800d0 100644 --- a/src/ctrlm_main.cpp +++ b/src/ctrlm_main.cpp @@ -62,7 +62,7 @@ #endif #ifdef AUTH_ENABLED #include "ctrlm_auth.h" -#include "ctrlm_hal_certificate.h" +#include "ctrlm_auth_certificate.h" #endif #include "ctrlm_rfc.h" #include "ctrlm_telemetry.h" @@ -278,7 +278,7 @@ typedef struct { ctrlm_cs_values_t cs_values; #ifdef AUTH_ENABLED ctrlm_auth_t *authservice; - ctrlm_hal_certificate_t *hal_certificate; + ctrlm_auth_certificate_t *auth_certificate; #endif #ifdef CTRLM_THUNDER Thunder::DeviceInfo::ctrlm_thunder_plugin_device_info_t *thunder_device_info; @@ -694,14 +694,14 @@ int main(int argc, char *argv[]) { #ifdef AUTH_ENABLED XLOGD_INFO("ctrlm_auth init"); - g_ctrlm.authservice = ctrlm_auth_service_create(g_ctrlm.server_url_authservice); - g_ctrlm.hal_certificate = ctrlm_hal_certificate_get(); + g_ctrlm.authservice = ctrlm_auth_service_create(g_ctrlm.server_url_authservice); + g_ctrlm.auth_certificate = ctrlm_auth_certificate_get(); ctrlm_voice_cert_t device_cert; bool ocsp_verify_stapling = false; bool ocsp_verify_ca = false; - if(!g_ctrlm.hal_certificate->device_cert_get(device_cert, ocsp_verify_stapling, ocsp_verify_ca)) { + if(!g_ctrlm.auth_certificate->device_cert_get(device_cert, ocsp_verify_stapling, ocsp_verify_ca)) { XLOGD_ERROR("unable to get device certificate"); } else { if(!g_ctrlm.voice_session->voice_stb_data_device_certificate_set(device_cert, ocsp_verify_stapling, ocsp_verify_ca)) { diff --git a/src/voice/ctrlm_voice_obj.h b/src/voice/ctrlm_voice_obj.h index f20644f..70ddb4c 100644 --- a/src/voice/ctrlm_voice_obj.h +++ b/src/voice/ctrlm_voice_obj.h @@ -28,6 +28,7 @@ #include "ctrlm_ipc_voice.h" #include "ctrlm.h" #include "ctrlm_auth.h" +#include "ctrlm_auth_certificate.h" #include "jansson.h" #include "json_config.h" #include "xr_timestamp.h"