Allow QuicToyClient to provide a client certificate to the server, if requested.
PiperOrigin-RevId: 407883023
diff --git a/quic/tools/quic_toy_client.cc b/quic/tools/quic_toy_client.cc
index 0db266b..83fd7c0 100644
--- a/quic/tools/quic_toy_client.cc
+++ b/quic/tools/quic_toy_client.cc
@@ -42,6 +42,7 @@
#include "quic/tools/quic_toy_client.h"
+#include <fstream>
#include <iostream>
#include <memory>
#include <string>
@@ -184,6 +185,16 @@
"If true, don't verify the server certificate.");
DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string, default_client_cert, "",
+ "The path to the file containing PEM-encoded client default certificate to "
+ "be sent to the server, if server requested client certs.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string, default_client_cert_key, "",
+ "The path to the file containing PEM-encoded private key of the client's "
+ "default certificate for signing, if server requested client certs.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
bool,
drop_response_body,
false,
@@ -219,6 +230,42 @@
"Max inbound header list size. 0 means default.");
namespace quic {
+namespace {
+
+// Creates a ClientProofSource which only contains a default client certificate.
+// Return nullptr for failure.
+std::unique_ptr<ClientProofSource> CreateTestClientProofSource(
+ absl::string_view default_client_cert_file,
+ absl::string_view default_client_cert_key_file) {
+ std::ifstream cert_stream(std::string{default_client_cert_file},
+ std::ios::binary);
+ std::vector<std::string> certs =
+ CertificateView::LoadPemFromStream(&cert_stream);
+ if (certs.empty()) {
+ std::cerr << "Failed to load client certs." << std::endl;
+ return nullptr;
+ }
+
+ std::ifstream key_stream(std::string{default_client_cert_key_file},
+ std::ios::binary);
+ std::unique_ptr<CertificatePrivateKey> private_key =
+ CertificatePrivateKey::LoadPemFromStream(&key_stream);
+ if (private_key == nullptr) {
+ std::cerr << "Failed to load client cert key." << std::endl;
+ return nullptr;
+ }
+
+ auto proof_source = std::make_unique<DefaultClientProofSource>();
+ proof_source->AddCertAndKey(
+ {"*"},
+ QuicReferenceCountedPointer<ClientProofSource::Chain>(
+ new ClientProofSource::Chain(certs)),
+ std::move(*private_key));
+
+ return proof_source;
+}
+
+} // namespace
QuicToyClient::QuicToyClient(ClientFactory* client_factory)
: client_factory_(client_factory) {}
@@ -320,6 +367,18 @@
return 1;
}
+ if (!GetQuicFlag(FLAGS_default_client_cert).empty() &&
+ !GetQuicFlag(FLAGS_default_client_cert_key).empty()) {
+ std::unique_ptr<ClientProofSource> proof_source =
+ CreateTestClientProofSource(GetQuicFlag(FLAGS_default_client_cert),
+ GetQuicFlag(FLAGS_default_client_cert_key));
+ if (proof_source == nullptr) {
+ std::cerr << "Failed to create client proof source." << std::endl;
+ return 1;
+ }
+ client->crypto_config()->set_proof_source(std::move(proof_source));
+ }
+
int32_t initial_mtu = GetQuicFlag(FLAGS_initial_mtu);
client->set_initial_max_packet_length(
initial_mtu != 0 ? initial_mtu : quic::kDefaultMaxPacketSize);