• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2012 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 "p2p/base/transport_description_factory.h"
12 
13 #include <stddef.h>
14 
15 #include <memory>
16 #include <string>
17 
18 #include "p2p/base/transport_description.h"
19 #include "rtc_base/logging.h"
20 #include "rtc_base/ssl_fingerprint.h"
21 
22 namespace cricket {
23 
TransportDescriptionFactory()24 TransportDescriptionFactory::TransportDescriptionFactory()
25     : secure_(SEC_DISABLED) {}
26 
27 TransportDescriptionFactory::~TransportDescriptionFactory() = default;
28 
CreateOffer(const TransportOptions & options,const TransportDescription * current_description,IceCredentialsIterator * ice_credentials) const29 std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateOffer(
30     const TransportOptions& options,
31     const TransportDescription* current_description,
32     IceCredentialsIterator* ice_credentials) const {
33   auto desc = std::make_unique<TransportDescription>();
34 
35   // Generate the ICE credentials if we don't already have them.
36   if (!current_description || options.ice_restart) {
37     IceParameters credentials = ice_credentials->GetIceCredentials();
38     desc->ice_ufrag = credentials.ufrag;
39     desc->ice_pwd = credentials.pwd;
40   } else {
41     desc->ice_ufrag = current_description->ice_ufrag;
42     desc->ice_pwd = current_description->ice_pwd;
43   }
44   desc->AddOption(ICE_OPTION_TRICKLE);
45   if (options.enable_ice_renomination) {
46     desc->AddOption(ICE_OPTION_RENOMINATION);
47   }
48 
49   // If we are trying to establish a secure transport, add a fingerprint.
50   if (secure_ == SEC_ENABLED || secure_ == SEC_REQUIRED) {
51     // Fail if we can't create the fingerprint.
52     // If we are the initiator set role to "actpass".
53     if (!SetSecurityInfo(desc.get(), CONNECTIONROLE_ACTPASS)) {
54       return NULL;
55     }
56   }
57 
58   return desc;
59 }
60 
CreateAnswer(const TransportDescription * offer,const TransportOptions & options,bool require_transport_attributes,const TransportDescription * current_description,IceCredentialsIterator * ice_credentials) const61 std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateAnswer(
62     const TransportDescription* offer,
63     const TransportOptions& options,
64     bool require_transport_attributes,
65     const TransportDescription* current_description,
66     IceCredentialsIterator* ice_credentials) const {
67   // TODO(juberti): Figure out why we get NULL offers, and fix this upstream.
68   if (!offer) {
69     RTC_LOG(LS_WARNING) << "Failed to create TransportDescription answer "
70                            "because offer is NULL";
71     return NULL;
72   }
73 
74   auto desc = std::make_unique<TransportDescription>();
75   // Generate the ICE credentials if we don't already have them or ice is
76   // being restarted.
77   if (!current_description || options.ice_restart) {
78     IceParameters credentials = ice_credentials->GetIceCredentials();
79     desc->ice_ufrag = credentials.ufrag;
80     desc->ice_pwd = credentials.pwd;
81   } else {
82     desc->ice_ufrag = current_description->ice_ufrag;
83     desc->ice_pwd = current_description->ice_pwd;
84   }
85   desc->AddOption(ICE_OPTION_TRICKLE);
86   if (options.enable_ice_renomination) {
87     desc->AddOption(ICE_OPTION_RENOMINATION);
88   }
89 
90   // Negotiate security params.
91   if (offer && offer->identity_fingerprint.get()) {
92     // The offer supports DTLS, so answer with DTLS, as long as we support it.
93     if (secure_ == SEC_ENABLED || secure_ == SEC_REQUIRED) {
94       // Fail if we can't create the fingerprint.
95       // Setting DTLS role to active.
96       ConnectionRole role = (options.prefer_passive_role)
97                                 ? CONNECTIONROLE_PASSIVE
98                                 : CONNECTIONROLE_ACTIVE;
99 
100       if (!SetSecurityInfo(desc.get(), role)) {
101         return NULL;
102       }
103     }
104   } else if (require_transport_attributes && secure_ == SEC_REQUIRED) {
105     // We require DTLS, but the other side didn't offer it. Fail.
106     RTC_LOG(LS_WARNING) << "Failed to create TransportDescription answer "
107                            "because of incompatible security settings";
108     return NULL;
109   }
110 
111   return desc;
112 }
113 
SetSecurityInfo(TransportDescription * desc,ConnectionRole role) const114 bool TransportDescriptionFactory::SetSecurityInfo(TransportDescription* desc,
115                                                   ConnectionRole role) const {
116   if (!certificate_) {
117     RTC_LOG(LS_ERROR) << "Cannot create identity digest with no certificate";
118     return false;
119   }
120 
121   // This digest algorithm is used to produce the a=fingerprint lines in SDP.
122   // RFC 4572 Section 5 requires that those lines use the same hash function as
123   // the certificate's signature, which is what CreateFromCertificate does.
124   desc->identity_fingerprint =
125       rtc::SSLFingerprint::CreateFromCertificate(*certificate_);
126   if (!desc->identity_fingerprint) {
127     return false;
128   }
129 
130   // Assign security role.
131   desc->connection_role = role;
132   return true;
133 }
134 
135 }  // namespace cricket
136