OpenSSLConnection.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #include "OpenSSLConnection.h"
  2. #ifdef HTTPS_BACKEND_OPENSSL
  3. #include "../common/LibraryLoader.h"
  4. // Not present in openssl 1.1 headers
  5. #define SSL_CTRL_OPTIONS 32
  6. static bool TryOpenLibraries(const char *sslName, LibraryLoader::handle *& sslHandle, const char *cryptoName, LibraryLoader::handle *&cryptoHandle)
  7. {
  8. sslHandle = LibraryLoader::OpenLibrary(sslName);
  9. cryptoHandle = LibraryLoader::OpenLibrary(cryptoName);
  10. if (sslHandle && cryptoHandle)
  11. return true;
  12. if (sslHandle)
  13. LibraryLoader::CloseLibrary(sslHandle);
  14. if (cryptoHandle)
  15. LibraryLoader::CloseLibrary(cryptoHandle);
  16. return false;
  17. }
  18. OpenSSLConnection::SSLFuncs::SSLFuncs()
  19. {
  20. using namespace LibraryLoader;
  21. handle *sslhandle = nullptr;
  22. handle *cryptohandle = nullptr;
  23. valid = TryOpenLibraries("libssl.so.3", sslhandle, "libcrypto.so.3", cryptohandle)
  24. || TryOpenLibraries("libssl.so.1.1", sslhandle, "libcrypto.so.1.1", cryptohandle)
  25. || TryOpenLibraries("libssl.so.1.0.0", sslhandle, "libcrypto.so.1.0.0", cryptohandle)
  26. // Try the version-less name last, it may not be compatible or tested
  27. || TryOpenLibraries("libssl.so", sslhandle, "libcrypto.so", cryptohandle);
  28. if (!valid)
  29. return;
  30. valid = true;
  31. valid = valid && (
  32. LoadSymbol(init_ssl, sslhandle, "OPENSSL_init_ssl") ||
  33. LoadSymbol(library_init, sslhandle, "SSL_library_init"));
  34. valid = valid && LoadSymbol(CTX_new, sslhandle, "SSL_CTX_new");
  35. valid = valid && LoadSymbol(CTX_ctrl, sslhandle, "SSL_CTX_ctrl");
  36. if (valid)
  37. LoadSymbol(CTX_set_options, sslhandle, "SSL_CTX_set_options");
  38. valid = valid && LoadSymbol(CTX_set_verify, sslhandle, "SSL_CTX_set_verify");
  39. valid = valid && LoadSymbol(CTX_set_default_verify_paths, sslhandle, "SSL_CTX_set_default_verify_paths");
  40. valid = valid && LoadSymbol(CTX_free, sslhandle, "SSL_CTX_free");
  41. valid = valid && LoadSymbol(SSL_new, sslhandle, "SSL_new");
  42. valid = valid && LoadSymbol(SSL_free, sslhandle, "SSL_free");
  43. valid = valid && LoadSymbol(set_fd, sslhandle, "SSL_set_fd");
  44. valid = valid && LoadSymbol(connect, sslhandle, "SSL_connect");
  45. valid = valid && LoadSymbol(read, sslhandle, "SSL_read");
  46. valid = valid && LoadSymbol(write, sslhandle, "SSL_write");
  47. valid = valid && LoadSymbol(shutdown, sslhandle, "SSL_shutdown");
  48. valid = valid && LoadSymbol(get_verify_result, sslhandle, "SSL_get_verify_result");
  49. valid = valid && (LoadSymbol(get_peer_certificate, sslhandle, "SSL_get1_peer_certificate") ||
  50. LoadSymbol(get_peer_certificate, sslhandle, "SSL_get_peer_certificate"));
  51. valid = valid && (
  52. LoadSymbol(SSLv23_method, sslhandle, "TLS_client_method") ||
  53. LoadSymbol(SSLv23_method, sslhandle, "TLS_method") ||
  54. LoadSymbol(SSLv23_method, sslhandle, "SSLv23_method"));
  55. valid = valid && LoadSymbol(check_host, cryptohandle, "X509_check_host");
  56. valid = valid && LoadSymbol(X509_free, cryptohandle, "X509_free");
  57. if (library_init)
  58. library_init();
  59. else if(init_ssl)
  60. init_ssl(0, nullptr);
  61. // else not valid
  62. }
  63. bool OpenSSLConnection::valid()
  64. {
  65. return ssl.valid;
  66. }
  67. OpenSSLConnection::OpenSSLConnection()
  68. : conn(nullptr)
  69. {
  70. context = ssl.CTX_new(ssl.SSLv23_method());
  71. if (!context)
  72. return;
  73. if (ssl.CTX_set_options)
  74. ssl.CTX_set_options(context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
  75. else
  76. ssl.CTX_ctrl(context, SSL_CTRL_OPTIONS, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3, nullptr);
  77. ssl.CTX_set_verify(context, SSL_VERIFY_PEER, nullptr);
  78. ssl.CTX_set_default_verify_paths(context);
  79. }
  80. OpenSSLConnection::~OpenSSLConnection()
  81. {
  82. if (conn)
  83. ssl.SSL_free(conn);
  84. if (context)
  85. ssl.CTX_free(context);
  86. }
  87. bool OpenSSLConnection::connect(const std::string &hostname, uint16_t port)
  88. {
  89. if (!context)
  90. return false;
  91. if (!socket.connect(hostname, port))
  92. return false;
  93. conn = ssl.SSL_new(context);
  94. if (!conn)
  95. {
  96. socket.close();
  97. return false;
  98. }
  99. ssl.set_fd(conn, socket.getFd());
  100. if (ssl.connect(conn) != 1 || ssl.get_verify_result(conn) != X509_V_OK)
  101. {
  102. socket.close();
  103. return false;
  104. }
  105. X509 *cert = ssl.get_peer_certificate(conn);
  106. if (ssl.check_host(cert, hostname.c_str(), hostname.size(), 0, nullptr) != 1)
  107. {
  108. close();
  109. return false;
  110. }
  111. ssl.X509_free(cert);
  112. return true;
  113. }
  114. size_t OpenSSLConnection::read(char *buffer, size_t size)
  115. {
  116. return ssl.read(conn, buffer, (int) size);
  117. }
  118. size_t OpenSSLConnection::write(const char *buffer, size_t size)
  119. {
  120. return ssl.write(conn, buffer, (int) size);
  121. }
  122. void OpenSSLConnection::close()
  123. {
  124. ssl.shutdown(conn);
  125. socket.close();
  126. }
  127. OpenSSLConnection::SSLFuncs OpenSSLConnection::ssl;
  128. #endif // HTTPS_BACKEND_OPENSSL