1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "remoting/host/token_validator_base.h"
6 
7 #include <vector>
8 
9 #include "base/atomic_sequence_num.h"
10 #include "crypto/rsa_private_key.h"
11 #include "net/cert/x509_util.h"
12 #include "net/ssl/client_cert_identity_test_util.h"
13 #include "net/ssl/test_ssl_private_key.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 namespace {
17 
18 const char kTokenUrl[] = "https://example.com/token";
19 const char kTokenValidationUrl[] = "https://example.com/validate";
20 const char kTokenValidationCertIssuer[] = "*";
21 
22 base::AtomicSequenceNumber g_serial_number;
23 
CreateFakeCert(base::Time valid_start,base::Time valid_expiry)24 std::unique_ptr<net::FakeClientCertIdentity> CreateFakeCert(
25     base::Time valid_start,
26     base::Time valid_expiry) {
27   std::unique_ptr<crypto::RSAPrivateKey> rsa_private_key;
28   std::string cert_der;
29   net::x509_util::CreateKeyAndSelfSignedCert(
30       "CN=subject", g_serial_number.GetNext(), valid_start, valid_expiry,
31       &rsa_private_key, &cert_der);
32 
33   scoped_refptr<net::X509Certificate> cert =
34       net::X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
35   if (!cert)
36     return nullptr;
37 
38   scoped_refptr<net::SSLPrivateKey> ssl_private_key =
39       net::WrapRSAPrivateKey(rsa_private_key.get());
40   if (!ssl_private_key)
41     return nullptr;
42 
43   return std::make_unique<net::FakeClientCertIdentity>(cert, ssl_private_key);
44 }
45 
46 }  // namespace
47 
48 namespace remoting {
49 
50 class TestTokenValidator : TokenValidatorBase {
51  public:
52   explicit TestTokenValidator(const ThirdPartyAuthConfig& config);
53   ~TestTokenValidator() override;
54 
55   void SelectCertificates(net::ClientCertIdentityList selected_certs);
56 
57   void ExpectContinueWithCertificate(
58       const net::FakeClientCertIdentity* identity);
59 
60  protected:
61   void ContinueWithCertificate(
62       scoped_refptr<net::X509Certificate> client_cert,
63       scoped_refptr<net::SSLPrivateKey> client_private_key) override;
64 
65  private:
StartValidateRequest(const std::string & token)66   void StartValidateRequest(const std::string& token) override {}
67 
68   net::X509Certificate* expected_client_cert_ = nullptr;
69   net::SSLPrivateKey* expected_private_key_ = nullptr;
70 };
71 
TestTokenValidator(const ThirdPartyAuthConfig & config)72 TestTokenValidator::TestTokenValidator(const ThirdPartyAuthConfig& config) :
73     TokenValidatorBase(config, "", nullptr) {
74 }
75 
76 TestTokenValidator::~TestTokenValidator() = default;
77 
SelectCertificates(net::ClientCertIdentityList selected_certs)78 void TestTokenValidator::SelectCertificates(
79     net::ClientCertIdentityList selected_certs) {
80   OnCertificatesSelected(nullptr, std::move(selected_certs));
81 }
82 
ExpectContinueWithCertificate(const net::FakeClientCertIdentity * identity)83 void TestTokenValidator::ExpectContinueWithCertificate(
84     const net::FakeClientCertIdentity* identity) {
85   if (identity) {
86     expected_client_cert_ = identity->certificate();
87     expected_private_key_ = identity->ssl_private_key();
88   } else {
89     expected_client_cert_ = nullptr;
90     expected_private_key_ = nullptr;
91   }
92 }
93 
ContinueWithCertificate(scoped_refptr<net::X509Certificate> client_cert,scoped_refptr<net::SSLPrivateKey> client_private_key)94 void TestTokenValidator::ContinueWithCertificate(
95     scoped_refptr<net::X509Certificate> client_cert,
96     scoped_refptr<net::SSLPrivateKey> client_private_key) {
97   EXPECT_EQ(expected_client_cert_, client_cert.get());
98   EXPECT_EQ(expected_private_key_, client_private_key.get());
99 }
100 
101 class TokenValidatorBaseTest : public testing::Test {
102  public:
103   void SetUp() override;
104  protected:
105   std::unique_ptr<TestTokenValidator> token_validator_;
106 };
107 
SetUp()108 void TokenValidatorBaseTest::SetUp() {
109   ThirdPartyAuthConfig config;
110   config.token_url = GURL(kTokenUrl);
111   config.token_validation_url = GURL(kTokenValidationUrl);
112   config.token_validation_cert_issuer = kTokenValidationCertIssuer;
113   token_validator_.reset(new TestTokenValidator(config));
114 }
115 
TEST_F(TokenValidatorBaseTest,TestSelectCertificate)116 TEST_F(TokenValidatorBaseTest, TestSelectCertificate) {
117   base::Time now = base::Time::Now();
118 
119   std::unique_ptr<net::FakeClientCertIdentity> cert_expired_5_minutes_ago =
120       CreateFakeCert(now - base::TimeDelta::FromMinutes(10),
121                      now - base::TimeDelta::FromMinutes(5));
122   ASSERT_TRUE(cert_expired_5_minutes_ago);
123 
124   std::unique_ptr<net::FakeClientCertIdentity> cert_start_5min_expire_5min =
125       CreateFakeCert(now - base::TimeDelta::FromMinutes(5),
126                      now + base::TimeDelta::FromMinutes(5));
127   ASSERT_TRUE(cert_start_5min_expire_5min);
128 
129   std::unique_ptr<net::FakeClientCertIdentity> cert_start_10min_expire_5min =
130       CreateFakeCert(now - base::TimeDelta::FromMinutes(10),
131                      now + base::TimeDelta::FromMinutes(5));
132   ASSERT_TRUE(cert_start_10min_expire_5min);
133 
134   std::unique_ptr<net::FakeClientCertIdentity> cert_start_5min_expire_10min =
135       CreateFakeCert(now - base::TimeDelta::FromMinutes(5),
136                      now + base::TimeDelta::FromMinutes(10));
137   ASSERT_TRUE(cert_start_5min_expire_10min);
138 
139   // No certificate.
140   token_validator_->ExpectContinueWithCertificate(nullptr);
141   token_validator_->SelectCertificates(net::ClientCertIdentityList());
142   {
143     // One invalid certificate.
144     net::ClientCertIdentityList client_certs;
145     client_certs.push_back(cert_expired_5_minutes_ago->Copy());
146     token_validator_->ExpectContinueWithCertificate(nullptr);
147     token_validator_->SelectCertificates(std::move(client_certs));
148   }
149   {
150     // One valid certificate.
151     net::ClientCertIdentityList client_certs;
152     client_certs.push_back(cert_start_5min_expire_5min->Copy());
153     token_validator_->ExpectContinueWithCertificate(
154         cert_start_5min_expire_5min.get());
155     token_validator_->SelectCertificates(std::move(client_certs));
156   }
157   {
158     // One valid one invalid.
159     net::ClientCertIdentityList client_certs;
160     client_certs.push_back(cert_expired_5_minutes_ago->Copy());
161     client_certs.push_back(cert_start_5min_expire_5min->Copy());
162     token_validator_->ExpectContinueWithCertificate(
163         cert_start_5min_expire_5min.get());
164     token_validator_->SelectCertificates(std::move(client_certs));
165   }
166   {
167     // Two valid certs. Choose latest created.
168     net::ClientCertIdentityList client_certs;
169     client_certs.push_back(cert_start_10min_expire_5min->Copy());
170     client_certs.push_back(cert_start_5min_expire_5min->Copy());
171     token_validator_->ExpectContinueWithCertificate(
172         cert_start_5min_expire_5min.get());
173     token_validator_->SelectCertificates(std::move(client_certs));
174   }
175   {
176     // Two valid certs. Choose latest expires.
177     net::ClientCertIdentityList client_certs;
178     client_certs.push_back(cert_start_5min_expire_5min->Copy());
179     client_certs.push_back(cert_start_5min_expire_10min->Copy());
180     token_validator_->ExpectContinueWithCertificate(
181         cert_start_5min_expire_10min.get());
182     token_validator_->SelectCertificates(std::move(client_certs));
183   }
184   {
185     // Pick the best given all certificates.
186     net::ClientCertIdentityList client_certs;
187     client_certs.push_back(cert_expired_5_minutes_ago->Copy());
188     client_certs.push_back(cert_start_5min_expire_5min->Copy());
189     client_certs.push_back(cert_start_5min_expire_10min->Copy());
190     client_certs.push_back(cert_start_10min_expire_5min->Copy());
191     token_validator_->ExpectContinueWithCertificate(
192         cert_start_5min_expire_10min.get());
193     token_validator_->SelectCertificates(std::move(client_certs));
194   }
195 }
196 
197 }  // namespace remoting
198