Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fetch missing SSL certificates to fix curl error: unable to get local issuer certificate #4469

Open
milahu opened this issue May 26, 2024 · 0 comments · May be fixed by #4478
Open

fetch missing SSL certificates to fix curl error: unable to get local issuer certificate #4469

milahu opened this issue May 26, 2024 · 0 comments · May be fixed by #4478
Assignees
Labels
bug Something isn't working pyLoad Next

Comments

@milahu
Copy link

milahu commented May 26, 2024

actually fix #4273

This is either pycurl error or a server error.

this is a missing feature in curl, so its a pycurl error

urls like https://www788.ucdn.to:183/ work in chrome, but fail with curl

$ curl https://www788.ucdn.to:183/
curl: (60) SSL certificate problem: unable to get local issuer certificate

strictly speaking, this is server error

$ echo quit | openssl s_client -connect www788.ucdn.to:183
CONNECTED(00000003)
depth=0 CN = *.ucdn.to
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = *.ucdn.to
verify error:num=21:unable to verify the first certificate
verify return:1
depth=0 CN = *.ucdn.to
verify return:1
---
Certificate chain
 0 s:CN = *.ucdn.to
   i:C = BE, O = GlobalSign nv-sa, CN = GlobalSign GCC R6 AlphaSSL CA 2023
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Feb  6 20:42:58 2024 GMT; NotAfter: Mar  9 20:42:57 2025 GMT
 1 s:C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
   i:C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA1
   v:NotBefore: Sep  1 12:00:00 1998 GMT; NotAfter: Jan 28 12:00:00 2028 GMT
---

cert 0 issuer: GlobalSign GCC R6 AlphaSSL CA 2023
cert 1 subject: GlobalSign Root CA

... these should be identical in a full chain of certs

but cert 0 has the Authority Information Access extension
and we need to fetch the missing issuer cert from CA Issuers - URI

cert 0 = leaf cert

$ echo quit | openssl s_client -showcerts -connect www788.ucdn.to:183 2>&1 | openssl x509 -noout -text | grep -e 'Certificate:' -e 'Data:' -e 'Issuer:' -e 'Subject:' -e 'Authority Information Access' -e 'CA Issuers - URI:' -e 'OCSP - URI:'
Certificate:
    Data:
        Issuer: C = BE, O = GlobalSign nv-sa, CN = GlobalSign GCC R6 AlphaSSL CA 2023
        Subject: CN = *.ucdn.to
            Authority Information Access: 
                CA Issuers - URI:http://secure.globalsign.com/cacert/gsgccr6alphasslca2023.crt
                OCSP - URI:http://ocsp.globalsign.com/gsgccr6alphasslca2023

actual cert 1 = intermediary cert

$ curl -s http://secure.globalsign.com/cacert/gsgccr6alphasslca2023.crt | openssl x509 -noout -text | grep -e 'Certificate:' -e 'Data:' -e 'Issuer:' -e 'Subject:' -e 'Authority Information Access' -e 'CA Issuers - URI:' -e 'OCSP - URI:'
Certificate:
    Data:
        Issuer: OU = GlobalSign Root CA - R6, O = GlobalSign, CN = GlobalSign
        Subject: C = BE, O = GlobalSign nv-sa, CN = GlobalSign GCC R6 AlphaSSL CA 2023
            Authority Information Access: 
                OCSP - URI:http://ocsp2.globalsign.com/rootr6
                CA Issuers - URI:http://secure.globalsign.com/cacert/root-r6.crt

here, cert 0 issuer and cert 1 subject are identical:
C = BE, O = GlobalSign nv-sa, CN = GlobalSign GCC R6 AlphaSSL CA 2023

actual cert 1 can be verified offline
because cert 1 issuer is in the system ca-bundle.crt
so there is no need to fetch http://secure.globalsign.com/cacert/root-r6.crt

$ curl -s http://secure.globalsign.com/cacert/gsgccr6alphasslca2023.crt | openssl verify
stdin: OK

cert 1 subject: GlobalSign Root CA

this cert is not needed to verify cert 0
its just wrong and misleading, either by accident or on purpose

strictly speaking, this is server error

but in the real world, many servers have such a "broken" config
so chrome fetches the missing issuer certs from CA Issuers - URI

there is a shit-ton of discussions on this topic ...

... yepp, i already spent 2 days on this ^^

... but the TLDR is:
chrome defines the standard, and curl refuses to follow because "all hail the RFC"...

this reminds me very much of the curl issue curl/curl#11125
where curl maintainers are over-fulfilling the RFC in the name of "security"
but that is hurting real-world users

from AIA fetching in Chrome for Android

While Brian's absolutely correct that AIA also covers misconfigurations, such as a server only supplying a single certificate, I don't agree with causing users pain and conditioning them on errors simply for an ideological stand. Past attempts at such stands, such as refusing to persist TLS errors, resulted in much worse experiences for Chrome users.

workaround for curl

  • catch the unable to get local issuer certificate error
  • fetch missing certificates and add them to ca-bundle.crt
    • note: we do not trust the extra certs. we add them as -----BEGIN CERTIFICATE----- not as -----BEGIN TRUSTED CERTIFICATE-----. so in rare cases, the user will have to decide whether he trusts an unknown root cert... but that situation would also break in chrome
  • call curl again with the updated ca-bundle.crt
  • cache our ca-bundle.crt in ~/.pyload/ca-bundle.crt

fetching certs in python is 3x slower than in curl
so we always should try to call curl first
and only on curl error, fetch certs in python, and retry curl

src/pyload/core/network/http/http_request.py

        if "ssl_verify" in options:
            if options["ssl_verify"]:
                self.c.setopt(pycurl.CAINFO, certifi.where())

certifi.where() returns the path to the system ca-bundle.crt
usually /etc/ssl/certs/ca-bundle.crt

currently im working on danilobellini/aia#3
hope to get this done in the next 1...2 days, then add aia to pyload

@milahu milahu added bug Something isn't working pyLoad Next labels May 26, 2024
milahu added a commit to milahu/pyload that referenced this issue Jun 1, 2024
fix curl error:

curl: (60) SSL certificate problem: unable to get local issuer certificate
milahu added a commit to milahu/pyload that referenced this issue Jun 1, 2024
fix curl error:

curl: (60) SSL certificate problem: unable to get local issuer certificate
@milahu milahu linked a pull request Jun 1, 2024 that will close this issue
@milahu milahu changed the title fetch missing TLS certificates to fix curl error: unable to get local issuer certificate fetch missing SSL certificates to fix curl error: unable to get local issuer certificate Jun 1, 2024
milahu added a commit to milahu/pyload that referenced this issue Jun 16, 2024
fix curl error:

curl: (60) SSL certificate problem: unable to get local issuer certificate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working pyLoad Next
Development

Successfully merging a pull request may close this issue.

2 participants