Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: remoting/signaling/xmpp_login_handler.cc

Issue 958703003: Remove dependency on XMPP implementation in WebRTC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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/signaling/xmpp_login_handler.h"
6
7 #include <set>
8
9 #include "base/base64.h"
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "remoting/signaling/xmpp_stream_parser.h"
13 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
14
15 namespace remoting {
16
17 buzz::StaticQName kXmppIqName = {"jabber:client", "iq"};
18
19 char kXmppBindNs[] = "urn:ietf:params:xml:ns:xmpp-bind";
20 buzz::StaticQName kXmppBindName = {kXmppBindNs, "bind"};
21 buzz::StaticQName kXmppJidName = {kXmppBindNs, "jid"};
22
23 buzz::StaticQName kJabberFeaturesName = {"http://etherx.jabber.org/streams",
24 "features"};
25
26 char kXmppTlsNs[] = "urn:ietf:params:xml:ns:xmpp-tls";
27 buzz::StaticQName kStartTlsName = {kXmppTlsNs, "starttls"};
28 buzz::StaticQName kTlsProceedName = {kXmppTlsNs, "proceed"};
29
30 char kXmppSaslNs[] = "urn:ietf:params:xml:ns:xmpp-sasl";
31 buzz::StaticQName kSaslMechanismsName = {kXmppSaslNs, "mechanisms"};
32 buzz::StaticQName kSaslMechanismName = {kXmppSaslNs, "mechanism"};
33 buzz::StaticQName kSaslSuccessName = {kXmppSaslNs, "success"};
34
35 XmppLoginHandler::XmppLoginHandler(const std::string& server,
36 const std::string& username,
37 const std::string& auth_token,
38 const std::string& auth_service,
39 bool need_handshake_before_tls,
40 Delegate* delegate)
41 : server_(server),
42 username_(username),
43 auth_token_(auth_token),
44 auth_service_(auth_service),
45 auth_mechanism_((auth_service == "oauth2") ? "X-OAUTH2"
rmsousa 2015/02/28 06:33:29 nit: if this is for client login, it can be remove
Sergey Ulanov 2015/03/02 18:11:09 Done.
46 : "X-GOOGLE-TOKEN"),
47 need_handshake_before_tls_(need_handshake_before_tls),
48 delegate_(delegate),
49 state_(State::INIT) {
50 }
51
52 XmppLoginHandler::~XmppLoginHandler() {
53 }
54
55 void XmppLoginHandler::Start() {
56 if (need_handshake_before_tls_) {
57 state_ = State::WAIT_STREAM_HEADER;
58 StartStream("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
59 } else {
60 // If <starttls> handshake is not required then start TLS right away.
61 state_ = State::STARTING_TLS;
62 delegate_->StartTls();
63 }
64 }
65
66 void XmppLoginHandler::OnDataReceived(const std::string& data) {
67 DCHECK(state_ != State::INIT && state_ != State::DONE &&
68 state_ != State::ERROR);
69 stream_parser_->AppendData(data);
70 }
71
72 void XmppLoginHandler::OnStanza(scoped_ptr<buzz::XmlElement> stanza) {
73 switch (state_) {
74 case State::WAIT_STREAM_HEADER: {
75 if (stanza->Name() == kJabberFeaturesName &&
76 stanza->FirstNamed(kStartTlsName) != nullptr) {
77 state_ = State::WAIT_STARTTLS_RESPONSE;
78 } else {
79 LOG(ERROR) << "Server doesn't support TLS.";
80 OnError(SignalStrategy::PROTOCOL_ERROR);
81 }
82 break;
83 }
84
85 case State::WAIT_STARTTLS_RESPONSE: {
86 if (stanza->Name() == kTlsProceedName) {
87 state_ = State::STARTING_TLS;
88 delegate_->StartTls();
89 } else {
90 LOG(ERROR) << "Failed to start TLS: " << stanza->Str();
91 OnError(SignalStrategy::PROTOCOL_ERROR);
92 }
93 break;
94 }
95
96 case State::WAIT_STREAM_HEADER_AFTER_TLS: {
97 buzz::XmlElement* mechanisms_element =
98 stanza->FirstNamed(kSaslMechanismsName);
99 std::set<std::string> mechanisms;
100 if (mechanisms_element) {
101 for (buzz::XmlElement* element =
102 mechanisms_element->FirstNamed(kSaslMechanismName);
103 element; element = element->NextNamed(kSaslMechanismName)) {
104 mechanisms.insert(element->BodyText());
105 }
106 }
107
108 if (mechanisms.find(auth_mechanism_) == mechanisms.end()) {
109 LOG(ERROR) << auth_mechanism_
110 << " auth mechanism is not supported by the server.";
111 OnError(SignalStrategy::PROTOCOL_ERROR);
112 return;
113 }
114
115 state_ = State::WAIT_AUTH_RESULT;
116 break;
117 }
118
119 case State::WAIT_AUTH_RESULT: {
120 if (stanza->Name() == kSaslSuccessName) {
121 state_ = State::WAIT_STREAM_HEADER_AFTER_AUTH;
122 StartStream(
123 "<iq type=\"set\" id=\"0\">"
124 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
125 "<resource>chromoting</resource>"
126 "</bind>"
127 "</iq>"
128 "<iq type=\"set\" id=\"1\">"
129 "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
130 "</iq>");
131 } else {
132 OnError(SignalStrategy::AUTHENTICATION_FAILED);
133 }
134 break;
135 }
136
137 case State::WAIT_STREAM_HEADER_AFTER_AUTH:
138 if (stanza->Name() == kJabberFeaturesName &&
139 stanza->FirstNamed(kXmppBindName) != nullptr) {
140 state_ = State::WAIT_BIND_RESULT;
141 } else {
142 LOG(ERROR) << "Server doesn't support bind after authentication.";
143 OnError(SignalStrategy::PROTOCOL_ERROR);
144 }
145 break;
146
147 case State::WAIT_BIND_RESULT: {
148 buzz::XmlElement* bind = stanza->FirstNamed(kXmppBindName);
149 buzz::XmlElement* jid = bind ? bind->FirstNamed(kXmppJidName) : nullptr;
150 if (stanza->Attr(buzz::QName("", "id")) != "0" ||
151 stanza->Attr(buzz::QName("", "type")) != "result" || !jid) {
152 LOG(ERROR) << "Received unexpected response to bind: " << stanza->Str();
153 OnError(SignalStrategy::PROTOCOL_ERROR);
154 return;
155 }
156 jid_ = jid->BodyText();
157 state_ = State::WAIT_SESSION_IQ_RESULT;
158 break;
159 }
160
161 case State::WAIT_SESSION_IQ_RESULT:
162 if (stanza->Name() != kXmppIqName ||
163 stanza->Attr(buzz::QName("", "id")) != "1" ||
164 stanza->Attr(buzz::QName("", "type")) != "result") {
165 LOG(ERROR) << "Failed to start session: " << stanza->Str();
166 OnError(SignalStrategy::PROTOCOL_ERROR);
167 return;
168 }
169 state_ = State::DONE;
170 delegate_->OnHandshakeDone(jid_, stream_parser_.Pass());
171 break;
172
173 default:
174 NOTREACHED();
175 break;
176 }
177 }
178
179 void XmppLoginHandler::OnTlsStarted() {
180 DCHECK(state_ == State::STARTING_TLS);
181 state_ = State::WAIT_STREAM_HEADER_AFTER_TLS;
182
183 std::string cookie;
184 base::Base64Encode(
185 std::string("\0", 1) + username_ + std::string("\0", 1) + auth_token_,
186 &cookie);
187 StartStream(
188 "<auth xmlns=\"" + std::string(kXmppSaslNs) + "\" "
189 "mechanism=\"" + auth_mechanism_+ "\" "
190 "auth:service=\"" + auth_service_ + "\" "
191 "auth:allow-generated-jid=\"true\" "
192 "auth:client-uses-full-bind-result=\"true\" "
193 "auth:allow-non-google-login=\"true\" "
194 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">" +
195 cookie +
196 "</auth>");
197 };
198
199 void XmppLoginHandler::OnParserError() {
200 OnError(SignalStrategy::PROTOCOL_ERROR);
201 }
202
203 void XmppLoginHandler::StartStream(const std::string& first_message) {
204 delegate_->SendMessage("<stream:stream to=\"" + server_ +
205 "\" version=\"1.0\" xmlns=\"jabber:client\" "
206 "xmlns:stream=\"http://etherx.jabber.org/streams\">" +
207 first_message);
208 stream_parser_.reset(new XmppStreamParser());
209 stream_parser_->SetCallbacks(
210 base::Bind(&XmppLoginHandler::OnStanza, base::Unretained(this)),
211 base::Bind(&XmppLoginHandler::OnParserError, base::Unretained(this)));
212 }
213
214 void XmppLoginHandler::OnError(SignalStrategy::Error error) {
215 if (state_ != State::ERROR) {
216 state_ = State::ERROR;
217 delegate_->OnLoginHandlerError(error);
218 }
219 }
220
221 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698