jaymzh / concordance

Program Harmony remote controls from Linux, Windows, or Mac!
GNU General Public License v3.0
146 stars 19 forks source link

Libcurl connection failure on Windows + options to fix/workaround #55

Closed Ben-Meister closed 6 months ago

Ben-Meister commented 6 months ago

On Windows, Concordance fails to connnect to members.harmonyremote.com, even though the site has a valid SSL cert. This applies to the released download and when I compile from the main branch.

Libcurl attempted to open ca-bundle.crt from a compiled-in location that is non-existent on Windows (/usr/i686-w64-mingw32/sys-root/mingw/etc/pki/tls/certs/ca-bundle.crt) and failed. Libcurl did not use Windows' system CA store for validation by default.

Fix A: To use Windows' system CA store, I added the following to the list of options in the Zap function in libconcord's web.cpp:

curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);

This worked. Libcurl was able to use Windows' system CA store to successfully verify the certificate, and it did not need the ca-bundle.crt file. (It tries to load it, sees it's missing, and continues on instead of failing.)

Fix B: The Concordance installer does not provide a copy of ca-bundle.crt. And just copying ca-bundle.crt to the program directory does not solve the problem. However, if I copy it and pass the path to ca-bundle.crt to libcurl using

curl_easy_setopt(curl, CURLOPT_CAINFO, "C:\\Program Files (x86)\\Concordance\\ca-bundle.crt");

then it works. (Production code would, of course, not use a hardcoded path.)

Workaround C: Disabling SSL cert verification works as well, as presented in Issue #48.

========== Traces Below ==========

Here's the error on Windows without any code changes (output is from _DEBUG):

* processing: https://members.harmonyremote.com/EasyZapper/New/ProcConnectivity/Connectivity_Receive_Zaps.asp
*   Trying 52.44.86.125:443...
* Connected to members.harmonyremote.com (52.44.86.125) port 443
* ALPN: offers http/1.1
* error setting certificate file: /usr/i686-w64-mingw32/sys-root/mingw/etc/pki/tls/certs/ca-bundle.crt
* error setting certificate file: /usr/i686-w64-mingw32/sys-root/mingw/etc/pki/tls/certs/ca-bundle.crt
* Closing connection
* error setting certificate file: /usr/i686-w64-mingw32/sys-root/mingw/etc/pki/tls/certs/ca-bundle.crt
DEBUG (Zap): curl_easy_perform() failed: Problem with the SSL CA cert (path? access rights?)

Failed with error 13

The connection succeeds when I set CURLSSLOPT_NATIVE_CA, no other changes:

* processing: https://members.harmonyremote.com/EasyZapper/New/ProcConnectivity/Connectivity_Receive_Zaps.asp
*   Trying 52.44.86.125:443...
* Connected to members.harmonyremote.com (52.44.86.125) port 443
* ALPN: offers http/1.1
* successfully imported Windows CA store
* error setting certificate file, continuing anyway
*  CAfile: /usr/i686-w64-mingw32/sys-root/mingw/etc/pki/tls/certs/ca-bundle.crt
*  CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: CN=members.harmonyremote.com
*  start date: Dec 12 03:58:41 2023 GMT
*  expire date: Mar 11 03:58:40 2024 GMT
*  subjectAltName: host "members.harmonyremote.com" matched cert's "members.harmonyremote.com"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* using HTTP/1.1
> POST /EasyZapper/New/ProcConnectivity/Connectivity_Receive_Zaps.asp HTTP/1.1
--<snip>--
< HTTP/1.1 200 OK

The connection also succeeds when I copy ca-bundle.crt to the program directory and set CURLOPT_CAINFO to point at the ca-bundle.crt file, no other changes:

* processing: https://members.harmonyremote.com/EasyZapper/New/ProcConnectivity/Connectivity_Receive_Zaps.asp
*   Trying 52.44.86.125:443...
* Connected to members.harmonyremote.com (52.44.86.125) port 443
* ALPN: offers http/1.1
*  CAfile: C:\Program Files (x86)\Concordance\ca-bundle.crt
*  CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: CN=members.harmonyremote.com
*  start date: Dec 12 03:58:41 2023 GMT
*  expire date: Mar 11 03:58:40 2024 GMT
*  subjectAltName: host "members.harmonyremote.com" matched cert's "members.harmonyremote.com"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* using HTTP/1.1
> POST /EasyZapper/New/ProcConnectivity/Connectivity_Receive_Zaps.asp HTTP/1.1
--<snip>--
< HTTP/1.1 200 OK
swt2c commented 6 months ago

Thanks for the detailed analysis! My thoughts are that adding the CURLSSLOPT_NATIVE_CA option is a reasonable solution, especially if that works on Linux/macOS too. I'll try to test that (if you haven't already or can't).

swt2c commented 6 months ago

It did work fine on Linux too, so I made a pull request with your suggestion (guarded by the libcurl version where this option was added, just to support old libcurls).

Ben-Meister commented 6 months ago

Thank you for resolving this so quickly, and for testing it on Linux. I tried the Windows version that was compiled by the pull request CI and it works. I don't have a Mac to test.