gpt4 book ai didi

c - TLS 服务器未收到来自客户端的证书,无法终止握手

转载 作者:太空宇宙 更新时间:2023-11-03 12:53:17 25 4
gpt4 key购买 nike

我有一个客户端和一个服务器试图相互验证并发起一个 TLS 连接。我现在使用的证书是自签名的。

在服务器代码中,我设置了 SSL_VERIFY_FAIL_IF_NO_PEER_CERT。握手成功,但 SSL_get_peer_certificate 在服务器端返回 NULL 指针。如果客户端没有返回证书,为什么握手没有失败?

如果我在服务器端注释掉 SSL_get_peer_certificate 检查,客户端和服务器确实连接并且能够通信,但这不是 TLS 连接。当我看到他们通过 wireshark 交换数据包时,我只看到 TCP 流量。

服务器代码:

BIO *acceptTLSConnection(char *port) {

BIO *sbio, *bbio, *acpt = NULL;
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;

SSL_library_init();

ctx = SSL_CTX_new(TLSv1_server_method());

SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);

if(!SSL_CTX_use_certificate_file(ctx,"servercert.pem",SSL_FILETYPE_PEM)
|| !SSL_CTX_use_PrivateKey_file(ctx,"serverkey.pem",SSL_FILETYPE_PEM)
|| !SSL_CTX_check_private_key(ctx)) {
ERR_print_errors_fp(stderr);
fatalError("Error setting up SSL_CTX.");
}

if(!SSL_CTX_load_verify_locations(ctx, "clientcert.pem", NULL))
fatalError("Could not load trusted CA certificates.");

sbio=BIO_new_ssl(ctx,0);

BIO_get_ssl(sbio, &ssl);

if(!ssl) {
fatalError("Can't locate BIO SSL pointer.");
}

SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

bbio = BIO_new(BIO_f_buffer());
sbio = BIO_push(bbio, sbio);

acpt=BIO_new_accept(port);
BIO_set_accept_bios(acpt,sbio);

/* Setup accept BIO */
if(BIO_do_accept(acpt) <= 0) {
ERR_print_errors_fp(stderr);
fatalError("Error in setting up accept BIO");
}

/* Now wait for incoming connection */
if(BIO_do_accept(acpt) <= 0) {
ERR_print_errors_fp(stderr);
fatalError("Error in connection");
}

sbio = BIO_pop(acpt);
BIO_free_all(acpt);

if(BIO_do_handshake(sbio) <= 0) {
ERR_print_errors_fp(stderr);
fatalError("Error in SSL handshake");
}

/* Verify a client certificate was presented during the negotiation */
X509* cert = SSL_get_peer_certificate(ssl);
if(cert) { X509_free(cert); } /* Free immediately */
if(NULL == cert) fatalError("Client did not present a cert during handshake.");

/* Verify the result of chain verification */
int res = SSL_get_verify_result(ssl);
if(!(X509_V_OK == res)) fatalError("Cert presented by client couldn't be verified.");

return sbio;
}

客户端代码:

BIO *makeTLSConnection(char *servIP, char *servPort) {

char *servLoc = calloc(strlen(servIP) + strlen(servPort) + 2, sizeof(char));
strcat(servLoc, servIP);
strcat(servLoc, ":");
strcat(servLoc, servPort);

BIO *sbio = NULL;
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;

SSL_library_init();

ctx = SSL_CTX_new(TLSv1_client_method());

SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

if(!SSL_CTX_use_certificate_file(ctx,"clientcert.pem",SSL_FILETYPE_PEM)
|| !SSL_CTX_use_PrivateKey_file(ctx,"clientkey.pem",SSL_FILETYPE_PEM)
|| !SSL_CTX_check_private_key(ctx)) {
ERR_print_errors_fp(stderr);
fatalError("Error setting up SSL_CTX.");
}

if(!SSL_CTX_load_verify_locations(ctx, "servercert.pem", NULL))
fatalError("Could not load trusted CA certificates.");

sbio = BIO_new_ssl_connect(ctx);

BIO_get_ssl(sbio, &ssl);

if(!ssl) {
fatalError("Can't locate SSL pointer.");
}

BIO_set_conn_hostname(sbio, servLoc);

if(BIO_do_connect(sbio) <= 0) {
ERR_print_errors_fp(stderr);
fatalError("Error connecting to server.");
}

if(BIO_do_handshake(sbio) <= 0) {
ERR_print_errors_fp(stderr);
fatalError("Error establishing SSL connection.");
}

/* Verify a server certificate was presented during the negotiation */
X509* cert = SSL_get_peer_certificate(ssl);
if(cert) { X509_free(cert); } /* Free immediately */
if(NULL == cert) fatalError("Server did not present a cert during handshake.");

/* Verify the result of chain verification */
int res = SSL_get_verify_result(ssl);
if(!(X509_V_OK == res)) fatalError("Cert presented by server couldn't be verified.");

return sbio;
}

最佳答案

您似乎错过了对 SSL_CTX_use_certificate_chain_file 的调用和 SSL_CTX_set_client_CA_list在服务器上。我相信 SSL_CTX_set_client_CA_list 会触发执行客户端身份验证的机制(即,它会在交换期间从 RFC 的第 7.4.6 节中引出 ClientCertificate message)。

如果 SSL_CTX_set_client_CA_list 导致您正在寻找的失败,那么我倾向于相信它是 OpenSSL 库中的错误。在服务器上指定 SSL_VERIFY_PEERSSL_VERIFY_FAIL_IF_NO_PEER_CERT 时应该会失败,因为文档就是这么说的。

另见 Is verification supposed to fail with SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT without SSL_CTX_set_client_CA_list在 OpenSSL 用户邮件列表中。这是对这个问题的回应。


另见 Testing SSL/TLS Client Authentication with OpenSSLOpenSSL client not sending client certificate .

关于c - TLS 服务器未收到来自客户端的证书,无法终止握手,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35666017/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com