未禁用 CURLOPT_SSL_VERIFYPEER 时,libcurl 返回错误代码 77 [英] libcurl returns error code 77 when the CURLOPT_SSL_VERIFYPEER is not disabled

查看:146
本文介绍了未禁用 CURLOPT_SSL_VERIFYPEER 时,libcurl 返回错误代码 77的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 curl 或 HTTP 请求不是很熟悉,但正在努力学习.

I am not very familiar with curl or HTTP requests, but trying to learn.

就我而言,我尝试在 C++ 中使用 libcurl(在 Windows 10 上使用 Visual Studio 2019)来执行 GET 请求.我尝试了 C++ 中的 Curl - 无法从 HTTPS 获取数据 中的解决方案,但唯一对我有用的是禁用SSL 对等验证使用:

In my case, I am trying to use libcurl in C++ (using Visual Studio 2019 on Windows 10) to perform a GET request. I tried solutions from Curl in C++ - Can't get data from HTTPS, but the only thing that worked for me was to disable SSL peer verification using:

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);

这是我的代码:

void getPairPrice(string & pair) {
    string url(BINANCE_HOST);
    url += "/api/v3/ticker/price?symbol=";
    url += pair;
    CURL* curl;
    CURLcode res;
    std::string readBuffer;
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
        curl_easy_setopt(curl, CURLOPT_URL,  url.c_str());
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_ENCODING, "gzip");

        struct curl_slist* headers = NULL;
        headers = curl_slist_append(headers, PUBLIC_KEY_HEADER);
        headers = curl_slist_append(headers, CONTENT_TYPE_HEADER);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        res = curl_easy_perform(curl);

        //cout << "res : " << res << endl;
        std::cout <<  "GET symbol " << pair << " price : "  << readBuffer << std::endl;
        const string jsonKey = "price";
        cout << "Price : " << extractJsonValue(readBuffer, jsonKey) << endl;
    }
    curl_easy_cleanup(curl);
    curl_global_cleanup();
}

如果不禁用 SSL_VERIFYPEER 选项,响应总是 77.这对于测试来说很好,但我想知道在发布我的软件时如何解决这个问题.看来我应该以某种方式以 PEM 格式下载主机的 SSL 证书并将 libcurl 指向它.

Without disabling the SSL_VERIFYPEER option, the response is always 77. This is fine for testing, but I would like to know how to solve that when releasing my software. It seems that I should somehow download the host's SSL certificate in PEM format and point libcurl to it.

有人可以帮忙吗?

推荐答案

Error 77 is CURLE_SSL_CACERT_BADFILE

Error 77 is CURLE_SSL_CACERT_BADFILE

读取 SSL CA 证书的问题(路径?访问权限?)

Problem with reading the SSL CA cert (path? access rights?)

CURLOPT_SSL_VERIFYPEER 文档 说:

在协商 TLS 或 SSL 连接时,服务器会发送一个表明其身份的证书.Curl 验证证书是否真实,即您可以相信服务器就是证书所说的那个人.这种信任基于数字签名链,植根于您提供的证书颁发机构 (CA) 证书.curl 使用默认的 CA 证书包(其路径在构建时确定),您可以使用 CURLOPT_CAINFO 选项或 CURLOPT_CAPATH 选项.

When negotiating a TLS or SSL connection, the server sends a certificate indicating its identity. Curl verifies whether the certificate is authentic, i.e. that you can trust that the server is who the certificate says it is. This trust is based on a chain of digital signatures, rooted in certification authority (CA) certificates you supply. curl uses a default bundle of CA certificates (the path for that is determined at build time) and you can specify alternate certificates with the CURLOPT_CAINFO option or the CURLOPT_CAPATH option.

当启用CURLOPT_SSL_VERIFYPEER时,验证失败证明证书是正品,连接失败.当该选项为零时,对等证书验证无论如何都会成功.

When CURLOPT_SSL_VERIFYPEER is enabled, and the verification fails to prove that the certificate is authentic, the connection fails. When the option is zero, the peer certificate verification succeeds regardless.

所以是的,如果您打算验证服务器的证书,则需要向 libcurl 提供用于签署服务器证书的证书颁发机构 (CA).如果您没有可用的 CA,则无法验证证书.

So yes, if you intend to validate the server's certificate, you need to provide libcurl with the Certificate Authority (CA) that was used to sign the server's certificate. If you don't have the CA available, you can't validate the certificate.

文档还说:

认证证书不足以确定服务器.您通常还希望确保服务器是您要与之交谈的服务器.为此使用 CURLOPT_SSL_VERIFYHOST.检查证书中的主机名是否对您连接的主机名有效是独立于 CURLOPT_SSL_VERIFYPEER 选项.

Authenticating the certificate is not enough to be sure about the server. You typically also want to ensure that the server is the server you mean to be talking to. Use CURLOPT_SSL_VERIFYHOST for that. The check that the host name in the certificate is valid for the host name you're connecting to is done independently of the CURLOPT_SSL_VERIFYPEER option.

警告:禁用证书验证会导致不法分子在您不知情的情况下进行中间人通信.禁用验证会使通信不安全.仅对传输进行加密是不够的,因为您无法确定正在与正确的端点通信.

WARNING: disabling verification of the certificate allows bad guys to man-in-the-middle the communication without you knowing it. Disabling verification makes the communication insecure. Just having encryption on a transfer is not enough as you cannot be sure that you are communicating with the correct end-point.

注意:即使禁用此选项,根据使用的 TLS 后端,curl 仍可能加载 CURLOPT_CAINFO.某些发行版中的 curl 默认设置可能会使用相当大的文件作为 CURLOPT_CAINFO 的默认设置,因此加载文件可能会非常昂贵,尤其是在处理许多连接时.因此,在某些情况下,您可能希望通过设置 CURLOPT_CAINFO 到 NULL - 但也请考虑上面的警告!

NOTE: even when this option is disabled, depending on the used TLS backend, curl may still load the certificate file specified in CURLOPT_CAINFO. curl default settings in some distributions might use quite a large file as a default setting for CURLOPT_CAINFO, so loading the file can be quite expensive, especially when dealing with many connections. Thus, in some situations, you might want to disable verification fully to save resources by setting CURLOPT_CAINFO to NULL - but please also consider the warning above!

这篇关于未禁用 CURLOPT_SSL_VERIFYPEER 时,libcurl 返回错误代码 77的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆