SSLSessionTest.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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. #include <folly/ssl/SSLSession.h>
  17. #include <folly/io/async/test/AsyncSSLSocketTest.h>
  18. #include <folly/portability/GTest.h>
  19. #include <folly/portability/Sockets.h>
  20. #include <memory>
  21. using namespace std;
  22. using namespace testing;
  23. using folly::ssl::SSLSession;
  24. namespace folly {
  25. void getfds(int fds[2]) {
  26. if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) != 0) {
  27. LOG(ERROR) << "failed to create socketpair: " << errnoStr(errno);
  28. }
  29. for (int idx = 0; idx < 2; ++idx) {
  30. int flags = fcntl(fds[idx], F_GETFL, 0);
  31. if (flags == -1) {
  32. LOG(ERROR) << "failed to get flags for socket " << idx << ": "
  33. << errnoStr(errno);
  34. }
  35. if (fcntl(fds[idx], F_SETFL, flags | O_NONBLOCK) != 0) {
  36. LOG(ERROR) << "failed to put socket " << idx
  37. << " in non-blocking mode: " << errnoStr(errno);
  38. }
  39. }
  40. }
  41. void getctx(
  42. std::shared_ptr<folly::SSLContext> clientCtx,
  43. std::shared_ptr<folly::SSLContext> serverCtx) {
  44. clientCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
  45. serverCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
  46. serverCtx->loadCertificate(kTestCert);
  47. serverCtx->loadPrivateKey(kTestKey);
  48. }
  49. class SSLSessionTest : public testing::Test {
  50. public:
  51. void SetUp() override {
  52. clientCtx.reset(new folly::SSLContext());
  53. dfServerCtx.reset(new folly::SSLContext());
  54. hskServerCtx.reset(new folly::SSLContext());
  55. serverName = "xyz.newdev.facebook.com";
  56. getctx(clientCtx, dfServerCtx);
  57. }
  58. void TearDown() override {}
  59. folly::EventBase eventBase;
  60. std::shared_ptr<SSLContext> clientCtx;
  61. std::shared_ptr<SSLContext> dfServerCtx;
  62. // Use the same SSLContext to continue the handshake after
  63. // tlsext_hostname match.
  64. std::shared_ptr<SSLContext> hskServerCtx;
  65. std::string serverName;
  66. };
  67. /**
  68. * 1. Client sends TLSEXT_HOSTNAME in client hello.
  69. * 2. Server found a match SSL_CTX and use this SSL_CTX to
  70. * continue the SSL handshake.
  71. * 3. Server sends back TLSEXT_HOSTNAME in server hello.
  72. */
  73. TEST_F(SSLSessionTest, BasicTest) {
  74. std::unique_ptr<SSLSession> sess;
  75. {
  76. int fds[2];
  77. getfds(fds);
  78. AsyncSSLSocket::UniquePtr clientSock(
  79. new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
  80. auto clientPtr = clientSock.get();
  81. AsyncSSLSocket::UniquePtr serverSock(
  82. new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
  83. SSLHandshakeClient client(std::move(clientSock), false, false);
  84. SSLHandshakeServerParseClientHello server(
  85. std::move(serverSock), false, false);
  86. eventBase.loop();
  87. ASSERT_TRUE(client.handshakeSuccess_);
  88. sess = std::make_unique<SSLSession>(clientPtr->getSSLSession());
  89. ASSERT_NE(sess.get(), nullptr);
  90. }
  91. {
  92. int fds[2];
  93. getfds(fds);
  94. AsyncSSLSocket::UniquePtr clientSock(
  95. new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
  96. auto clientPtr = clientSock.get();
  97. clientSock->setSSLSession(sess->getRawSSLSessionDangerous(), true);
  98. AsyncSSLSocket::UniquePtr serverSock(
  99. new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
  100. SSLHandshakeClient client(std::move(clientSock), false, false);
  101. SSLHandshakeServerParseClientHello server(
  102. std::move(serverSock), false, false);
  103. eventBase.loop();
  104. ASSERT_TRUE(client.handshakeSuccess_);
  105. ASSERT_TRUE(clientPtr->getSSLSessionReused());
  106. }
  107. }
  108. TEST_F(SSLSessionTest, SerializeDeserializeTest) {
  109. std::string sessiondata;
  110. {
  111. int fds[2];
  112. getfds(fds);
  113. AsyncSSLSocket::UniquePtr clientSock(
  114. new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
  115. auto clientPtr = clientSock.get();
  116. AsyncSSLSocket::UniquePtr serverSock(
  117. new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
  118. SSLHandshakeClient client(std::move(clientSock), false, false);
  119. SSLHandshakeServerParseClientHello server(
  120. std::move(serverSock), false, false);
  121. eventBase.loop();
  122. ASSERT_TRUE(client.handshakeSuccess_);
  123. std::unique_ptr<SSLSession> sess =
  124. std::make_unique<SSLSession>(clientPtr->getSSLSession());
  125. sessiondata = sess->serialize();
  126. ASSERT_TRUE(!sessiondata.empty());
  127. }
  128. {
  129. int fds[2];
  130. getfds(fds);
  131. AsyncSSLSocket::UniquePtr clientSock(
  132. new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
  133. auto clientPtr = clientSock.get();
  134. std::unique_ptr<SSLSession> sess =
  135. std::make_unique<SSLSession>(sessiondata);
  136. ASSERT_NE(sess.get(), nullptr);
  137. clientSock->setSSLSession(sess->getRawSSLSessionDangerous(), true);
  138. AsyncSSLSocket::UniquePtr serverSock(
  139. new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
  140. SSLHandshakeClient client(std::move(clientSock), false, false);
  141. SSLHandshakeServerParseClientHello server(
  142. std::move(serverSock), false, false);
  143. eventBase.loop();
  144. ASSERT_TRUE(client.handshakeSuccess_);
  145. ASSERT_TRUE(clientPtr->getSSLSessionReused());
  146. }
  147. }
  148. TEST_F(SSLSessionTest, GetSessionID) {
  149. int fds[2];
  150. getfds(fds);
  151. AsyncSSLSocket::UniquePtr clientSock(
  152. new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
  153. auto clientPtr = clientSock.get();
  154. AsyncSSLSocket::UniquePtr serverSock(
  155. new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
  156. SSLHandshakeClient client(std::move(clientSock), false, false);
  157. SSLHandshakeServerParseClientHello server(
  158. std::move(serverSock), false, false);
  159. eventBase.loop();
  160. ASSERT_TRUE(client.handshakeSuccess_);
  161. std::unique_ptr<SSLSession> sess =
  162. std::make_unique<SSLSession>(clientPtr->getSSLSession());
  163. ASSERT_NE(sess, nullptr);
  164. auto sessID = sess->getSessionID();
  165. ASSERT_GE(sessID.length(), 0);
  166. }
  167. } // namespace folly