[FFmpeg-devel,3/5] lavf/tls_openssl: on 1.1 or later, verify the server's hostname

Submitted by Rodger Combs on Jan. 18, 2019, 8:46 a.m.

Details

Message ID 20190118084604.82324-3-rodger.combs@gmail.com
State New
Headers show

Commit Message

Rodger Combs Jan. 18, 2019, 8:46 a.m.
---
 libavformat/tls_openssl.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c
index ae3fd6e236..ba233c0229 100644
--- a/libavformat/tls_openssl.c
+++ b/libavformat/tls_openssl.c
@@ -35,6 +35,7 @@ 
 #include <openssl/bio.h>
 #include <openssl/ssl.h>
 #include <openssl/err.h>
+#include <openssl/x509v3.h>
 
 static int openssl_init;
 
@@ -269,8 +270,6 @@  static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op
         ret = AVERROR(EIO);
         goto fail;
     }
-    // Note, this doesn't check that the peer certificate actually matches
-    // the requested hostname.
     if (c->verify)
         SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
     p->ssl = SSL_new(p->ctx);
@@ -294,8 +293,23 @@  static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op
     bio->ptr = c->tcp;
 #endif
     SSL_set_bio(p->ssl, bio, bio);
-    if (!c->listen && !c->numerichost)
-        SSL_set_tlsext_host_name(p->ssl, c->host);
+    if (!c->listen && !c->numerichost) {
+#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
+        X509_VERIFY_PARAM *param = SSL_get0_param(p->ssl);
+        X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+#endif
+        if (
+#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
+            // Note, if on OpenSSL prior to 1.1.0, we won't check that
+            // the peer certificate actually matches the requested hostname.
+            !X509_VERIFY_PARAM_set1_host(param, c->host, 0) ||
+#endif
+            !SSL_set_tlsext_host_name(p->ssl, c->host)) {
+            av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
+            ret = AVERROR(EIO);
+            goto fail;
+        }
+    }
     ret = c->listen ? SSL_accept(p->ssl) : SSL_connect(p->ssl);
     if (ret == 0) {
         av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");