OpenSSLConnection.cpp 3.9 KB

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