Openssl Verifique o certificado de ponto (cliente) em C ++
-
27-09-2019 - |
Pergunta
Eu tenho um aplicativo de trabalho que estabelece uma conexão SSL com um servidor. O servidor usa um certificado autoassinado e o cliente carrega uma cadeia de autoridade de certificação para dizer que o servidor está bem para confiar. Eu fiz isso com código como este no cliente:
SSL_METHOD* method = TLSv1_client_method();
_ctx = SSL_CTX_new(method);
if ( SSL_CTX_load_verify_locations(_ctx, "ca-all.crt", NULL) != 1 )
{
return false;
}
_ssl = SSL_new(_ctx);
int val = SSL_set_fd(_ssl, _socket->GetFD());
if ( val != SSL_SUCCESS )
{
int err = SSL_get_error(_ssl, val);
return false;
}
val = SSL_connect(_ssl);
E no servidor:
if ( SSL_CTX_use_certificate_chain_file( g_ctx, "ca-chain1.crt" ) <= 0 ) {
return 1;
}
ppem_file = getenv( "PEM_FILE" );
if ( ppem_file == NULL ) {
ppem_file = pem_file;
}
if ( SSL_CTX_use_certificate_file( g_ctx, ppem_file,
SSL_FILETYPE_PEM ) <= 0 ) {
return 1;
}
if ( SSL_CTX_use_PrivateKey_file( g_ctx, ppem_file,
SSL_FILETYPE_PEM ) <= 0 ) {
return 2;
}
Estou tentando modificar esse código para que o servidor também verifique o certificado de pares do cliente (auto-inscrito, usando o mesmo emissor que o servidor) e tendo um pouco de problemas. Não encontrei uma boa documentação "Visão geral conceitual" em nenhum lugar, e isso parece ser um obstáculo típico com as bibliotecas OpenSSL.
No cliente, adicionei isso após a chamada SSL_CTX_LOAD_VERIFY_LOCATIONS ():
if ( SSL_CTX_use_certificate_file(_ctx, "generic_client.pem", SSL_FILETYPE_PEM ) != 1 )
{
return false;
}
No servidor, adicionei isso após a chamada SSL_CTX_USE_PRIVATEKEY_FILE ():
STACK_OF(X509_NAME) *list;
list = SSL_load_client_CA_file( "ca_chain2.crt" );
if( list == NULL ) {
return 4;
}
SSL_CTX_set_client_CA_list( g_ctx, list );
SSL_CTX_set_verify( g_ctx, SSL_VERIFY_PEER, NULL );
A conexão falha porque o certificado não valida. O cliente parece carregar a multa do certificado e, se eu comentar a linha SSL_CTX_SET_VERIFY, o cliente se conecta sem problemas (porque seu certificado nunca foi verificado).
Parece que o servidor não pensa que a cadeia de autoridade de certificação do cliente é boa. O que estou perdendo aqui?
A partir da linha de comando que posso executar: OpenSSL verifique -CAfile Ca -Chain2.crt generic_client.pem e ele passa, por isso tenho os dados de certificado correto disponíveis, devo estar usando -o errado de alguma forma.
Solução
No servidor, você também deve ligar SSL_CTX_load_verify_locations()
. Esta função informa ao servidor quais certificados usar para verificação de certificados; a SSL_CTX_set_client_CA_list()
A função define a lista de CAS permitidos que são enviados ao cliente no aperto de mão. Ambos são necessários.
(Você também precisa de um SSL_CTX_use_PrivateKey_file()
ligue para o cliente, depois do use_certificate_file
Ligue, mas acho que você está fazendo isso e deixou de fora).
Outras dicas
Ssl_ctx_set_client_ca_list define o Ca Lista. Um certificado de CA, por definição, é distinto de um certificado de usuário (por exemplo, ele tem o conjunto de bits CA). Por isso, recomendo que você crie um CA adequado (cujo certificado CA é auto-signitado) e use-o para assinar o cliente e o certificado do servidor. Suponho que o OpenSSL não espera que o cliente também use o certificado da CA para comunicação.