1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <folly/Optional.h>
20 #include <folly/io/async/SSLContext.h>
21 #include <folly/io/async/SSLOptions.h>
22 #include <set>
23 #include <string>
24 #include <vector>
25 
26 /**
27  * SSLContextConfig helps to describe the configs/options for
28  * a SSL_CTX. For example:
29  *
30  *   1. Filename of X509, private key and its password.
31  *   2. ciphers list
32  *   3. NPN list
33  *   4. Is session cache enabled?
34  *   5. Is it the default X509 in SNI operation?
35  *   6. .... and a few more
36  */
37 namespace wangle {
38 
39 struct SSLContextConfig {
40   SSLContextConfig() = default;
41   virtual ~SSLContextConfig() = default;
42 
43   struct CertificateInfo {
CertificateInfoSSLContextConfig::CertificateInfo44     CertificateInfo(
45         const std::string& crtPath,
46         const std::string& kyPath,
47         const std::string& passwdPath)
48         : certPath(crtPath), keyPath(kyPath), passwordPath(passwdPath) {}
49 
CertificateInfoSSLContextConfig::CertificateInfo50     CertificateInfo(const std::string& crtBuf, const std::string& kyBuf)
51         : certPath(crtBuf), keyPath(kyBuf), isBuffer(true) {}
52 
53     std::string certPath;
54     std::string keyPath;
55     std::string passwordPath;
56     bool isBuffer{false};
57   };
58 
getDefaultCiphersSSLContextConfig59   static const std::string& getDefaultCiphers() {
60     static const std::string& defaultCiphers =
61         folly::join(':', folly::ssl::SSLServerOptions::ciphers());
62     return defaultCiphers;
63   }
64 
getDefaultCiphersuitesSSLContextConfig65   static const std::string& getDefaultCiphersuites() {
66     static const std::string& defaultCiphersuites =
67         folly::join(':', folly::ssl::SSLServerOptions::ciphersuites());
68     return defaultCiphersuites;
69   }
70 
71   struct KeyOffloadParams {
72     // What keys do we want to offload
73     // Currently supported values: "rsa", "ec" (can also be empty)
74     // Note that the corresponding thrift IDL has a list instead
75     std::set<std::string> offloadType;
76     // An identifier for the service to which we are offloading.
77     std::string serviceId{"default"};
78     // Whether we want to offload certificates
79     bool enableCertOffload{false};
80   };
81 
82   /**
83    * Helpers to set/add a certificate
84    */
setCertificateSSLContextConfig85   virtual void setCertificate(
86       const std::string& certPath,
87       const std::string& keyPath,
88       const std::string& passwordPath) {
89     certificates.clear();
90     addCertificate(certPath, keyPath, passwordPath);
91   }
92 
setCertificateBufSSLContextConfig93   void setCertificateBuf(const std::string& cert, const std::string& key) {
94     certificates.clear();
95     addCertificateBuf(cert, key);
96   }
97 
addCertificateSSLContextConfig98   void addCertificate(
99       const std::string& certPath,
100       const std::string& keyPath,
101       const std::string& passwordPath) {
102     certificates.emplace_back(certPath, keyPath, passwordPath);
103   }
104 
addCertificateBufSSLContextConfig105   void addCertificateBuf(const std::string& cert, const std::string& key) {
106     certificates.emplace_back(cert, key);
107   }
108 
109   /**
110    * Set the optional list of protocols to advertise via TLS
111    * Next Protocol Negotiation. An empty list means NPN is not enabled.
112    */
setNextProtocolsSSLContextConfig113   void setNextProtocols(const std::list<std::string>& inNextProtocols) {
114     nextProtocols.clear();
115     nextProtocols.emplace_back(1, inNextProtocols);
116   }
117 
118   typedef std::function<bool(char const* server_name)> SNINoMatchFn;
119 
120   std::vector<CertificateInfo> certificates;
121   folly::SSLContext::SSLVersion sslVersion{folly::SSLContext::TLSv1_2};
122   bool sessionCacheEnabled{true};
123   bool sessionTicketEnabled{true};
124   std::string sslCiphers{getDefaultCiphers()};
125   std::string sslCiphersuites{getDefaultCiphersuites()};
126   folly::Optional<std::string> sigAlgs;
127   std::string eccCurveName{"prime256v1"};
128 
129   // Weighted lists of NPN strings to advertise
130   std::list<folly::SSLContext::NextProtocolsItem> nextProtocols;
131   bool isLocalPrivateKey{true};
132   // Should this SSLContextConfig be the default for SNI purposes
133   bool isDefault{false};
134   // File containing trusted CA's to validate client certificates
135   std::string clientCAFile;
136   // List of files containing trusted CA's to validate client certificates
137   std::vector<std::string> clientCAFiles;
138 
139   // Verification method to use for client certificates.
140   folly::SSLContext::VerifyClientCertificate clientVerification{
141       folly::SSLContext::VerifyClientCertificate::ALWAYS};
142 
143   // Key offload configuration
144   KeyOffloadParams keyOffloadParams;
145 
146   // If true, read cert-key files locally. Otherwise, fetch them from cryptossl
147   bool offloadDisabled{true};
148 
149   // Load cert-key pairs corresponding to these domains
150   std::vector<std::string> domains;
151 
152   // A namespace to use for sessions generated from this context so that
153   // they will not be shared between other sessions generated from the
154   // same context. If not specified the vip name will be used by default
155   folly::Optional<std::string> sessionContext;
156 
157   bool alpnAllowMismatch{true};
158 };
159 
160 } // namespace wangle
161