Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用OpenSSL 1.1.0验证主机名?_C++_C_Validation_Openssl_Hostname - Fatal编程技术网

C++ 如何使用OpenSSL 1.1.0验证主机名?

C++ 如何使用OpenSSL 1.1.0验证主机名?,c++,c,validation,openssl,hostname,C++,C,Validation,Openssl,Hostname,我正在尝试使用实现一个示例。 我编写的示例C/C++代码是: // please note I'm connecting to https://openssl.org itself // enable SNI if(!SSL_set_tlsext_host_name(ssl, "www.openssl.org")) throw; if(!SSL_connect(ssl)) throw; // connection is fine, I can get the homepage via HTTP

我正在尝试使用实现一个示例。 我编写的示例C/C++代码是:

// please note I'm connecting to https://openssl.org itself
// enable SNI
if(!SSL_set_tlsext_host_name(ssl, "www.openssl.org")) throw;
if(!SSL_connect(ssl)) throw;
// connection is fine, I can get the homepage via HTTP
X509 *cert = SSL_get_peer_certificate(ssl);
if(cert) {
    if(!X509_VERIFY_PARAM_set1_host(SSL_get0_param(ssl), "google.com", 0)) throw;
    SSL_set_verify(ssl, SSL_VERIFY_PEER, 0);
    const long cert_res = SSL_get_verify_result(ssl);
    if(cert_res == X509_V_OK) {
        printf("Certificate verified!\n");
    }
    X509_free(cert);
}
根据上面的代码,我正在成功连接到openssl.org域;然后我将名称设置为verify as google.com以测试失败,但代码仍然成功

我做错了什么? 如何使用API实现主机名的彻底验证?我不想重新实现库中已经实现的内容(很可能是错误的)


我正在使用Ubuntu 16.04和这个libssl版本:
/lib/x86\u 64-linux-gnu/libssl.so.1.0.0

正如
jww
所建议的,只需设置(至少)

在执行连接之前:

if(!SSL_connect(ssl)) throw;
在这种情况下,一种情况是通过添加以下代码确保OpenSSL在连接时自动执行检查:

SSL_set_verify(ssl, SSL_VERIFY_PEER, 0);
在调用
SSL\u connect
之前,或者按照与以前相同的路径,通过
SSL\u get\u verify\u result
返回
X509\u V\u ERR\u主机名\u MISMATCH
,如果希望更详细地处理问题:

// please note I'm connecting to https://openssl.org itself
// enable SNI
if(!SSL_set_tlsext_host_name(ssl, "www.openssl.org")) throw;
// enable name/domain verification
if(!X509_VERIFY_PARAM_set1_host(SSL_get0_param(ssl), "google.com", 0)) throw;
if(!SSL_connect(ssl)) throw;
// get certificate
X509 *cert = SSL_get_peer_certificate(ssl);
if(cert) {
    const long cert_res = SSL_get_verify_result(ssl);
    // in case of name/domain mismatch cert_res will
    // be set as 62 --> X509_V_ERR_HOSTNAME_MISMATCH
    if(cert_res != X509_V_OK) throw; // certificate has been tampered with
    X509_free(cert);
} else throw; // we couldn't get certificate

OpenSSL 1.1.0内置了主机名验证。请参见OpenSSL wiki上的。对于OpenSSL 1.0.2及以下版本,您通常会获取其他人的实现,如SSL Observatory或cURL。请参见OpenSSL wiki上的。至于您的代码的特殊问题,我相信您需要在建立连接之前设置参数;在连接建立之后就不需要了。@jww你说得对,先生,我需要在调用
SSL_connect
之前设置验证参数;我已经按照建议做了,现在它起作用了!如果你把它作为答案贴出来,我会投你的票!
// please note I'm connecting to https://openssl.org itself
// enable SNI
if(!SSL_set_tlsext_host_name(ssl, "www.openssl.org")) throw;
// enable name/domain verification
if(!X509_VERIFY_PARAM_set1_host(SSL_get0_param(ssl), "google.com", 0)) throw;
if(!SSL_connect(ssl)) throw;
// get certificate
X509 *cert = SSL_get_peer_certificate(ssl);
if(cert) {
    const long cert_res = SSL_get_verify_result(ssl);
    // in case of name/domain mismatch cert_res will
    // be set as 62 --> X509_V_ERR_HOSTNAME_MISMATCH
    if(cert_res != X509_V_OK) throw; // certificate has been tampered with
    X509_free(cert);
} else throw; // we couldn't get certificate