matrix-org / sygnal

Sygnal: reference Push Gateway for Matrix
Apache License 2.0
160 stars 144 forks source link

CA_MD_TOO_WEAK for dev APNS certificate #260

Closed irl closed 2 years ago

irl commented 2 years ago

Describe the bug A freshly signed dev APNS certificate causes a crash with openssl error below.

To Reproduce Steps to reproduce the behavior:

  1. Use the sygnal docker container
  2. Use a freshly signed dev APNS certificate
  3. Check logs

Expected behavior Certificate is accepted.

Screenshots

sygnal_1   | Using configuration file: /config/sygnal.yaml
sygnal_1   | 2021-10-25 12:47:46,830 [1] INFO  __main__ Starting Prometheus Server on 0.0.0.0 port 8000
sygnal_1   | 2021-10-25 12:47:46,836 [1] INFO  __main__ Importing pushkin module: sygnal.apnspushkin
sygnal_1   | 2021-10-25 12:47:46,853 [1] INFO  __main__ Creating pushkin: ApnsPushkin
sygnal_1   | 2021-10-25 12:47:46,855 [1] ERROR __main__ Failed to load and create pushkin for kind 'apns'
sygnal_1   | Error during startup:
sygnal_1   | Traceback (most recent call last):
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/sygnal/sygnal.py", line 199, in start
sygnal_1   |     yield ensureDeferred(self.make_pushkins_then_start())
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/twisted/internet/defer.py", line 1130, in ensureDeferred
sygnal_1   |     return Deferred.fromCoroutine(coro)
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/twisted/internet/defer.py", line 1106, in fromCoroutine
sygnal_1   |     return _cancellableInlineCallbacks(coro)
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/twisted/internet/defer.py", line 1816, in _cancellableInlineCallbacks
sygnal_1   |     _inlineCallbacks(None, gen, status)
sygnal_1   | --- <exception caught here> ---
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/sygnal/sygnal.py", line 199, in start
sygnal_1   |     yield ensureDeferred(self.make_pushkins_then_start())
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/twisted/internet/defer.py", line 1661, in _inlineCallbacks
sygnal_1   |     result = current_context.run(gen.send, result)
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/sygnal/sygnal.py", line 171, in make_pushkins_then_start
sygnal_1   |     self.pushkins[app_id] = await self._make_pushkin(app_id, app_cfg)
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/sygnal/sygnal.py", line 166, in _make_pushkin
sygnal_1   |     return await clarse.create(app_name, self, app_config)
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/sygnal/notifications.py", line 132, in create
sygnal_1   |     return cls(name, sygnal, config)
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/sygnal/apnspushkin.py", line 151, in __init__
sygnal_1   |     loop=loop,
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/aioapns/client.py", line 36, in __init__
sygnal_1   |     ssl_context=ssl_context,
sygnal_1   |   File "/usr/local/lib/python3.7/site-packages/aioapns/connection.py", line 450, in __init__
sygnal_1   |     self.ssl_context.load_cert_chain(cert_file)
sygnal_1   | ssl.SSLError: [SSL: CA_MD_TOO_WEAK] ca md too weak (_ssl.c:3911)

Similar issues:

DMRobertson commented 2 years ago

This looks like openssl is unhappy about your certificate. I don't think it's a problem with Sygnal as such.

https://stackoverflow.com/a/52220373/5252017 looks promising. The author there writes:

You may need to regenerate the certificate and use a stronger hash to sign, for example SHA1.

richvdh commented 2 years ago

the problem here is that the cert is generated by Apple :/

irl commented 2 years ago

the problem here is that the cert is generated by Apple :/

Yes, we generated a brand new certificate to make sure we're not using one generated with older parameters but still getting the same issue. It might not be a problem with Sygnal specifically, but does affect the Sygnal docker image which I believe is built from this repository, so I think this issue is in the right place.

reivilibre commented 2 years ago

Assuming we're happy with people using these certificates, we can fix this by configuring OpenSSL's security level to be level 1 rather than 2.

This involves editing this part of /etc/ssl/openssl.cnf:

[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT@SECLEVEL=2

I believe this can also be configured in Sygnal code (IIRC you can specify it when configuring the list of allowed ciphers), but I'm not sure that's the right solution here.

irl commented 2 years ago

Assuming we're happy with people using these certificates, we can fix this by configuring OpenSSL's security level to be level 1 rather than 2.

Yeah, if we can do this for the Docker image then the issue should resolve itself. I'm happy to test it out as soon as a build is available as I'm blocking on this for a project.

richvdh commented 2 years ago

but I'm not sure that's the right solution here.

Yeah, it sounds like using a JWT key might be a better solution than a client cert.

In the meantime, it might be good to update openssl.cnf in the docker image.

callahad commented 2 years ago

Let's do the one line change in then openssl conf for now and figure out how to support JWTs later. (I'll file a separate bug)

reivilibre commented 2 years ago

@irl are you happy to try token-based (JWT) authentication?

Instead of specifying a certfile, you would need to specify (copied from the README):

I would hope it's easy to find these from Apple?

callahad commented 2 years ago

We believe JWT-based authentication, which is supported by Sygnal for APNS, is a reasonable alternative, and preferable to downgrading the security level of OpenSSL in our container.

@irl: If it is not possible for you to use JWTs, please reply with why and we can re-open this issue and fix it.