blob: 8d09e0f9bdc77fff7d564f38500203097df59cf3 [file] [log] [blame]
deadbeef49f34fd2016-12-06 16:22:06 -08001/*
2 * Copyright 2011 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 <memory>
12
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "p2p/base/fakedtlstransport.h"
14#include "p2p/base/fakeicetransport.h"
15#include "rtc_base/fakesslidentity.h"
16#include "rtc_base/gunit.h"
17#include "rtc_base/network.h"
deadbeef49f34fd2016-12-06 16:22:06 -080018
19using cricket::JsepTransport;
zhihuangb2cdd932017-01-19 16:54:25 -080020using cricket::FakeDtlsTransport;
21using cricket::FakeIceTransport;
deadbeef49f34fd2016-12-06 16:22:06 -080022using cricket::IceRole;
23using cricket::TransportDescription;
24using rtc::SocketAddress;
25
26static const char kIceUfrag1[] = "TESTICEUFRAG0001";
27static const char kIcePwd1[] = "TESTICEPWD00000000000001";
28
29static const char kIceUfrag2[] = "TESTICEUFRAG0002";
30static const char kIcePwd2[] = "TESTICEPWD00000000000002";
31
32class JsepTransportTest : public testing::Test, public sigslot::has_slots<> {
33 public:
deadbeefd8cfa1a2017-03-27 10:33:26 -070034 JsepTransportTest() { RecreateTransport(); }
35
deadbeef49f34fd2016-12-06 16:22:06 -080036 bool SetupChannel() {
deadbeeff5346592017-01-24 21:51:21 -080037 fake_ice_transport_.reset(new FakeIceTransport(transport_->mid(), 1));
38 fake_dtls_transport_.reset(
39 new FakeDtlsTransport(fake_ice_transport_.get()));
zhihuangb2cdd932017-01-19 16:54:25 -080040 return transport_->AddChannel(fake_dtls_transport_.get(), 1);
deadbeef49f34fd2016-12-06 16:22:06 -080041 }
deadbeefd8cfa1a2017-03-27 10:33:26 -070042
deadbeef49f34fd2016-12-06 16:22:06 -080043 void DestroyChannel() { transport_->RemoveChannel(1); }
44
deadbeefd8cfa1a2017-03-27 10:33:26 -070045 void RecreateTransport() {
46 transport_.reset(new JsepTransport("test content name", nullptr));
47 }
48
deadbeef49f34fd2016-12-06 16:22:06 -080049 protected:
zhihuangb2cdd932017-01-19 16:54:25 -080050 std::unique_ptr<FakeDtlsTransport> fake_dtls_transport_;
deadbeeff5346592017-01-24 21:51:21 -080051 std::unique_ptr<FakeIceTransport> fake_ice_transport_;
deadbeef49f34fd2016-12-06 16:22:06 -080052 std::unique_ptr<JsepTransport> transport_;
53};
54
55// This test verifies channels are created with proper ICE
56// ufrag/password after a transport description is applied.
57TEST_F(JsepTransportTest, TestChannelIceParameters) {
58 cricket::TransportDescription local_desc(kIceUfrag1, kIcePwd1);
59 ASSERT_TRUE(transport_->SetLocalTransportDescription(
60 local_desc, cricket::CA_OFFER, NULL));
61 EXPECT_TRUE(SetupChannel());
deadbeeff5346592017-01-24 21:51:21 -080062 EXPECT_EQ(cricket::ICEMODE_FULL, fake_ice_transport_->remote_ice_mode());
63 EXPECT_EQ(kIceUfrag1, fake_ice_transport_->ice_ufrag());
64 EXPECT_EQ(kIcePwd1, fake_ice_transport_->ice_pwd());
deadbeef49f34fd2016-12-06 16:22:06 -080065
66 cricket::TransportDescription remote_desc(kIceUfrag1, kIcePwd1);
67 ASSERT_TRUE(transport_->SetRemoteTransportDescription(
68 remote_desc, cricket::CA_ANSWER, NULL));
deadbeeff5346592017-01-24 21:51:21 -080069 EXPECT_EQ(cricket::ICEMODE_FULL, fake_ice_transport_->remote_ice_mode());
70 EXPECT_EQ(kIceUfrag1, fake_ice_transport_->remote_ice_ufrag());
71 EXPECT_EQ(kIcePwd1, fake_ice_transport_->remote_ice_pwd());
deadbeef49f34fd2016-12-06 16:22:06 -080072}
73
74// Verifies that IceCredentialsChanged returns true when either ufrag or pwd
75// changed, and false in other cases.
76TEST_F(JsepTransportTest, TestIceCredentialsChanged) {
77 EXPECT_TRUE(cricket::IceCredentialsChanged("u1", "p1", "u2", "p2"));
78 EXPECT_TRUE(cricket::IceCredentialsChanged("u1", "p1", "u2", "p1"));
79 EXPECT_TRUE(cricket::IceCredentialsChanged("u1", "p1", "u1", "p2"));
80 EXPECT_FALSE(cricket::IceCredentialsChanged("u1", "p1", "u1", "p1"));
81}
82
deadbeefd1a38b52016-12-10 13:15:33 -080083// Tests SetNeedsIceRestartFlag and NeedsIceRestart, ensuring NeedsIceRestart
84// only starts returning "false" once an ICE restart has been initiated.
85TEST_F(JsepTransportTest, NeedsIceRestart) {
86 // Do initial offer/answer so there's something to restart.
87 cricket::TransportDescription local_desc(kIceUfrag1, kIcePwd1);
88 cricket::TransportDescription remote_desc(kIceUfrag1, kIcePwd1);
89 ASSERT_TRUE(transport_->SetLocalTransportDescription(
90 local_desc, cricket::CA_OFFER, nullptr));
91 ASSERT_TRUE(transport_->SetRemoteTransportDescription(
92 remote_desc, cricket::CA_ANSWER, nullptr));
93
94 // Flag initially should be false.
95 EXPECT_FALSE(transport_->NeedsIceRestart());
96
97 // After setting flag, it should be true.
98 transport_->SetNeedsIceRestartFlag();
99 EXPECT_TRUE(transport_->NeedsIceRestart());
100
101 // Doing an identical offer/answer shouldn't clear the flag.
102 ASSERT_TRUE(transport_->SetLocalTransportDescription(
103 local_desc, cricket::CA_OFFER, nullptr));
104 ASSERT_TRUE(transport_->SetRemoteTransportDescription(
105 remote_desc, cricket::CA_ANSWER, nullptr));
106 EXPECT_TRUE(transport_->NeedsIceRestart());
107
108 // Doing an offer/answer that restarts ICE should clear the flag.
109 cricket::TransportDescription ice_restart_local_desc(kIceUfrag2, kIcePwd2);
110 cricket::TransportDescription ice_restart_remote_desc(kIceUfrag2, kIcePwd2);
111 ASSERT_TRUE(transport_->SetLocalTransportDescription(
112 ice_restart_local_desc, cricket::CA_OFFER, nullptr));
113 ASSERT_TRUE(transport_->SetRemoteTransportDescription(
114 ice_restart_remote_desc, cricket::CA_ANSWER, nullptr));
115 EXPECT_FALSE(transport_->NeedsIceRestart());
116}
117
deadbeef49f34fd2016-12-06 16:22:06 -0800118TEST_F(JsepTransportTest, TestGetStats) {
119 EXPECT_TRUE(SetupChannel());
120 cricket::TransportStats stats;
121 EXPECT_TRUE(transport_->GetStats(&stats));
zhihuangb2cdd932017-01-19 16:54:25 -0800122 // Note that this tests the behavior of a FakeIceTransport.
deadbeef49f34fd2016-12-06 16:22:06 -0800123 ASSERT_EQ(1U, stats.channel_stats.size());
124 EXPECT_EQ(1, stats.channel_stats[0].component);
125 // Set local transport description for FakeTransport before connecting.
126 TransportDescription faketransport_desc(
127 std::vector<std::string>(),
128 rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH),
129 rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), cricket::ICEMODE_FULL,
130 cricket::CONNECTIONROLE_NONE, nullptr);
131 transport_->SetLocalTransportDescription(faketransport_desc,
132 cricket::CA_OFFER, nullptr);
133 EXPECT_TRUE(transport_->GetStats(&stats));
134 ASSERT_EQ(1U, stats.channel_stats.size());
135 EXPECT_EQ(1, stats.channel_stats[0].component);
136}
137
138// Tests that VerifyCertificateFingerprint only returns true when the
139// certificate matches the fingerprint.
140TEST_F(JsepTransportTest, TestVerifyCertificateFingerprint) {
141 std::string error_desc;
142 EXPECT_FALSE(
143 transport_->VerifyCertificateFingerprint(nullptr, nullptr, &error_desc));
144 rtc::KeyType key_types[] = {rtc::KT_RSA, rtc::KT_ECDSA};
145
146 for (auto& key_type : key_types) {
147 rtc::scoped_refptr<rtc::RTCCertificate> certificate =
148 rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
149 rtc::SSLIdentity::Generate("testing", key_type)));
150 ASSERT_NE(nullptr, certificate);
151
152 std::string digest_algorithm;
153 ASSERT_TRUE(certificate->ssl_certificate().GetSignatureDigestAlgorithm(
154 &digest_algorithm));
155 ASSERT_FALSE(digest_algorithm.empty());
156 std::unique_ptr<rtc::SSLFingerprint> good_fingerprint(
157 rtc::SSLFingerprint::Create(digest_algorithm, certificate->identity()));
158 ASSERT_NE(nullptr, good_fingerprint);
159
160 EXPECT_TRUE(transport_->VerifyCertificateFingerprint(
161 certificate.get(), good_fingerprint.get(), &error_desc));
162 EXPECT_FALSE(transport_->VerifyCertificateFingerprint(
163 certificate.get(), nullptr, &error_desc));
164 EXPECT_FALSE(transport_->VerifyCertificateFingerprint(
165 nullptr, good_fingerprint.get(), &error_desc));
166
167 rtc::SSLFingerprint bad_fingerprint = *good_fingerprint;
168 bad_fingerprint.digest.AppendData("0", 1);
169 EXPECT_FALSE(transport_->VerifyCertificateFingerprint(
170 certificate.get(), &bad_fingerprint, &error_desc));
171 }
172}
173
deadbeefd8cfa1a2017-03-27 10:33:26 -0700174// Tests the logic of DTLS role negotiation for an initial offer/answer.
175TEST_F(JsepTransportTest, DtlsRoleNegotiation) {
176 rtc::scoped_refptr<rtc::RTCCertificate> certificate =
177 rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
178 rtc::SSLIdentity::Generate("testing", rtc::KT_ECDSA)));
179 std::unique_ptr<rtc::SSLFingerprint> fingerprint(
180 rtc::SSLFingerprint::CreateFromCertificate(certificate));
181
deadbeef49f34fd2016-12-06 16:22:06 -0800182 TransportDescription local_desc(kIceUfrag1, kIcePwd1);
183 TransportDescription remote_desc(kIceUfrag2, kIcePwd2);
deadbeefd8cfa1a2017-03-27 10:33:26 -0700184 // Just use the same fingerprint in both descriptions; the remote fingerprint
185 // doesn't matter in a non end-to-end test.
186 local_desc.identity_fingerprint.reset(
187 TransportDescription::CopyFingerprint(fingerprint.get()));
188 remote_desc.identity_fingerprint.reset(
189 TransportDescription::CopyFingerprint(fingerprint.get()));
deadbeef49f34fd2016-12-06 16:22:06 -0800190
191 struct NegotiateRoleParams {
192 cricket::ConnectionRole local_role;
193 cricket::ConnectionRole remote_role;
194 cricket::ContentAction local_action;
195 cricket::ContentAction remote_action;
196 };
197
deadbeef49f34fd2016-12-06 16:22:06 -0800198 std::string error_desc;
199
200 // Parameters which set the SSL role to SSL_CLIENT.
201 NegotiateRoleParams valid_client_params[] = {
202 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTPASS,
203 cricket::CA_ANSWER, cricket::CA_OFFER},
204 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTPASS,
205 cricket::CA_PRANSWER, cricket::CA_OFFER},
206 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_PASSIVE,
207 cricket::CA_OFFER, cricket::CA_ANSWER},
208 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_PASSIVE,
209 cricket::CA_OFFER, cricket::CA_PRANSWER}};
210
211 for (auto& param : valid_client_params) {
deadbeefd8cfa1a2017-03-27 10:33:26 -0700212 RecreateTransport();
213 transport_->SetLocalCertificate(certificate);
214
deadbeef49f34fd2016-12-06 16:22:06 -0800215 local_desc.connection_role = param.local_role;
216 remote_desc.connection_role = param.remote_role;
217
deadbeefd8cfa1a2017-03-27 10:33:26 -0700218 // Set the offer first.
219 if (param.local_action == cricket::CA_OFFER) {
220 EXPECT_TRUE(transport_->SetLocalTransportDescription(
221 local_desc, param.local_action, nullptr));
222 EXPECT_TRUE(transport_->SetRemoteTransportDescription(
223 remote_desc, param.remote_action, nullptr));
224 } else {
225 EXPECT_TRUE(transport_->SetRemoteTransportDescription(
226 remote_desc, param.remote_action, nullptr));
227 EXPECT_TRUE(transport_->SetLocalTransportDescription(
228 local_desc, param.local_action, nullptr));
229 }
230 EXPECT_EQ(rtc::SSL_CLIENT, *transport_->GetSslRole());
deadbeef49f34fd2016-12-06 16:22:06 -0800231 }
232
233 // Parameters which set the SSL role to SSL_SERVER.
234 NegotiateRoleParams valid_server_params[] = {
235 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTPASS,
236 cricket::CA_ANSWER, cricket::CA_OFFER},
237 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTPASS,
238 cricket::CA_PRANSWER, cricket::CA_OFFER},
239 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTIVE,
240 cricket::CA_OFFER, cricket::CA_ANSWER},
241 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTIVE,
242 cricket::CA_OFFER, cricket::CA_PRANSWER}};
243
244 for (auto& param : valid_server_params) {
deadbeefd8cfa1a2017-03-27 10:33:26 -0700245 RecreateTransport();
246 transport_->SetLocalCertificate(certificate);
247
deadbeef49f34fd2016-12-06 16:22:06 -0800248 local_desc.connection_role = param.local_role;
249 remote_desc.connection_role = param.remote_role;
250
deadbeefd8cfa1a2017-03-27 10:33:26 -0700251 // Set the offer first.
252 if (param.local_action == cricket::CA_OFFER) {
253 EXPECT_TRUE(transport_->SetLocalTransportDescription(
254 local_desc, param.local_action, nullptr));
255 EXPECT_TRUE(transport_->SetRemoteTransportDescription(
256 remote_desc, param.remote_action, nullptr));
257 } else {
258 EXPECT_TRUE(transport_->SetRemoteTransportDescription(
259 remote_desc, param.remote_action, nullptr));
260 EXPECT_TRUE(transport_->SetLocalTransportDescription(
261 local_desc, param.local_action, nullptr));
262 }
263 EXPECT_EQ(rtc::SSL_SERVER, *transport_->GetSslRole());
deadbeef49f34fd2016-12-06 16:22:06 -0800264 }
265
266 // Invalid parameters due to both peers having a duplicate role.
267 NegotiateRoleParams duplicate_params[] = {
268 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTIVE,
269 cricket::CA_ANSWER, cricket::CA_OFFER},
270 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTPASS,
271 cricket::CA_ANSWER, cricket::CA_OFFER},
272 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_PASSIVE,
273 cricket::CA_ANSWER, cricket::CA_OFFER},
274 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTIVE,
275 cricket::CA_PRANSWER, cricket::CA_OFFER},
276 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTPASS,
277 cricket::CA_PRANSWER, cricket::CA_OFFER},
278 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_PASSIVE,
279 cricket::CA_PRANSWER, cricket::CA_OFFER},
280 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTIVE,
281 cricket::CA_OFFER, cricket::CA_ANSWER},
282 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTPASS,
283 cricket::CA_OFFER, cricket::CA_ANSWER},
284 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_PASSIVE,
285 cricket::CA_OFFER, cricket::CA_ANSWER},
286 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTIVE,
287 cricket::CA_OFFER, cricket::CA_PRANSWER},
288 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTPASS,
289 cricket::CA_OFFER, cricket::CA_PRANSWER},
290 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_PASSIVE,
291 cricket::CA_OFFER, cricket::CA_PRANSWER}};
292
293 for (auto& param : duplicate_params) {
deadbeefd8cfa1a2017-03-27 10:33:26 -0700294 RecreateTransport();
295 transport_->SetLocalCertificate(certificate);
296
deadbeef49f34fd2016-12-06 16:22:06 -0800297 local_desc.connection_role = param.local_role;
298 remote_desc.connection_role = param.remote_role;
299
deadbeefd8cfa1a2017-03-27 10:33:26 -0700300 // Set the offer first.
301 if (param.local_action == cricket::CA_OFFER) {
302 EXPECT_TRUE(transport_->SetLocalTransportDescription(
303 local_desc, param.local_action, nullptr));
304 EXPECT_FALSE(transport_->SetRemoteTransportDescription(
305 remote_desc, param.remote_action, nullptr));
306 } else {
307 EXPECT_TRUE(transport_->SetRemoteTransportDescription(
308 remote_desc, param.remote_action, nullptr));
309 EXPECT_FALSE(transport_->SetLocalTransportDescription(
310 local_desc, param.local_action, nullptr));
311 }
deadbeef49f34fd2016-12-06 16:22:06 -0800312 }
313
314 // Invalid parameters due to the offerer not using ACTPASS.
315 NegotiateRoleParams offerer_without_actpass_params[] = {
316 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_PASSIVE,
317 cricket::CA_ANSWER, cricket::CA_OFFER},
318 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTIVE,
319 cricket::CA_ANSWER, cricket::CA_OFFER},
320 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_PASSIVE,
321 cricket::CA_ANSWER, cricket::CA_OFFER},
322 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_PASSIVE,
323 cricket::CA_PRANSWER, cricket::CA_OFFER},
324 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTIVE,
325 cricket::CA_PRANSWER, cricket::CA_OFFER},
326 {cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_PASSIVE,
327 cricket::CA_PRANSWER, cricket::CA_OFFER},
328 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_PASSIVE,
329 cricket::CA_OFFER, cricket::CA_ANSWER},
330 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTIVE,
331 cricket::CA_OFFER, cricket::CA_ANSWER},
332 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTPASS,
333 cricket::CA_OFFER, cricket::CA_ANSWER},
334 {cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_PASSIVE,
335 cricket::CA_OFFER, cricket::CA_PRANSWER},
336 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTIVE,
337 cricket::CA_OFFER, cricket::CA_PRANSWER},
338 {cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTPASS,
339 cricket::CA_OFFER, cricket::CA_PRANSWER}};
340
341 for (auto& param : offerer_without_actpass_params) {
deadbeefd8cfa1a2017-03-27 10:33:26 -0700342 RecreateTransport();
343 transport_->SetLocalCertificate(certificate);
344
deadbeef49f34fd2016-12-06 16:22:06 -0800345 local_desc.connection_role = param.local_role;
346 remote_desc.connection_role = param.remote_role;
347
deadbeefd8cfa1a2017-03-27 10:33:26 -0700348 // Set the offer first.
349 // TODO(deadbeef): Really this should fail as soon as the offer is
350 // attempted to be applied, and not when the answer is applied.
351 if (param.local_action == cricket::CA_OFFER) {
352 EXPECT_TRUE(transport_->SetLocalTransportDescription(
353 local_desc, param.local_action, nullptr));
354 EXPECT_FALSE(transport_->SetRemoteTransportDescription(
355 remote_desc, param.remote_action, nullptr));
356 } else {
357 EXPECT_TRUE(transport_->SetRemoteTransportDescription(
358 remote_desc, param.remote_action, nullptr));
359 EXPECT_FALSE(transport_->SetLocalTransportDescription(
360 local_desc, param.local_action, nullptr));
361 }
deadbeef49f34fd2016-12-06 16:22:06 -0800362 }
363}
deadbeefd8cfa1a2017-03-27 10:33:26 -0700364
365// Test that a remote offer with the current negotiated role can be accepted.
366// This is allowed by dtls-sdp, though we'll never generate such an offer,
367// since JSEP requires generating "actpass".
368TEST_F(JsepTransportTest, RemoteOfferWithCurrentNegotiatedDtlsRole) {
369 rtc::scoped_refptr<rtc::RTCCertificate> certificate =
370 rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
371 rtc::SSLIdentity::Generate("testing", rtc::KT_ECDSA)));
372 std::unique_ptr<rtc::SSLFingerprint> fingerprint(
373 rtc::SSLFingerprint::CreateFromCertificate(certificate));
374 transport_->SetLocalCertificate(certificate);
375
376 TransportDescription local_desc(kIceUfrag1, kIcePwd1);
377 TransportDescription remote_desc(kIceUfrag2, kIcePwd2);
378 // Just use the same fingerprint in both descriptions; the remote fingerprint
379 // doesn't matter in a non end-to-end test.
380 local_desc.identity_fingerprint.reset(
381 TransportDescription::CopyFingerprint(fingerprint.get()));
382 remote_desc.identity_fingerprint.reset(
383 TransportDescription::CopyFingerprint(fingerprint.get()));
384
385 remote_desc.connection_role = cricket::CONNECTIONROLE_ACTPASS;
386 local_desc.connection_role = cricket::CONNECTIONROLE_ACTIVE;
387
388 // Normal initial offer/answer with "actpass" in the offer and "active" in
389 // the answer.
390 ASSERT_TRUE(transport_->SetRemoteTransportDescription(
391 remote_desc, cricket::CA_OFFER, nullptr));
392 ASSERT_TRUE(transport_->SetLocalTransportDescription(
393 local_desc, cricket::CA_ANSWER, nullptr));
394
395 // Sanity check that role was actually negotiated.
396 rtc::Optional<rtc::SSLRole> role = transport_->GetSslRole();
397 ASSERT_TRUE(role);
398 EXPECT_EQ(rtc::SSL_CLIENT, *role);
399
400 // Subsequent offer with current negotiated role of "passive".
401 remote_desc.connection_role = cricket::CONNECTIONROLE_PASSIVE;
402 EXPECT_TRUE(transport_->SetRemoteTransportDescription(
403 remote_desc, cricket::CA_OFFER, nullptr));
404 EXPECT_TRUE(transport_->SetLocalTransportDescription(
405 local_desc, cricket::CA_ANSWER, nullptr));
406}
407
408// Test that a remote offer with the inverse of the current negotiated DTLS
409// role is rejected.
410TEST_F(JsepTransportTest, RemoteOfferThatChangesNegotiatedDtlsRole) {
411 rtc::scoped_refptr<rtc::RTCCertificate> certificate =
412 rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
413 rtc::SSLIdentity::Generate("testing", rtc::KT_ECDSA)));
414 std::unique_ptr<rtc::SSLFingerprint> fingerprint(
415 rtc::SSLFingerprint::CreateFromCertificate(certificate));
416 transport_->SetLocalCertificate(certificate);
417
418 TransportDescription local_desc(kIceUfrag1, kIcePwd1);
419 TransportDescription remote_desc(kIceUfrag2, kIcePwd2);
420 // Just use the same fingerprint in both descriptions; the remote fingerprint
421 // doesn't matter in a non end-to-end test.
422 local_desc.identity_fingerprint.reset(
423 TransportDescription::CopyFingerprint(fingerprint.get()));
424 remote_desc.identity_fingerprint.reset(
425 TransportDescription::CopyFingerprint(fingerprint.get()));
426
427 remote_desc.connection_role = cricket::CONNECTIONROLE_ACTPASS;
428 local_desc.connection_role = cricket::CONNECTIONROLE_ACTIVE;
429
430 // Normal initial offer/answer with "actpass" in the offer and "active" in
431 // the answer.
432 ASSERT_TRUE(transport_->SetRemoteTransportDescription(
433 remote_desc, cricket::CA_OFFER, nullptr));
434 ASSERT_TRUE(transport_->SetLocalTransportDescription(
435 local_desc, cricket::CA_ANSWER, nullptr));
436
437 // Sanity check that role was actually negotiated.
438 rtc::Optional<rtc::SSLRole> role = transport_->GetSslRole();
439 ASSERT_TRUE(role);
440 EXPECT_EQ(rtc::SSL_CLIENT, *role);
441
442 // Subsequent offer with "active", which is the opposite of the remote
443 // endpoint's negotiated role.
444 // TODO(deadbeef): Really this should fail as soon as the offer is
445 // attempted to be applied, and not when the answer is applied.
446 remote_desc.connection_role = cricket::CONNECTIONROLE_ACTIVE;
447 EXPECT_TRUE(transport_->SetRemoteTransportDescription(
448 remote_desc, cricket::CA_OFFER, nullptr));
449 EXPECT_FALSE(transport_->SetLocalTransportDescription(
450 local_desc, cricket::CA_ANSWER, nullptr));
451}