blob: 1c75b322926df936e66b9eb5fccfaded5aa6a5ac [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
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 "webrtc/p2p/base/transportdescriptionfactory.h"
12
kwiberg3ec46792016-04-27 07:22:53 -070013#include <memory>
14
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000015#include "webrtc/p2p/base/transportdescription.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020016#include "webrtc/rtc_base/helpers.h"
17#include "webrtc/rtc_base/logging.h"
18#include "webrtc/rtc_base/messagedigest.h"
19#include "webrtc/rtc_base/sslfingerprint.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000020
21namespace cricket {
22
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000023TransportDescriptionFactory::TransportDescriptionFactory()
Peter Thatcher7cbd1882015-09-17 18:54:52 -070024 : secure_(SEC_DISABLED) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000025}
26
27TransportDescription* TransportDescriptionFactory::CreateOffer(
28 const TransportOptions& options,
29 const TransportDescription* current_description) const {
kwiberg3ec46792016-04-27 07:22:53 -070030 std::unique_ptr<TransportDescription> desc(new TransportDescription());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000031
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000032 // Generate the ICE credentials if we don't already have them.
33 if (!current_description || options.ice_restart) {
34 desc->ice_ufrag = rtc::CreateRandomString(ICE_UFRAG_LENGTH);
35 desc->ice_pwd = rtc::CreateRandomString(ICE_PWD_LENGTH);
36 } else {
37 desc->ice_ufrag = current_description->ice_ufrag;
38 desc->ice_pwd = current_description->ice_pwd;
39 }
deadbeef30952b42017-04-21 02:41:29 -070040 desc->AddOption(ICE_OPTION_TRICKLE);
Honghai Zhang4cedf2b2016-08-31 08:18:11 -070041 if (options.enable_ice_renomination) {
deadbeef30952b42017-04-21 02:41:29 -070042 desc->AddOption(ICE_OPTION_RENOMINATION);
Honghai Zhang4cedf2b2016-08-31 08:18:11 -070043 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000044
45 // If we are trying to establish a secure transport, add a fingerprint.
46 if (secure_ == SEC_ENABLED || secure_ == SEC_REQUIRED) {
47 // Fail if we can't create the fingerprint.
48 // If we are the initiator set role to "actpass".
49 if (!SetSecurityInfo(desc.get(), CONNECTIONROLE_ACTPASS)) {
50 return NULL;
51 }
52 }
53
54 return desc.release();
55}
56
57TransportDescription* TransportDescriptionFactory::CreateAnswer(
58 const TransportDescription* offer,
59 const TransportOptions& options,
deadbeefb7892532017-02-22 19:35:18 -080060 bool require_transport_attributes,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000061 const TransportDescription* current_description) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000062 // TODO(juberti): Figure out why we get NULL offers, and fix this upstream.
Peter Thatcher7cbd1882015-09-17 18:54:52 -070063 if (!offer) {
64 LOG(LS_WARNING) << "Failed to create TransportDescription answer " <<
65 "because offer is NULL";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000066 return NULL;
67 }
68
kwiberg3ec46792016-04-27 07:22:53 -070069 std::unique_ptr<TransportDescription> desc(new TransportDescription());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000070 // Generate the ICE credentials if we don't already have them or ice is
71 // being restarted.
72 if (!current_description || options.ice_restart) {
73 desc->ice_ufrag = rtc::CreateRandomString(ICE_UFRAG_LENGTH);
74 desc->ice_pwd = rtc::CreateRandomString(ICE_PWD_LENGTH);
75 } else {
76 desc->ice_ufrag = current_description->ice_ufrag;
77 desc->ice_pwd = current_description->ice_pwd;
78 }
deadbeef30952b42017-04-21 02:41:29 -070079 desc->AddOption(ICE_OPTION_TRICKLE);
Honghai Zhang4cedf2b2016-08-31 08:18:11 -070080 if (options.enable_ice_renomination) {
deadbeef30952b42017-04-21 02:41:29 -070081 desc->AddOption(ICE_OPTION_RENOMINATION);
Honghai Zhang4cedf2b2016-08-31 08:18:11 -070082 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000083
84 // Negotiate security params.
85 if (offer && offer->identity_fingerprint.get()) {
86 // The offer supports DTLS, so answer with DTLS, as long as we support it.
87 if (secure_ == SEC_ENABLED || secure_ == SEC_REQUIRED) {
88 // Fail if we can't create the fingerprint.
89 // Setting DTLS role to active.
90 ConnectionRole role = (options.prefer_passive_role) ?
91 CONNECTIONROLE_PASSIVE : CONNECTIONROLE_ACTIVE;
92
93 if (!SetSecurityInfo(desc.get(), role)) {
94 return NULL;
95 }
96 }
deadbeefb7892532017-02-22 19:35:18 -080097 } else if (require_transport_attributes && secure_ == SEC_REQUIRED) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000098 // We require DTLS, but the other side didn't offer it. Fail.
99 LOG(LS_WARNING) << "Failed to create TransportDescription answer "
100 "because of incompatible security settings";
101 return NULL;
102 }
103
104 return desc.release();
105}
106
107bool TransportDescriptionFactory::SetSecurityInfo(
108 TransportDescription* desc, ConnectionRole role) const {
Henrik Boström3a14bf32015-08-31 09:27:58 +0200109 if (!certificate_) {
110 LOG(LS_ERROR) << "Cannot create identity digest with no certificate";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000111 return false;
112 }
113
114 // This digest algorithm is used to produce the a=fingerprint lines in SDP.
115 // RFC 4572 Section 5 requires that those lines use the same hash function as
deadbeef8662f942017-01-20 21:20:51 -0800116 // the certificate's signature, which is what CreateFromCertificate does.
117 desc->identity_fingerprint.reset(
118 rtc::SSLFingerprint::CreateFromCertificate(certificate_));
119 if (!desc->identity_fingerprint) {
120 return false;
121 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000122 std::string digest_alg;
Henrik Boström3a14bf32015-08-31 09:27:58 +0200123 if (!certificate_->ssl_certificate().GetSignatureDigestAlgorithm(
124 &digest_alg)) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000125 LOG(LS_ERROR) << "Failed to retrieve the certificate's digest algorithm";
126 return false;
127 }
128
129 desc->identity_fingerprint.reset(
Henrik Boström3a14bf32015-08-31 09:27:58 +0200130 rtc::SSLFingerprint::Create(digest_alg, certificate_->identity()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000131 if (!desc->identity_fingerprint.get()) {
132 LOG(LS_ERROR) << "Failed to create identity fingerprint, alg="
133 << digest_alg;
134 return false;
135 }
136
137 // Assign security role.
138 desc->connection_role = role;
139 return true;
140}
141
142} // namespace cricket