Reputation: 13
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
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