proxygen
SSLSessionCacheUtils.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-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  */
17 
18 #include <memory>
19 
20 #include <folly/io/IOBuf.h>
21 #include <wangle/ssl/SSLUtil.h>
22 
23 namespace wangle {
24 
25 namespace {
26 static int32_t getSessionServiceIdentityIdx() {
27  static int32_t index = []{
28  int result = -1;
30  return result;
31  }();
32  return index;
33 }
34 
35 static SSL_SESSION* fbStringToSession(const folly::fbstring& str) {
36  auto sessionData = reinterpret_cast<const unsigned char*>(str.c_str());
37  // Create a SSL_SESSION and return. In failure it returns nullptr.
38  return d2i_SSL_SESSION(nullptr, &sessionData, str.length());
39 }
40 
41 // serialize and deserialize session data
42 static
43 folly::Optional<folly::fbstring> sessionToFbString(SSL_SESSION* session) {
44  if (!session) {
46  }
47  // Get the length first, then we know how much space to allocate. An invalid
48  // session returns a zero len.
49  int len = i2d_SSL_SESSION(session, nullptr);
50  if (len > 0) {
51  try {
52  auto sessionData = folly::IOBuf::create(len);
53  // i2d_SSL_SESSION increments the pointer pointed to by buf to point one
54  // byte after the saved data (unfortunately, the man page isn't very
55  // clear on this point). That's why we need to save the sessionData in
56  // advance because we will not be able to get it after this call.
57  //
58  // Check this reference:
59  // http://stackoverflow.com/questions/4281992/
60  // fail-to-use-d2i-ssl-session-to-unserialise-ssl-session
61  auto buf = reinterpret_cast<unsigned char*>(sessionData->writableData());
62  len = i2d_SSL_SESSION(session, &buf);
63  if (len > 0) {
64  // Update the amount of data in the IOBuf
65  sessionData->append(len);
66  return folly::Optional<folly::fbstring>(sessionData->moveToFbString());
67  }
68  } catch (const std::bad_alloc& ex) {
69  LOG(ERROR) << "Failed to allocate memory for sessionData: " << ex.what();
70  }
71  }
72 
74 }
75 }
76 
77 bool
78 setSessionServiceIdentity(SSL_SESSION* session, const std::string& str) {
79  if (!session || str.empty()) {
80  return false;
81  }
82  auto serviceExData = new std::string(str);
83  return SSL_SESSION_set_ex_data(
84  session, getSessionServiceIdentityIdx(), serviceExData) > 0;
85 }
86 
88 getSessionServiceIdentity(SSL_SESSION* session) {
89  if (!session) {
91  }
92  auto data = SSL_SESSION_get_ex_data(session, getSessionServiceIdentityIdx());
93  if (!data) {
95  }
96  return *(reinterpret_cast<std::string*>(data));
97 }
98 
100  auto sessionData = sessionToFbString(sess);
101  if (!sessionData) {
103  }
104  SSLSessionCacheData result;
105  result.sessionData = std::move(*sessionData);
106  auto serviceIdentity = getSessionServiceIdentity(sess);
107  if (serviceIdentity) {
108  result.serviceIdentity = std::move(*serviceIdentity);
109  }
110 #ifdef WANGLE_HAVE_SSL_SESSION_DUP
111  result.sessionDuplicateTemplate =
112  std::shared_ptr<SSL_SESSION>(SSL_SESSION_dup(sess), SessionDestructor{});
113 #endif
114  return result;
115 }
116 
118 #ifdef WANGLE_HAVE_SSL_SESSION_DUP
119  if (data.sessionDuplicateTemplate) {
120  return SSL_SESSION_dup(data.sessionDuplicateTemplate.get());
121  }
122 #endif
123  auto result = fbStringToSession(data.sessionData);
124  if (!result) {
125  return nullptr;
126  }
128  return result;
129 }
130 
131 SSL_SESSION* cloneSSLSession(SSL_SESSION* toClone) {
132  if (!toClone) {
133  return nullptr;
134  }
135 
136 #ifdef WANGLE_HAVE_SSL_SESSION_DUP
137  return SSL_SESSION_dup(toClone);
138 #else
139  auto sessionData = sessionToFbString(toClone);
140  if (!sessionData) {
141  return nullptr;
142  }
143  auto clone = fbStringToSession(std::move(*sessionData));
144 
145  if (!clone) {
146  return nullptr;
147  }
148  auto serviceIdentity = getSessionServiceIdentity(toClone);
149  if (serviceIdentity) {
150  setSessionServiceIdentity(clone, serviceIdentity.value());
151  }
152  return clone;
153 #endif
154 }
155 
156 }
const value_type * c_str() const
Definition: FBString.h:1712
bool setSessionServiceIdentity(SSL_SESSION *session, const std::string &str)
static std::unique_ptr< IOBuf > create(std::size_t capacity)
Definition: IOBuf.cpp:229
std::shared_ptr< SSL_SESSION > sessionDuplicateTemplate
static void getSSLSessionExStrIndex(int *pindex)
Definition: SSLUtil.h:138
folly::Optional< std::string > getSessionServiceIdentity(SSL_SESSION *session)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::Optional< SSLSessionCacheData > getCacheDataForSession(SSL_SESSION *sess)
SSL_SESSION * getSessionFromCacheData(const SSLSessionCacheData &data)
std::basic_string< E, T, A > toStdString() const
Definition: FBString.h:1227
SSL_SESSION * cloneSSLSession(SSL_SESSION *toClone)
const char * string
Definition: Conv.cpp:212
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
size_type length() const
Definition: FBString.h:1341