mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
RTC: refine dtls certificate
This commit is contained in:
parent
0bf0a61401
commit
f3f9636d80
5 changed files with 100 additions and 53 deletions
|
@ -149,10 +149,6 @@ srs_error_t SrsRtcDtls::initialize(SrsRequest* r)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
if ((err = SrsDtls::instance()->init(r)) != srs_success) {
|
|
||||||
return srs_error_wrap(err, "DTLS init");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: FIXME: Leak for SSL_CTX* return by build_dtls_ctx.
|
// TODO: FIXME: Leak for SSL_CTX* return by build_dtls_ctx.
|
||||||
if ((dtls = SSL_new(SrsDtls::instance()->build_dtls_ctx())) == NULL) {
|
if ((dtls = SSL_new(SrsDtls::instance()->build_dtls_ctx())) == NULL) {
|
||||||
return srs_error_new(ERROR_OpenSslCreateSSL, "SSL_new dtls");
|
return srs_error_new(ERROR_OpenSslCreateSSL, "SSL_new dtls");
|
||||||
|
|
|
@ -34,16 +34,14 @@ using namespace std;
|
||||||
#include <srtp2/srtp.h>
|
#include <srtp2/srtp.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
SrsDtls* SrsDtls::_instance = NULL;
|
SrsDtlsCertificate::SrsDtlsCertificate()
|
||||||
|
|
||||||
SrsDtls::SrsDtls()
|
|
||||||
{
|
{
|
||||||
dtls_cert = NULL;
|
dtls_cert = NULL;
|
||||||
dtls_pkey = NULL;
|
dtls_pkey = NULL;
|
||||||
eckey = NULL;
|
eckey = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsDtls::~SrsDtls()
|
SrsDtlsCertificate::~SrsDtlsCertificate()
|
||||||
{
|
{
|
||||||
if (eckey) {
|
if (eckey) {
|
||||||
EC_KEY_free(eckey);
|
EC_KEY_free(eckey);
|
||||||
|
@ -58,22 +56,7 @@ SrsDtls::~SrsDtls()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The return value of verify_callback controls the strategy of the further verification process. If verify_callback
|
srs_error_t SrsDtlsCertificate::initialize()
|
||||||
// returns 0, the verification process is immediately stopped with "verification failed" state. If SSL_VERIFY_PEER is
|
|
||||||
// set, a verification failure alert is sent to the peer and the TLS/SSL handshake is terminated. If verify_callback
|
|
||||||
// returns 1, the verification process is continued. If verify_callback always returns 1, the TLS/SSL handshake will
|
|
||||||
// not be terminated with respect to verification failures and the connection will be established. The calling process
|
|
||||||
// can however retrieve the error code of the last verification error using SSL_get_verify_result(3) or by maintaining
|
|
||||||
// its own error storage managed by verify_callback.
|
|
||||||
// @see https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html
|
|
||||||
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
|
||||||
{
|
|
||||||
// Always OK, we don't check the certificate of client,
|
|
||||||
// because we allow client self-sign certificate.
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
srs_error_t SrsDtls::init(SrsRequest* r)
|
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
@ -94,12 +77,12 @@ srs_error_t SrsDtls::init(SrsRequest* r)
|
||||||
srs_assert(srtp_init() == 0);
|
srs_assert(srtp_init() == 0);
|
||||||
|
|
||||||
// Whether use ECDSA certificate.
|
// Whether use ECDSA certificate.
|
||||||
bool is_ecdsa = _srs_config->get_rtc_server_ecdsa();
|
ecdsa_mode = _srs_config->get_rtc_server_ecdsa();
|
||||||
|
|
||||||
// Create keys by RSA or ECDSA.
|
// Create keys by RSA or ECDSA.
|
||||||
dtls_pkey = EVP_PKEY_new();
|
dtls_pkey = EVP_PKEY_new();
|
||||||
srs_assert(dtls_pkey);
|
srs_assert(dtls_pkey);
|
||||||
if (!is_ecdsa) { // By RSA
|
if (!ecdsa_mode) { // By RSA
|
||||||
RSA* rsa = RSA_new();
|
RSA* rsa = RSA_new();
|
||||||
srs_assert(rsa);
|
srs_assert(rsa);
|
||||||
|
|
||||||
|
@ -119,7 +102,7 @@ srs_error_t SrsDtls::init(SrsRequest* r)
|
||||||
RSA_free(rsa);
|
RSA_free(rsa);
|
||||||
BN_free(exponent);
|
BN_free(exponent);
|
||||||
}
|
}
|
||||||
if (is_ecdsa) { // By ECDSA, https://stackoverflow.com/a/6006898
|
if (ecdsa_mode) { // By ECDSA, https://stackoverflow.com/a/6006898
|
||||||
eckey = EC_KEY_new();
|
eckey = EC_KEY_new();
|
||||||
srs_assert(eckey);
|
srs_assert(eckey);
|
||||||
|
|
||||||
|
@ -208,6 +191,56 @@ srs_error_t SrsDtls::init(SrsRequest* r)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X509* SrsDtlsCertificate::get_cert()
|
||||||
|
{
|
||||||
|
return dtls_cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY* SrsDtlsCertificate::get_public_key()
|
||||||
|
{
|
||||||
|
return dtls_pkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
EC_KEY* SrsDtlsCertificate::get_ecdsa_key()
|
||||||
|
{
|
||||||
|
return eckey;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SrsDtlsCertificate::get_fingerprint()
|
||||||
|
{
|
||||||
|
return fingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsDtlsCertificate::is_ecdsa()
|
||||||
|
{
|
||||||
|
return ecdsa_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsDtls* SrsDtls::_instance = NULL;
|
||||||
|
|
||||||
|
SrsDtls::SrsDtls()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsDtls::~SrsDtls()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// The return value of verify_callback controls the strategy of the further verification process. If verify_callback
|
||||||
|
// returns 0, the verification process is immediately stopped with "verification failed" state. If SSL_VERIFY_PEER is
|
||||||
|
// set, a verification failure alert is sent to the peer and the TLS/SSL handshake is terminated. If verify_callback
|
||||||
|
// returns 1, the verification process is continued. If verify_callback always returns 1, the TLS/SSL handshake will
|
||||||
|
// not be terminated with respect to verification failures and the connection will be established. The calling process
|
||||||
|
// can however retrieve the error code of the last verification error using SSL_get_verify_result(3) or by maintaining
|
||||||
|
// its own error storage managed by verify_callback.
|
||||||
|
// @see https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html
|
||||||
|
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
||||||
|
{
|
||||||
|
// Always OK, we don't check the certificate of client,
|
||||||
|
// because we allow client self-sign certificate.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
SrsDtls* SrsDtls::instance()
|
SrsDtls* SrsDtls::instance()
|
||||||
{
|
{
|
||||||
if (!_instance) {
|
if (!_instance) {
|
||||||
|
@ -227,12 +260,7 @@ SSL_CTX* SrsDtls::build_dtls_ctx()
|
||||||
//dtls_ctx = SSL_CTX_new(DTLSv1_2_method());
|
//dtls_ctx = SSL_CTX_new(DTLSv1_2_method());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Whether use ECDSA certificate.
|
if (_rtc_dtls_certificate->is_ecdsa()) { // By ECDSA, https://stackoverflow.com/a/6006898
|
||||||
// TODO: FIXME: Support config by vhost to use RSA or ECDSA certificate.
|
|
||||||
bool is_ecdsa = _srs_config->get_rtc_server_ecdsa();
|
|
||||||
if (is_ecdsa) { // By ECDSA, https://stackoverflow.com/a/6006898
|
|
||||||
EC_KEY* eckey = EC_KEY_new();
|
|
||||||
srs_assert(eckey);
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L // v1.0.2
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L // v1.0.2
|
||||||
// For ECDSA, we could set the curves list.
|
// For ECDSA, we could set the curves list.
|
||||||
|
@ -244,7 +272,7 @@ SSL_CTX* SrsDtls::build_dtls_ctx()
|
||||||
// @see https://stackoverrun.com/cn/q/10791887
|
// @see https://stackoverrun.com/cn/q/10791887
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L // v1.1.x
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L // v1.1.x
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10002000L // v1.0.2
|
#if OPENSSL_VERSION_NUMBER < 0x10002000L // v1.0.2
|
||||||
SSL_CTX_set_tmp_ecdh(dtls_ctx, eckey);
|
SSL_CTX_set_tmp_ecdh(dtls_ctx, _rtc_dtls_certificate->get_ecdsa_key());
|
||||||
#else
|
#else
|
||||||
SSL_CTX_set_ecdh_auto(dtls_ctx, 1);
|
SSL_CTX_set_ecdh_auto(dtls_ctx, 1);
|
||||||
#endif
|
#endif
|
||||||
|
@ -258,8 +286,8 @@ SSL_CTX* SrsDtls::build_dtls_ctx()
|
||||||
srs_assert(SSL_CTX_set_cipher_list(dtls_ctx, "ALL") == 1);
|
srs_assert(SSL_CTX_set_cipher_list(dtls_ctx, "ALL") == 1);
|
||||||
|
|
||||||
// Setup the certificate.
|
// Setup the certificate.
|
||||||
srs_assert(SSL_CTX_use_certificate(dtls_ctx, dtls_cert) == 1);
|
srs_assert(SSL_CTX_use_certificate(dtls_ctx, _rtc_dtls_certificate->get_cert()) == 1);
|
||||||
srs_assert(SSL_CTX_use_PrivateKey(dtls_ctx, dtls_pkey) == 1);
|
srs_assert(SSL_CTX_use_PrivateKey(dtls_ctx, _rtc_dtls_certificate->get_public_key()) == 1);
|
||||||
|
|
||||||
// Server will send Certificate Request.
|
// Server will send Certificate Request.
|
||||||
// @see https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html
|
// @see https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html
|
||||||
|
@ -283,9 +311,3 @@ SSL_CTX* SrsDtls::build_dtls_ctx()
|
||||||
|
|
||||||
return dtls_ctx;
|
return dtls_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SrsDtls::get_fingerprint() const
|
|
||||||
{
|
|
||||||
return fingerprint;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -32,25 +32,45 @@ class SrsRequest;
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
class SrsDtlsCertificate
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string fingerprint;
|
||||||
|
bool ecdsa_mode;
|
||||||
|
X509* dtls_cert;
|
||||||
|
EVP_PKEY* dtls_pkey;
|
||||||
|
EC_KEY* eckey;
|
||||||
|
public:
|
||||||
|
SrsDtlsCertificate();
|
||||||
|
virtual ~SrsDtlsCertificate();
|
||||||
|
public:
|
||||||
|
// Initialize DTLS certificate.
|
||||||
|
srs_error_t initialize();
|
||||||
|
// dtls_cert
|
||||||
|
X509* get_cert();
|
||||||
|
// public key
|
||||||
|
EVP_PKEY* get_public_key();
|
||||||
|
// ECDSA key
|
||||||
|
EC_KEY* get_ecdsa_key();
|
||||||
|
// certificate fingerprint
|
||||||
|
std::string get_fingerprint();
|
||||||
|
// whether is ecdsa
|
||||||
|
bool is_ecdsa();
|
||||||
|
};
|
||||||
|
|
||||||
|
// @global dtls certficate for rtc module.
|
||||||
|
SrsDtlsCertificate* _rtc_dtls_certificate = new SrsDtlsCertificate();
|
||||||
|
|
||||||
class SrsDtls
|
class SrsDtls
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static SrsDtls* _instance;
|
static SrsDtls* _instance;
|
||||||
private:
|
|
||||||
std::string fingerprint;
|
|
||||||
X509* dtls_cert;
|
|
||||||
EVP_PKEY* dtls_pkey;
|
|
||||||
EC_KEY* eckey;
|
|
||||||
private:
|
private:
|
||||||
SrsDtls();
|
SrsDtls();
|
||||||
virtual ~SrsDtls();
|
virtual ~SrsDtls();
|
||||||
public:
|
|
||||||
srs_error_t init(SrsRequest* r);
|
|
||||||
public:
|
public:
|
||||||
static SrsDtls* instance();
|
static SrsDtls* instance();
|
||||||
SSL_CTX* build_dtls_ctx();
|
SSL_CTX* build_dtls_ctx();
|
||||||
public:
|
|
||||||
std::string get_fingerprint() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -333,7 +333,7 @@ srs_error_t SrsRtcServer::create_session(
|
||||||
local_sdp.set_ice_ufrag(local_ufrag);
|
local_sdp.set_ice_ufrag(local_ufrag);
|
||||||
local_sdp.set_ice_pwd(local_pwd);
|
local_sdp.set_ice_pwd(local_pwd);
|
||||||
local_sdp.set_fingerprint_algo("sha-256");
|
local_sdp.set_fingerprint_algo("sha-256");
|
||||||
local_sdp.set_fingerprint(SrsDtls::instance()->get_fingerprint());
|
local_sdp.set_fingerprint(_rtc_dtls_certificate->get_fingerprint());
|
||||||
|
|
||||||
// We allows to mock the eip of server.
|
// We allows to mock the eip of server.
|
||||||
if (!mock_eip.empty()) {
|
if (!mock_eip.empty()) {
|
||||||
|
@ -366,7 +366,7 @@ srs_error_t SrsRtcServer::create_session2(SrsSdp& local_sdp, SrsRtcSession** pse
|
||||||
local_sdp.set_ice_ufrag(local_ufrag);
|
local_sdp.set_ice_ufrag(local_ufrag);
|
||||||
local_sdp.set_ice_pwd(local_pwd);
|
local_sdp.set_ice_pwd(local_pwd);
|
||||||
local_sdp.set_fingerprint_algo("sha-256");
|
local_sdp.set_fingerprint_algo("sha-256");
|
||||||
local_sdp.set_fingerprint(SrsDtls::instance()->get_fingerprint());
|
local_sdp.set_fingerprint(_rtc_dtls_certificate->get_fingerprint());
|
||||||
|
|
||||||
// We allows to mock the eip of server.
|
// We allows to mock the eip of server.
|
||||||
std::vector<string> candidate_ips = get_candidate_ips();
|
std::vector<string> candidate_ips = get_candidate_ips();
|
||||||
|
@ -521,12 +521,20 @@ RtcServerAdapter::RtcServerAdapter()
|
||||||
RtcServerAdapter::~RtcServerAdapter()
|
RtcServerAdapter::~RtcServerAdapter()
|
||||||
{
|
{
|
||||||
srs_freep(rtc);
|
srs_freep(rtc);
|
||||||
|
|
||||||
|
if (_rtc_dtls_certificate) {
|
||||||
|
srs_freep(_rtc_dtls_certificate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t RtcServerAdapter::initialize()
|
srs_error_t RtcServerAdapter::initialize()
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
if ((err = _rtc_dtls_certificate->initialize()) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "rtc dtls certificate initialize");
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = rtc->initialize()) != srs_success) {
|
if ((err = rtc->initialize()) != srs_success) {
|
||||||
return srs_error_wrap(err, "rtc server initialize");
|
return srs_error_wrap(err, "rtc server initialize");
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <srs_app_reload.hpp>
|
#include <srs_app_reload.hpp>
|
||||||
#include <srs_app_hourglass.hpp>
|
#include <srs_app_hourglass.hpp>
|
||||||
#include <srs_app_hybrid.hpp>
|
#include <srs_app_hybrid.hpp>
|
||||||
|
#include <srs_app_rtc_dtls.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue