11#include <asio/ssl.hpp>
24#include <openssl/evp.h>
25#include <openssl/rsa.h>
26#include <openssl/x509.h>
27#include <openssl/x509v3.h>
41#define RESIPROCATE_SUBSYSTEM FlowManagerSubsystem::FLOWMANAGER
43#define DTLS_CERT_KEY_LENGTH 4096
59 asio::io_context& mIOService;
66 mSslContext(asio::ssl::context::sslv23),
73 mIOServiceWork =
new asio::executor_work_guard<asio::io_context::executor_type>(mIOService.get_executor());
75 mIOServiceThread->run();
80 mSslContext.set_verify_mode(asio::ssl::context::verify_peer |
81 asio::ssl::context::verify_fail_if_no_peer_cert);
84#define VERIFY_FILE "ca.pem"
89 InfoLog(<<
"Unable to load verify file: " <<
VERIFY_FILE <<
", error=" << ec.value() <<
"(" << ec.message() <<
")");
94 srtp_err_status_t status = srtp_init();
95 if(status && status != srtp_err_status_bad_param)
97 ErrLog(<<
"Unable to initialize SRTP engine, error code=" << status);
100 status = srtp_install_event_handler(FlowManager::srtpEventHandler);
109 if(mDtlsTimerContext) mDtlsTimerContext->
stop();
111 delete mIOServiceWork;
112 mIOServiceThread->
join();
113 delete mIOServiceThread;
116 if(mDtlsFactory)
delete mDtlsFactory;
117 if(mClientCert) X509_free(mClientCert);
118 if(mClientKey) EVP_PKEY_free(mClientKey);
128 ErrLog(<<
"initializeDtlsFactory called when DtlsFactory is already initialized.");
136 mDtlsFactory =
new DtlsFactory(std::unique_ptr<DtlsTimerContext>(mDtlsTimerContext), mClientCert, mClientKey);
141 ErrLog(<<
"Unable to create a client cert, cannot use Dtls-Srtp.");
147FlowManager::srtpEventHandler(srtp_event_data_t *data)
149 switch(data->event) {
150 case event_ssrc_collision:
153 case event_key_soft_limit:
154 WarningLog(<<
"SRTP key usage soft limit reached");
156 case event_key_hard_limit:
157 WarningLog(<<
"SRTP key usage hard limit reached");
159 case event_packet_index_limit:
160 WarningLog(<<
"SRTP packet index limit reached");
163 WarningLog(<<
"SRTP unknown event reported to handler");
172 const char* natTraversalServerHostname,
173 unsigned short natTraversalServerPort,
174 const char* stunUsername,
175 const char* stunPassword,
177 std::shared_ptr<FlowContext> context)
194 natTraversalServerHostname,
195 natTraversalServerPort,
199 mRtcpEventLoggingHandler,
201 mValidateTlsServerHostname);
217 natTraversalServerHostname,
218 natTraversalServerPort,
224 mValidateTlsServerHostname);
226 return newMediaStream;
234 mSslContext.load_verify_file(rootCertificatesFile.
c_str(), ec);
237 ErrLog(<<
"Unable to load TLS root certificates from " << rootCertificatesFile <<
", error=" << ec.value() <<
"(" << ec.message() <<
")");
248 Data aor =
"sip:" + pAor;
256 EVP_PKEY_CTX* keyCtx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
258 EVP_PKEY_keygen_init(keyCtx) == 1 &&
259 EVP_PKEY_CTX_set_rsa_keygen_bits(keyCtx, keyLen) == 1 &&
260 EVP_PKEY_keygen(keyCtx, &privkey) == 1;
261 EVP_PKEY_CTX_free(keyCtx);
267 X509* cert = X509_new();
270 X509_NAME* subject = X509_NAME_new();
274 X509_set_version(cert, 2L);
278 ASN1_INTEGER_set(X509_get_serialNumber(cert),serial);
284 ret = X509_NAME_add_entry_by_txt( subject,
"CN", MBSTRING_ASC,
285 (
unsigned char *) aor.
data(), (
int)aor.
size(),
289 ret = X509_set_issuer_name(cert, subject);
291 ret = X509_set_subject_name(cert, subject);
293 X509_NAME_free(subject);
295 const long duration = 60*60*24*expireDays;
296 X509_gmtime_adj(X509_getm_notBefore(cert),0);
297 X509_gmtime_adj(X509_getm_notAfter(cert), duration);
299 ret = X509_set_pubkey(cert, privkey);
302 Data subjectAltNameStr =
Data(
"URI:sip:") + aor
303 +
Data(
",URI:im:")+aor
304 +
Data(
",URI:pres:")+aor;
305 ext = X509V3_EXT_conf_nid( NULL , NULL , NID_subject_alt_name,
306 (
char*) subjectAltNameStr.
c_str() );
307 X509_add_ext( cert, ext, -1);
308 X509_EXTENSION_free(ext);
310 static char CA_FALSE[] =
"CA:FALSE";
311 ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, CA_FALSE);
312 ret = X509_add_ext( cert, ext, -1);
314 X509_EXTENSION_free(ext);
319 ret = X509_sign(cert, privkey, EVP_sha256());
struct evp_pkey_st EVP_PKEY
#define DTLS_CERT_KEY_LENGTH
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
This class is used to raise exceptions in the flow manager.
bool addTlsRootCertificates(const resip::Data &rootCertificatesFile)
Adds the root (CA) certificates in a PEM file to those TURN servers' TLS certificates are verified wi...
static int createCert(const resip::Data &pAor, int expireDays, int keyLen, X509 *&outCert, EVP_PKEY *&outKey)
void initializeDtlsFactory(const char *certAor)
MediaStream * createMediaStream(MediaStreamHandler &mediaStreamHandler, const StunTuple &localBinding, bool rtcpEnabled=true, MediaStream::NatTraversalMode natTraversalMode=MediaStream::NoNatTraversal, const char *natTraversalServerHostname=0, unsigned short natTraversalServerPort=0, const char *stunUsername=0, const char *stunPassword=0, bool forceCOMedia=false, std::shared_ptr< FlowContext > context=nullptr)
virtual ~IOServiceThread()
IOServiceThread(asio::io_context &ioService)
TransportType getTransportType() const
const asio::ip::address & getAddress() const
unsigned int getPort() const
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
const char * c_str() const
Returns a null-terminated string representing.
size_type size() const noexcept
Returns the number of bytes in this Data.
const char * data() const noexcept
Returns a pointer to the contents of this Data.
static int getRandom()
Returns a postive integer (31 bits) of randomness.
A wrapper class to create and spawn a thread.
This class is used during media sessions that use Dtls-Srtp for a media transport.
dcm! – add UnusedChecking(_enum) below;