blob: 521339271ce237cebae190d431889dc306b84d7d [file] [log] [blame]
Benjamin Wright9201d1a2018-04-05 12:12:26 -07001/*
2 * Copyright 2018 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "rtc_base/opensslcommon.h"
12
13#if defined(WEBRTC_POSIX)
14#include <unistd.h>
15#endif
16
17#if defined(WEBRTC_WIN)
18// Must be included first before openssl headers.
19#include "rtc_base/win32.h" // NOLINT
20#endif // WEBRTC_WIN
21
22#include <openssl/bio.h>
23#include <openssl/crypto.h>
24#include <openssl/x509.h>
25#include <openssl/x509v3.h>
26
27#include "rtc_base/checks.h"
28#include "rtc_base/logging.h"
29#include "rtc_base/openssl.h"
30
31namespace rtc {
32namespace openssl {
33
34// Holds various helper methods.
35namespace {
36void LogCertificates(SSL* ssl, X509* certificate) {
37// Logging certificates is extremely verbose. So it is disabled by default.
38#ifdef LOG_CERTIFICATES
39 BIO* mem = BIO_new(BIO_s_mem());
40 if (mem == nullptr) {
41 RTC_DLOG(LS_ERROR) << "BIO_new() failed to allocate memory.";
42 return;
43 }
44
45 RTC_DLOG(LS_INFO) << "Certificate from server:";
46 X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
47 BIO_write(mem, "\0", 1);
48
49 char* buffer = nullptr;
50 BIO_get_mem_data(mem, &buffer);
51 if (buffer != nullptr) {
52 RTC_DLOG(LS_INFO) << buffer;
53 } else {
54 RTC_DLOG(LS_ERROR) << "BIO_get_mem_data() failed to get buffer.";
55 }
56 BIO_free(mem);
57
58 const char* cipher_name = SSL_CIPHER_get_name(SSL_get_current_cipher(ssl));
59 if (cipher_name != nullptr) {
60 RTC_DLOG(LS_INFO) << "Cipher: " << cipher_name;
61 } else {
62 RTC_DLOG(LS_ERROR) << "SSL_CIPHER_DESCRIPTION() failed to get cipher_name.";
63 }
64#endif
65}
66} // namespace
67
68bool VerifyPeerCertMatchesHost(SSL* ssl, const std::string& host) {
69 if (host.empty()) {
70 RTC_DLOG(LS_ERROR) << "Hostname is empty. Cannot verify peer certificate.";
71 return false;
72 }
73
74 if (ssl == nullptr) {
75 RTC_DLOG(LS_ERROR) << "SSL is nullptr. Cannot verify peer certificate.";
76 return false;
77 }
78
79 X509* certificate = SSL_get_peer_certificate(ssl);
80 if (certificate == nullptr) {
81 RTC_DLOG(LS_ERROR)
82 << "SSL_get_peer_certificate failed. This should never happen.";
83 return false;
84 }
85
86 LogCertificates(ssl, certificate);
87
88 bool is_valid_cert_name =
89 X509_check_host(certificate, host.c_str(), host.size(), 0, nullptr) == 1;
90 X509_free(certificate);
91 return is_valid_cert_name;
92}
93
94} // namespace openssl
95} // namespace rtc