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

schannel error for validating hosts with AltNames #3711

Closed
jeroen opened this issue Mar 27, 2019 · 5 comments

Comments

@jeroen
Copy link
Contributor

commented Mar 27, 2019

Trying to upgrade the R bindings on Windows from 7.59.1 to 7.64.1. The curl configuration is dual-ssl (openssl + schannel) with the latter being the default.

$version
[1] "7.64.1"

$ssl_version
[1] "(OpenSSL/1.1.1a) Schannel"

The bindings set CURLOPT_CAINFO to the path of our cert bundle. However, I think in libcurl 7.59.1 this option was only needed for the openssl back-end, because schannel would ignore it and use the Windows certificate store to validate certs? Not sure.

curl_easy_setopt(handle, CURLOPT_CAINFO, CA_BUNDLE);

Anyway, with the new version, trying to connect to e.g. www.github.com fails like this:

* Hostname in DNS cache was stale, zapped
*   Trying 140.82.118.4...
* TCP_NODELAY set
* Connected to www.github.com (140.82.118.4) port 443 (#3)
* schannel: added 143 certificate(s) from CA file 'C:/PROGRA~1/R/R-35~1.3/etc/curl-ca-bundle.crt'
* schannel: connection hostname (www.github.com) did not match against certificate name (github.com)
* schannel: CertGetNameString() failed to match connection hostname (www.github.com) against server certificate names
* Closing connection 3
* schannel: shutting down SSL/TLS connection with www.github.com port 443
Error in curl::curl_fetch_memory("https://www.github.com", handle = new_handle(verbose = T)) : 
  schannel: CertGetNameString() failed to match connection hostname (www.github.com) against server certificate names

The line below wasn't there in 7.59.1, I guess it is now using the bundle instead of windows certificate store for validating certs with schannel which was probably already added in 7.60.0.

schannel: added 143 certificate(s) from CA file 'C:/PROGRA~1/R/R-35~1.3/etc/curl-ca-bundle.crt'

However it doesn't seem to support AltName certs, which is why connecting to www.github.com fails. If we connect to github.com instead then it works, because github.com is the primary CN on the cert:

*   Trying 140.82.118.4...
* TCP_NODELAY set
* Connected to github.com (140.82.118.4) port 443 (#4)
* schannel: added 143 certificate(s) from CA file 'C:/PROGRA~1/R/R-35~1.3/etc/curl-ca-bundle.crt'
* schannel: connection hostname (github.com) validated against certificate name (github.com)
> GET / HTTP/1.1
Host: github.com
User-Agent: R (3.5.3 i386-w64-mingw32 i386 mingw32)
Accept: */*
Accept-Encoding: deflate, gzip

< HTTP/1.1 200 OK

The problem does not appear when using the openssl backend (so the bundle file is not the problem), or when using the schannel without setting CURLOPT_CAINFO (in which case I guess it uses the Windows certificate store).

@jay

This comment has been minimized.

Copy link
Member

commented Mar 29, 2019

CERT_NAME_SEARCH_ALL_NAMES_FLAG isn't available earlier than Windows 8 as discussed here.

#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
name_flags |= CERT_NAME_SEARCH_ALL_NAMES_FLAG;
#endif

curl tool doesn't set CAINFO for schannel, it does it like this:

curl/src/tool_operate.c

Lines 261 to 269 in 521bbbe

/* Set the CA cert locations specified in the environment. For Windows if
* no environment-specified filename is found then check for CA bundle
* default filename curl-ca-bundle.crt in the user's PATH.
*
* If Schannel is the selected SSL backend then these locations are
* ignored. We allow setting CA location for schannel only when explicitly
* specified by the user via CURLOPT_CAINFO / --cacert.
*/
if(tls_backend_info->backend != CURLSSLBACKEND_SCHANNEL) {

Likely you specified CAINFO and the CERT_NAME_SEARCH_ALL_NAMES_FLAG was not available at build time because you targeted < Windows 8. It's fixable but I've focused on other issues. It should be possible to fix by iterating through CERT_ALT_NAME_INFO instead of using that flag.

@jeroen

This comment has been minimized.

Copy link
Contributor Author

commented Mar 31, 2019

Likely you specified CAINFO and the CERT_NAME_SEARCH_ALL_NAMES_FLAG was not available at build time because you targeted < Windows 8.

Right this is the case. I will make sure to not set CAINFO icw/ CURLSSLBACKEND_SCHANNEL then.

Perhaps there should be a warning of some sort in the CURLOPT_CAINFO documentation because https really doesn't function without CERT_NAME_SEARCH_ALL_NAMES_FLAG in today's world (almost all certs from CDNs have many different domains in them).

@jeroen jeroen closed this Mar 31, 2019
@jay

This comment has been minimized.

Copy link
Member

commented Apr 1, 2019

Perhaps there should be a warning of some sort in the CURLOPT_CAINFO documentation because https really doesn't function without CERT_NAME_SEARCH_ALL_NAMES_FLAG in today's world (almost all certs from CDNs have many different domains in them).

Yeah that's a fair point we'll try to fix it for the next release.

@jay jay reopened this Apr 1, 2019
@bagder

This comment has been minimized.

Copy link
Member

commented Apr 13, 2019

Maybe turn that into a new separate issue with a description explaining it (I didn't follow it totally I think)? I fear it mostly gets lost here.

bagder added a commit that referenced this issue May 12, 2019
Clues-provided-by: Jay Satiro
Clues-provided-by: Jeroen Ooms
Fixes #3711
@bagder

This comment has been minimized.

Copy link
Member

commented May 12, 2019

My attempt at documenting this is now in #3874.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
3 participants
You can’t perform that action at this time.