1 | /* |
2 | * Copyright 2016-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #include <folly/ssl/detail/SSLSessionImpl.h> |
18 | #include <folly/portability/OpenSSL.h> |
19 | #include <folly/ssl/OpenSSLVersionFinder.h> |
20 | |
21 | namespace folly { |
22 | namespace ssl { |
23 | namespace detail { |
24 | |
25 | // |
26 | // Wrapper OpenSSL 1.0.2 (and possibly 1.0.1) |
27 | // |
28 | |
29 | SSLSessionImpl::SSLSessionImpl(SSL_SESSION* session, bool takeOwnership) |
30 | : session_(session) { |
31 | if (session_ == nullptr) { |
32 | throw std::runtime_error("SSL_SESSION is null" ); |
33 | } |
34 | // If we're not given ownership, we need to up the refcount so the SSL_SESSION |
35 | // object won't be freed while SSLSessionImpl is alive |
36 | if (!takeOwnership) { |
37 | upRef(); |
38 | } |
39 | } |
40 | |
41 | SSLSessionImpl::SSLSessionImpl(const std::string& serializedSession) { |
42 | auto sessionData = |
43 | reinterpret_cast<const unsigned char*>(serializedSession.data()); |
44 | auto longLen = long(serializedSession.length()); |
45 | if ((session_ = d2i_SSL_SESSION(nullptr, &sessionData, longLen)) == nullptr) { |
46 | throw std::runtime_error("Cannot deserialize SSLSession string" ); |
47 | } |
48 | } |
49 | |
50 | SSLSessionImpl::~SSLSessionImpl() { |
51 | downRef(); |
52 | } |
53 | |
54 | std::string SSLSessionImpl::serialize() const { |
55 | std::string ret; |
56 | |
57 | // Get the length first, then we know how much space to allocate. |
58 | auto len = i2d_SSL_SESSION(session_, nullptr); |
59 | |
60 | if (len > 0) { |
61 | std::unique_ptr<unsigned char[]> uptr(new unsigned char[size_t(len)]); |
62 | auto p = uptr.get(); |
63 | auto written = i2d_SSL_SESSION(session_, &p); |
64 | if (written <= 0) { |
65 | VLOG(2) << "Could not serialize SSL_SESSION!" ; |
66 | } else { |
67 | ret.assign(uptr.get(), uptr.get() + written); |
68 | } |
69 | } |
70 | return ret; |
71 | } |
72 | |
73 | std::string SSLSessionImpl::getSessionID() const { |
74 | std::string ret; |
75 | if (session_) { |
76 | const unsigned char* ptr = nullptr; |
77 | unsigned int len = 0; |
78 | ptr = SSL_SESSION_get_id(session_, &len); |
79 | ret.assign(ptr, ptr + len); |
80 | } |
81 | return ret; |
82 | } |
83 | |
84 | const SSL_SESSION* SSLSessionImpl::getRawSSLSession() const { |
85 | return const_cast<SSL_SESSION*>(session_); |
86 | } |
87 | |
88 | SSL_SESSION* SSLSessionImpl::getRawSSLSessionDangerous() { |
89 | upRef(); |
90 | return session_; |
91 | } |
92 | |
93 | void SSLSessionImpl::upRef() { |
94 | if (session_) { |
95 | SSL_SESSION_up_ref(session_); |
96 | } |
97 | } |
98 | |
99 | void SSLSessionImpl::downRef() { |
100 | if (session_) { |
101 | SSL_SESSION_free(session_); |
102 | } |
103 | } |
104 | |
105 | } // namespace detail |
106 | } // namespace ssl |
107 | } // namespace folly |
108 | |