Skip to content

Commit efd0beb

Browse files
authored
fix TLS implementation quarks (#398)
1 parent 720db22 commit efd0beb

7 files changed

Lines changed: 24 additions & 246 deletions

File tree

trantor/net/inner/Socket.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ void Socket::closeWrite()
108108
#endif
109109
{
110110
LOG_SYSERR << "sockets::shutdownWrite";
111+
abort();
111112
}
112113
}
113114
int Socket::read(char *buffer, uint64_t len)

trantor/net/inner/tlsprovider/BotanTLSProvider.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,6 @@ SSLContextPtr trantor::newSSLContext(const TLSPolicy &policy, bool server)
474474
ctx->certStore =
475475
std::make_shared<Botan::Flatfile_Certificate_Store>(
476476
policy.getCaPath());
477-
if (server)
478-
ctx->requireClientCert = true;
479477
}
480478
else if (policy.getUseSystemCertStore())
481479
{
@@ -484,6 +482,8 @@ SSLContextPtr trantor::newSSLContext(const TLSPolicy &policy, bool server)
484482
ctx->certStore = systemCertStore;
485483
}
486484
}
485+
if (server && policy.getValidate() && !policy.getCaPath().empty())
486+
ctx->requireClientCert = true;
487487

488488
if (policy.getUseOldTLS())
489489
LOG_WARN << "SSLPloicy have set useOldTLS to true. BUt Botan does not "

trantor/net/inner/tlsprovider/OpenSSLProvider.cc

Lines changed: 21 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@
88
#include <openssl/bio.h>
99
#include <openssl/x509v3.h>
1010

11-
#include <fstream>
1211
#include <memory>
1312
#include <mutex>
1413
#include <list>
1514
#include <unordered_map>
16-
#include <array>
1715
#include <limits>
1816
#include "callbacks.h"
1917

@@ -70,62 +68,6 @@ inline bool loadWindowsSystemCert(X509_STORE *store)
7068
}
7169
#endif
7270

73-
inline bool verifyCommonName(X509 *cert, const std::string &hostname)
74-
{
75-
X509_NAME *subjectName = X509_get_subject_name(cert);
76-
77-
if (subjectName != nullptr)
78-
{
79-
std::array<char, BUFSIZ> name;
80-
auto length = X509_NAME_get_text_by_NID(subjectName,
81-
NID_commonName,
82-
name.data(),
83-
(int)name.size());
84-
if (length == -1)
85-
return false;
86-
87-
return utils::verifySslName(std::string(name.begin(),
88-
name.begin() + length),
89-
hostname);
90-
}
91-
92-
return false;
93-
}
94-
95-
inline bool verifyAltName(X509 *cert, const std::string &hostname)
96-
{
97-
bool good = false;
98-
auto altNames = static_cast<const struct stack_st_GENERAL_NAME *>(
99-
X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
100-
101-
if (altNames)
102-
{
103-
int numNames = sk_GENERAL_NAME_num(altNames);
104-
105-
for (int i = 0; i < numNames && !good; i++)
106-
{
107-
auto val = sk_GENERAL_NAME_value(altNames, i);
108-
if (val->type != GEN_DNS)
109-
{
110-
LOG_WARN << "Name using IP addresses are not supported. Open "
111-
"an issue if you need that feature";
112-
continue;
113-
}
114-
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
115-
auto name = (const char *)ASN1_STRING_get0_data(val->d.ia5);
116-
#else
117-
auto name = (const char *)ASN1_STRING_data(val->d.ia5);
118-
#endif
119-
auto name_len = (size_t)ASN1_STRING_length(val->d.ia5);
120-
good = utils::verifySslName(std::string(name, name + name_len),
121-
hostname);
122-
}
123-
}
124-
125-
GENERAL_NAMES_free((STACK_OF(GENERAL_NAME) *)altNames);
126-
return good;
127-
}
128-
12971
static bool validatePeerCertificate(SSL *ssl,
13072
X509 *cert,
13173
const std::string &hostname,
@@ -136,12 +78,16 @@ static bool validatePeerCertificate(SSL *ssl,
13678
assert(cert != nullptr);
13779
LOG_TRACE << "Validating peer certificate";
13880

139-
if (isServer)
81+
if (!isServer)
14082
{
141-
bool domainIsValid =
142-
verifyCommonName(cert, hostname) || verifyAltName(cert, hostname);
143-
if (!domainIsValid)
83+
const int rc =
84+
X509_check_host(cert, hostname.data(), hostname.size(), 0, nullptr);
85+
if (rc != 1)
86+
{
87+
LOG_TRACE << "Peer certificate does not match hostname: "
88+
<< hostname;
14489
return false;
90+
}
14591
}
14692

14793
auto result = SSL_get_verify_result(ssl);
@@ -423,16 +369,20 @@ class SessionManager
423369
#endif
424370
}
425371

372+
// Returns a session with an additional reference held by the caller.
373+
// Caller must SSL_SESSION_free() when done. Required because the entry
374+
// in sessionMap_ may be evicted/replaced/expired by another thread the
375+
// moment we release the mutex, so the SessionManager's reference is not
376+
// a stable ownership root for the returned pointer.
426377
SSL_SESSION *get(const std::string &hostname, InetAddress peerAddr)
427378
{
428379
std::lock_guard<std::mutex> lock(mutex_);
429-
auto key = toKey(hostname, peerAddr);
430-
auto it = sessionMap_.find(key);
431-
if (it != sessionMap_.end())
432-
{
433-
return it->second->session;
434-
}
435-
return nullptr;
380+
auto it = sessionMap_.find(toKey(hostname, peerAddr));
381+
if (it == sessionMap_.end())
382+
return nullptr;
383+
SSL_SESSION *s = it->second->session;
384+
SSL_SESSION_up_ref(s);
385+
return s;
436386
}
437387

438388
void removeExcessSession()
@@ -529,7 +479,9 @@ struct OpenSSLProvider : public TLSProvider, public NonCopyable
529479
conn_->peerAddr());
530480
if (cachedSession)
531481
{
482+
// SSL_set_session takes its own reference; release ours.
532483
SSL_set_session(ssl_, cachedSession);
484+
SSL_SESSION_free(cachedSession);
533485
}
534486
SSL_set_connect_state(ssl_);
535487
}

trantor/unittests/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ add_executable(inetaddress_unittest InetAddressUnittest.cc)
44
add_executable(date_unittest DateUnittest.cc)
55
add_executable(split_string_unittest splitStringUnittest.cc)
66
add_executable(string_encoding_unittest stringEncodingUnittest.cc)
7-
add_executable(ssl_name_verify_unittest sslNameVerifyUnittest.cc)
87
add_executable(hash_unittest HashUnittest.cc)
98
set(UNITTEST_TARGETS
109
msgbuffer_unittest
1110
inetaddress_unittest
1211
date_unittest
1312
split_string_unittest
1413
string_encoding_unittest
15-
ssl_name_verify_unittest
1614
hash_unittest
1715
)
1816
set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_STANDARD 14)

trantor/unittests/sslNameVerifyUnittest.cc

Lines changed: 0 additions & 50 deletions
This file was deleted.

trantor/utils/Utilities.cc

Lines changed: 0 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -228,120 +228,6 @@ std::string fromWidePath(const std::wstring &wstrPath)
228228
return toUtf8(srcPath);
229229
}
230230

231-
bool verifySslName(const std::string &certName, const std::string &hostname)
232-
{
233-
if (certName.find('*') == std::string::npos)
234-
{
235-
return certName == hostname;
236-
}
237-
238-
size_t firstDot = certName.find('.');
239-
size_t hostFirstDot = hostname.find('.');
240-
size_t pos, len, hostPos, hostLen;
241-
242-
if (firstDot != std::string::npos)
243-
{
244-
pos = firstDot + 1;
245-
}
246-
else
247-
{
248-
firstDot = pos = certName.size();
249-
}
250-
251-
len = certName.size() - pos;
252-
253-
if (hostFirstDot != std::string::npos)
254-
{
255-
hostPos = hostFirstDot + 1;
256-
}
257-
else
258-
{
259-
hostFirstDot = hostPos = hostname.size();
260-
}
261-
262-
hostLen = hostname.size() - hostPos;
263-
264-
// *. in the beginning of the cert name
265-
if (certName.compare(0, firstDot, "*") == 0)
266-
{
267-
return certName.compare(pos, len, hostname, hostPos, hostLen) == 0;
268-
}
269-
// * in the left most. but other chars in the right
270-
else if (certName[0] == '*')
271-
{
272-
// compare if `hostname` ends with `certName` but without the leftmost
273-
// should be fine as domain names can't be that long
274-
intmax_t hostnameIdx = hostname.size() - 1;
275-
intmax_t certNameIdx = certName.size() - 1;
276-
while (hostnameIdx >= 0 && certNameIdx != 0)
277-
{
278-
if (hostname[hostnameIdx] != certName[certNameIdx])
279-
{
280-
return false;
281-
}
282-
hostnameIdx--;
283-
certNameIdx--;
284-
}
285-
if (certNameIdx != 0)
286-
{
287-
return false;
288-
}
289-
return true;
290-
}
291-
// * in the right of the first dot
292-
else if (firstDot != 0 && certName[firstDot - 1] == '*')
293-
{
294-
if (certName.compare(pos, len, hostname, hostPos, hostLen) != 0)
295-
{
296-
return false;
297-
}
298-
for (size_t i = 0;
299-
i < hostFirstDot && i < firstDot && certName[i] != '*';
300-
i++)
301-
{
302-
if (hostname[i] != certName[i])
303-
{
304-
return false;
305-
}
306-
}
307-
return true;
308-
}
309-
// else there's a * in the middle
310-
else
311-
{
312-
if (certName.compare(pos, len, hostname, hostPos, hostLen) != 0)
313-
{
314-
return false;
315-
}
316-
for (size_t i = 0;
317-
i < hostFirstDot && i < firstDot && certName[i] != '*';
318-
i++)
319-
{
320-
if (hostname[i] != certName[i])
321-
{
322-
return false;
323-
}
324-
}
325-
intmax_t hostnameIdx = hostFirstDot - 1;
326-
intmax_t certNameIdx = firstDot - 1;
327-
while (hostnameIdx >= 0 && certNameIdx >= 0 &&
328-
certName[certNameIdx] != '*')
329-
{
330-
if (hostname[hostnameIdx] != certName[certNameIdx])
331-
{
332-
return false;
333-
}
334-
hostnameIdx--;
335-
certNameIdx--;
336-
}
337-
return true;
338-
}
339-
340-
assert(false && "This line should not be reached in verifySslName");
341-
// should not reach
342-
return certName == hostname;
343-
}
344-
345231
#define STRINGIFY(x) #x
346232
#define TOSTRING(x) STRINGIFY(x)
347233

trantor/utils/Utilities.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,15 +171,6 @@ inline std::string fromNativePath(const std::wstring &strPath)
171171
return fromWidePath(strPath);
172172
}
173173

174-
/**
175-
* @brief Check if the name supplied by the SSL Cert matches a FQDN
176-
* @param certName The name supplied by the SSL Cert
177-
* @param hostName The FQDN to match
178-
*
179-
* @return true if matches. false otherwise
180-
*/
181-
bool verifySslName(const std::string &certName, const std::string &hostName);
182-
183174
/**
184175
* @brief Returns the TLS backend used by trantor. Could be "None", "OpenSSL" or
185176
* "Botan"

0 commit comments

Comments
 (0)