about summary refs log tree commit diff
diff options
context:
space:
mode:
authordirkf <fieldhouse@gmx.net>2022-01-26 17:00:08 +0000
committerdirkf <fieldhouse@gmx.net>2022-01-27 05:38:13 +0000
commitcd1ffab8e17c2d6126e3bbe361c8c760ba3aefc6 (patch)
tree99a6e2e7fb0d2cd1a857de9f2ba060360c7c6916
parent2f6a844faf0d115d71c541a008b3c8d2cc92ef28 (diff)
downloadyoutube-dl-cd1ffab8e17c2d6126e3bbe361c8c760ba3aefc6.tar.gz
youtube-dl-cd1ffab8e17c2d6126e3bbe361c8c760ba3aefc6.tar.xz
youtube-dl-cd1ffab8e17c2d6126e3bbe361c8c760ba3aefc6.zip
Work-around for yt-dlp issue 1060 (skip bad certs from Windows, Py>=3.7)
-rw-r--r--youtube_dl/utils.py39
1 files changed, 32 insertions, 7 deletions
diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py
index 3c8b748b4..6b18cb893 100644
--- a/youtube_dl/utils.py
+++ b/youtube_dl/utils.py
@@ -2305,12 +2305,39 @@ def formatSeconds(secs):
 
 
 def make_HTTPS_handler(params, **kwargs):
-    opts_no_check_certificate = params.get('nocheckcertificate', False)
+    opts_check_certificate = not params.get('nocheckcertificate', False)
+
+    if sys.version_info >= (3, 7) and opts_check_certificate and sys.platform == 'win32' and hasattr(ssl, 'enum_certificates'):
+        # From yt-dlp: work around issue in load_default_certs if there are bad certificates. See:
+        # https://github.com/yt-dlp/yt-dlp/issues/1060,
+        # https://bugs.python.org/issue35665, https://bugs.python.org/issue4531
+        # but not with MingW (no enum_certificates())
+        from types import MethodType
+
+        def _ssl_load_windows_store_certs(ssl_context, storename):
+            # Code adapted from _load_windows_store_certs in https://github.com/python/cpython/blob/main/Lib/ssl.py
+            try:
+                certs = [cert for cert, encoding, trust in ssl.enum_certificates(storename)
+                         if encoding == 'x509_asn' and (
+                             trust is True or ssl.Purpose.SERVER_AUTH.oid in trust)]
+            except PermissionError:
+                return
+            for cert in certs:
+                try:
+                    ssl_context.load_verify_locations(cadata=cert)
+                except ssl.SSLError:
+                    # no warning here, as the problem is probably a permanent unfixable feature of the platform
+                    pass
+
+        ssl.SSLContext._ssl_load_windows_store_certs = MethodType(_ssl_load_windows_store_certs, ssl.SSLContext)
+        ssl_cert_verify_mode = True
+    else:
+        ssl_cert_verify_mode = ssl.CERT_REQUIRED if opts_check_certificate else ssl.CERT_NONE
+
     if hasattr(ssl, 'create_default_context'):  # Python >= 3.4 or 2.7.9
         context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
-        if opts_no_check_certificate:
-            context.check_hostname = False
-            context.verify_mode = ssl.CERT_NONE
+        context.check_hostname = opts_check_certificate
+        context.verify_mode = ssl_cert_verify_mode
         try:
             return YoutubeDLHTTPSHandler(params, context=context, **kwargs)
         except TypeError:
@@ -2322,9 +2349,7 @@ def make_HTTPS_handler(params, **kwargs):
         return YoutubeDLHTTPSHandler(params, **kwargs)
     else:  # Python < 3.4
         context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
-        context.verify_mode = (ssl.CERT_NONE
-                               if opts_no_check_certificate
-                               else ssl.CERT_REQUIRED)
+        context.verify_mode = ssl_cert_verify_mode
         context.set_default_verify_paths()
         return YoutubeDLHTTPSHandler(params, context=context, **kwargs)