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