champouxa
champouxa

Reputation: 13

gRPC client not returning certificate

I'm trying to build a gRPC application with mutual authentication using c++. When I set the GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY option on the server, the client does not return it's certificate. The server shows the following error:

Handshake failed with fatal error SSL_ERROR_SSL: error:1417C0C7:SSL routines:tls_process_client_certificate:peer did not return a certificate.

Without this option, only the server is authenticated and communication works properly.

Certificate chain is a self-signed root CA which signed an intermediate CA, which signed both the server and client certificates. I tested the connection using the following command and using the same certificate I load on the client side.

openssl s_client -connect localhost:50051 /
    -cert client_cert.pem -key client_pkey.pem /
    -CAfile ca-chain.pem /
    -state -debug

Which gave me no connection error. The ca-chain.pem file contains the concatenation of the root CA and the intermediate CA.

I tried finding anything on the gRPC which would cause this but I find the documentation is pretty minimal for c++... Any tip on what might be the issue? Here is an example of the code I'm using.

Client code

/* Set the certificates */
grpc::SslCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs = loadCertificate(ca-chain);
ssl_opts.pem_private_key = loadCertificate(client_pkey);
ssl_opts.pem_cert_chain = loadCertificate(client_cert);

/* Override hostname */
grpc::ChannelArguments args;
args.SetSslTargetNameOverride("server");

/* Create the channel */
std::shared_ptr<grpc::ChannelCredentials> creds = grpc::SslCredentials(ssl_opts);
ClientImpl client(grpc::CreateCustomChannel("localhost:50051", creds, args));

Server code

std::string server_address("0.0.0.0:50051");
ServerImpl service();

/* Set the certificates */
grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp = { x509_loadPEM(server_pkey).c_str(), x509_loadPEM(server_cert).c_str() };
grpc::SslServerCredentialsOptions ssl_opts(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
//grpc::SslServerCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs = x509_loadPEM(ca_chain);
ssl_opts.pem_key_cert_pairs.push_back(pkcp);

std::shared_ptr<grpc::ServerCredentials> creds;
creds = grpc::SslServerCredentials(ssl_opts);

/* Start the server */
ServerBuilder builder;
builder.AddListeningPort(server_address, creds);
builder.RegisterService(&service);
m_server = builder.BuildAndStart();

UPDATE

Here's the output with GRPC_TRACE set to transport_security,tsi and GRPC_VERBOSITY to debug

Server side

I0705 15:46:59.119538389   11583 ssl_transport_security.cc:220]      HANDSHAKE START -      before SSL initialization  - PINIT 
I0705 15:46:59.119574620   11583 ssl_transport_security.cc:220]                 LOOP -      before SSL initialization  - PINIT 
I0705 15:46:59.119583946   11583 ssl_transport_security.cc:220]                 LOOP -      before SSL initialization  - PINIT 
I0705 15:46:59.119670552   11583 ssl_transport_security.cc:220]                 LOOP -    SSLv3/TLS read client hello  -  TRCH
I0705 15:46:59.119686772   11583 ssl_transport_security.cc:220]                 LOOP -   SSLv3/TLS write server hello  -  TWSH
I0705 15:46:59.119880739   11583 ssl_transport_security.cc:220]                 LOOP -    SSLv3/TLS write certificate  -  TWSC
I0705 15:46:59.122456250   11583 ssl_transport_security.cc:220]                 LOOP -   SSLv3/TLS write key exchange  - TWSKE
I0705 15:46:59.122500516   11583 ssl_transport_security.cc:220]                 LOOP - SSLv3/TLS write certificate re  -  TWCR
I0705 15:46:59.122517841   11583 ssl_transport_security.cc:220]                 LOOP -    SSLv3/TLS write server done  -  TWSD
I0705 15:46:59.124324895   11583 ssl_transport_security.cc:220]                 LOOP -    SSLv3/TLS write server done  -  TWSD
E0705 15:46:59.124354539   11583 ssl_transport_security.cc:1395] Handshake failed with fatal error SSL_ERROR_SSL: error:1417C0C7:SSL routines:tls_process_client_certificate:peer did not return a certificate.
D0705 15:46:59.124376983   11583 security_handshaker.cc:184] Security handshake failed: {"created":"@1625514419.124366009","description":"Handshake failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":307,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"}
D0705 15:46:59.124406454   11583 chttp2_server.cc:124]       Handshaking failed: {"created":"@1625514419.124366009","description":"Handshake failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":307,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"}

Client side

I0705 15:46:59.119384991   11756 ssl_transport_security.cc:220]      HANDSHAKE START -      before SSL initialization  - PINIT 
I0705 15:46:59.119435471   11756 ssl_transport_security.cc:220]                 LOOP -      before SSL initialization  - PINIT 
I0705 15:46:59.119479876   11756 ssl_transport_security.cc:220]                 LOOP -   SSLv3/TLS write client hello  -  TWCH
I0705 15:46:59.122745953   11756 ssl_transport_security.cc:220]                 LOOP -   SSLv3/TLS write client hello  -  TWCH
I0705 15:46:59.122815300   11756 ssl_transport_security.cc:220]                 LOOP -    SSLv3/TLS read server hello  -  TRSH
I0705 15:46:59.123253349   11756 ssl_transport_security.cc:220]                 LOOP - SSLv3/TLS read server certific  -  TRSC
I0705 15:46:59.123607078   11756 ssl_transport_security.cc:220]                 LOOP - SSLv3/TLS read server key exch  - TRSKE
I0705 15:46:59.123813288   11756 ssl_transport_security.cc:220]                 LOOP - SSLv3/TLS read server certific  -  TRCR
I0705 15:46:59.123855701   11756 ssl_transport_security.cc:220]                 LOOP -     SSLv3/TLS read server done  -  TRSD
I0705 15:46:59.123881908   11756 ssl_transport_security.cc:220]                 LOOP - SSLv3/TLS write client certifi  -  TWCC
I0705 15:46:59.124188107   11756 ssl_transport_security.cc:220]                 LOOP - SSLv3/TLS write client key exc  - TWCKE
I0705 15:46:59.124227044   11756 ssl_transport_security.cc:220]                 LOOP - SSLv3/TLS write change cipher   - TWCCS
I0705 15:46:59.124253244   11756 ssl_transport_security.cc:220]                 LOOP -       SSLv3/TLS write finished  - TWFIN
D0705 15:46:59.124435035   11756 security_handshaker.cc:184] Security handshake failed: {"created":"@1625514419.124412434","description":"Handshake read failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":397,"referenced_errors":[{"created":"@1625514419.124410133","description":"Socket closed","fd":9,"file":"src/core/lib/iomgr/tcp_posix.cc","file_line":781,"grpc_status":14,"target_address":"ipv6:[::1]:50051"}]}
I0705 15:46:59.124541128   11756 subchannel.cc:1033]         Connect failed: {"created":"@1625514419.124412434","description":"Handshake read failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":397,"referenced_errors":[{"created":"@1625514419.124410133","description":"Socket closed","fd":9,"file":"src/core/lib/iomgr/tcp_posix.cc","file_line":781,"grpc_status":14,"target_address":"ipv6:[::1]:50051"}]}

Upvotes: 1

Views: 2617

Answers (1)

Zhen Lian
Zhen Lian

Reputation: 111

Hello from the gRPC team! The code looks fine to me. From the error message, it seems the server is not able to receive the client's certificates, while you apparently already set them in your client code. Could it be possible that your client certificates have some format issues, that are not recognized by the client stack?

To make sure it's not the problem with the client's cert, you can simply replace the client certs with server's certs(as well as the private key), and see if it works, since they are both signed by the same CA.

If the problem still persists, then we at least know the client's certs are good. I will probably reproduce on my end and see if I could see the same error.

Upvotes: 1

Related Questions