proxygen
CertManager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
10 
11 #include <folly/String.h>
12 
13 using namespace folly;
14 
15 namespace fizz {
16 namespace server {
17 
18 // Find a matching cert given a key. If lastResort is none the first cert found
19 // (by supportedSigSchemes priority) matching key but not peerSigSchemes will be
20 // saved in lastResort.
21 CertManager::CertMatch CertManager::findCert(
22  const std::string& key,
23  const std::vector<SignatureScheme>& supportedSigSchemes,
24  const std::vector<SignatureScheme>& peerSigSchemes,
25  CertMatch& lastResort) const {
26  auto it = certs_.find(key);
27  if (it == certs_.end()) {
28  return none;
29  }
30  for (auto scheme : supportedSigSchemes) {
31  auto cert = it->second.find(scheme);
32  if (cert == it->second.end()) {
33  continue;
34  }
35  if (std::find(peerSigSchemes.begin(), peerSigSchemes.end(), scheme) !=
36  peerSigSchemes.end()) {
37  return std::make_pair(cert->second, scheme);
38  } else if (!lastResort) {
39  lastResort = std::make_pair(cert->second, scheme);
40  }
41  }
42  return none;
43 }
44 
47  const std::vector<SignatureScheme>& supportedSigSchemes,
48  const std::vector<SignatureScheme>& peerSigSchemes) const {
49  CertMatch lastResort;
50  if (sni) {
51  auto key = *sni;
52  toLowerAscii(key);
53 
54  auto ret = findCert(key, supportedSigSchemes, peerSigSchemes, lastResort);
55  if (ret) {
56  VLOG(8) << "Found exact SNI match for: " << key;
57  return ret;
58  }
59 
60  auto dot = key.find_first_of('.');
61  if (dot != std::string::npos) {
62  std::string wildcardKey(key, dot);
63  ret = findCert(
64  wildcardKey, supportedSigSchemes, peerSigSchemes, lastResort);
65  if (ret) {
66  VLOG(8) << "Found wildcard SNI match for: " << key;
67  return ret;
68  }
69  }
70 
71  VLOG(8) << "Did not find match for SNI: " << key;
72  }
73 
74  auto ret =
75  findCert(default_, supportedSigSchemes, peerSigSchemes, lastResort);
76  if (ret) {
77  return ret;
78  }
79 
80  VLOG(8) << "No matching cert for client sig schemes found";
81  return lastResort;
82 }
83 
84 std::shared_ptr<SelfCert> CertManager::getCert(
85  const std::string& identity) const {
86  auto it = identMap_.find(identity);
87  if (it == identMap_.end()) {
88  return nullptr;
89  }
90  return it->second;
91 }
92 
93 static std::string getKeyFromIdent(const std::string& ident) {
94  if (ident.empty()) {
95  throw std::runtime_error("empty identity");
96  }
97 
98  std::string key;
99  if (ident.front() == '*') {
100  key = std::string(ident, 1);
101  } else {
102  key = ident;
103  }
104  toLowerAscii(key);
105 
106  return key;
107 }
108 
109 void CertManager::addCertIdentity(
110  std::shared_ptr<SelfCert> cert,
111  const std::string& ident) {
112  auto key = getKeyFromIdent(ident);
113 
114  if (key.empty() || key == "." || key.find('*') != std::string::npos) {
115  throw std::runtime_error(to<std::string>("invalid identity: ", ident));
116  }
117 
118  auto sigSchemes = cert->getSigSchemes();
119  auto& schemeMap = certs_[key];
120  for (auto sigScheme : sigSchemes) {
121  if (schemeMap.find(sigScheme) != schemeMap.end()) {
122  LOG(INFO) << "Skipping duplicate certificate for " << key;
123  } else {
124  schemeMap[sigScheme] = cert;
125  }
126  }
127 }
128 
129 void CertManager::addCert(std::shared_ptr<SelfCert> cert, bool defaultCert) {
130  auto primaryIdent = cert->getIdentity();
131  addCertIdentity(cert, primaryIdent);
132 
133  auto altIdents = cert->getAltIdentities();
134  for (const auto& ident : altIdents) {
135  if (ident != primaryIdent) {
136  addCertIdentity(cert, ident);
137  }
138  }
139 
140  if (defaultCert) {
141  default_ = getKeyFromIdent(primaryIdent);
142  }
143 
144  if (identMap_.find(primaryIdent) == identMap_.end()) {
145  identMap_[primaryIdent] = cert;
146  }
147 }
148 } // namespace server
149 } // namespace fizz
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
folly::ssl::X509UniquePtr getCert(folly::StringPiece cert)
Definition: TestUtil.cpp:48
Definition: Actions.h:16
void toLowerAscii(char *str, size_t length)
Definition: String.cpp:601
StringPiece sni
const char * string
Definition: Conv.cpp:212
constexpr None none
Definition: Optional.h:87
static std::string getKeyFromIdent(const std::string &ident)
Definition: CertManager.cpp:93
constexpr auto dot