ossrs / srs

SRS is a simple, high-efficiency, real-time video server supporting RTMP, WebRTC, HLS, HTTP-FLV, SRT, MPEG-DASH, and GB28181.

Home Page:https://ossrs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug: SrsHttpxConn SSL Key&Cert config problem.

suzp1984 opened this issue · comments

Describe the bug

// Do SSL handshake if HTTPS.
if (ssl) {
srs_utime_t starttime = srs_update_system_time();
string crt_file = _srs_config->get_https_stream_ssl_cert();
string key_file = _srs_config->get_https_stream_ssl_key();
if ((err = ssl->handshake(key_file, crt_file)) != srs_success) {

SrsHttpxConn can be used as HTTP API and HTTP Server, for both plain and SSL connection. For the SSL connection, we can config the SSL key & cert in this way.

http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
https {
enabled on;
listen 8088;
key ./conf/server.key;
cert ./conf/server.crt;
}
}
http_api {
enabled on;
listen 1985;
https {
enabled on;
listen 1990;
key ./conf/server.key;
cert ./conf/server.crt;
}
}

And SrsConfig has apis to get the key & cert.

virtual std::string get_https_api_ssl_key();
virtual std::string get_https_api_ssl_cert();

virtual std::string get_https_stream_ssl_key();
virtual std::string get_https_stream_ssl_cert();

But SrsHttpxConn only calling get_https_stream_ssl_cert & get_https_stream_ssl_key even for the Https API connections.

Version
All SRS version.

To Reproduce
Steps to reproduce the behavior:

  1. config https api and https stream with different key & cert pair.
  2. boot the srs.

Expected behavior
http_api.https.key | cert should be loaded correctly.

Additional context
I found this bug when try to do #3701, found this bug and also #4024

Nice work, your work clearly describe how this bug occurs. You are correct, it's really a bug for HTTPS API, the get_https_api_ssl_key is not used. Could you please file an pullrequest to fix this issue?

Nice work, your work clearly describe how this bug occurs. You are correct, it's really a bug for HTTPS API, the get_https_api_ssl_key is not used. Could you please file an pullrequest to fix this issue?

yes, I will try.

Another problem of SSL Key&Cert config is that to config the key&cert for SSL or SSL_CTX.

https://www.openssl.org/docs/manmaster/man3/SSL_use_certificate_file.html

the SSL is generated from SSL_CTX.

#if (OPENSSL_VERSION_NUMBER < 0x10002000L) // v1.0.2
ssl_ctx = SSL_CTX_new(TLS_method());
#else
ssl_ctx = SSL_CTX_new(TLSv1_2_method());
#endif
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
srs_assert(SSL_CTX_set_cipher_list(ssl_ctx, "ALL") == 1);
// TODO: Setup callback, see SSL_set_ex_data and SSL_set_info_callback
if ((ssl = SSL_new(ssl_ctx)) == NULL) {
return srs_error_new(ERROR_HTTPS_HANDSHAKE, "SSL_new ssl");
}

In general, a SSL map to a tcp connection. So each tcp connection can custom its SSL certificate, that's what the SRS did.

if ((r0 = SSL_use_certificate_chain_file(ssl, crt_file.c_str())) != 1) {
return srs_error_new(ERROR_HTTPS_KEY_CRT, "use cert %s", crt_file.c_str());
}
if ((r0 = SSL_use_RSAPrivateKey_file(ssl, key_file.c_str(), SSL_FILETYPE_PEM)) != 1) {

But it's overkill. the tcp connections shared same listen port at server side, have same SSL key&Cert, that's the usual case.
So the more general solution is the config Key&Cert for a SSL_CTX, by api SSL_CTX_use_certificate_chain_file & SSL_CTX_use_PrivateKey_file, and shared this SSL_CTX for all the SrsTcpConnections generated from the same SrsTcpListener.