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-
12971static 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 }
0 commit comments