287 std::vector<std::string> alpns;
289 bool fallback =
false;
293 {
"-accept", {
true, [&port](
const std::string& arg) {
296 {
"-ciphers", {
true, [&ciphers](
const std::string& arg) {
297 std::vector<CipherSuite> newCiphers;
298 auto remainder = arg;
300 for (
auto commaPos = remainder.find(
',');
301 commaPos != std::string::npos;
302 commaPos = remainder.find(
',')) {
303 auto cipher = parse<CipherSuite>(remainder.substr(0, commaPos));
304 remainder = remainder.substr(commaPos+1);
305 newCiphers.push_back(
cipher);
308 newCiphers.push_back(parse<CipherSuite>(remainder));
311 catch (
const std::exception& e) {
312 LOG(ERROR) <<
"Error parsing cipher suites: " << e.what();
315 {
"-cert", {
true, [&certPath](
const std::string& arg) { certPath = arg; }}},
316 {
"-key", {
true, [&keyPath](
const std::string& arg) { keyPath = arg; }}},
317 {
"-pass", {
true, [&keyPass](
const std::string& arg) { keyPass = arg; }}},
318 {
"-requestcert", {
false, [&clientAuthMode](
const std::string&) {
319 clientAuthMode = ClientAuthMode::Optional;
321 {
"-requirecert", {
false, [&clientAuthMode](
const std::string&) {
322 clientAuthMode = ClientAuthMode::Required;
324 {
"-capaths", {
true, [&caPaths](
const std::string& arg) { caPaths = arg; }}},
325 {
"-cafile", {
true, [&caFile](
const std::string& arg) { caFile = arg; }}},
326 {
"-early", {
false, [&early](
const std::string&) { early =
true; }}},
327 {
"-alpn", {
true, [&alpns](
const std::string& arg) {
329 auto remainder = arg;
330 for (
auto commaPos = remainder.find(
',');
331 commaPos != std::string::npos;
332 commaPos = remainder.find(
',')) {
333 alpns.push_back(remainder.substr(0, commaPos));
334 remainder = remainder.substr(commaPos+1);
337 alpns.push_back(remainder);
341 FLAGS_minloglevel = google::GLOG_ERROR;
343 {
"-fallback", {
false, [&fallback](
const std::string&) {
354 }
catch (
const std::exception& e) {
355 LOG(ERROR) <<
"Error: " << e.what();
360 if (certPath.empty() != keyPath.empty()) {
361 LOG(ERROR) <<
"-cert and -key are both required when specified";
366 std::shared_ptr<const CertificateVerifier> verifier;
368 if (clientAuthMode != ClientAuthMode::None) {
371 if (!caPaths.empty() || !caFile.empty()) {
372 storePtr.reset(X509_STORE_new());
373 auto caFilePtr = caFile.empty() ?
nullptr : caFile.c_str();
374 auto caPathPtr = caPaths.empty() ?
nullptr : caPaths.c_str();
376 if (X509_STORE_load_locations(storePtr.get(), caFilePtr, caPathPtr) ==
378 LOG(ERROR) <<
"Failed to load CA certificates";
383 verifier = std::make_shared<const DefaultCertificateVerifier>(
384 VerificationContext::Server,
std::move(storePtr));
387 auto serverContext = std::make_shared<FizzServerContext>();
389 serverContext->setSupportedCiphers({*ciphers});
391 serverContext->setClientAuthMode(clientAuthMode);
392 serverContext->setClientCertVerifier(verifier);
395 OpenSSLEVPCipher<AESGCM128>,
397 HkdfImpl<Sha256>>>();
398 auto ticketSeed = RandomGenerator<32>().generateRandom();
399 ticketCipher->setTicketSecrets({{
range(ticketSeed)}});
400 serverContext->setTicketCipher(ticketCipher);
402 auto certManager = std::make_unique<CertManager>();
403 if (!certPath.empty()) {
406 if (!
readFile(certPath.c_str(), certData)) {
407 LOG(ERROR) <<
"Failed to read certificate";
409 }
else if (!
readFile(keyPath.c_str(), keyData)) {
410 LOG(ERROR) <<
"Failed to read private key";
413 std::unique_ptr<SelfCert> cert;
414 if (!keyPass.empty()) {
415 cert = CertUtils::makeSelfCert(certData, keyData, keyPass);
417 cert = CertUtils::makeSelfCert(certData, keyData);
419 certManager->addCert(
std::move(cert),
true);
422 std::vector<folly::ssl::X509UniquePtr> certChain;
423 certChain.push_back(
std::move(certData.cert));
424 auto cert = std::make_unique<SelfCertImpl<KeyType::P256>>(
426 certManager->addCert(
std::move(cert),
true);
428 serverContext->setCertManager(
std::move(certManager));
431 serverContext->setEarlyDataSettings(
433 {std::chrono::seconds(-10), std::chrono::seconds(10)},
434 std::make_shared<SlidingBloomReplayCache>(240, 140000, 0.0005, &evb));
437 std::shared_ptr<SSLContext> sslContext;
439 if (certPath.empty()) {
440 LOG(ERROR) <<
"Fallback mode requires explicit certificates";
443 sslContext = std::make_shared<SSLContext>();
444 sslContext->loadCertKeyPairFromFiles(certPath.c_str(), keyPath.c_str());
445 SSL_CTX_set_ecdh_auto(sslContext->getSSLCtx(), 1);
447 serverContext->setVersionFallbackEnabled(fallback);
449 if (!alpns.empty()) {
450 serverContext->setSupportedAlpns(
std::move(alpns));
453 serverContext->setSupportedVersions(
454 {ProtocolVersion::tls_1_3, ProtocolVersion::tls_1_3_28});
455 FizzServerAcceptor acceptor(port, serverContext, loop, &evb, sslContext);
bool readFile(int fd, Container &out, size_t num_bytes=std::numeric_limits< size_t >::max())
constexpr detail::Map< Move > move
Gen range(Value begin, Value end)
std::unique_ptr< X509_STORE, X509StoreDeleter > X509StoreUniquePtr
CertAndKey createCert(std::string cn, bool ca, CertAndKey *issuer)