1 /*
2  *  Copyright 2018 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 "pc/jsep_transport.h"
12 
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #include <memory>
17 #include <utility>  // for std::pair
18 
19 #include "api/array_view.h"
20 #include "api/candidate.h"
21 #include "p2p/base/p2p_constants.h"
22 #include "p2p/base/p2p_transport_channel.h"
23 #include "pc/sctp_data_channel_transport.h"
24 #include "rtc_base/checks.h"
25 #include "rtc_base/copy_on_write_buffer.h"
26 #include "rtc_base/logging.h"
27 #include "rtc_base/ref_counted_object.h"
28 #include "rtc_base/strings/string_builder.h"
29 
30 using webrtc::SdpType;
31 
32 namespace cricket {
33 
JsepTransportDescription()34 JsepTransportDescription::JsepTransportDescription() {}
35 
JsepTransportDescription(bool rtcp_mux_enabled,const std::vector<CryptoParams> & cryptos,const std::vector<int> & encrypted_header_extension_ids,int rtp_abs_sendtime_extn_id,const TransportDescription & transport_desc)36 JsepTransportDescription::JsepTransportDescription(
37     bool rtcp_mux_enabled,
38     const std::vector<CryptoParams>& cryptos,
39     const std::vector<int>& encrypted_header_extension_ids,
40     int rtp_abs_sendtime_extn_id,
41     const TransportDescription& transport_desc)
42     : rtcp_mux_enabled(rtcp_mux_enabled),
43       cryptos(cryptos),
44       encrypted_header_extension_ids(encrypted_header_extension_ids),
45       rtp_abs_sendtime_extn_id(rtp_abs_sendtime_extn_id),
46       transport_desc(transport_desc) {}
47 
JsepTransportDescription(const JsepTransportDescription & from)48 JsepTransportDescription::JsepTransportDescription(
49     const JsepTransportDescription& from)
50     : rtcp_mux_enabled(from.rtcp_mux_enabled),
51       cryptos(from.cryptos),
52       encrypted_header_extension_ids(from.encrypted_header_extension_ids),
53       rtp_abs_sendtime_extn_id(from.rtp_abs_sendtime_extn_id),
54       transport_desc(from.transport_desc) {}
55 
56 JsepTransportDescription::~JsepTransportDescription() = default;
57 
operator =(const JsepTransportDescription & from)58 JsepTransportDescription& JsepTransportDescription::operator=(
59     const JsepTransportDescription& from) {
60   if (this == &from) {
61     return *this;
62   }
63   rtcp_mux_enabled = from.rtcp_mux_enabled;
64   cryptos = from.cryptos;
65   encrypted_header_extension_ids = from.encrypted_header_extension_ids;
66   rtp_abs_sendtime_extn_id = from.rtp_abs_sendtime_extn_id;
67   transport_desc = from.transport_desc;
68 
69   return *this;
70 }
71 
JsepTransport(const std::string & mid,const rtc::scoped_refptr<rtc::RTCCertificate> & local_certificate,rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,std::unique_ptr<webrtc::SrtpTransport> sdes_transport,std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,std::unique_ptr<SctpTransportInternal> sctp_transport)72 JsepTransport::JsepTransport(
73     const std::string& mid,
74     const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
75     rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,
76     rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,
77     std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
78     std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
79     std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
80     std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
81     std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
82     std::unique_ptr<SctpTransportInternal> sctp_transport)
83     : network_thread_(rtc::Thread::Current()),
84       mid_(mid),
85       local_certificate_(local_certificate),
86       ice_transport_(std::move(ice_transport)),
87       rtcp_ice_transport_(std::move(rtcp_ice_transport)),
88       unencrypted_rtp_transport_(std::move(unencrypted_rtp_transport)),
89       sdes_transport_(std::move(sdes_transport)),
90       dtls_srtp_transport_(std::move(dtls_srtp_transport)),
91       rtp_dtls_transport_(
92           rtp_dtls_transport ? new rtc::RefCountedObject<webrtc::DtlsTransport>(
93                                    std::move(rtp_dtls_transport))
94                              : nullptr),
95       rtcp_dtls_transport_(
96           rtcp_dtls_transport
97               ? new rtc::RefCountedObject<webrtc::DtlsTransport>(
98                     std::move(rtcp_dtls_transport))
99               : nullptr),
100       sctp_data_channel_transport_(
101           sctp_transport ? std::make_unique<webrtc::SctpDataChannelTransport>(
102                                sctp_transport.get())
103                          : nullptr),
104       sctp_transport_(sctp_transport
105                           ? new rtc::RefCountedObject<webrtc::SctpTransport>(
106                                 std::move(sctp_transport))
107                           : nullptr) {
108   RTC_DCHECK(ice_transport_);
109   RTC_DCHECK(rtp_dtls_transport_);
110   // |rtcp_ice_transport_| must be present iff |rtcp_dtls_transport_| is
111   // present.
112   RTC_DCHECK_EQ((rtcp_ice_transport_ != nullptr),
113                 (rtcp_dtls_transport_ != nullptr));
114   // Verify the "only one out of these three can be set" invariant.
115   if (unencrypted_rtp_transport_) {
116     RTC_DCHECK(!sdes_transport);
117     RTC_DCHECK(!dtls_srtp_transport);
118   } else if (sdes_transport_) {
119     RTC_DCHECK(!unencrypted_rtp_transport);
120     RTC_DCHECK(!dtls_srtp_transport);
121   } else {
122     RTC_DCHECK(dtls_srtp_transport_);
123     RTC_DCHECK(!unencrypted_rtp_transport);
124     RTC_DCHECK(!sdes_transport);
125   }
126 
127   if (sctp_transport_) {
128     sctp_transport_->SetDtlsTransport(rtp_dtls_transport_);
129   }
130 }
131 
~JsepTransport()132 JsepTransport::~JsepTransport() {
133   if (sctp_transport_) {
134     sctp_transport_->Clear();
135   }
136 
137   // Clear all DtlsTransports. There may be pointers to these from
138   // other places, so we can't assume they'll be deleted by the destructor.
139   rtp_dtls_transport_->Clear();
140   if (rtcp_dtls_transport_) {
141     rtcp_dtls_transport_->Clear();
142   }
143 
144   // ICE will be the last transport to be deleted.
145 }
146 
SetLocalJsepTransportDescription(const JsepTransportDescription & jsep_description,SdpType type)147 webrtc::RTCError JsepTransport::SetLocalJsepTransportDescription(
148     const JsepTransportDescription& jsep_description,
149     SdpType type) {
150   webrtc::RTCError error;
151 
152   RTC_DCHECK_RUN_ON(network_thread_);
153 
154   IceParameters ice_parameters =
155       jsep_description.transport_desc.GetIceParameters();
156   webrtc::RTCError ice_parameters_result = ice_parameters.Validate();
157   if (!ice_parameters_result.ok()) {
158     rtc::StringBuilder sb;
159     sb << "Invalid ICE parameters: " << ice_parameters_result.message();
160     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
161                             sb.Release());
162   }
163 
164   if (!SetRtcpMux(jsep_description.rtcp_mux_enabled, type,
165                   ContentSource::CS_LOCAL)) {
166     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
167                             "Failed to setup RTCP mux.");
168   }
169 
170   // If doing SDES, setup the SDES crypto parameters.
171   if (sdes_transport_) {
172     RTC_DCHECK(!unencrypted_rtp_transport_);
173     RTC_DCHECK(!dtls_srtp_transport_);
174     if (!SetSdes(jsep_description.cryptos,
175                  jsep_description.encrypted_header_extension_ids, type,
176                  ContentSource::CS_LOCAL)) {
177       return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
178                               "Failed to setup SDES crypto parameters.");
179     }
180   } else if (dtls_srtp_transport_) {
181     RTC_DCHECK(!unencrypted_rtp_transport_);
182     RTC_DCHECK(!sdes_transport_);
183     dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
184         jsep_description.encrypted_header_extension_ids);
185   }
186   bool ice_restarting =
187       local_description_ != nullptr &&
188       IceCredentialsChanged(local_description_->transport_desc.ice_ufrag,
189                             local_description_->transport_desc.ice_pwd,
190                             ice_parameters.ufrag, ice_parameters.pwd);
191   local_description_.reset(new JsepTransportDescription(jsep_description));
192 
193   rtc::SSLFingerprint* local_fp =
194       local_description_->transport_desc.identity_fingerprint.get();
195 
196   if (!local_fp) {
197     local_certificate_ = nullptr;
198   } else {
199     error = VerifyCertificateFingerprint(local_certificate_, local_fp);
200     if (!error.ok()) {
201       local_description_.reset();
202       return error;
203     }
204   }
205     RTC_DCHECK(rtp_dtls_transport_->internal());
206     rtp_dtls_transport_->internal()->ice_transport()->SetIceParameters(
207         ice_parameters);
208 
209     {
210       if (rtcp_dtls_transport_) {
211         RTC_DCHECK(rtcp_dtls_transport_->internal());
212         rtcp_dtls_transport_->internal()->ice_transport()->SetIceParameters(
213             ice_parameters);
214       }
215     }
216   // If PRANSWER/ANSWER is set, we should decide transport protocol type.
217   if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
218     error = NegotiateAndSetDtlsParameters(type);
219   }
220   if (!error.ok()) {
221     local_description_.reset();
222     return error;
223   }
224 
225   if (needs_ice_restart_ && ice_restarting) {
226     needs_ice_restart_ = false;
227     RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag cleared for transport "
228                         << mid();
229   }
230 
231   return webrtc::RTCError::OK();
232 }
233 
SetRemoteJsepTransportDescription(const JsepTransportDescription & jsep_description,webrtc::SdpType type)234 webrtc::RTCError JsepTransport::SetRemoteJsepTransportDescription(
235     const JsepTransportDescription& jsep_description,
236     webrtc::SdpType type) {
237   webrtc::RTCError error;
238 
239   RTC_DCHECK_RUN_ON(network_thread_);
240 
241   IceParameters ice_parameters =
242       jsep_description.transport_desc.GetIceParameters();
243   webrtc::RTCError ice_parameters_result = ice_parameters.Validate();
244   if (!ice_parameters_result.ok()) {
245     remote_description_.reset();
246     rtc::StringBuilder sb;
247     sb << "Invalid ICE parameters: " << ice_parameters_result.message();
248     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
249                             sb.Release());
250   }
251 
252   if (!SetRtcpMux(jsep_description.rtcp_mux_enabled, type,
253                   ContentSource::CS_REMOTE)) {
254     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
255                             "Failed to setup RTCP mux.");
256   }
257 
258   // If doing SDES, setup the SDES crypto parameters.
259   if (sdes_transport_) {
260     RTC_DCHECK(!unencrypted_rtp_transport_);
261     RTC_DCHECK(!dtls_srtp_transport_);
262     if (!SetSdes(jsep_description.cryptos,
263                  jsep_description.encrypted_header_extension_ids, type,
264                  ContentSource::CS_REMOTE)) {
265       return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
266                               "Failed to setup SDES crypto parameters.");
267     }
268     sdes_transport_->CacheRtpAbsSendTimeHeaderExtension(
269         jsep_description.rtp_abs_sendtime_extn_id);
270   } else if (dtls_srtp_transport_) {
271     RTC_DCHECK(!unencrypted_rtp_transport_);
272     RTC_DCHECK(!sdes_transport_);
273     dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
274         jsep_description.encrypted_header_extension_ids);
275     dtls_srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
276         jsep_description.rtp_abs_sendtime_extn_id);
277   }
278 
279   remote_description_.reset(new JsepTransportDescription(jsep_description));
280   RTC_DCHECK(rtp_dtls_transport());
281   SetRemoteIceParameters(ice_parameters, rtp_dtls_transport()->ice_transport());
282 
283   if (rtcp_dtls_transport()) {
284     SetRemoteIceParameters(ice_parameters,
285                            rtcp_dtls_transport()->ice_transport());
286   }
287 
288   // If PRANSWER/ANSWER is set, we should decide transport protocol type.
289   if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
290     error = NegotiateAndSetDtlsParameters(SdpType::kOffer);
291   }
292   if (!error.ok()) {
293     remote_description_.reset();
294     return error;
295   }
296   return webrtc::RTCError::OK();
297 }
298 
AddRemoteCandidates(const Candidates & candidates)299 webrtc::RTCError JsepTransport::AddRemoteCandidates(
300     const Candidates& candidates) {
301   RTC_DCHECK_RUN_ON(network_thread_);
302   if (!local_description_ || !remote_description_) {
303     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
304                             mid() +
305                                 " is not ready to use the remote candidate "
306                                 "because the local or remote description is "
307                                 "not set.");
308   }
309 
310   for (const cricket::Candidate& candidate : candidates) {
311     auto transport =
312         candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
313             ? rtp_dtls_transport_
314             : rtcp_dtls_transport_;
315     if (!transport) {
316       return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
317                               "Candidate has an unknown component: " +
318                                   candidate.ToSensitiveString() + " for mid " +
319                                   mid());
320     }
321     RTC_DCHECK(transport->internal() && transport->internal()->ice_transport());
322     transport->internal()->ice_transport()->AddRemoteCandidate(candidate);
323   }
324   return webrtc::RTCError::OK();
325 }
326 
SetNeedsIceRestartFlag()327 void JsepTransport::SetNeedsIceRestartFlag() {
328   RTC_DCHECK_RUN_ON(network_thread_);
329   if (!needs_ice_restart_) {
330     needs_ice_restart_ = true;
331     RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag set for transport " << mid();
332   }
333 }
334 
GetDtlsRole() const335 absl::optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const {
336   RTC_DCHECK_RUN_ON(network_thread_);
337   RTC_DCHECK(rtp_dtls_transport_);
338   RTC_DCHECK(rtp_dtls_transport_->internal());
339   rtc::SSLRole dtls_role;
340   if (!rtp_dtls_transport_->internal()->GetDtlsRole(&dtls_role)) {
341     return absl::optional<rtc::SSLRole>();
342   }
343 
344   return absl::optional<rtc::SSLRole>(dtls_role);
345 }
346 
GetStats(TransportStats * stats)347 bool JsepTransport::GetStats(TransportStats* stats) {
348   RTC_DCHECK_RUN_ON(network_thread_);
349   stats->transport_name = mid();
350   stats->channel_stats.clear();
351   RTC_DCHECK(rtp_dtls_transport_->internal());
352   bool ret = GetTransportStats(rtp_dtls_transport_->internal(),
353                                ICE_CANDIDATE_COMPONENT_RTP, stats);
354 
355   if (rtcp_dtls_transport_) {
356     RTC_DCHECK(rtcp_dtls_transport_->internal());
357     ret &= GetTransportStats(rtcp_dtls_transport_->internal(),
358                              ICE_CANDIDATE_COMPONENT_RTCP, stats);
359   }
360   return ret;
361 }
362 
VerifyCertificateFingerprint(const rtc::RTCCertificate * certificate,const rtc::SSLFingerprint * fingerprint) const363 webrtc::RTCError JsepTransport::VerifyCertificateFingerprint(
364     const rtc::RTCCertificate* certificate,
365     const rtc::SSLFingerprint* fingerprint) const {
366   RTC_DCHECK_RUN_ON(network_thread_);
367   if (!fingerprint) {
368     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
369                             "No fingerprint");
370   }
371   if (!certificate) {
372     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
373                             "Fingerprint provided but no identity available.");
374   }
375   std::unique_ptr<rtc::SSLFingerprint> fp_tmp =
376       rtc::SSLFingerprint::CreateUnique(fingerprint->algorithm,
377                                         *certificate->identity());
378   RTC_DCHECK(fp_tmp.get() != NULL);
379   if (*fp_tmp == *fingerprint) {
380     return webrtc::RTCError::OK();
381   }
382   char ss_buf[1024];
383   rtc::SimpleStringBuilder desc(ss_buf);
384   desc << "Local fingerprint does not match identity. Expected: ";
385   desc << fp_tmp->ToString();
386   desc << " Got: " << fingerprint->ToString();
387   return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
388                           std::string(desc.str()));
389 }
390 
SetActiveResetSrtpParams(bool active_reset_srtp_params)391 void JsepTransport::SetActiveResetSrtpParams(bool active_reset_srtp_params) {
392   RTC_DCHECK_RUN_ON(network_thread_);
393   if (dtls_srtp_transport_) {
394     RTC_LOG(INFO)
395         << "Setting active_reset_srtp_params of DtlsSrtpTransport to: "
396         << active_reset_srtp_params;
397     dtls_srtp_transport_->SetActiveResetSrtpParams(active_reset_srtp_params);
398   }
399 }
400 
SetRemoteIceParameters(const IceParameters & ice_parameters,IceTransportInternal * ice_transport)401 void JsepTransport::SetRemoteIceParameters(
402     const IceParameters& ice_parameters,
403     IceTransportInternal* ice_transport) {
404   RTC_DCHECK_RUN_ON(network_thread_);
405   RTC_DCHECK(ice_transport);
406   RTC_DCHECK(remote_description_);
407   ice_transport->SetRemoteIceParameters(ice_parameters);
408   ice_transport->SetRemoteIceMode(remote_description_->transport_desc.ice_mode);
409 }
410 
SetNegotiatedDtlsParameters(DtlsTransportInternal * dtls_transport,absl::optional<rtc::SSLRole> dtls_role,rtc::SSLFingerprint * remote_fingerprint)411 webrtc::RTCError JsepTransport::SetNegotiatedDtlsParameters(
412     DtlsTransportInternal* dtls_transport,
413     absl::optional<rtc::SSLRole> dtls_role,
414     rtc::SSLFingerprint* remote_fingerprint) {
415   RTC_DCHECK(dtls_transport);
416   // Set SSL role. Role must be set before fingerprint is applied, which
417   // initiates DTLS setup.
418   if (dtls_role && !dtls_transport->SetDtlsRole(*dtls_role)) {
419     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
420                             "Failed to set SSL role for the transport.");
421   }
422   // Apply remote fingerprint.
423   if (!remote_fingerprint ||
424       !dtls_transport->SetRemoteFingerprint(
425           remote_fingerprint->algorithm, remote_fingerprint->digest.cdata(),
426           remote_fingerprint->digest.size())) {
427     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
428                             "Failed to apply remote fingerprint.");
429   }
430   return webrtc::RTCError::OK();
431 }
432 
SetRtcpMux(bool enable,webrtc::SdpType type,ContentSource source)433 bool JsepTransport::SetRtcpMux(bool enable,
434                                webrtc::SdpType type,
435                                ContentSource source) {
436   RTC_DCHECK_RUN_ON(network_thread_);
437   bool ret = false;
438   switch (type) {
439     case SdpType::kOffer:
440       ret = rtcp_mux_negotiator_.SetOffer(enable, source);
441       break;
442     case SdpType::kPrAnswer:
443       // This may activate RTCP muxing, but we don't yet destroy the transport
444       // because the final answer may deactivate it.
445       ret = rtcp_mux_negotiator_.SetProvisionalAnswer(enable, source);
446       break;
447     case SdpType::kAnswer:
448       ret = rtcp_mux_negotiator_.SetAnswer(enable, source);
449       if (ret && rtcp_mux_negotiator_.IsActive()) {
450         ActivateRtcpMux();
451       }
452       break;
453     default:
454       RTC_NOTREACHED();
455   }
456 
457   if (!ret) {
458     return false;
459   }
460 
461   auto transport = rtp_transport();
462   transport->SetRtcpMuxEnabled(rtcp_mux_negotiator_.IsActive());
463   return ret;
464 }
465 
ActivateRtcpMux()466 void JsepTransport::ActivateRtcpMux() {
467   if (unencrypted_rtp_transport_) {
468     RTC_DCHECK(!sdes_transport_);
469     RTC_DCHECK(!dtls_srtp_transport_);
470     unencrypted_rtp_transport_->SetRtcpPacketTransport(nullptr);
471   } else if (sdes_transport_) {
472     RTC_DCHECK(!unencrypted_rtp_transport_);
473     RTC_DCHECK(!dtls_srtp_transport_);
474     sdes_transport_->SetRtcpPacketTransport(nullptr);
475   } else if (dtls_srtp_transport_) {
476     RTC_DCHECK(dtls_srtp_transport_);
477     RTC_DCHECK(!unencrypted_rtp_transport_);
478     RTC_DCHECK(!sdes_transport_);
479     dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport(),
480                                             /*rtcp_dtls_transport=*/nullptr);
481   }
482   rtcp_dtls_transport_ = nullptr;  // Destroy this reference.
483   // Notify the JsepTransportController to update the aggregate states.
484   SignalRtcpMuxActive();
485 }
486 
SetSdes(const std::vector<CryptoParams> & cryptos,const std::vector<int> & encrypted_extension_ids,webrtc::SdpType type,ContentSource source)487 bool JsepTransport::SetSdes(const std::vector<CryptoParams>& cryptos,
488                             const std::vector<int>& encrypted_extension_ids,
489                             webrtc::SdpType type,
490                             ContentSource source) {
491   RTC_DCHECK_RUN_ON(network_thread_);
492   bool ret = false;
493   ret = sdes_negotiator_.Process(cryptos, type, source);
494   if (!ret) {
495     return ret;
496   }
497 
498   if (source == ContentSource::CS_LOCAL) {
499     recv_extension_ids_ = encrypted_extension_ids;
500   } else {
501     send_extension_ids_ = encrypted_extension_ids;
502   }
503 
504   // If setting an SDES answer succeeded, apply the negotiated parameters
505   // to the SRTP transport.
506   if ((type == SdpType::kPrAnswer || type == SdpType::kAnswer) && ret) {
507     if (sdes_negotiator_.send_cipher_suite() &&
508         sdes_negotiator_.recv_cipher_suite()) {
509       RTC_DCHECK(send_extension_ids_);
510       RTC_DCHECK(recv_extension_ids_);
511       ret = sdes_transport_->SetRtpParams(
512           *(sdes_negotiator_.send_cipher_suite()),
513           sdes_negotiator_.send_key().data(),
514           static_cast<int>(sdes_negotiator_.send_key().size()),
515           *(send_extension_ids_), *(sdes_negotiator_.recv_cipher_suite()),
516           sdes_negotiator_.recv_key().data(),
517           static_cast<int>(sdes_negotiator_.recv_key().size()),
518           *(recv_extension_ids_));
519     } else {
520       RTC_LOG(LS_INFO) << "No crypto keys are provided for SDES.";
521       if (type == SdpType::kAnswer) {
522         // Explicitly reset the |sdes_transport_| if no crypto param is
523         // provided in the answer. No need to call |ResetParams()| for
524         // |sdes_negotiator_| because it resets the params inside |SetAnswer|.
525         sdes_transport_->ResetParams();
526       }
527     }
528   }
529   return ret;
530 }
531 
NegotiateAndSetDtlsParameters(SdpType local_description_type)532 webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
533     SdpType local_description_type) {
534   RTC_DCHECK_RUN_ON(network_thread_);
535   if (!local_description_ || !remote_description_) {
536     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
537                             "Applying an answer transport description "
538                             "without applying any offer.");
539   }
540   std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint;
541   absl::optional<rtc::SSLRole> negotiated_dtls_role;
542 
543   rtc::SSLFingerprint* local_fp =
544       local_description_->transport_desc.identity_fingerprint.get();
545   rtc::SSLFingerprint* remote_fp =
546       remote_description_->transport_desc.identity_fingerprint.get();
547   if (remote_fp && local_fp) {
548     remote_fingerprint = std::make_unique<rtc::SSLFingerprint>(*remote_fp);
549     webrtc::RTCError error =
550         NegotiateDtlsRole(local_description_type,
551                           local_description_->transport_desc.connection_role,
552                           remote_description_->transport_desc.connection_role,
553                           &negotiated_dtls_role);
554     if (!error.ok()) {
555       return error;
556     }
557   } else if (local_fp && (local_description_type == SdpType::kAnswer)) {
558     return webrtc::RTCError(
559         webrtc::RTCErrorType::INVALID_PARAMETER,
560         "Local fingerprint supplied when caller didn't offer DTLS.");
561   } else {
562     // We are not doing DTLS
563     remote_fingerprint = std::make_unique<rtc::SSLFingerprint>(
564         "", rtc::ArrayView<const uint8_t>());
565   }
566   // Now that we have negotiated everything, push it downward.
567   // Note that we cache the result so that if we have race conditions
568   // between future SetRemote/SetLocal invocations and new transport
569   // creation, we have the negotiation state saved until a new
570   // negotiation happens.
571   RTC_DCHECK(rtp_dtls_transport());
572   webrtc::RTCError error = SetNegotiatedDtlsParameters(
573       rtp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
574   if (!error.ok()) {
575     return error;
576   }
577 
578   if (rtcp_dtls_transport()) {
579     error = SetNegotiatedDtlsParameters(
580         rtcp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
581   }
582   return error;
583 }
584 
NegotiateDtlsRole(SdpType local_description_type,ConnectionRole local_connection_role,ConnectionRole remote_connection_role,absl::optional<rtc::SSLRole> * negotiated_dtls_role)585 webrtc::RTCError JsepTransport::NegotiateDtlsRole(
586     SdpType local_description_type,
587     ConnectionRole local_connection_role,
588     ConnectionRole remote_connection_role,
589     absl::optional<rtc::SSLRole>* negotiated_dtls_role) {
590   // From RFC 4145, section-4.1, The following are the values that the
591   // 'setup' attribute can take in an offer/answer exchange:
592   //       Offer      Answer
593   //      ________________
594   //      active     passive / holdconn
595   //      passive    active / holdconn
596   //      actpass    active / passive / holdconn
597   //      holdconn   holdconn
598   //
599   // Set the role that is most conformant with RFC 5763, Section 5, bullet 1
600   // The endpoint MUST use the setup attribute defined in [RFC4145].
601   // The endpoint that is the offerer MUST use the setup attribute
602   // value of setup:actpass and be prepared to receive a client_hello
603   // before it receives the answer.  The answerer MUST use either a
604   // setup attribute value of setup:active or setup:passive.  Note that
605   // if the answerer uses setup:passive, then the DTLS handshake will
606   // not begin until the answerer is received, which adds additional
607   // latency. setup:active allows the answer and the DTLS handshake to
608   // occur in parallel.  Thus, setup:active is RECOMMENDED.  Whichever
609   // party is active MUST initiate a DTLS handshake by sending a
610   // ClientHello over each flow (host/port quartet).
611   // IOW - actpass and passive modes should be treated as server and
612   // active as client.
613   bool is_remote_server = false;
614   if (local_description_type == SdpType::kOffer) {
615     if (local_connection_role != CONNECTIONROLE_ACTPASS) {
616       return webrtc::RTCError(
617           webrtc::RTCErrorType::INVALID_PARAMETER,
618           "Offerer must use actpass value for setup attribute.");
619     }
620 
621     if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
622         remote_connection_role == CONNECTIONROLE_PASSIVE ||
623         remote_connection_role == CONNECTIONROLE_NONE) {
624       is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
625     } else {
626       return webrtc::RTCError(
627           webrtc::RTCErrorType::INVALID_PARAMETER,
628           "Answerer must use either active or passive value "
629           "for setup attribute.");
630     }
631     // If remote is NONE or ACTIVE it will act as client.
632   } else {
633     if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
634         remote_connection_role != CONNECTIONROLE_NONE) {
635       // Accept a remote role attribute that's not "actpass", but matches the
636       // current negotiated role. This is allowed by dtls-sdp, though our
637       // implementation will never generate such an offer as it's not
638       // recommended.
639       //
640       // See https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-dtls-sdp,
641       // section 5.5.
642       auto current_dtls_role = GetDtlsRole();
643       if (!current_dtls_role ||
644           (*current_dtls_role == rtc::SSL_CLIENT &&
645            remote_connection_role == CONNECTIONROLE_ACTIVE) ||
646           (*current_dtls_role == rtc::SSL_SERVER &&
647            remote_connection_role == CONNECTIONROLE_PASSIVE)) {
648         return webrtc::RTCError(
649             webrtc::RTCErrorType::INVALID_PARAMETER,
650             "Offerer must use actpass value or current negotiated role for "
651             "setup attribute.");
652       }
653     }
654 
655     if (local_connection_role == CONNECTIONROLE_ACTIVE ||
656         local_connection_role == CONNECTIONROLE_PASSIVE) {
657       is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
658     } else {
659       return webrtc::RTCError(
660           webrtc::RTCErrorType::INVALID_PARAMETER,
661           "Answerer must use either active or passive value "
662           "for setup attribute.");
663     }
664 
665     // If local is passive, local will act as server.
666   }
667 
668   *negotiated_dtls_role =
669       (is_remote_server ? rtc::SSL_CLIENT : rtc::SSL_SERVER);
670   return webrtc::RTCError::OK();
671 }
672 
GetTransportStats(DtlsTransportInternal * dtls_transport,int component,TransportStats * stats)673 bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport,
674                                       int component,
675                                       TransportStats* stats) {
676   RTC_DCHECK_RUN_ON(network_thread_);
677   RTC_DCHECK(dtls_transport);
678   TransportChannelStats substats;
679   substats.component = component;
680   dtls_transport->GetSslVersionBytes(&substats.ssl_version_bytes);
681   dtls_transport->GetSrtpCryptoSuite(&substats.srtp_crypto_suite);
682   dtls_transport->GetSslCipherSuite(&substats.ssl_cipher_suite);
683   substats.dtls_state = dtls_transport->dtls_state();
684   if (!dtls_transport->ice_transport()->GetStats(
685           &substats.ice_transport_stats)) {
686     return false;
687   }
688   stats->channel_stats.push_back(substats);
689   return true;
690 }
691 
692 }  // namespace cricket
693