in fizz/client/ClientProtocol.cpp [1657:1715]
static MutateState handleCertMsg(
const State& state,
CertificateMsg certMsg,
folly::Optional<CertificateCompressionAlgorithm> algo) {
if (!certMsg.certificate_request_context->empty()) {
throw FizzException(
"certificate request context must be empty",
AlertDescription::illegal_parameter);
}
std::vector<std::shared_ptr<const PeerCert>> serverCerts;
bool leaf = true;
for (auto& certEntry : certMsg.certificate_list) {
if (state.extensions()) {
// Check that these extensions correspond to ones we requested.
auto sentExtensions = state.extensions()->getClientHelloExtensions();
for (auto& ext : certEntry.extensions) {
auto extIt = std::find_if(
sentExtensions.begin(),
sentExtensions.end(),
[type = ext.extension_type](const Extension& sentExt) {
return sentExt.extension_type == type;
});
if (extIt == sentExtensions.end()) {
throw FizzException(
"unrequested certificate extension:" +
toString(ext.extension_type),
AlertDescription::illegal_parameter);
}
}
} else {
if (!certEntry.extensions.empty()) {
throw FizzException(
"certificate extensions must be empty",
AlertDescription::illegal_parameter);
}
}
serverCerts.emplace_back(state.context()->getFactory()->makePeerCert(
std::move(certEntry), leaf));
leaf = false;
}
if (serverCerts.empty()) {
throw FizzException(
"no certificates received", AlertDescription::illegal_parameter);
}
ClientAuthType authType =
state.clientAuthRequested().value_or(ClientAuthType::NotRequested);
return [unverifiedCertChain = std::move(serverCerts),
authType,
compAlgo = std::move(algo)](State& newState) mutable {
newState.unverifiedCertChain() = std::move(unverifiedCertChain);
newState.clientAuthRequested() = authType;
newState.serverCertCompAlgo() = std::move(compAlgo);
};
}