This changeset addresses concerns about how the OpenSSLAdapter does certificate name matching. The current approach has a number of issues which are outlined in the bug description. The approach taken in this changeset is to use the standard function X509_check_host which should correctly parse the wildcard expansions and is directly supported in OpenSSL instead of attempting my own implementation. This changeset uses this as an opportunity to add additional parameter checking and refactoring logging code out of the main code path. Bug: webrtc:8888 Change-Id: Iaffe1daddcd52193ba674489f613ce8515b81e91 Reviewed-on: https://webrtc-review.googlesource.com/65022 Commit-Queue: Benjamin Wright <benwright@webrtc.org> Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org> Reviewed-by: Emad Omara <emadomara@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22755}
153 lines
7.1 KiB
C++
153 lines
7.1 KiB
C++
/*
|
|
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#if defined(WEBRTC_POSIX)
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#if defined(WEBRTC_WIN)
|
|
// Must be included first before openssl headers.
|
|
#include "rtc_base/win32.h" // NOLINT
|
|
#endif // WEBRTC_WIN
|
|
|
|
#include <openssl/bio.h>
|
|
#include <openssl/crypto.h>
|
|
#include <openssl/x509.h>
|
|
#include <openssl/x509v3.h>
|
|
|
|
#include "rtc_base/arraysize.h"
|
|
#include "rtc_base/gunit.h"
|
|
#include "rtc_base/numerics/safe_conversions.h"
|
|
#include "rtc_base/openssl.h"
|
|
#include "rtc_base/opensslcommon.h"
|
|
#include "rtc_base/sslroots.h"
|
|
#include "test/gmock.h"
|
|
|
|
namespace rtc {
|
|
namespace {
|
|
// Fake Self-Signed SSL Certifiacte with CN: *.webrtc.org.
|
|
// This is only to be used for testing (it isn't signed by a CA anyway).
|
|
const unsigned char kFakeSSLCertificate[] = {
|
|
0x30, 0x82, 0x02, 0x68, 0x30, 0x82, 0x02, 0x12, 0xA0, 0x03, 0x02, 0x01,
|
|
0x02, 0x02, 0x09, 0x00, 0xC8, 0x83, 0x59, 0x4D, 0x90, 0xC3, 0x5F, 0xC8,
|
|
0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
|
|
0x0B, 0x05, 0x00, 0x30, 0x81, 0x8D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
|
|
0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0B, 0x30, 0x09, 0x06,
|
|
0x03, 0x55, 0x04, 0x08, 0x0C, 0x02, 0x57, 0x41, 0x31, 0x2C, 0x30, 0x2A,
|
|
0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x23, 0x46, 0x61, 0x6B, 0x65, 0x20,
|
|
0x57, 0x65, 0x62, 0x52, 0x54, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
|
|
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x54,
|
|
0x65, 0x73, 0x74, 0x69, 0x6E, 0x67, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03,
|
|
0x55, 0x04, 0x0B, 0x0C, 0x23, 0x46, 0x61, 0x6B, 0x65, 0x20, 0x57, 0x65,
|
|
0x62, 0x52, 0x54, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
|
0x63, 0x61, 0x74, 0x65, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x54, 0x65, 0x73,
|
|
0x74, 0x69, 0x6E, 0x67, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04,
|
|
0x03, 0x0C, 0x0C, 0x2A, 0x2E, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x2E,
|
|
0x6F, 0x72, 0x67, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, 0x30,
|
|
0x33, 0x32, 0x31, 0x35, 0x34, 0x30, 0x38, 0x5A, 0x17, 0x0D, 0x31, 0x39,
|
|
0x30, 0x34, 0x30, 0x33, 0x32, 0x31, 0x35, 0x34, 0x30, 0x38, 0x5A, 0x30,
|
|
0x81, 0x8D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
|
|
0x02, 0x55, 0x53, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08,
|
|
0x0C, 0x02, 0x57, 0x41, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04,
|
|
0x0A, 0x0C, 0x23, 0x46, 0x61, 0x6B, 0x65, 0x20, 0x57, 0x65, 0x62, 0x52,
|
|
0x54, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
|
0x74, 0x65, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x69,
|
|
0x6E, 0x67, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C,
|
|
0x23, 0x46, 0x61, 0x6B, 0x65, 0x20, 0x57, 0x65, 0x62, 0x52, 0x54, 0x43,
|
|
0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
|
|
0x20, 0x46, 0x6F, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6E, 0x67,
|
|
0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0C, 0x2A,
|
|
0x2E, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x2E, 0x6F, 0x72, 0x67, 0x30,
|
|
0x5C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
|
|
0x01, 0x01, 0x05, 0x00, 0x03, 0x4B, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00,
|
|
0xAE, 0xAE, 0x85, 0x2A, 0x40, 0xD6, 0x99, 0x35, 0x09, 0x34, 0x1B, 0xC5,
|
|
0xAC, 0x6C, 0x79, 0xC7, 0xC3, 0xDE, 0x1B, 0xCF, 0x17, 0x8D, 0x6B, 0x84,
|
|
0xEC, 0x8B, 0x4E, 0x2B, 0xC1, 0x83, 0x43, 0xDF, 0x76, 0x0F, 0x5F, 0x5A,
|
|
0xA9, 0x7D, 0x94, 0xC0, 0x54, 0x5C, 0xFF, 0xBC, 0x7C, 0x86, 0xDC, 0x9A,
|
|
0xCE, 0xB9, 0xDF, 0xE6, 0x0B, 0xC4, 0x5B, 0x6E, 0x56, 0x9F, 0xBC, 0x40,
|
|
0xF5, 0xA0, 0x52, 0xA7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x53, 0x30,
|
|
0x51, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14,
|
|
0xB7, 0xC0, 0x9A, 0xA7, 0x22, 0xAF, 0xF8, 0x7D, 0xFF, 0x68, 0xDB, 0x80,
|
|
0xAC, 0x0A, 0xB6, 0xDC, 0x64, 0x89, 0xDB, 0xD4, 0x30, 0x1F, 0x06, 0x03,
|
|
0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xB7, 0xC0, 0x9A,
|
|
0xA7, 0x22, 0xAF, 0xF8, 0x7D, 0xFF, 0x68, 0xDB, 0x80, 0xAC, 0x0A, 0xB6,
|
|
0xDC, 0x64, 0x89, 0xDB, 0xD4, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13,
|
|
0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D,
|
|
0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05,
|
|
0x00, 0x03, 0x41, 0x00, 0x50, 0x6D, 0xCC, 0x62, 0xAE, 0xD1, 0x7C, 0x4D,
|
|
0xEF, 0x90, 0x1E, 0x9B, 0x72, 0x73, 0xE0, 0x56, 0x66, 0x32, 0x6A, 0x78,
|
|
0xE8, 0x0F, 0xAD, 0x21, 0x32, 0x54, 0xA5, 0xB3, 0xB8, 0x14, 0x54, 0xBC,
|
|
0x50, 0xF7, 0x7F, 0x73, 0xD6, 0x44, 0x1E, 0x82, 0xD9, 0x4B, 0x49, 0x48,
|
|
0x9E, 0x02, 0x8B, 0xFE, 0xC3, 0xFD, 0x5D, 0x15, 0x02, 0xE1, 0x78, 0xAC,
|
|
0x9A, 0xAE, 0xFC, 0xC7, 0x48, 0xC6, 0x48, 0x6B};
|
|
|
|
// Simple testing helper method to create a fake SSL_SESSION with a testing
|
|
// peer connection set.
|
|
SSL_SESSION* CreateSSLSessionWithFakePeerCertificate(SSL_CTX* ssl_ctx) {
|
|
SSL_SESSION* ssl_session = SSL_SESSION_new(ssl_ctx);
|
|
const unsigned char* cert_buffer = kFakeSSLCertificate;
|
|
size_t cert_buffer_len = arraysize(kFakeSSLCertificate);
|
|
X509* ssl_peer_certificate = d2i_X509(
|
|
nullptr, &cert_buffer, checked_cast<long>(cert_buffer_len)); // NOLINT
|
|
EXPECT_NE(ssl_peer_certificate, nullptr);
|
|
#ifdef OPENSSL_IS_BORINGSSL
|
|
ssl_session->x509_peer = ssl_peer_certificate;
|
|
#else
|
|
ssl_session->peer = ssl_peer_certificate;
|
|
#endif
|
|
return ssl_session;
|
|
}
|
|
} // namespace
|
|
|
|
TEST(OpenSSLCommonTest, VerifyPeerCertMatchesHostFailsOnNoPeerCertificate) {
|
|
SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
|
|
SSL* ssl = SSL_new(ssl_ctx);
|
|
|
|
EXPECT_FALSE(openssl::VerifyPeerCertMatchesHost(ssl, "webrtc.org"));
|
|
|
|
SSL_free(ssl);
|
|
SSL_CTX_free(ssl_ctx);
|
|
}
|
|
|
|
TEST(OpenSSLCommonTest, VerifyPeerCertMatchesHostSucceedsOnCorrectHostname) {
|
|
SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
|
|
SSL* ssl = SSL_new(ssl_ctx);
|
|
SSL_SESSION* ssl_session = CreateSSLSessionWithFakePeerCertificate(ssl_ctx);
|
|
SSL_set_session(ssl, ssl_session);
|
|
|
|
EXPECT_TRUE(openssl::VerifyPeerCertMatchesHost(ssl, "www.webrtc.org"));
|
|
EXPECT_TRUE(openssl::VerifyPeerCertMatchesHost(ssl, "alice.webrtc.org"));
|
|
EXPECT_TRUE(openssl::VerifyPeerCertMatchesHost(ssl, "bob.webrtc.org"));
|
|
|
|
SSL_SESSION_free(ssl_session);
|
|
SSL_free(ssl);
|
|
SSL_CTX_free(ssl_ctx);
|
|
}
|
|
|
|
TEST(OpenSSLCommonTest, VerifyPeerCertMatchesHostFailsOnInvalidHostname) {
|
|
SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
|
|
SSL* ssl = SSL_new(ssl_ctx);
|
|
SSL_SESSION* ssl_session = CreateSSLSessionWithFakePeerCertificate(ssl_ctx);
|
|
SSL_set_session(ssl, ssl_session);
|
|
|
|
EXPECT_FALSE(openssl::VerifyPeerCertMatchesHost(ssl, "a.b.webrtc.org"));
|
|
EXPECT_FALSE(openssl::VerifyPeerCertMatchesHost(ssl, "notwebrtc.org"));
|
|
EXPECT_FALSE(openssl::VerifyPeerCertMatchesHost(ssl, "webrtc.org"));
|
|
|
|
SSL_SESSION_free(ssl_session);
|
|
SSL_free(ssl);
|
|
SSL_CTX_free(ssl_ctx);
|
|
}
|
|
|
|
} // namespace rtc
|