我正在尝试使用hostname validation实施示例OpenSSL。 我整理的样本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 域;然后我将名称设置为验证为 google.com 以测试失败,但代码仍然成功。
我做错了什么? 如何使用OpenSSL API实施主机名彻底验证?我不想重新实现(很可能是错误/错误)库中已经实现的内容......
我正在使用Ubuntu 16.04和 libssl 版本:/lib/x86_64-linux-gnu/libssl.so.1.0.0
。
答案 0 :(得分:0)
根据jww
的建议,只需设置(至少)
if(!X509_VERIFY_PARAM_set1_host(SSL_get0_param(ssl), "google.com", 0)) throw;
在执行连接之前:
if(!SSL_connect(ssl)) throw;
在这种情况下,一个案例通过添加以下代码确保OpenSSL在连接时自动执行检查:
SSL_set_verify(ssl, SSL_VERIFY_PEER, 0);
在致电SSL_connect
之前,或按照与之前相同的路径,如果想要更详细地处理事情,请X509_V_ERR_HOSTNAME_MISMATCH
返回SSL_get_verify_result
:
// 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