blob: e62a8e375534ea292685a9aee61c9399b03b6498 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/protocol/negotiating_authenticator.h"
#include "base/bind.h"
#include "net/base/net_errors.h"
#include "remoting/protocol/authenticator_test_base.h"
#include "remoting/protocol/channel_authenticator.h"
#include "remoting/protocol/connection_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
using testing::_;
using testing::DeleteArg;
using testing::SaveArg;
namespace remoting {
namespace protocol {
namespace {
const int kMessageSize = 100;
const int kMessages = 1;
const char kTestHostId[] = "12345678910123456";
const char kTestSharedSecret[] = "1234-1234-5678";
const char kTestSharedSecretBad[] = "0000-0000-0001";
} // namespace
class NegotiatingAuthenticatorTest : public AuthenticatorTestBase {
public:
NegotiatingAuthenticatorTest() {
}
virtual ~NegotiatingAuthenticatorTest() {
}
protected:
void InitAuthenticators(
const std::string& client_secret,
const std::string& host_secret,
AuthenticationMethod::HashFunction hash_function,
bool client_hmac_only) {
std::string host_secret_hash = AuthenticationMethod::ApplyHashFunction(
hash_function, kTestHostId, host_secret);
host_ = NegotiatingAuthenticator::CreateForHost(
host_cert_, *private_key_, host_secret_hash, hash_function);
std::vector<AuthenticationMethod> methods;
methods.push_back(AuthenticationMethod::Spake2(
AuthenticationMethod::HMAC_SHA256));
if (!client_hmac_only) {
methods.push_back(AuthenticationMethod::Spake2(
AuthenticationMethod::NONE));
}
client_ = NegotiatingAuthenticator::CreateForClient(
kTestHostId, client_secret, methods);
}
void VerifyRejected(Authenticator::RejectionReason reason) {
ASSERT_TRUE((client_->state() == Authenticator::REJECTED &&
(client_->rejection_reason() == reason)) ||
(host_->state() == Authenticator::REJECTED &&
(host_->rejection_reason() == reason)));
}
DISALLOW_COPY_AND_ASSIGN(NegotiatingAuthenticatorTest);
};
TEST_F(NegotiatingAuthenticatorTest, SuccessfulAuthHmac) {
ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
kTestSharedSecret, kTestSharedSecret,
AuthenticationMethod::HMAC_SHA256, false));
ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
ASSERT_EQ(Authenticator::ACCEPTED, host_->state());
ASSERT_EQ(Authenticator::ACCEPTED, client_->state());
client_auth_ = client_->CreateChannelAuthenticator();
host_auth_ = host_->CreateChannelAuthenticator();
RunChannelAuth(false);
EXPECT_TRUE(client_socket_.get() != NULL);
EXPECT_TRUE(host_socket_.get() != NULL);
StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
kMessageSize, kMessages);
tester.Start();
message_loop_.Run();
tester.CheckResults();
}
TEST_F(NegotiatingAuthenticatorTest, SuccessfulAuthPlain) {
ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
kTestSharedSecret, kTestSharedSecret,
AuthenticationMethod::NONE, false));
ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
ASSERT_EQ(Authenticator::ACCEPTED, host_->state());
ASSERT_EQ(Authenticator::ACCEPTED, client_->state());
client_auth_ = client_->CreateChannelAuthenticator();
host_auth_ = host_->CreateChannelAuthenticator();
RunChannelAuth(false);
EXPECT_TRUE(client_socket_.get() != NULL);
EXPECT_TRUE(host_socket_.get() != NULL);
StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
kMessageSize, kMessages);
tester.Start();
message_loop_.Run();
tester.CheckResults();
}
TEST_F(NegotiatingAuthenticatorTest, InvalidSecretHmac) {
ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
kTestSharedSecret, kTestSharedSecretBad,
AuthenticationMethod::HMAC_SHA256, false));
ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
VerifyRejected(Authenticator::INVALID_CREDENTIALS);
}
TEST_F(NegotiatingAuthenticatorTest, InvalidSecretPlain) {
ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
kTestSharedSecret, kTestSharedSecretBad,
AuthenticationMethod::NONE, false));
ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
VerifyRejected(Authenticator::INVALID_CREDENTIALS);
}
TEST_F(NegotiatingAuthenticatorTest, IncompatibleMethods) {
ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
kTestSharedSecret, kTestSharedSecretBad,
AuthenticationMethod::NONE, true));
ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
VerifyRejected(Authenticator::PROTOCOL_ERROR);
}
} // namespace protocol
} // namespace remoting