Home | History | Annotate | Download | only in protocol
      1 // Copyright (c) 2012 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 "base/bind.h"
      6 #include "net/base/net_errors.h"
      7 #include "remoting/base/rsa_key_pair.h"
      8 #include "remoting/protocol/authenticator_test_base.h"
      9 #include "remoting/protocol/channel_authenticator.h"
     10 #include "remoting/protocol/connection_tester.h"
     11 #include "remoting/protocol/negotiating_authenticator_base.h"
     12 #include "remoting/protocol/negotiating_client_authenticator.h"
     13 #include "remoting/protocol/negotiating_host_authenticator.h"
     14 #include "remoting/protocol/pairing_registry.h"
     15 #include "remoting/protocol/protocol_mock_objects.h"
     16 #include "testing/gmock/include/gmock/gmock.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
     19 
     20 using testing::_;
     21 using testing::DeleteArg;
     22 using testing::SaveArg;
     23 
     24 namespace remoting {
     25 namespace protocol {
     26 
     27 namespace {
     28 
     29 const int kMessageSize = 100;
     30 const int kMessages = 1;
     31 
     32 const char kNoClientId[] = "";
     33 const char kNoPairedSecret[] = "";
     34 const char kTestClientName[] = "client-name";
     35 const char kTestClientId[] = "client-id";
     36 const char kTestHostId[] = "12345678910123456";
     37 
     38 const char kTestPairedSecret[] = "1111-2222-3333";
     39 const char kTestPairedSecretBad[] = "4444-5555-6666";
     40 const char kTestPin[] = "123456";
     41 const char kTestPinBad[] = "654321";
     42 
     43 }  // namespace
     44 
     45 class NegotiatingAuthenticatorTest : public AuthenticatorTestBase {
     46  public:
     47   NegotiatingAuthenticatorTest() {
     48   }
     49   virtual ~NegotiatingAuthenticatorTest() {
     50   }
     51 
     52  protected:
     53   void InitAuthenticators(
     54       const std::string& client_id,
     55       const std::string& client_paired_secret,
     56       const std::string& client_interactive_pin,
     57       const std::string& host_secret,
     58       AuthenticationMethod::HashFunction hash_function,
     59       bool client_hmac_only) {
     60     std::string host_secret_hash = AuthenticationMethod::ApplyHashFunction(
     61         hash_function, kTestHostId, host_secret);
     62     host_ = NegotiatingHostAuthenticator::CreateWithSharedSecret(
     63         host_cert_, key_pair_, host_secret_hash, hash_function,
     64         pairing_registry_);
     65 
     66     std::vector<AuthenticationMethod> methods;
     67     methods.push_back(AuthenticationMethod::Spake2Pair());
     68     methods.push_back(AuthenticationMethod::Spake2(
     69         AuthenticationMethod::HMAC_SHA256));
     70     if (!client_hmac_only) {
     71       methods.push_back(AuthenticationMethod::Spake2(
     72           AuthenticationMethod::NONE));
     73     }
     74     bool pairing_expected = pairing_registry_.get() != NULL;
     75     FetchSecretCallback fetch_secret_callback =
     76         base::Bind(&NegotiatingAuthenticatorTest::FetchSecret,
     77                    client_interactive_pin,
     78                    pairing_expected);
     79     client_as_negotiating_authenticator_ = new NegotiatingClientAuthenticator(
     80         client_id, client_paired_secret,
     81         kTestHostId, fetch_secret_callback,
     82         scoped_ptr<ThirdPartyClientAuthenticator::TokenFetcher>(), methods);
     83     client_.reset(client_as_negotiating_authenticator_);
     84   }
     85 
     86   void CreatePairingRegistry(bool with_paired_client) {
     87     pairing_registry_ = new SynchronousPairingRegistry(
     88         scoped_ptr<PairingRegistry::Delegate>(
     89             new MockPairingRegistryDelegate()));
     90     if (with_paired_client) {
     91       PairingRegistry::Pairing pairing(
     92           base::Time(), kTestClientName, kTestClientId, kTestPairedSecret);
     93       pairing_registry_->AddPairing(pairing);
     94     }
     95   }
     96 
     97   static void FetchSecret(
     98       const std::string& client_secret,
     99       bool pairing_supported,
    100       bool pairing_expected,
    101       const protocol::SecretFetchedCallback& secret_fetched_callback) {
    102     secret_fetched_callback.Run(client_secret);
    103     ASSERT_EQ(pairing_supported, pairing_expected);
    104   }
    105 
    106   void VerifyRejected(Authenticator::RejectionReason reason) {
    107     ASSERT_TRUE(client_->state() == Authenticator::REJECTED ||
    108                 host_->state() == Authenticator::REJECTED);
    109     if (client_->state() == Authenticator::REJECTED) {
    110       ASSERT_EQ(client_->rejection_reason(), reason);
    111     }
    112     if (host_->state() == Authenticator::REJECTED) {
    113       ASSERT_EQ(host_->rejection_reason(), reason);
    114     }
    115   }
    116 
    117   void VerifyAccepted(const AuthenticationMethod& expected_method) {
    118     ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    119 
    120     ASSERT_EQ(Authenticator::ACCEPTED, host_->state());
    121     ASSERT_EQ(Authenticator::ACCEPTED, client_->state());
    122 
    123     client_auth_ = client_->CreateChannelAuthenticator();
    124     host_auth_ = host_->CreateChannelAuthenticator();
    125     RunChannelAuth(false);
    126 
    127     EXPECT_TRUE(client_socket_.get() != NULL);
    128     EXPECT_TRUE(host_socket_.get() != NULL);
    129 
    130     StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
    131                                   kMessageSize, kMessages);
    132 
    133     tester.Start();
    134     message_loop_.Run();
    135     tester.CheckResults();
    136     EXPECT_EQ(
    137         expected_method,
    138         client_as_negotiating_authenticator_->current_method_for_testing());
    139   }
    140 
    141   // Use a bare pointer because the storage is managed by the base class.
    142   NegotiatingClientAuthenticator* client_as_negotiating_authenticator_;
    143 
    144  private:
    145   scoped_refptr<PairingRegistry> pairing_registry_;
    146 
    147   DISALLOW_COPY_AND_ASSIGN(NegotiatingAuthenticatorTest);
    148 };
    149 
    150 // These tests use net::SSLServerSocket which is not implemented for OpenSSL.
    151 #if defined(USE_OPENSSL)
    152 #define MAYBE(x) DISABLED_##x
    153 #else
    154 #define MAYBE(x) x
    155 #endif
    156 
    157 TEST_F(NegotiatingAuthenticatorTest, MAYBE(SuccessfulAuthHmac)) {
    158   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    159       kNoClientId, kNoPairedSecret, kTestPin, kTestPin,
    160       AuthenticationMethod::HMAC_SHA256, false));
    161   VerifyAccepted(
    162       AuthenticationMethod::Spake2(AuthenticationMethod::HMAC_SHA256));
    163 }
    164 
    165 TEST_F(NegotiatingAuthenticatorTest, MAYBE(SuccessfulAuthPlain)) {
    166   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    167       kNoClientId, kNoPairedSecret, kTestPin, kTestPin,
    168       AuthenticationMethod::NONE, false));
    169   VerifyAccepted(AuthenticationMethod::Spake2(AuthenticationMethod::NONE));
    170 }
    171 
    172 TEST_F(NegotiatingAuthenticatorTest, MAYBE(InvalidSecretHmac)) {
    173   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    174       kNoClientId, kNoPairedSecret, kTestPinBad, kTestPin,
    175       AuthenticationMethod::HMAC_SHA256, false));
    176   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    177 
    178   VerifyRejected(Authenticator::INVALID_CREDENTIALS);
    179 }
    180 
    181 TEST_F(NegotiatingAuthenticatorTest, MAYBE(InvalidSecretPlain)) {
    182   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    183       kNoClientId, kNoPairedSecret, kTestPin, kTestPinBad,
    184       AuthenticationMethod::NONE, false));
    185   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    186 
    187   VerifyRejected(Authenticator::INVALID_CREDENTIALS);
    188 }
    189 
    190 TEST_F(NegotiatingAuthenticatorTest, MAYBE(IncompatibleMethods)) {
    191   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    192       kNoClientId, kNoPairedSecret, kTestPin, kTestPinBad,
    193       AuthenticationMethod::NONE, true));
    194   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    195 
    196   VerifyRejected(Authenticator::PROTOCOL_ERROR);
    197 }
    198 
    199 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingNotSupported)) {
    200   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    201       kTestClientId, kTestPairedSecret, kTestPin, kTestPin,
    202       AuthenticationMethod::HMAC_SHA256, false));
    203   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    204   VerifyAccepted(
    205       AuthenticationMethod::Spake2(AuthenticationMethod::HMAC_SHA256));
    206 }
    207 
    208 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingSupportedButNotPaired)) {
    209   CreatePairingRegistry(false);
    210   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    211       kNoClientId, kNoPairedSecret, kTestPin, kTestPin,
    212       AuthenticationMethod::HMAC_SHA256, false));
    213   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    214   VerifyAccepted(AuthenticationMethod::Spake2Pair());
    215 }
    216 
    217 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingRevokedPinOkay)) {
    218   CreatePairingRegistry(false);
    219   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    220       kTestClientId, kTestPairedSecret, kTestPin, kTestPin,
    221       AuthenticationMethod::HMAC_SHA256, false));
    222   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    223   VerifyAccepted(AuthenticationMethod::Spake2Pair());
    224 }
    225 
    226 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingRevokedPinBad)) {
    227   CreatePairingRegistry(false);
    228   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    229       kTestClientId, kTestPairedSecret, kTestPinBad, kTestPin,
    230       AuthenticationMethod::HMAC_SHA256, false));
    231   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    232   VerifyRejected(Authenticator::INVALID_CREDENTIALS);
    233 }
    234 
    235 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingSucceeded)) {
    236   CreatePairingRegistry(true);
    237   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    238       kTestClientId, kTestPairedSecret, kTestPinBad, kTestPin,
    239       AuthenticationMethod::HMAC_SHA256, false));
    240   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    241   VerifyAccepted(AuthenticationMethod::Spake2Pair());
    242 }
    243 
    244 TEST_F(NegotiatingAuthenticatorTest,
    245        MAYBE(PairingSucceededInvalidSecretButPinOkay)) {
    246   CreatePairingRegistry(true);
    247   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    248       kTestClientId, kTestPairedSecretBad, kTestPin, kTestPin,
    249       AuthenticationMethod::HMAC_SHA256, false));
    250   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    251   VerifyAccepted(AuthenticationMethod::Spake2Pair());
    252 }
    253 
    254 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingFailedInvalidSecretAndPin)) {
    255   CreatePairingRegistry(true);
    256   ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
    257       kTestClientId, kTestPairedSecretBad, kTestPinBad, kTestPin,
    258       AuthenticationMethod::HMAC_SHA256, false));
    259   ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
    260   VerifyRejected(Authenticator::INVALID_CREDENTIALS);
    261 }
    262 
    263 }  // namespace protocol
    264 }  // namespace remoting
    265