Windows: point libcurl at a CA bundle
ci / linux (clang) (push) Canceled after 0s
ci / linux (gcc) (push) Canceled after 0s
ci / sanitizers (push) Canceled after 0s
ci / musl (push) Canceled after 0s
ci / macos (push) Canceled after 0s
ci / linux (clang) (pull_request) Canceled after 0s
ci / linux (gcc) (pull_request) Canceled after 0s
ci / sanitizers (pull_request) Canceled after 0s
ci / musl (pull_request) Canceled after 0s
ci / macos (pull_request) Canceled after 0s
ci / linux (clang) (push) Canceled after 0s
ci / linux (gcc) (push) Canceled after 0s
ci / sanitizers (push) Canceled after 0s
ci / musl (push) Canceled after 0s
ci / macos (push) Canceled after 0s
ci / linux (clang) (pull_request) Canceled after 0s
ci / linux (gcc) (pull_request) Canceled after 0s
ci / sanitizers (pull_request) Canceled after 0s
ci / musl (pull_request) Canceled after 0s
ci / macos (pull_request) Canceled after 0s
An OpenSSL-based libcurl keeps the CA path it was built with. MSYS2's is "/mingw64/etc/ssl/certs/ca-bundle.crt", which resolves to nothing once the binary runs outside an MSYS2 shell, and that build ignores CURL_CA_BUNDLE, SSL_CERT_FILE and SSL_CERT_DIR. Every HTTPS request then failed with CURLE_SSL_CACERT_BADFILE (77). llm_apply_ca_bundle() sets CURLOPT_CAINFO from $CST_CA_BUNDLE, falling back to ca-bundle.crt beside the executable. If neither exists nothing is set, so a libcurl linked against Schannel (the Windows certificate store) behaves exactly as before.
This commit was merged in pull request #2.
This commit is contained in:
+45
-4
@@ -22,6 +22,45 @@
|
|||||||
#define ERRBODY_MAX 4096
|
#define ERRBODY_MAX 4096
|
||||||
#define LLM_MAX_RETRIES 3
|
#define LLM_MAX_RETRIES 3
|
||||||
|
|
||||||
|
/* Point libcurl at a CA bundle on Windows.
|
||||||
|
*
|
||||||
|
* An OpenSSL-based libcurl keeps the path it was built with -- MSYS2's is
|
||||||
|
* "/mingw64/etc/ssl/certs/ca-bundle.crt", which resolves to nothing once the
|
||||||
|
* binary runs outside an MSYS2 shell, and that build ignores CURL_CA_BUNDLE.
|
||||||
|
* Every HTTPS request then dies with CURLE_SSL_CACERT_BADFILE (77).
|
||||||
|
*
|
||||||
|
* Order: $CST_CA_BUNDLE, then ca-bundle.crt beside the executable. If neither
|
||||||
|
* exists nothing is set, so a libcurl linked against Schannel (the Windows
|
||||||
|
* certificate store) behaves exactly as before. */
|
||||||
|
static void llm_apply_ca_bundle(CURL *curl) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
static char ca[OS_PATH_MAX];
|
||||||
|
static int checked;
|
||||||
|
if (!checked) {
|
||||||
|
checked = 1;
|
||||||
|
const char *env = getenv("CST_CA_BUNDLE");
|
||||||
|
if (env && env[0]) {
|
||||||
|
snprintf(ca, sizeof(ca), "%s", env);
|
||||||
|
} else {
|
||||||
|
char dir[OS_PATH_MAX];
|
||||||
|
if (os_exe_dir(dir, sizeof(dir)) == 0)
|
||||||
|
os_path_join(ca, sizeof(ca), dir, "ca-bundle.crt");
|
||||||
|
}
|
||||||
|
if (ca[0]) {
|
||||||
|
FILE *f = fopen(ca, "rb");
|
||||||
|
if (f)
|
||||||
|
fclose(f);
|
||||||
|
else
|
||||||
|
ca[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ca[0])
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CAINFO, ca);
|
||||||
|
#else
|
||||||
|
(void)curl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* --- wire body ----------------------------------------------------------- */
|
/* --- wire body ----------------------------------------------------------- */
|
||||||
|
|
||||||
static size_t wire_tool_cap(const cst_llm_request_t *req) {
|
static size_t wire_tool_cap(const cst_llm_request_t *req) {
|
||||||
@@ -621,6 +660,7 @@ int cst_llm_chat_stream(const cst_llm_request_t *req, char *err,
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
llm_apply_ca_bundle(curl);
|
||||||
sse_reset(&s);
|
sse_reset(&s);
|
||||||
s.curl = curl;
|
s.curl = curl;
|
||||||
if (rec_dir && rec_dir[0]) {
|
if (rec_dir && rec_dir[0]) {
|
||||||
@@ -765,10 +805,11 @@ int cst_llm_list_models(const char *api_base, const char *api_key,
|
|||||||
}
|
}
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
if (!curl) {
|
if (!curl) {
|
||||||
snprintf(err, err_sz, "curl init failed");
|
snprintf(err, err_sz, "curl init failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
char url[1024];
|
llm_apply_ca_bundle(curl);
|
||||||
|
char url[1024];
|
||||||
size_t bl = strlen(api_base);
|
size_t bl = strlen(api_base);
|
||||||
while (bl && api_base[bl - 1] == '/')
|
while (bl && api_base[bl - 1] == '/')
|
||||||
bl--;
|
bl--;
|
||||||
|
|||||||
Reference in New Issue
Block a user