• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "remoting/protocol/fake_authenticator.h"
6 
7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11 #include "net/socket/stream_socket.h"
12 #include "remoting/base/constants.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
15 
16 namespace remoting {
17 namespace protocol {
18 
FakeChannelAuthenticator(bool accept,bool async)19 FakeChannelAuthenticator::FakeChannelAuthenticator(bool accept, bool async)
20     : result_(accept ? net::OK : net::ERR_FAILED),
21       async_(async),
22       did_read_bytes_(false),
23       did_write_bytes_(false),
24       weak_factory_(this) {
25 }
26 
~FakeChannelAuthenticator()27 FakeChannelAuthenticator::~FakeChannelAuthenticator() {
28 }
29 
SecureAndAuthenticate(scoped_ptr<net::StreamSocket> socket,const DoneCallback & done_callback)30 void FakeChannelAuthenticator::SecureAndAuthenticate(
31     scoped_ptr<net::StreamSocket> socket,
32     const DoneCallback& done_callback) {
33   socket_ = socket.Pass();
34 
35   if (async_) {
36     done_callback_ = done_callback;
37 
38     if (result_ != net::OK) {
39       // Don't write anything if we are going to reject auth to make test
40       // ordering deterministic.
41       did_write_bytes_ = true;
42     } else {
43       scoped_refptr<net::IOBuffer> write_buf = new net::IOBuffer(1);
44       write_buf->data()[0] = 0;
45       int result = socket_->Write(
46           write_buf.get(), 1,
47           base::Bind(&FakeChannelAuthenticator::OnAuthBytesWritten,
48                      weak_factory_.GetWeakPtr()));
49       if (result != net::ERR_IO_PENDING) {
50         // This will not call the callback because |did_read_bytes_| is
51         // still set to false.
52         OnAuthBytesWritten(result);
53       }
54     }
55 
56     scoped_refptr<net::IOBuffer> read_buf = new net::IOBuffer(1);
57     int result =
58         socket_->Read(read_buf.get(), 1,
59                       base::Bind(&FakeChannelAuthenticator::OnAuthBytesRead,
60                                  weak_factory_.GetWeakPtr()));
61     if (result != net::ERR_IO_PENDING)
62       OnAuthBytesRead(result);
63   } else {
64     CallDoneCallback();
65   }
66 }
67 
OnAuthBytesWritten(int result)68 void FakeChannelAuthenticator::OnAuthBytesWritten(int result) {
69   EXPECT_EQ(1, result);
70   EXPECT_FALSE(did_write_bytes_);
71   did_write_bytes_ = true;
72   if (did_read_bytes_)
73     CallDoneCallback();
74 }
75 
OnAuthBytesRead(int result)76 void FakeChannelAuthenticator::OnAuthBytesRead(int result) {
77   EXPECT_EQ(1, result);
78   EXPECT_FALSE(did_read_bytes_);
79   did_read_bytes_ = true;
80   if (did_write_bytes_)
81     CallDoneCallback();
82 }
83 
CallDoneCallback()84 void FakeChannelAuthenticator::CallDoneCallback() {
85   DoneCallback callback = done_callback_;
86   done_callback_.Reset();
87   if (result_ != net::OK)
88     socket_.reset();
89   callback.Run(result_, socket_.Pass());
90 }
91 
FakeAuthenticator(Type type,int round_trips,Action action,bool async)92 FakeAuthenticator::FakeAuthenticator(
93     Type type, int round_trips, Action action, bool async)
94     : type_(type),
95       round_trips_(round_trips),
96       action_(action),
97       async_(async),
98       messages_(0),
99       messages_till_started_(0) {
100 }
101 
~FakeAuthenticator()102 FakeAuthenticator::~FakeAuthenticator() {
103 }
104 
set_messages_till_started(int messages)105 void FakeAuthenticator::set_messages_till_started(int messages) {
106   messages_till_started_ = messages;
107 }
108 
state() const109 Authenticator::State FakeAuthenticator::state() const {
110   EXPECT_LE(messages_, round_trips_ * 2);
111   if (messages_ >= round_trips_ * 2) {
112     if (action_ == REJECT) {
113       return REJECTED;
114     } else {
115       return ACCEPTED;
116     }
117   }
118 
119   // Don't send the last message if this is a host that wants to
120   // reject a connection.
121   if (messages_ == round_trips_ * 2 - 1 &&
122       type_ == HOST && action_ == REJECT) {
123     return REJECTED;
124   }
125 
126   // We are not done yet. process next message.
127   if ((messages_ % 2 == 0 && type_ == CLIENT) ||
128       (messages_ % 2 == 1 && type_ == HOST)) {
129     return MESSAGE_READY;
130   } else {
131     return WAITING_MESSAGE;
132   }
133 }
134 
started() const135 bool FakeAuthenticator::started() const {
136   return messages_ > messages_till_started_;
137 }
138 
rejection_reason() const139 Authenticator::RejectionReason FakeAuthenticator::rejection_reason() const {
140   EXPECT_EQ(REJECTED, state());
141   return INVALID_CREDENTIALS;
142 }
143 
ProcessMessage(const buzz::XmlElement * message,const base::Closure & resume_callback)144 void FakeAuthenticator::ProcessMessage(const buzz::XmlElement* message,
145                                        const base::Closure& resume_callback) {
146   EXPECT_EQ(WAITING_MESSAGE, state());
147   std::string id =
148       message->TextNamed(buzz::QName(kChromotingXmlNamespace, "id"));
149   EXPECT_EQ(id, base::IntToString(messages_));
150   ++messages_;
151   resume_callback.Run();
152 }
153 
GetNextMessage()154 scoped_ptr<buzz::XmlElement> FakeAuthenticator::GetNextMessage() {
155   EXPECT_EQ(MESSAGE_READY, state());
156 
157   scoped_ptr<buzz::XmlElement> result(new buzz::XmlElement(
158       buzz::QName(kChromotingXmlNamespace, "authentication")));
159   buzz::XmlElement* id = new buzz::XmlElement(
160       buzz::QName(kChromotingXmlNamespace, "id"));
161   id->AddText(base::IntToString(messages_));
162   result->AddElement(id);
163 
164   ++messages_;
165   return result.Pass();
166 }
167 
168 scoped_ptr<ChannelAuthenticator>
CreateChannelAuthenticator() const169 FakeAuthenticator::CreateChannelAuthenticator() const {
170   EXPECT_EQ(ACCEPTED, state());
171   return scoped_ptr<ChannelAuthenticator>(
172       new FakeChannelAuthenticator(action_ != REJECT_CHANNEL, async_));
173 }
174 
FakeHostAuthenticatorFactory(int round_trips,int messages_till_started,FakeAuthenticator::Action action,bool async)175 FakeHostAuthenticatorFactory::FakeHostAuthenticatorFactory(
176     int round_trips, int messages_till_started,
177     FakeAuthenticator::Action action, bool async)
178     : round_trips_(round_trips),
179       messages_till_started_(messages_till_started),
180       action_(action), async_(async) {
181 }
182 
~FakeHostAuthenticatorFactory()183 FakeHostAuthenticatorFactory::~FakeHostAuthenticatorFactory() {
184 }
185 
CreateAuthenticator(const std::string & local_jid,const std::string & remote_jid,const buzz::XmlElement * first_message)186 scoped_ptr<Authenticator> FakeHostAuthenticatorFactory::CreateAuthenticator(
187     const std::string& local_jid,
188     const std::string& remote_jid,
189     const buzz::XmlElement* first_message) {
190   FakeAuthenticator* authenticator = new FakeAuthenticator(
191       FakeAuthenticator::HOST, round_trips_, action_, async_);
192   authenticator->set_messages_till_started(messages_till_started_);
193 
194   scoped_ptr<Authenticator> result(authenticator);
195   return result.Pass();
196 }
197 
198 }  // namespace protocol
199 }  // namespace remoting
200