1.32.x Breaks Plugins on Windows (OpenSSL)

With PMS 1.32.x OpenSSL v1.1.1 was dropped in favor of OpenSSL v3. This is totally reasonable and think its a good change in general.

However, the Python included with Plex for plugins to use is 2.7.x, which doesn’t support OpenSSL v3, meaning that the SSL handshake fails when plugins try to interact with Plex. fails trying to contact any https when interacting with Plex’s foundation library (httprequest helpers) or general urllib2 usage.

I understand that plugins have been in legacy for awhile now, but was wondering if there might be plans on including Python 3.9+ or is this the real end for plugins?

Edit: Updated to clarify. Realize that my original comment made it seem like what I meant was plugins talking directly to Plex via api, apologies.

1 Like

When a bundle communicates with a PMS, it should use the loopback address for the url

http://127.0.0.1:32400 and as such should not break a well written bundle

Sorry, I should have clarified more about what I meant.

So with plugins, anything that uses urllib2 to do a https request throws errors, including Plex framework things that may be used:

  • HTTPRequest (Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\networking.py)
  • Stuff that uses networkkit._http_request(Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\networkkit.py) like JSONKit.ObjectFromURL, YAMLKit.ObjectFromURL, ArchiveKit.ZipFromURL, etc.

I made a quick test that you can throw in a bundle to show what I mean

import urllib2 
import ssl

def test_urllib2():
  url = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Utah_teapot_%28solid%29.stl/1200px-Utah_teapot_%28solid%29.stl.png"
  Log.Info(u'Python Version %s', sys.version)
  Log.Info(u'OpenSSL Version %s', ssl.OPENSSL_VERSION) 
  try:
    opener = urllib2.build_opener()
    opener.open(url)
    # or
    urllib2.urlopen(url)
  except Exception, e:
    Log.Error(e)
    raise

Which should result in something like this

2023-04-18 20:10:44,726 (5004) :  INFO (logkit:16) - Python Version 2.7.17 (default, Mar 17 2023, 22:05:45) [gcc]
2023-04-18 20:10:44,726 (5004) :  INFO (logkit:16) - OpenSSL Version OpenSSL 3.0.8 7 Feb 2023
2023-04-18 20:10:44,732 (5004) :  ERROR (logkit:22) - unknown error (_ssl.c:2938)
...
  File "C:\Users\TChil\AppData\Local\Plex Media Server\Plug-ins\Test.bundle\Contents\Code\__init__.py", line 300, in Update
    test_urllib2()
  File "C:\Users\TChil\AppData\Local\Plex Media Server\Plug-ins\Test.bundle\Contents\Code\__init__.py", line 119, in test_urllib2
    opener.open(url)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 429, in open
    response = self._open(req, data)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 447, in _open
    '_open', req)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 407, in _call_chain
    result = func(*args)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 1241, in https_open
    context=self._context)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 1167, in do_open
    h = http_class(host, timeout=req.timeout, **http_conn_args)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\httplib.py", line 1274, in __init__
    context = ssl._create_default_https_context()
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 445, in create_default_context
    context.load_default_certs(purpose)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 412, in load_default_certs
    self._load_windows_store_certs(storename, purpose)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 404, in _load_windows_store_certs
    self.load_verify_locations(cadata=certs)
SSLError: unknown error (_ssl.c:2938)

Python is v2.7.17 and OpenSSL is v3.0.8. If you look at the end of the stack trace and the error being thrown (unknown error (_ssl.c:2938)), its from not being able to load it’s own certificate.

Running a version of Python that uses a version of OpenSSL that it doesn’t support is going to break on a lot of https request things.

1 Like

A bundle should not use urllib2, but the HTTP module from the framework. See attached doc

PlexPlug-inFramework.zip (749.7 KB)

When said, Python is NOT going to get upgraded

2 Likes
A bundle should not use urllib2, but the HTTP module from the framework. 

Yes, that was just a quick example to show any urllib2 usage is broken and why I said including Plex framework things and gave examples.

HTTP.Request throws the exact same exception

def test_foundation():
  url = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Utah_teapot_%28solid%29.stl/1200px-Utah_teapot_%28solid%29.stl.png"
  Log.Info(u'Python Version %s', sys.version)
  Log.Info(u'OpenSSL Version %s', ssl.OPENSSL_VERSION) 
  try:
    HTTP.Request(url).content
  except Exception, e:
    Log.Error(e)
    raise
2023-04-19 06:38:27,280 (40bc) :  INFO (logkit:16) - Python Version 2.7.17 (default, Mar 17 2023, 22:05:45) [gcc]
2023-04-19 06:38:27,280 (40bc) :  INFO (logkit:16) - OpenSSL Version OpenSSL 3.0.8 7 Feb 2023
2023-04-19 06:38:27,290 (40bc) :  DEBUG (networking:144) - Requesting 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Utah_teapot_%28solid%29.stl/1200px-Utah_teapot_%28solid%29.stl.png'
2023-04-19 06:38:27,295 (40bc) :  ERROR (logkit:22) - unknown error (_ssl.c:2938)
2023-04-19 06:38:27,296 (40bc) :  CRITICAL (core:574) - Exception in the update function of agent named 'TestSeries', called with guid 'XXXX' (most recent call last):
  File "C:\Program Files\Plex\Plex Media Server\Resources\Plug-ins-8521b7d99\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\agentkit.py", line 1093, in _update
    agent.update(obj, media, lang, **kwargs)
  File "C:\Users\TChil\AppData\Local\Plex Media Server\Plug-ins\Test.bundle\Contents\Code\__init__.py", line 565, in update
    def update (self, metadata, media, lang, force ):  Update (metadata, media, lang, force,  False)
  File "C:\Users\TChil\AppData\Local\Plex Media Server\Plug-ins\Test.bundle\Contents\Code\__init__.py", line 436, in Update
    metadata.posters [thumb_channel] = Proxy.Media(HTTP.Request(thumb_channel).content, sort_order=1 if Prefs['media_poster_source']=='Channel' else 2)
  File "C:\Users\TChil\AppData\Local\Plex Media Server\Plug-ins\Test.bundle\Contents\Code\__init__.py", line 197, in test_foundation
    HTTP.Request(url).content
  File "C:\Program Files\Plex\Plex Media Server\Resources\Plug-ins-8521b7d99\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\networking.py", line 251, in content
    return self.__str__()
  File "C:\Program Files\Plex\Plex Media Server\Resources\Plug-ins-8521b7d99\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\networking.py", line 229, in __str__
    self.load()
  File "C:\Program Files\Plex\Plex Media Server\Resources\Plug-ins-8521b7d99\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\networking.py", line 162, in load
    f = self._opener.open(req, timeout=self._timeout)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 429, in open
    response = self._open(req, data)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 447, in _open
    '_open', req)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 407, in _call_chain
    result = func(*args)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 1241, in https_open
    context=self._context)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 1167, in do_open
    h = http_class(host, timeout=req.timeout, **http_conn_args)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\httplib.py", line 1274, in __init__
    context = ssl._create_default_https_context()
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 445, in create_default_context
    context.load_default_certs(purpose)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 412, in load_default_certs
    self._load_windows_store_certs(storename, purpose)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 404, in _load_windows_store_certs
    self.load_verify_locations(cadata=certs)
SSLError: unknown error (_ssl.c:2938)

When said, Python is NOT going to get upgraded

Alright, that’s all I wanted to know. Was just trying to help figure out why it all of the sudden broke horribly for people who still use plugins.

1 Like

@dane22 @TChilderhose thank you for clarifying…

Since my check for urllib2 usage on plug-ins that I use was positive, I would like to change the plug-in code to become compatible.

Could please some kind soul give me a quick code example (before… after) how the changed requests should look like in th code example incl. HTTP.request (like in @TChilderhose 's example code given above)?

Thank you very much in advance…

@rossinior

Take a peak at my old no longer developed WebTools.bundle

I mean, changing from urllib2 to HTTP.request will not fix the issue as it uses urllib2 behind the scenes as well. None of my plugins use urllib2 directly and use the foundation functions. I only used urllib2 directly as a quick example to show its a low level issue and not a bug with HTTP.request.

My Webtools.bundle still works fine!

Can access both server on http://127.0.0.1 as well as GitHub on https and the translation site also on https

Hmm it’s running into the same issue for me

com.plexapp.plugins.WebTools.log (12.8 KB)

2023-04-19 19:25:24,592 (3190) :  INFO (logkit:16) - No Basic Auth header, so looking for params
2023-04-19 19:25:24,592 (3190) :  INFO (logkit:16) - User is: tchilderhose
2023-04-19 19:25:24,592 (3190) :  DEBUG (networking:143) - Requesting 'http://127.0.0.1:32400/identity'
2023-04-19 19:25:24,595 (3190) :  DEBUG (networking:143) - Requesting 'http://127.0.0.1:32400'
2023-04-19 19:25:24,598 (3190) :  DEBUG (networking:143) - Requesting 'http://127.0.0.1:32400/identity'
2023-04-19 19:25:24,599 (3190) :  INFO (logkit:16) - Start to auth towards plex.tv
2023-04-19 19:25:24,599 (3190) :  DEBUG (networking:143) - Requesting 'https://plex.tv/users/sign_in.json'
2023-04-19 19:25:24,605 (3190) :  CRITICAL (core:574) - Login error: unknown error (_ssl.c:2938) (most recent call last):
  File "C:\Users\TChil\AppData\Local\Plex Media Server\Plug-ins\WebTools.bundle\Contents\Code\plextvhelper.py", line 44, in login
    self.loginUrl + '.json', headers=self.myHeader, method='POST')['user']['authToken']
  File "C:\Program Files\Plex\Plex Media Server\Resources\Plug-ins-56a60573f\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\parsekit.py", line 145, in ObjectFromURL
    method=method,
  File "C:\Program Files\Plex\Plex Media Server\Resources\Plug-ins-56a60573f\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\api\networkkit.py", line 67, in _http_request
    req = self._core.networking.http_request(url, *args, **kwargs)
  File "C:\Program Files\Plex\Plex Media Server\Resources\Plug-ins-56a60573f\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\networking.py", line 346, in http_request
    return HTTPRequest(self._core, url, data, h, url_cache, encoding, errors, timeout, immediate, sleep, opener, follow_redirects, method)
  File "C:\Program Files\Plex\Plex Media Server\Resources\Plug-ins-56a60573f\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\networking.py", line 118, in __init__
    self.load()
  File "C:\Program Files\Plex\Plex Media Server\Resources\Plug-ins-56a60573f\Framework.bundle\Contents\Resources\Versions\2\Python\Framework\components\networking.py", line 158, in load
    f = self._opener.open(req, timeout=self._timeout)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 429, in open
    response = self._open(req, data)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 447, in _open
    '_open', req)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 407, in _call_chain
    result = func(*args)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 1241, in https_open
    context=self._context)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\urllib2.py", line 1167, in do_open
    h = http_class(host, timeout=req.timeout, **http_conn_args)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\httplib.py", line 1274, in __init__
    context = ssl._create_default_https_context()
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 445, in create_default_context
    context.load_default_certs(purpose)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 412, in load_default_certs
    self._load_windows_store_certs(storename, purpose)
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 404, in _load_windows_store_certs
    self.load_verify_locations(cadata=certs)
SSLError: unknown error (_ssl.c:2938)

2023-04-19 19:25:24,605 (3190) :  ERROR (logkit:22) - Bad credentials detected, denying access

What OS are you using? And to confirm it’s PMS 1.32.X you’re running?

2023-04-19 19:25:24,605 (3190) : ERROR (logkit:22) - Bad credentials detected, denying access

If you are using 2FA, you need to append your 2FA code to the password

Like:

MyPwd: MySecret
2FA: 123456

So in the password field, enter MySecret123456

And yes, I’m on 1.32.1.6954-56a60573f

Edit: And yes, WT bundle outdates the invention of 2FA :wink:

Not using 2FA and double checked the credentials.

Here is a recording of me logging into app.plex.tv and then webtools
plex_recording.zip (3.1 MB)

@dane22 How do you rate @TChilderhose’s test case in Post 5…? with wikipedia there are no credentials necessary and the URL is valid.

The error thrown on his side looks like an SSL problem.

2023-04-19 06:38:27,280 (40bc) :  INFO (logkit:16) - Python Version 2.7.17 (default, Mar 17 2023, 22:05:45) [gcc]
2023-04-19 06:38:27,280 (40bc) :  INFO (logkit:16) - OpenSSL Version OpenSSL 3.0.8 7 Feb 2023

What is your output with this one and do you have any guesses what may be the underlying problem - to me, it looks like a certificate problem:

...
  File "C:\Program Files\Plex\Plex Media Server\python27.zip\ssl.py", line 404, in _load_windows_store_certs
    self.load_verify_locations(cadata=certs)
SSLError: unknown error (_ssl.c:2938)

@TChilderhose Is your server running on Windows (looks like it is) and on which version of Windows?

Ohh, and confirmed broken on Windows, but did work on my QNAP

1 Like

Yes it’s running on Windows 11 Pro 22621.1555.

Was actually starting to wonder if it was OS related yesterday when you said it was working for you. I tried to get my old linux server back up and running quickly last night but wasn’t able to. Was going to try a spinning up plex in WSL at some point to check there.

Well it’s at least promising that it’s playing a little nicer with OpenSSL than I thought it would. Looks like potentially the only problem is with the cert that its trying to load on Windows.

Will see if I can get to the certificate and see what python doesn’t like about it. And worst case investigate generating/using my own cert and using the SSL_CERT_FILE env variable, but not a big fan of that. Dont think using my own is an option as it’s failing checking the windows cert store anyways.

We are looking into it.

No ETA

3 Likes

Please do, this has caused some major issues for me. Can you please provide instructions how to revert back to older plex version?

  1. Uninstall current version of Plex Media Server. Use standard Windows uninstaller. No Revo, CCleaner, etc.

  2. Install desired version of Plex Media Server.

Startup will take longer as PMS has to update the database schema. If you see a 503 message in Plex Web mentioning database maintenance, then just wait and try a few minutes later.

PMS keeps three prior versions in the Updates folder of the Plex Data Folder.

Older (1.31.3) also available here: Plex Media Server support ending for older versions of Windows (7, 8, and 8.1), macOS (10.11, 10.12)

4 Likes

Had a bit of time today to try a few things and was able to get it working. Here is a patch file with the changes I made to Framework.bundle.

plex_network_ssl.zip (1.1 KB)

2 Likes

how is this applied?