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

Loop over all CA Issuers #496

Open
rlueckl opened this issue Jan 10, 2024 · 13 comments
Open

Loop over all CA Issuers #496

rlueckl opened this issue Jan 10, 2024 · 13 comments
Assignees
Labels
bug need more info Not enough information to reproduce or analyse the problem

Comments

@rlueckl
Copy link

rlueckl commented Jan 10, 2024

Is your feature request related to a problem? Please describe.

Similar to #258 could we also have a feature that the OCSP check loops over all "CA Issuers" found in the certificate? Currently it only looks at the first issuer and if that doesn't match the certificate, the OCSP validation fails.

Our internal CA writes 3 different issuers in the certificate (one old one and two new ones), but only one of them (the last one) matches the certificate.

Describe the solution you'd like

check_ssl_cert should loop over all "CA Issuers" and only throw an error if the certificate can't be validated against any of them.

Additional context

Certificate contains:

        X509v3 extensions:
            Authority Information Access: 
                CA Issuers - URI:http://company.pki.infrastructure/pub/internalissuer_old.cer
                CA Issuers - URI:http://company.pki.infrastructure/pub/internalissuer_new_a.cer
                CA Issuers - URI:http://company.pki.infrastructure/pub/internalissuer_new_b.cer
                OCSP - URI:http://company.ocsp.infrastructure/ocsp

The certificate issuer is internalissuer_new_b.

check_ssl_cert only looks at internalissuer_old. Debug log from testing:

[DBG 1s] ------------------------------------------------------------------------------
[DBG 1s] Checking OCSP status of element 1
[DBG 1s] temporary file /tmp/QkBALW created
[DBG 1s] Storing the chain element in /tmp/QkBALW
[DBG 1s] Checking revocation via OCSP
[DBG 1s] extracting cert attribute issuer_hash
[DBG 1s] Issuer hash: f31059ce
[DBG 1s] extracting cert attribute issuer_uri
[DBG 1s] Chain element issuer URIs: http://company.pki.infrastructure/pub/internalissuer_old.cer
[DBG 1s] http://company.pki.infrastructure/pub/internalissuer_new_a.cer
[DBG 1s] http://company.pki.infrastructure/pub/internalissuer_new_b.cer
[DBG 1s] checking issuer URIs: http://company.pki.infrastructure/pub/internalissuer_old.cer
[DBG 1s] OCSP: fetching issuer certificate http://company.pki.infrastructure/pub/internalissuer_old.cer to /tmp/VfkrIY
[DBG 1s] exec_with_timeout: TIMEOUT=120, CURRENT_TIMEOUT=119, ELAPSED=1
[DBG 1s] exec_with_timeout /usr/bin/curl     --silent --user-agent 'check_ssl_cert/2.78.0' --location \"http://company.pki.infrastructure/pub/internalissuer_old.cer\" > /tmp/VfkrIY
[DBG 1s] executing with timeout (119s): /usr/bin/curl     --silent --user-agent 'check_ssl_cert/2.78.0' --location \"http://company.pki.infrastructure/pub/internalissuer_old.cer\" > /tmp/VfkrIY
[DBG 1s] /usr/bin/timeout 119 /bin/sh -c "/usr/bin/curl     --silent --user-agent 'check_ssl_cert/2.78.0' --location \"http://company.pki.infrastructure/pub/internalissuer_old.cer\" > /tmp/VfkrIY"
[DBG 1s] OCSP: issuer certificate type (1): Certificate, Version=3
[DBG 1s] OCSP: issuer certificate type (2): Certificate, Version=3
[DBG 1s] OCSP: converting issuer certificate from DER to PEM
[DBG 1s] OCSP: issuer certificate type (3): PEM certificate
[DBG 1s] checking issuer URIs: http://company.pki.infrastructure/pub/internalissuer_new_a.cer
[DBG 1s] checking issuer URIs: http://company.pki.infrastructure/pub/internalissuer_new_b.cer
[DBG 1s] extracting cert attribute oscp_uri
[DBG 1s] OCSP: URIs = http://company.ocsp.infrastructure/ocsp
[DBG 1s] OCSP: URI = http://company.ocsp.infrastructure/ocsp
[DBG 1s] OCSP: host = company.ocsp.infrastructure
[DBG 1s] openssl ocsp supports the -header option
[DBG 1s] /usr/bin/openssl ocsp -header requires 'key=value'
[DBG 1s] executing (5) /usr/bin/openssl ocsp -timeout "119" -no_nonce -issuer /tmp/VfkrIY -cert /tmp/QkBALW  -url http://company.ocsp.infrastructure/ocsp  -header HOST=company.ocsp.infrastructure
[DBG 1s] OCSP: response = Responder Error: unauthorized (6)
[DBG 1s] OCSP: not good. HTTP_PROXY = 
[DBG 1s] executing /usr/bin/openssl ocsp -timeout "119" -no_nonce -issuer "/tmp/VfkrIY" -cert "/tmp/QkBALW" -url "http://company.ocsp.infrastructure/ocsp" "" 2>&1
[DBG 1s] Responder Error: unauthorized (6)
CRITICAL error: OCSP error (Responder Error: unauthorized (6))
[DBG 1s] CRITICAL ----------------------------------------
[DBG 1s] prepend_critical_message: new message    = OCSP error (Responder Error: unauthorized (6))
[DBG 1s] prepend_critical_message: CRITICAL_MSG   =
[DBG 1s] prepend_critical_message: ALL_MSG 1      =
[DBG 1s] prepend_critical_message: MSG 2          = SSL_CERT CRITICAL servername01.lan:8443: OCSP error (Responder Error: unauthorized (6))
[DBG 1s] prepend_critical_message: CRITICAL_MSG 2 = SSL_CERT CRITICAL servername01.lan:8443: OCSP error (Responder Error: unauthorized (6))
[DBG 1s] prepend_critical_message: ALL_MSG 2      = \n    SSL_CERT CRITICAL servername01.lan:8443: OCSP error (Responder Error: unauthorized (6))
[DBG 1s] CRITICAL ----------------------------------------

Testing manually:

LIVE root@servername01 ~ # /usr/bin/openssl ocsp -timeout "119" -no_nonce -issuer internalissuer_old.pem -cert servername01.pem  -url http://company.ocsp.infrastructure/ocsp  -header HOST=company.ocsp.infrastructure
Responder Error: unauthorized (6)

LIVE root@servername01 ~ # /usr/bin/openssl ocsp -timeout "119" -no_nonce -issuer internalissuer_new_b.pem -cert servername01.pem  -url http://company.ocsp.infrastructure/ocsp  -header HOST=company.ocsp.infrastructure
Response verify OK
servername01.pem: good
	This Update: Jan 10 12:55:13 2024 GMT
@matteocorti matteocorti self-assigned this Jan 10, 2024
@matteocorti
Copy link
Owner

I would first check if this really makes sense. Why more then one issuer? Is there a use case? I didn't find any other examples...

But on the other end, the "s" at the end of "Issuers" seems to indicate that more then one should be possible

@matteocorti
Copy link
Owner

Just as info

Authority Information Access (AIA) is a special extension in SSL certificates that contains information about the issuer of the certificate. This extension helps fetch intermediate certificates from the issuing certification authority. In case if server does not provide intermediate certificates, they could be downloaded from the link contained in the AIA field. This approach allows saving the certificate chain and performing an SSL certificate check, even if the server incorrectly configured. If user's client supports AIA Fetching, then user does not even aware of server configuration errors.

@matteocorti
Copy link
Owner

Since I do not have host to test. Do you (@rlueckl) have a host I could use for debugging? You could send it to me privately and I would not disclose it.

@lukastribus
Copy link
Contributor

I just had check_ssl_cert correctly return CRITICAL for a revoked certificate due to OCSP a few days ago, so I do think it works currently.

@matteocorti
Copy link
Owner

I just had check_ssl_cert correctly return CRITICAL for a revoked certificate due to OCSP a few days ago, so I do think it works currently.

I just checked, and it works (I deleted my earlier comments, as the implementation seems correct).

The OCSP client needs the intermediate certificate to perform the check. What should be done if multiple are specified and if one is not OK is not really clear to me.

The extension is there to permit a check even if the server does not deliver the intermediate certificate. On a first thought, it seems to me that an invalid intermediate certificate should not be accepted. On the other hand, since this attribute is there to help in case of a misconfigured server, I do not see a lot of problems by checking all of them.

@matteocorti
Copy link
Owner

@matteocorti
Copy link
Owner

Seems that multiple certifcates are possible:

An authorityInfoAccess extension may include multiple instances of
the id-ad-caIssuers accessMethod. The different instances may
specify different methods for accessing the same information or may
point to different information. When the id-ad-caIssuers
accessMethod is used, at least one instance SHOULD specify an
accessLocation that is an HTTP [RFC2616] or LDAP [RFC4516] URI.

@matteocorti
Copy link
Owner

And again: https://security.stackexchange.com/questions/26577/is-an-aia-or-crl-useful-required-at-the-root-ca-if-that-root-is-used-to-cross

The AIA extensions are used to help in path building, by pointing to potential certificates for the issuer. Use of these certificate is not mandatory; mass deployment of intermediate CA certificates is a viable alternative (at least in organized networks which offer facilities for that, e.g. Active Directory servers).

In this case the issue is valid and is a bug

@matteocorti matteocorti added bug need more info Not enough information to reproduce or analyse the problem and removed enhancement labels Jan 10, 2024
@lukastribus
Copy link
Contributor

I'm not sure if I understand this ticket, but if this is about hiding server configuration issues by downloading intermediate certificates from AIA, I strongly disagree, as previously discussed:

#366 (comment)

@matteocorti
Copy link
Owner

I'm not sure if I understand this ticket, but if this is about hiding server configuration issues by downloading intermediate certificates from AIA, I strongly disagree, as previously discussed:

#366 (comment)

I agree with you. I am not using the information from AIA to validate the chain. A missing intermediate certificate is an error.

According to the RFC the information in the AIA is there to perform the OCSP check.

I still have to check, but I could completely ignore the certificate specified with AIA and send the intermediate from the chain.

I need some time to perform some checks.

@rlueckl
Copy link
Author

rlueckl commented Jan 11, 2024

Sorry, this goes a little bit above my head. 😄

As far as I understand https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.7 multiple certificates are possible and can be used to validate the chain (as you already wrote). I think the intention of multiple entries was to have a fallback in case one URL isn't reachable.

According to the RFC the information in the AIA is there to perform the OCSP check.

I still have to check, but I could completely ignore the certificate specified with AIA and send the intermediate from the chain.

This would also work for us. Our servers offer the complete chain, no need to download the intermediate from the AIA.

Unfortunately I can't send you a host (even privately), because all the information is confidential. I can give you debug logs with the hostnames, filenames, etc. altered like in the initial message.

@matteocorti
Copy link
Owner

Sorry, this goes a little bit above my head. 😄

As far as I understand https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.7 multiple certificates are possible and can be used to validate the chain (as you already wrote). I think the intention of multiple entries was to have a fallback in case one URL isn't reachable.

According to the RFC the information in the AIA is there to perform the OCSP check.
I still have to check, but I could completely ignore the certificate specified with AIA and send the intermediate from the chain.

This would also work for us. Our servers offer the complete chain, no need to download the intermediate from the AIA.

Unfortunately I can't send you a host (even privately), because all the information is confidential. I can give you debug logs with the hostnames, filenames, etc. altered like in the initial message.

I'll have to craft a local test certificate then ...

@grimz-ly
Copy link

maybe wrong to comment here, but I feel it's related.

if local CA root certificate is expired, the certificate chain validation doesn't happen at all and the check returns OK status. Should the test return CRIT if the local CA root cert is expired given it leverages it for these checks?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug need more info Not enough information to reproduce or analyse the problem
Projects
None yet
Development

When branches are created from issues, their pull requests are automatically linked.

4 participants