OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <iostream> | |
12 #include <memory> | |
13 #include <sstream> | |
14 #include <string> | |
15 | |
16 #include "webrtc/libjingle/xmllite/xmlelement.h" | |
17 #include "webrtc/libjingle/xmpp/constants.h" | |
18 #include "webrtc/libjingle/xmpp/plainsaslhandler.h" | |
19 #include "webrtc/libjingle/xmpp/saslplainmechanism.h" | |
20 #include "webrtc/libjingle/xmpp/util_unittest.h" | |
21 #include "webrtc/libjingle/xmpp/xmppengine.h" | |
22 #include "webrtc/base/common.h" | |
23 #include "webrtc/base/cryptstring.h" | |
24 #include "webrtc/base/gunit.h" | |
25 #include "webrtc/typedefs.h" | |
26 | |
27 using buzz::Jid; | |
28 using buzz::QName; | |
29 using buzz::XmlElement; | |
30 using buzz::XmppEngine; | |
31 using buzz::XmppTestHandler; | |
32 | |
33 enum XlttStage { | |
34 XLTT_STAGE_CONNECT = 0, | |
35 XLTT_STAGE_STREAMSTART, | |
36 XLTT_STAGE_TLS_FEATURES, | |
37 XLTT_STAGE_TLS_PROCEED, | |
38 XLTT_STAGE_ENCRYPTED_START, | |
39 XLTT_STAGE_AUTH_FEATURES, | |
40 XLTT_STAGE_AUTH_SUCCESS, | |
41 XLTT_STAGE_AUTHENTICATED_START, | |
42 XLTT_STAGE_BIND_FEATURES, | |
43 XLTT_STAGE_BIND_SUCCESS, | |
44 XLTT_STAGE_SESSION_SUCCESS, | |
45 }; | |
46 | |
47 class XmppLoginTaskTest : public testing::Test { | |
48 public: | |
49 XmppEngine* engine() { return engine_.get(); } | |
50 XmppTestHandler* handler() { return handler_.get(); } | |
51 virtual void SetUp() { | |
52 engine_.reset(XmppEngine::Create()); | |
53 handler_.reset(new XmppTestHandler(engine_.get())); | |
54 | |
55 Jid jid("david@my-server"); | |
56 rtc::InsecureCryptStringImpl pass; | |
57 pass.password() = "david"; | |
58 engine_->SetSessionHandler(handler_.get()); | |
59 engine_->SetOutputHandler(handler_.get()); | |
60 engine_->AddStanzaHandler(handler_.get()); | |
61 engine_->SetUser(jid); | |
62 engine_->SetSaslHandler( | |
63 new buzz::PlainSaslHandler(jid, rtc::CryptString(pass), true)); | |
64 } | |
65 virtual void TearDown() { | |
66 handler_.reset(); | |
67 engine_.reset(); | |
68 } | |
69 void RunPartialLogin(XlttStage startstage, XlttStage endstage); | |
70 void SetTlsOptions(buzz::TlsOptions option); | |
71 | |
72 private: | |
73 std::unique_ptr<XmppEngine> engine_; | |
74 std::unique_ptr<XmppTestHandler> handler_; | |
75 }; | |
76 | |
77 void XmppLoginTaskTest::SetTlsOptions(buzz::TlsOptions option) { | |
78 engine_->SetTls(option); | |
79 } | |
80 void XmppLoginTaskTest::RunPartialLogin(XlttStage startstage, | |
81 XlttStage endstage) { | |
82 std::string input; | |
83 | |
84 switch (startstage) { | |
85 case XLTT_STAGE_CONNECT: { | |
86 engine_->Connect(); | |
87 XmlElement appStanza(QName("test", "app-stanza")); | |
88 appStanza.AddText("this-is-a-test"); | |
89 engine_->SendStanza(&appStanza); | |
90 | |
91 EXPECT_EQ("<stream:stream to=\"my-server\" xml:lang=\"*\" " | |
92 "version=\"1.0\" xmlns:stream=\"http://etherx.jabber.org/streams\" " | |
93 "xmlns=\"jabber:client\">\r\n", handler_->OutputActivity()); | |
94 EXPECT_EQ("[OPENING]", handler_->SessionActivity()); | |
95 EXPECT_EQ("", handler_->StanzaActivity()); | |
96 if (endstage == XLTT_STAGE_CONNECT) | |
97 return; | |
98 FALLTHROUGH(); | |
99 } | |
100 | |
101 case XLTT_STAGE_STREAMSTART: { | |
102 input = "<stream:stream id=\"a5f2d8c9\" version=\"1.0\" " | |
103 "xmlns:stream=\"http://etherx.jabber.org/streams\" " | |
104 "xmlns=\"jabber:client\">"; | |
105 engine_->HandleInput(input.c_str(), input.length()); | |
106 EXPECT_EQ("", handler_->StanzaActivity()); | |
107 EXPECT_EQ("", handler_->SessionActivity()); | |
108 EXPECT_EQ("", handler_->OutputActivity()); | |
109 if (endstage == XLTT_STAGE_STREAMSTART) | |
110 return; | |
111 FALLTHROUGH(); | |
112 } | |
113 | |
114 case XLTT_STAGE_TLS_FEATURES: { | |
115 input = "<stream:features>" | |
116 "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>" | |
117 "</stream:features>"; | |
118 engine_->HandleInput(input.c_str(), input.length()); | |
119 EXPECT_EQ("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>", | |
120 handler_->OutputActivity()); | |
121 EXPECT_EQ("", handler_->StanzaActivity()); | |
122 EXPECT_EQ("", handler_->SessionActivity()); | |
123 if (endstage == XLTT_STAGE_TLS_FEATURES) | |
124 return; | |
125 FALLTHROUGH(); | |
126 } | |
127 | |
128 case XLTT_STAGE_TLS_PROCEED: { | |
129 input = std::string("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); | |
130 engine_->HandleInput(input.c_str(), input.length()); | |
131 EXPECT_EQ("[START-TLS my-server]" | |
132 "<stream:stream to=\"my-server\" xml:lang=\"*\" " | |
133 "version=\"1.0\" xmlns:stream=\"http://etherx.jabber.org/streams\" " | |
134 "xmlns=\"jabber:client\">\r\n", handler_->OutputActivity()); | |
135 EXPECT_EQ("", handler_->StanzaActivity()); | |
136 EXPECT_EQ("", handler_->SessionActivity()); | |
137 if (endstage == XLTT_STAGE_TLS_PROCEED) | |
138 return; | |
139 FALLTHROUGH(); | |
140 } | |
141 | |
142 case XLTT_STAGE_ENCRYPTED_START: { | |
143 input = std::string("<stream:stream id=\"01234567\" version=\"1.0\" " | |
144 "xmlns:stream=\"http://etherx.jabber.org/streams\" " | |
145 "xmlns=\"jabber:client\">"); | |
146 engine_->HandleInput(input.c_str(), input.length()); | |
147 EXPECT_EQ("", handler_->StanzaActivity()); | |
148 EXPECT_EQ("", handler_->SessionActivity()); | |
149 EXPECT_EQ("", handler_->OutputActivity()); | |
150 if (endstage == XLTT_STAGE_ENCRYPTED_START) | |
151 return; | |
152 FALLTHROUGH(); | |
153 } | |
154 | |
155 case XLTT_STAGE_AUTH_FEATURES: { | |
156 input = "<stream:features>" | |
157 "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | |
158 "<mechanism>DIGEST-MD5</mechanism>" | |
159 "<mechanism>PLAIN</mechanism>" | |
160 "</mechanisms>" | |
161 "</stream:features>"; | |
162 engine_->HandleInput(input.c_str(), input.length()); | |
163 EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" " | |
164 "mechanism=\"PLAIN\" " | |
165 "auth:allow-non-google-login=\"true\" " | |
166 "auth:client-uses-full-bind-result=\"true\" " | |
167 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\"" | |
168 ">AGRhdmlkAGRhdmlk</auth>", | |
169 handler_->OutputActivity()); | |
170 EXPECT_EQ("", handler_->StanzaActivity()); | |
171 EXPECT_EQ("", handler_->SessionActivity()); | |
172 if (endstage == XLTT_STAGE_AUTH_FEATURES) | |
173 return; | |
174 FALLTHROUGH(); | |
175 } | |
176 | |
177 case XLTT_STAGE_AUTH_SUCCESS: { | |
178 input = "<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"; | |
179 engine_->HandleInput(input.c_str(), input.length()); | |
180 EXPECT_EQ("<stream:stream to=\"my-server\" xml:lang=\"*\" " | |
181 "version=\"1.0\" xmlns:stream=\"http://etherx.jabber.org/streams\" " | |
182 "xmlns=\"jabber:client\">\r\n", handler_->OutputActivity()); | |
183 EXPECT_EQ("", handler_->StanzaActivity()); | |
184 EXPECT_EQ("", handler_->SessionActivity()); | |
185 if (endstage == XLTT_STAGE_AUTH_SUCCESS) | |
186 return; | |
187 FALLTHROUGH(); | |
188 } | |
189 | |
190 case XLTT_STAGE_AUTHENTICATED_START: { | |
191 input = std::string("<stream:stream id=\"01234567\" version=\"1.0\" " | |
192 "xmlns:stream=\"http://etherx.jabber.org/streams\" " | |
193 "xmlns=\"jabber:client\">"); | |
194 engine_->HandleInput(input.c_str(), input.length()); | |
195 EXPECT_EQ("", handler_->StanzaActivity()); | |
196 EXPECT_EQ("", handler_->SessionActivity()); | |
197 EXPECT_EQ("", handler_->OutputActivity()); | |
198 if (endstage == XLTT_STAGE_AUTHENTICATED_START) | |
199 return; | |
200 FALLTHROUGH(); | |
201 } | |
202 | |
203 case XLTT_STAGE_BIND_FEATURES: { | |
204 input = "<stream:features>" | |
205 "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>" | |
206 "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>" | |
207 "</stream:features>"; | |
208 engine_->HandleInput(input.c_str(), input.length()); | |
209 EXPECT_EQ("<iq type=\"set\" id=\"0\">" | |
210 "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/></iq>", | |
211 handler_->OutputActivity()); | |
212 EXPECT_EQ("", handler_->StanzaActivity()); | |
213 EXPECT_EQ("", handler_->SessionActivity()); | |
214 if (endstage == XLTT_STAGE_BIND_FEATURES) | |
215 return; | |
216 FALLTHROUGH(); | |
217 } | |
218 | |
219 case XLTT_STAGE_BIND_SUCCESS: { | |
220 input = "<iq type='result' id='0'>" | |
221 "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>" | |
222 "<jid>david@my-server/test</jid></bind></iq>"; | |
223 engine_->HandleInput(input.c_str(), input.length()); | |
224 EXPECT_EQ("<iq type=\"set\" id=\"1\">" | |
225 "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/></iq>", | |
226 handler_->OutputActivity()); | |
227 EXPECT_EQ("", handler_->StanzaActivity()); | |
228 EXPECT_EQ("", handler_->SessionActivity()); | |
229 if (endstage == XLTT_STAGE_BIND_SUCCESS) | |
230 return; | |
231 FALLTHROUGH(); | |
232 } | |
233 | |
234 case XLTT_STAGE_SESSION_SUCCESS: { | |
235 input = "<iq type='result' id='1'/>"; | |
236 engine_->HandleInput(input.c_str(), input.length()); | |
237 EXPECT_EQ("<test:app-stanza xmlns:test=\"test\">this-is-a-test" | |
238 "</test:app-stanza>", handler_->OutputActivity()); | |
239 EXPECT_EQ("[OPEN]", handler_->SessionActivity()); | |
240 EXPECT_EQ("", handler_->StanzaActivity()); | |
241 if (endstage == XLTT_STAGE_SESSION_SUCCESS) | |
242 return; | |
243 FALLTHROUGH(); | |
244 } | |
245 default: | |
246 break; | |
247 } | |
248 } | |
249 | |
250 TEST_F(XmppLoginTaskTest, TestUtf8Good) { | |
251 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_CONNECT); | |
252 | |
253 std::string input = "<?xml version='1.0' encoding='UTF-8'?>" | |
254 "<stream:stream id=\"a5f2d8c9\" version=\"1.0\" " | |
255 "xmlns:stream=\"http://etherx.jabber.org/streams\" " | |
256 "xmlns=\"jabber:client\">"; | |
257 engine()->HandleInput(input.c_str(), input.length()); | |
258 EXPECT_EQ("", handler()->OutputActivity()); | |
259 EXPECT_EQ("", handler()->SessionActivity()); | |
260 EXPECT_EQ("", handler()->StanzaActivity()); | |
261 } | |
262 | |
263 TEST_F(XmppLoginTaskTest, TestNonUtf8Bad) { | |
264 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_CONNECT); | |
265 | |
266 std::string input = "<?xml version='1.0' encoding='ISO-8859-1'?>" | |
267 "<stream:stream id=\"a5f2d8c9\" version=\"1.0\" " | |
268 "xmlns:stream=\"http://etherx.jabber.org/streams\" " | |
269 "xmlns=\"jabber:client\">"; | |
270 engine()->HandleInput(input.c_str(), input.length()); | |
271 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
272 EXPECT_EQ("[CLOSED][ERROR-XML]", handler()->SessionActivity()); | |
273 EXPECT_EQ("", handler()->StanzaActivity()); | |
274 } | |
275 | |
276 TEST_F(XmppLoginTaskTest, TestNoFeatures) { | |
277 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART); | |
278 | |
279 std::string input = "<iq type='get' id='1'/>"; | |
280 engine()->HandleInput(input.c_str(), input.length()); | |
281 | |
282 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
283 EXPECT_EQ("[CLOSED][ERROR-VERSION]", handler()->SessionActivity()); | |
284 EXPECT_EQ("", handler()->StanzaActivity()); | |
285 } | |
286 | |
287 TEST_F(XmppLoginTaskTest, TestTlsRequiredNotPresent) { | |
288 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART); | |
289 | |
290 std::string input = "<stream:features>" | |
291 "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | |
292 "<mechanism>DIGEST-MD5</mechanism>" | |
293 "<mechanism>PLAIN</mechanism>" | |
294 "</mechanisms>" | |
295 "</stream:features>"; | |
296 engine()->HandleInput(input.c_str(), input.length()); | |
297 | |
298 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
299 EXPECT_EQ("[CLOSED][ERROR-TLS]", handler()->SessionActivity()); | |
300 EXPECT_EQ("", handler()->StanzaActivity()); | |
301 } | |
302 | |
303 TEST_F(XmppLoginTaskTest, TestTlsRequeiredAndPresent) { | |
304 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART); | |
305 | |
306 std::string input = "<stream:features>" | |
307 "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>" | |
308 "<required/>" | |
309 "</starttls>" | |
310 "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | |
311 "<mechanism>X-GOOGLE-TOKEN</mechanism>" | |
312 "<mechanism>PLAIN</mechanism>" | |
313 "<mechanism>X-OAUTH2</mechanism>" | |
314 "</mechanisms>" | |
315 "</stream:features>"; | |
316 engine()->HandleInput(input.c_str(), input.length()); | |
317 | |
318 EXPECT_EQ("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>", | |
319 handler()->OutputActivity()); | |
320 EXPECT_EQ("", handler()->SessionActivity()); | |
321 EXPECT_EQ("", handler()->StanzaActivity()); | |
322 } | |
323 | |
324 TEST_F(XmppLoginTaskTest, TestTlsEnabledNotPresent) { | |
325 SetTlsOptions(buzz::TLS_ENABLED); | |
326 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART); | |
327 | |
328 std::string input = "<stream:features>" | |
329 "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | |
330 "<mechanism>DIGEST-MD5</mechanism>" | |
331 "<mechanism>PLAIN</mechanism>" | |
332 "</mechanisms>" | |
333 "</stream:features>"; | |
334 engine()->HandleInput(input.c_str(), input.length()); | |
335 | |
336 EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" " | |
337 "mechanism=\"PLAIN\" auth:allow-non-google-login=\"true\" " | |
338 "auth:client-uses-full-bind-result=\"true\" " | |
339 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\"" | |
340 ">AGRhdmlkAGRhdmlk</auth>", handler()->OutputActivity()); | |
341 EXPECT_EQ("", handler()->SessionActivity()); | |
342 EXPECT_EQ("", handler()->StanzaActivity()); | |
343 } | |
344 | |
345 TEST_F(XmppLoginTaskTest, TestTlsEnabledAndPresent) { | |
346 SetTlsOptions(buzz::TLS_ENABLED); | |
347 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART); | |
348 | |
349 std::string input = "<stream:features>" | |
350 "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | |
351 "<mechanism>X-GOOGLE-TOKEN</mechanism>" | |
352 "<mechanism>PLAIN</mechanism>" | |
353 "<mechanism>X-OAUTH2</mechanism>" | |
354 "</mechanisms>" | |
355 "</stream:features>"; | |
356 engine()->HandleInput(input.c_str(), input.length()); | |
357 | |
358 EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" " | |
359 "mechanism=\"PLAIN\" auth:allow-non-google-login=\"true\" " | |
360 "auth:client-uses-full-bind-result=\"true\" " | |
361 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\"" | |
362 ">AGRhdmlkAGRhdmlk</auth>", handler()->OutputActivity()); | |
363 EXPECT_EQ("", handler()->SessionActivity()); | |
364 EXPECT_EQ("", handler()->StanzaActivity()); | |
365 } | |
366 | |
367 TEST_F(XmppLoginTaskTest, TestTlsDisabledNotPresent) { | |
368 SetTlsOptions(buzz::TLS_DISABLED); | |
369 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART); | |
370 | |
371 std::string input = "<stream:features>" | |
372 "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | |
373 "<mechanism>DIGEST-MD5</mechanism>" | |
374 "<mechanism>PLAIN</mechanism>" | |
375 "</mechanisms>" | |
376 "</stream:features>"; | |
377 engine()->HandleInput(input.c_str(), input.length()); | |
378 | |
379 EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" " | |
380 "mechanism=\"PLAIN\" auth:allow-non-google-login=\"true\" " | |
381 "auth:client-uses-full-bind-result=\"true\" " | |
382 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\"" | |
383 ">AGRhdmlkAGRhdmlk</auth>", handler()->OutputActivity()); | |
384 EXPECT_EQ("", handler()->SessionActivity()); | |
385 EXPECT_EQ("", handler()->StanzaActivity()); | |
386 } | |
387 | |
388 TEST_F(XmppLoginTaskTest, TestTlsDisabledAndPresent) { | |
389 SetTlsOptions(buzz::TLS_DISABLED); | |
390 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_STREAMSTART); | |
391 | |
392 std::string input = "<stream:features>" | |
393 "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | |
394 "<mechanism>X-GOOGLE-TOKEN</mechanism>" | |
395 "<mechanism>PLAIN</mechanism>" | |
396 "<mechanism>X-OAUTH2</mechanism>" | |
397 "</mechanisms>" | |
398 "</stream:features>"; | |
399 engine()->HandleInput(input.c_str(), input.length()); | |
400 | |
401 EXPECT_EQ("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" " | |
402 "mechanism=\"PLAIN\" auth:allow-non-google-login=\"true\" " | |
403 "auth:client-uses-full-bind-result=\"true\" " | |
404 "xmlns:auth=\"http://www.google.com/talk/protocol/auth\"" | |
405 ">AGRhdmlkAGRhdmlk</auth>", handler()->OutputActivity()); | |
406 EXPECT_EQ("", handler()->SessionActivity()); | |
407 EXPECT_EQ("", handler()->StanzaActivity()); | |
408 } | |
409 | |
410 TEST_F(XmppLoginTaskTest, TestTlsFailure) { | |
411 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_TLS_FEATURES); | |
412 | |
413 std::string input = "<failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"; | |
414 engine()->HandleInput(input.c_str(), input.length()); | |
415 | |
416 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
417 EXPECT_EQ("[CLOSED][ERROR-TLS]", handler()->SessionActivity()); | |
418 EXPECT_EQ("", handler()->StanzaActivity()); | |
419 } | |
420 | |
421 TEST_F(XmppLoginTaskTest, TestTlsBadStream) { | |
422 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_TLS_PROCEED); | |
423 | |
424 std::string input = "<wrongtag>"; | |
425 engine()->HandleInput(input.c_str(), input.length()); | |
426 | |
427 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
428 EXPECT_EQ("[CLOSED][ERROR-VERSION]", handler()->SessionActivity()); | |
429 EXPECT_EQ("", handler()->StanzaActivity()); | |
430 } | |
431 | |
432 TEST_F(XmppLoginTaskTest, TestMissingSaslPlain) { | |
433 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_ENCRYPTED_START); | |
434 | |
435 std::string input = "<stream:features>" | |
436 "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | |
437 "<mechanism>DIGEST-MD5</mechanism>" | |
438 "</mechanisms>" | |
439 "</stream:features>"; | |
440 engine()->HandleInput(input.c_str(), input.length()); | |
441 | |
442 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
443 EXPECT_EQ("[CLOSED][ERROR-AUTH]", handler()->SessionActivity()); | |
444 EXPECT_EQ("", handler()->StanzaActivity()); | |
445 } | |
446 | |
447 TEST_F(XmppLoginTaskTest, TestWrongPassword) { | |
448 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_AUTH_FEATURES); | |
449 | |
450 std::string input = "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"; | |
451 engine()->HandleInput(input.c_str(), input.length()); | |
452 | |
453 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
454 EXPECT_EQ("[CLOSED][ERROR-UNAUTHORIZED]", handler()->SessionActivity()); | |
455 EXPECT_EQ("", handler()->StanzaActivity()); | |
456 } | |
457 | |
458 TEST_F(XmppLoginTaskTest, TestAuthBadStream) { | |
459 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_AUTH_SUCCESS); | |
460 | |
461 std::string input = "<wrongtag>"; | |
462 engine()->HandleInput(input.c_str(), input.length()); | |
463 | |
464 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
465 EXPECT_EQ("[CLOSED][ERROR-VERSION]", handler()->SessionActivity()); | |
466 EXPECT_EQ("", handler()->StanzaActivity()); | |
467 } | |
468 | |
469 TEST_F(XmppLoginTaskTest, TestMissingBindFeature) { | |
470 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_AUTHENTICATED_START); | |
471 | |
472 std::string input = "<stream:features>" | |
473 "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>" | |
474 "</stream:features>"; | |
475 engine()->HandleInput(input.c_str(), input.length()); | |
476 | |
477 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
478 EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity()); | |
479 } | |
480 | |
481 TEST_F(XmppLoginTaskTest, TestMissingSessionFeature) { | |
482 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_AUTHENTICATED_START); | |
483 | |
484 std::string input = "<stream:features>" | |
485 "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>" | |
486 "</stream:features>"; | |
487 engine()->HandleInput(input.c_str(), input.length()); | |
488 | |
489 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
490 EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity()); | |
491 EXPECT_EQ("", handler()->StanzaActivity()); | |
492 } | |
493 | |
494 /* TODO: Handle this case properly inside XmppLoginTask. | |
495 TEST_F(XmppLoginTaskTest, TestBindFailure1) { | |
496 // check wrong JID | |
497 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_FEATURES); | |
498 | |
499 std::string input = "<iq type='result' id='0'>" | |
500 "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>" | |
501 "<jid>davey@my-server/test</jid></bind></iq>"; | |
502 engine()->HandleInput(input.c_str(), input.length()); | |
503 | |
504 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
505 EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity()); | |
506 EXPECT_EQ("", handler()->StanzaActivity()); | |
507 } | |
508 */ | |
509 | |
510 TEST_F(XmppLoginTaskTest, TestBindFailure2) { | |
511 // check missing JID | |
512 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_FEATURES); | |
513 | |
514 std::string input = "<iq type='result' id='0'>" | |
515 "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></iq>"; | |
516 engine()->HandleInput(input.c_str(), input.length()); | |
517 | |
518 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
519 EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity()); | |
520 EXPECT_EQ("", handler()->StanzaActivity()); | |
521 } | |
522 | |
523 TEST_F(XmppLoginTaskTest, TestBindFailure3) { | |
524 // check plain failure | |
525 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_FEATURES); | |
526 | |
527 std::string input = "<iq type='error' id='0'/>"; | |
528 engine()->HandleInput(input.c_str(), input.length()); | |
529 | |
530 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
531 EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity()); | |
532 EXPECT_EQ("", handler()->StanzaActivity()); | |
533 } | |
534 | |
535 TEST_F(XmppLoginTaskTest, TestBindFailure4) { | |
536 // check wrong id to ignore | |
537 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_FEATURES); | |
538 | |
539 std::string input = "<iq type='error' id='1'/>"; | |
540 engine()->HandleInput(input.c_str(), input.length()); | |
541 | |
542 // continue after an ignored iq | |
543 RunPartialLogin(XLTT_STAGE_BIND_SUCCESS, XLTT_STAGE_SESSION_SUCCESS); | |
544 } | |
545 | |
546 TEST_F(XmppLoginTaskTest, TestSessionFailurePlain1) { | |
547 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_SUCCESS); | |
548 | |
549 std::string input = "<iq type='error' id='1'/>"; | |
550 engine()->HandleInput(input.c_str(), input.length()); | |
551 | |
552 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
553 EXPECT_EQ("[CLOSED][ERROR-BIND]", handler()->SessionActivity()); | |
554 } | |
555 | |
556 TEST_F(XmppLoginTaskTest, TestSessionFailurePlain2) { | |
557 RunPartialLogin(XLTT_STAGE_CONNECT, XLTT_STAGE_BIND_SUCCESS); | |
558 | |
559 // check reverse iq to ignore | |
560 // TODO: consider queueing or passing through? | |
561 std::string input = "<iq type='get' id='1'/>"; | |
562 engine()->HandleInput(input.c_str(), input.length()); | |
563 | |
564 EXPECT_EQ("", handler()->OutputActivity()); | |
565 EXPECT_EQ("", handler()->SessionActivity()); | |
566 | |
567 // continue after an ignored iq | |
568 RunPartialLogin(XLTT_STAGE_SESSION_SUCCESS, XLTT_STAGE_SESSION_SUCCESS); | |
569 } | |
570 | |
571 TEST_F(XmppLoginTaskTest, TestBadXml) { | |
572 int errorKind = 0; | |
573 for (XlttStage stage = XLTT_STAGE_CONNECT; | |
574 stage <= XLTT_STAGE_SESSION_SUCCESS; | |
575 stage = static_cast<XlttStage>(stage + 1)) { | |
576 RunPartialLogin(XLTT_STAGE_CONNECT, stage); | |
577 | |
578 std::string input; | |
579 switch (errorKind++ % 5) { | |
580 case 0: input = "&syntax;"; break; | |
581 case 1: input = "<nons:iq/>"; break; | |
582 case 2: input = "<iq a='b' a='dupe'/>"; break; | |
583 case 3: input = "<>"; break; | |
584 case 4: input = "<iq a='<wrong>'>"; break; | |
585 } | |
586 | |
587 engine()->HandleInput(input.c_str(), input.length()); | |
588 | |
589 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
590 EXPECT_EQ("[CLOSED][ERROR-XML]", handler()->SessionActivity()); | |
591 | |
592 TearDown(); | |
593 SetUp(); | |
594 } | |
595 } | |
596 | |
597 TEST_F(XmppLoginTaskTest, TestStreamError) { | |
598 for (XlttStage stage = XLTT_STAGE_CONNECT; | |
599 stage <= XLTT_STAGE_SESSION_SUCCESS; | |
600 stage = static_cast<XlttStage>(stage + 1)) { | |
601 switch (stage) { | |
602 case XLTT_STAGE_CONNECT: | |
603 case XLTT_STAGE_TLS_PROCEED: | |
604 case XLTT_STAGE_AUTH_SUCCESS: | |
605 continue; | |
606 default: | |
607 break; | |
608 } | |
609 | |
610 RunPartialLogin(XLTT_STAGE_CONNECT, stage); | |
611 | |
612 std::string input = "<stream:error>" | |
613 "<xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>" | |
614 "<text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>" | |
615 "Some special application diagnostic information!" | |
616 "</text>" | |
617 "<escape-your-data xmlns='application-ns'/>" | |
618 "</stream:error>"; | |
619 | |
620 engine()->HandleInput(input.c_str(), input.length()); | |
621 | |
622 EXPECT_EQ("[CLOSED]", handler()->OutputActivity()); | |
623 EXPECT_EQ("[CLOSED][ERROR-STREAM]", handler()->SessionActivity()); | |
624 | |
625 EXPECT_EQ("<str:error xmlns:str=\"http://etherx.jabber.org/streams\">" | |
626 "<xml-not-well-formed xmlns=\"urn:ietf:params:xml:ns:xmpp-streams\"/>" | |
627 "<text xml:lang=\"en\" xmlns=\"urn:ietf:params:xml:ns:xmpp-streams\">" | |
628 "Some special application diagnostic information!" | |
629 "</text>" | |
630 "<escape-your-data xmlns=\"application-ns\"/>" | |
631 "</str:error>", engine()->GetStreamError()->Str()); | |
632 | |
633 TearDown(); | |
634 SetUp(); | |
635 } | |
636 } | |
637 | |
OLD | NEW |