Skip to content

Commit 3fcfa58

Browse files
committed
Search for CA bundles in places other than the one hard-coded at compile-time.
1 parent 98633fe commit 3fcfa58

File tree

1 file changed

+84
-1
lines changed

1 file changed

+84
-1
lines changed

src/updateinformation/GithubReleasesZsyncUpdateInformation.cpp

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,83 @@
11
#include "GithubReleasesZsyncUpdateInformation.h"
22

3+
/* Eh, borrowed from zsync2. Why reinvent the wheel? */
4+
#include <sys/stat.h>
5+
6+
// returns non-zero ("true") on success, 0 ("false") on failure
7+
int file_exists(const char* path) {
8+
struct stat statbuf = {};
9+
10+
if (stat(path, &statbuf) == 0) {
11+
return 1;
12+
}
13+
14+
const int error = errno;
15+
if (error != ENOENT) {
16+
fprintf(stderr, "zsync2: Unknown error while checking whether file %s exists: %s\n", path, strerror(error));
17+
}
18+
19+
return 0;
20+
}
21+
22+
// memory returned by this function must not be freed by the user
23+
const char* ca_bundle_path() {
24+
// in case the user specifies a custom file, we use this one instead
25+
// TODO: consider merging the user-specified file with the system CA bundle into a temp file
26+
const char* path_from_environment = getenv("SSL_CERT_FILE");
27+
28+
if (path_from_environment != NULL) {
29+
return path_from_environment;
30+
}
31+
32+
#if CURL_AT_LEAST_VERSION(7, 84, 0)
33+
{
34+
// (very) recent libcurl versions provide us with a way to query the build-time search path they
35+
// use to find a suitable (distro-provided) CA certificate bundle they can hardcode
36+
// we can use this value to search for a bundle dynamically in the application
37+
CURL* curl = curl_easy_init();
38+
39+
if (curl != NULL) {
40+
CURLcode res;
41+
char* curl_provided_path = NULL;
42+
43+
curl_easy_getinfo(curl, CURLINFO_CAINFO, &curl_provided_path);
44+
45+
// should be safe to delete the handle and use the returned value, since it is allocated statically within libcurl
46+
curl_easy_cleanup(curl);
47+
48+
if (curl_provided_path != NULL) {
49+
if (file_exists(curl_provided_path)) {
50+
return curl_provided_path;
51+
}
52+
}
53+
}
54+
}
55+
#endif
56+
57+
// this list is a compilation of other AppImage projects' lists and the one used in libcurl's build system's autodiscovery
58+
// should cover most Linux distributions
59+
static const char* const possible_ca_bundle_paths[] = {
60+
"/etc/pki/tls/cacert.pem",
61+
"/etc/pki/tls/cert.pem",
62+
"/etc/pki/tls/certs/ca-bundle.crt",
63+
"/etc/ssl/ca-bundle.pem",
64+
"/etc/ssl/cert.pem",
65+
"/etc/ssl/certs/ca-certificates.crt",
66+
"/usr/local/share/certs/ca-root-nss.crt",
67+
"/usr/share/ssl/certs/ca-bundle.crt",
68+
};
69+
70+
for (size_t i = 0; i < sizeof(possible_ca_bundle_paths); ++i) {
71+
const char* path_to_check = possible_ca_bundle_paths[i];
72+
if (file_exists(path_to_check)) {
73+
return path_to_check;
74+
}
75+
}
76+
77+
return NULL;
78+
}
79+
/* End of zsync2 code */
80+
381
namespace appimage::update::updateinformation {
482

583
GithubReleasesUpdateInformation::GithubReleasesUpdateInformation(
@@ -29,7 +107,12 @@ namespace appimage::update::updateinformation {
29107
url << "tags/" << tag;
30108
}
31109

32-
auto response = cpr::Get(cpr::Url{url.str()});
110+
cpr::Session session;
111+
cpr::SslOptions options;
112+
options.ca_info = std::string(ca_bundle_path());
113+
session.SetSslOptions(options);
114+
session.SetUrl(cpr::Url{url.str()});
115+
auto response = session.Get();
33116

34117
nlohmann::json json;
35118

0 commit comments

Comments
 (0)