Cuberite
A lightweight, fast and extensible game server for Minecraft
SslConfig.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h"
3 
4 #include "mbedTLS++/SslConfig.h"
5 
6 #include "mbedTLS++/CryptoKey.h"
8 #include "mbedTLS++/X509Cert.h"
9 
10 
11 // This allows us to debug SSL and certificate problems, but produce way too much output,
12 // so it's disabled until someone needs it
13 // #define ENABLE_SSL_DEBUG_MSG
14 
15 
16 #if !defined(NDEBUG) && defined(ENABLE_SSL_DEBUG_MSG)
17  #include "mbedtls/debug.h"
18 
19 
20  namespace
21  {
22  void SSLDebugMessage(void * a_UserParam, int a_Level, const char * a_Filename, int a_LineNo, const char * a_Text)
23  {
24  if (a_Level > 3)
25  {
26  // Don't want the trace messages
27  return;
28  }
29 
30  // Remove the terminating LF:
31  size_t len = strlen(a_Text) - 1;
32  while ((len > 0) && (a_Text[len] <= 32))
33  {
34  len--;
35  }
36  AString Text(a_Text, len + 1);
37 
38  LOGD("SSL (%d): %s", a_Level, Text.c_str());
39  }
40 
41 
42 
43 
44 
45  int SSLVerifyCert(void * a_This, mbedtls_x509_crt * a_Crt, int a_Depth, uint32_t * a_Flags)
46  {
47  char buf[1024];
48  UNUSED(a_This);
49 
50  LOG("Verify requested for (Depth %d):", a_Depth);
51  mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", a_Crt);
52  LOG("%s", buf);
53 
54  uint32_t Flags = *a_Flags;
55  if ((Flags & MBEDTLS_X509_BADCERT_EXPIRED) != 0)
56  {
57  LOG(" ! server certificate has expired");
58  }
59 
60  if ((Flags & MBEDTLS_X509_BADCERT_REVOKED) != 0)
61  {
62  LOG(" ! server certificate has been revoked");
63  }
64 
65  if ((Flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) != 0)
66  {
67  LOG(" ! CN mismatch");
68  }
69 
70  if ((Flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) != 0)
71  {
72  LOG(" ! self-signed or not signed by a trusted CA");
73  }
74 
75  if ((Flags & MBEDTLS_X509_BADCRL_NOT_TRUSTED) != 0)
76  {
77  LOG(" ! CRL not trusted");
78  }
79 
80  if ((Flags & MBEDTLS_X509_BADCRL_EXPIRED) != 0)
81  {
82  LOG(" ! CRL expired");
83  }
84 
85  if ((Flags & MBEDTLS_X509_BADCERT_OTHER) != 0)
86  {
87  LOG(" ! other (unknown) flag");
88  }
89 
90  if (Flags == 0)
91  {
92  LOG(" This certificate has no flags");
93  }
94 
95  return 0;
96  }
97  }
98 #endif // !defined(NDEBUG) && defined(ENABLE_SSL_DEBUG_MSG)
99 
100 
101 
102 
104 // cSslConfig:
105 
107 {
108  mbedtls_ssl_config_init(&m_Config);
109 }
110 
111 
112 
113 
114 
116 {
117  mbedtls_ssl_config_free(&m_Config);
118 }
119 
120 
121 
122 
123 
124 int cSslConfig::InitDefaults(const bool a_IsClient)
125 {
126  return mbedtls_ssl_config_defaults(
127  &m_Config,
128  a_IsClient ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
129  MBEDTLS_SSL_TRANSPORT_STREAM,
130  MBEDTLS_SSL_PRESET_DEFAULT
131  );
132 }
133 
134 
135 
136 
137 
138 void cSslConfig::SetAuthMode(const eSslAuthMode a_AuthMode)
139 {
140  const int Mode = [=]()
141  {
142  switch (a_AuthMode)
143  {
144  case eSslAuthMode::None: return MBEDTLS_SSL_VERIFY_NONE;
145  case eSslAuthMode::Optional: return MBEDTLS_SSL_VERIFY_OPTIONAL;
146  case eSslAuthMode::Required: return MBEDTLS_SSL_VERIFY_REQUIRED;
147  case eSslAuthMode::Unset: return MBEDTLS_SSL_VERIFY_UNSET;
148  }
149  UNREACHABLE("Unsupported SSL auth mode");
150  }();
151 
152  mbedtls_ssl_conf_authmode(&m_Config, Mode);
153 }
154 
155 
156 
157 
158 
160 {
161  ASSERT(a_CtrDrbg != nullptr);
162  m_CtrDrbg = std::move(a_CtrDrbg);
163  mbedtls_ssl_conf_rng(&m_Config, mbedtls_ctr_drbg_random, &m_CtrDrbg->m_CtrDrbg);
164 }
165 
166 
167 
168 
169 
170 void cSslConfig::SetDebugCallback(cDebugCallback a_CallbackFun, void * a_CallbackData)
171 {
172  mbedtls_ssl_conf_dbg(&m_Config, a_CallbackFun, a_CallbackData);
173 }
174 
175 
176 
177 
178 
179 void cSslConfig::SetOwnCert(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnCertPrivKey)
180 {
181  ASSERT(a_OwnCert != nullptr);
182  ASSERT(a_OwnCertPrivKey != nullptr);
183 
184  // Make sure we have the cert stored for later, mbedTLS only uses the cert later on
185  m_OwnCert = std::move(a_OwnCert);
186  m_OwnCertPrivKey = std::move(a_OwnCertPrivKey);
187 
188  // Set into the config:
189  mbedtls_ssl_conf_own_cert(&m_Config, m_OwnCert->GetInternal(), m_OwnCertPrivKey->GetInternal());
190 }
191 
192 
193 
194 
195 
196 void cSslConfig::SetVerifyCallback(cVerifyCallback a_CallbackFun, void * a_CallbackData)
197 {
198  mbedtls_ssl_conf_verify(&m_Config, a_CallbackFun, a_CallbackData);
199 }
200 
201 
202 
203 
204 
205 void cSslConfig::SetCipherSuites(std::vector<int> a_CipherSuites)
206 {
207  m_CipherSuites = std::move(a_CipherSuites);
208  m_CipherSuites.push_back(0); // Must be null terminated
209  mbedtls_ssl_conf_ciphersuites(&m_Config, m_CipherSuites.data());
210 }
211 
212 
213 
214 
215 
217 {
218  m_CACerts = std::move(a_CACert);
219  mbedtls_ssl_conf_ca_chain(&m_Config, m_CACerts->GetInternal(), nullptr);
220 }
221 
222 
223 
224 
225 
226 std::shared_ptr<cSslConfig> cSslConfig::MakeDefaultConfig(bool a_IsClient)
227 {
228  auto Ret = std::make_shared<cSslConfig>();
229 
230  Ret->InitDefaults(a_IsClient);
231 
232  {
233  auto CtrDrbg = std::make_shared<cCtrDrbgContext>();
234  CtrDrbg->Initialize("Cuberite", 8);
235  Ret->SetRng(std::move(CtrDrbg));
236  }
237 
238  // By default we have no root CAs, so no cert verification can be done:
239  Ret->SetAuthMode(eSslAuthMode::None);
240 
241  #ifndef NDEBUG
242  #ifdef ENABLE_SSL_DEBUG_MSG
243  Ret->SetDebugCallback(&SSLDebugMessage, nullptr);
244  Ret->SetVerifyCallback(SSLVerifyCert, nullptr);
245  mbedtls_debug_set_threshold(2);
246  #endif
247 
248  /*
249  // Set ciphersuite to the easiest one to decode, so that the connection can be wireshark-decoded:
250  Ret->SetCipherSuites(
251  {
252  MBEDTLS_TLS_RSA_WITH_RC4_128_MD5,
253  MBEDTLS_TLS_RSA_WITH_RC4_128_SHA,
254  MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA
255  }
256  );
257  */
258  #endif
259 
260  return Ret;
261 }
262 
263 
264 
265 
266 
267 std::shared_ptr<const cSslConfig> cSslConfig::GetDefaultClientConfig()
268 {
269  static const std::shared_ptr<const cSslConfig> ClientConfig = MakeDefaultConfig(true);
270  return ClientConfig;
271 }
272 
273 
274 
275 
276 
277 std::shared_ptr<const cSslConfig> cSslConfig::GetDefaultServerConfig()
278 {
279  static const std::shared_ptr<const cSslConfig> ServerConfig = MakeDefaultConfig(false);
280  return ServerConfig;
281 }
282 
283 
284 
285 
#define UNREACHABLE(x)
Definition: Globals.h:288
#define ASSERT(x)
Definition: Globals.h:276
#define UNUSED
Definition: Globals.h:72
void LOG(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:55
#define LOGD
Definition: LoggerSimple.h:83
std::shared_ptr< cCryptoKey > cCryptoKeyPtr
Definition: CryptoKey.h:72
std::shared_ptr< cCtrDrbgContext > cCtrDrbgContextPtr
Definition: SslConfig.h:12
eSslAuthMode
Definition: SslConfig.h:16
std::shared_ptr< cX509Cert > cX509CertPtr
Definition: SslConfig.h:13
std::string AString
Definition: StringUtils.h:11
int(*)(void *, mbedtls_x509_crt *, int, uint32_t *) cVerifyCallback
Type of the SSL certificate verify callback.
Definition: SslConfig.h:44
std::vector< int > m_CipherSuites
Definition: SslConfig.h:92
void(*)(void *, int, const char *, int, const char *) cDebugCallback
Type of the SSL debug callback.
Definition: SslConfig.h:36
void SetRng(cCtrDrbgContextPtr a_CtrDrbg)
Set the random number generator.
Definition: SslConfig.cpp:159
static std::shared_ptr< cSslConfig > MakeDefaultConfig(bool a_IsClient)
Creates a new config with some sensible defaults on top of mbedTLS basic settings.
Definition: SslConfig.cpp:226
void SetCipherSuites(std::vector< int > a_CipherSuites)
Set the enabled cipher suites.
Definition: SslConfig.cpp:205
void SetOwnCert(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnCertPrivKey)
Set the certificate to use for connections.
Definition: SslConfig.cpp:179
int InitDefaults(bool a_IsClient)
Initialize with mbedTLS default settings.
Definition: SslConfig.cpp:124
static std::shared_ptr< const cSslConfig > GetDefaultServerConfig()
Returns the default config for server connections.
Definition: SslConfig.cpp:277
cX509CertPtr m_OwnCert
Definition: SslConfig.h:89
mbedtls_ssl_config m_Config
Definition: SslConfig.h:87
void SetVerifyCallback(cVerifyCallback a_CallbackFun, void *a_CallbackData)
Set the certificate verify callback.
Definition: SslConfig.cpp:196
cCryptoKeyPtr m_OwnCertPrivKey
Definition: SslConfig.h:90
void SetAuthMode(eSslAuthMode a_AuthMode)
Set the authorization mode.
Definition: SslConfig.cpp:138
static std::shared_ptr< const cSslConfig > GetDefaultClientConfig()
Returns the default config for client connections.
Definition: SslConfig.cpp:267
void SetDebugCallback(cDebugCallback a_CallbackFun, void *a_CallbackData)
Set the debug callback.
Definition: SslConfig.cpp:170
void SetCACerts(cX509CertPtr a_CACert)
Set the trusted certificate authority chain.
Definition: SslConfig.cpp:216
cX509CertPtr m_CACerts
Definition: SslConfig.h:91
cCtrDrbgContextPtr m_CtrDrbg
Definition: SslConfig.h:88