SSLErrors.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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/io/async/ssl/SSLErrors.h>
  17. #include <folly/Range.h>
  18. #include <folly/portability/OpenSSL.h>
  19. using namespace folly;
  20. namespace {
  21. std::string decodeOpenSSLError(
  22. int sslError,
  23. unsigned long errError,
  24. int sslOperationReturnValue) {
  25. if (sslError == SSL_ERROR_SYSCALL && errError == 0) {
  26. if (sslOperationReturnValue == 0) {
  27. return "Connection EOF";
  28. } else {
  29. // In this case errno is set, AsyncSocketException will add it.
  30. return "Network error";
  31. }
  32. } else if (sslError == SSL_ERROR_ZERO_RETURN) {
  33. // This signifies a TLS closure alert.
  34. return "SSL connection closed normally";
  35. } else {
  36. std::array<char, 256> buf;
  37. ERR_error_string_n(errError, buf.data(), buf.size());
  38. // OpenSSL will null terminate the string.
  39. return std::string(buf.data());
  40. }
  41. }
  42. const StringPiece getSSLErrorString(SSLError error) {
  43. StringPiece ret;
  44. switch (error) {
  45. case SSLError::CLIENT_RENEGOTIATION:
  46. ret = "Client tried to renegotiate with server";
  47. break;
  48. case SSLError::INVALID_RENEGOTIATION:
  49. ret = "Attempt to start renegotiation, but unsupported";
  50. break;
  51. case SSLError::EARLY_WRITE:
  52. ret = "Attempt to write before SSL connection established";
  53. break;
  54. case SSLError::SSL_ERROR:
  55. ret = "SSL error";
  56. break;
  57. case SSLError::NETWORK_ERROR:
  58. ret = "Network error";
  59. break;
  60. case SSLError::EOF_ERROR:
  61. ret = "SSL connection closed normally";
  62. break;
  63. }
  64. return ret;
  65. }
  66. AsyncSocketException::AsyncSocketExceptionType exTypefromSSLErrInfo(
  67. int sslErr,
  68. unsigned long errError,
  69. int sslOperationReturnValue) {
  70. if (sslErr == SSL_ERROR_ZERO_RETURN) {
  71. return AsyncSocketException::END_OF_FILE;
  72. } else if (sslErr == SSL_ERROR_SYSCALL) {
  73. if (errError == 0 && sslOperationReturnValue == 0) {
  74. return AsyncSocketException::END_OF_FILE;
  75. } else {
  76. return AsyncSocketException::NETWORK_ERROR;
  77. }
  78. } else {
  79. // Assume an actual SSL error
  80. return AsyncSocketException::SSL_ERROR;
  81. }
  82. }
  83. AsyncSocketException::AsyncSocketExceptionType exTypefromSSLErr(SSLError err) {
  84. switch (err) {
  85. case SSLError::EOF_ERROR:
  86. return AsyncSocketException::END_OF_FILE;
  87. case SSLError::NETWORK_ERROR:
  88. return AsyncSocketException::NETWORK_ERROR;
  89. default:
  90. // everything else is a SSL_ERROR
  91. return AsyncSocketException::SSL_ERROR;
  92. }
  93. }
  94. } // namespace
  95. namespace folly {
  96. SSLException::SSLException(
  97. int sslErr,
  98. unsigned long errError,
  99. int sslOperationReturnValue,
  100. int errno_copy)
  101. : AsyncSocketException(
  102. exTypefromSSLErrInfo(sslErr, errError, sslOperationReturnValue),
  103. decodeOpenSSLError(sslErr, errError, sslOperationReturnValue),
  104. sslErr == SSL_ERROR_SYSCALL ? errno_copy : 0) {
  105. if (sslErr == SSL_ERROR_ZERO_RETURN) {
  106. sslError = SSLError::EOF_ERROR;
  107. } else if (sslErr == SSL_ERROR_SYSCALL) {
  108. sslError = SSLError::NETWORK_ERROR;
  109. } else {
  110. // Conservatively assume that this is an SSL error
  111. sslError = SSLError::SSL_ERROR;
  112. }
  113. }
  114. SSLException::SSLException(SSLError error)
  115. : AsyncSocketException(
  116. exTypefromSSLErr(error),
  117. getSSLErrorString(error).str(),
  118. 0),
  119. sslError(error) {}
  120. } // namespace folly