OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2016 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/base/rtccertificategenerator.h" | |
12 | |
13 #include <algorithm> | |
14 #include <memory> | |
15 | |
16 #include "webrtc/base/checks.h" | |
17 #include "webrtc/base/sslidentity.h" | |
18 | |
19 namespace rtc { | |
20 | |
21 namespace { | |
22 | |
23 // A certificates' subject and issuer name. | |
24 const char kIdentityName[] = "WebRTC"; | |
25 | |
26 uint64_t kYearInSeconds = 365 * 24 * 60 * 60; | |
27 | |
28 enum { | |
29 MSG_GENERATE, | |
30 MSG_GENERATE_DONE, | |
31 }; | |
32 | |
33 // Helper class for generating certificates asynchronously; a single task | |
34 // instance is responsible for a single asynchronous certificate generation | |
35 // request. We are using a separate helper class so that a generation request | |
36 // can outlive the |RTCCertificateGenerator| that spawned it. | |
37 class RTCCertificateGenerationTask : public RefCountInterface, | |
38 public MessageHandler { | |
39 public: | |
40 RTCCertificateGenerationTask( | |
41 Thread* signaling_thread, | |
42 Thread* worker_thread, | |
43 const KeyParams& key_params, | |
44 const Optional<uint64_t>& expires_ms, | |
45 const scoped_refptr<RTCCertificateGeneratorCallback>& callback) | |
46 : signaling_thread_(signaling_thread), | |
47 worker_thread_(worker_thread), | |
48 key_params_(key_params), | |
49 expires_ms_(expires_ms), | |
50 callback_(callback) { | |
51 RTC_DCHECK(signaling_thread_); | |
52 RTC_DCHECK(worker_thread_); | |
53 RTC_DCHECK(callback_); | |
54 } | |
55 ~RTCCertificateGenerationTask() override {} | |
56 | |
57 // Handles |MSG_GENERATE| and its follow-up |MSG_GENERATE_DONE|. | |
58 void OnMessage(Message* msg) override { | |
59 switch (msg->message_id) { | |
60 case MSG_GENERATE: | |
61 RTC_DCHECK(worker_thread_->IsCurrent()); | |
62 | |
63 // Perform the certificate generation work here on the worker thread. | |
64 certificate_ = RTCCertificateGenerator::GenerateCertificate( | |
65 key_params_, expires_ms_); | |
66 | |
67 // Handle callbacks on signaling thread. Pass on the |msg->pdata| | |
68 // (which references |this| with ref counting) to that thread. | |
69 signaling_thread_->Post(RTC_FROM_HERE, this, MSG_GENERATE_DONE, | |
70 msg->pdata); | |
71 break; | |
72 case MSG_GENERATE_DONE: | |
73 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
74 | |
75 // Perform callback with result here on the signaling thread. | |
76 if (certificate_) { | |
77 callback_->OnSuccess(certificate_); | |
78 } else { | |
79 callback_->OnFailure(); | |
80 } | |
81 | |
82 // Destroy |msg->pdata| which references |this| with ref counting. This | |
83 // may result in |this| being deleted - do not touch member variables | |
84 // after this line. | |
85 delete msg->pdata; | |
86 return; | |
87 default: | |
88 RTC_NOTREACHED(); | |
89 } | |
90 } | |
91 | |
92 private: | |
93 Thread* const signaling_thread_; | |
94 Thread* const worker_thread_; | |
95 const KeyParams key_params_; | |
96 const Optional<uint64_t> expires_ms_; | |
97 const scoped_refptr<RTCCertificateGeneratorCallback> callback_; | |
98 scoped_refptr<RTCCertificate> certificate_; | |
99 }; | |
100 | |
101 } // namespace | |
102 | |
103 // static | |
104 scoped_refptr<RTCCertificate> | |
105 RTCCertificateGenerator::GenerateCertificate( | |
106 const KeyParams& key_params, | |
107 const Optional<uint64_t>& expires_ms) { | |
108 if (!key_params.IsValid()) | |
109 return nullptr; | |
110 SSLIdentity* identity; | |
111 if (!expires_ms) { | |
112 identity = SSLIdentity::Generate(kIdentityName, key_params); | |
113 } else { | |
114 uint64_t expires_s = *expires_ms / 1000; | |
115 // Limit the expiration time to something reasonable (a year). This was | |
116 // somewhat arbitrarily chosen. It also ensures that the value is not too | |
117 // large for the unspecified |time_t|. | |
118 expires_s = std::min(expires_s, kYearInSeconds); | |
119 // TODO(torbjorng): Stop using |time_t|, its type is unspecified. It it safe | |
120 // to assume it can hold up to a year's worth of seconds (and more), but | |
121 // |SSLIdentity::Generate| should stop relying on |time_t|. | |
122 // See bugs.webrtc.org/5720. | |
123 time_t cert_lifetime_s = static_cast<time_t>(expires_s); | |
124 identity = SSLIdentity::GenerateWithExpiration( | |
125 kIdentityName, key_params, cert_lifetime_s); | |
126 } | |
127 if (!identity) | |
128 return nullptr; | |
129 std::unique_ptr<SSLIdentity> identity_sptr(identity); | |
130 return RTCCertificate::Create(std::move(identity_sptr)); | |
131 } | |
132 | |
133 RTCCertificateGenerator::RTCCertificateGenerator( | |
134 Thread* signaling_thread, Thread* worker_thread) | |
135 : signaling_thread_(signaling_thread), | |
136 worker_thread_(worker_thread) { | |
137 RTC_DCHECK(signaling_thread_); | |
138 RTC_DCHECK(worker_thread_); | |
139 } | |
140 | |
141 void RTCCertificateGenerator::GenerateCertificateAsync( | |
142 const KeyParams& key_params, | |
143 const Optional<uint64_t>& expires_ms, | |
144 const scoped_refptr<RTCCertificateGeneratorCallback>& callback) { | |
145 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
146 RTC_DCHECK(callback); | |
147 | |
148 // Create a new |RTCCertificateGenerationTask| for this generation request. It | |
149 // is reference counted and referenced by the message data, ensuring it lives | |
150 // until the task has completed (independent of |RTCCertificateGenerator|). | |
151 ScopedRefMessageData<RTCCertificateGenerationTask>* msg_data = | |
152 new ScopedRefMessageData<RTCCertificateGenerationTask>( | |
153 new RefCountedObject<RTCCertificateGenerationTask>( | |
154 signaling_thread_, worker_thread_, key_params, expires_ms, | |
155 callback)); | |
156 worker_thread_->Post(RTC_FROM_HERE, msg_data->data().get(), MSG_GENERATE, | |
157 msg_data); | |
158 } | |
159 | |
160 } // namespace rtc | |
OLD | NEW |