📄 openssladapter.cc
字号:
#ifdef _HAVE_OPENSSL#include <openssl/bio.h>#include <openssl/ssl.h>#include <openssl/err.h>#include <openssl/x509v3.h>#include "common.h"#include "logging.h"#include "openssladapter.h"#include "stringutils.h"#include "Equifax_Secure_Global_eBusiness_CA-1.h"//////////////////////////////////////////////////////////////////////// StreamBIO//////////////////////////////////////////////////////////////////////#if 0static int stream_write(BIO* h, const char* buf, int num);static int stream_read(BIO* h, char* buf, int size);static int stream_puts(BIO* h, const char* str);static long stream_ctrl(BIO* h, int cmd, long arg1, void* arg2);static int stream_new(BIO* h);static int stream_free(BIO* data);static BIO_METHOD methods_stream = { BIO_TYPE_BIO, "stream", stream_write, stream_read, stream_puts, 0, stream_ctrl, stream_new, stream_free, NULL,};BIO_METHOD* BIO_s_stream() { return(&methods_stream); }BIO* BIO_new_stream(StreamInterface* stream) { BIO* ret = BIO_new(BIO_s_stream()); if (ret == NULL) return NULL; ret->ptr = stream; return ret;}static int stream_new(BIO* b) { b->shutdown = 0; b->init = 1; b->num = 0; // 1 means end-of-stream b->ptr = 0; return 1;}static int stream_free(BIO* b) { if (b == NULL) return 0; return 1;}static int stream_read(BIO* b, char* out, int outl) { if (!out) return -1; StreamInterface* stream = static_cast<StreamInterface*>(b->ptr); BIO_clear_retry_flags(b); size_t read; int error; StreamResult result = stream->Read(out, outl, &read, &error); if (result == SR_SUCCESS) { return read; } else if (result == SR_EOS) { b->num = 1; } else if (result == SR_BLOCK) { BIO_set_retry_read(b); } return -1;}static int stream_write(BIO* b, const char* in, int inl) { if (!in) return -1; StreamInterface* stream = static_cast<StreamInterface*>(b->ptr); BIO_clear_retry_flags(b); size_t written; int error; StreamResult result = stream->Write(in, inl, &written, &error); if (result == SR_SUCCESS) { return written; } else if (result == SR_BLOCK) { BIO_set_retry_write(b); } return -1;}static int stream_puts(BIO* b, const char* str) { return stream_write(b, str, strlen(str));}static long stream_ctrl(BIO* b, int cmd, long num, void* ptr) { UNUSED(num); UNUSED(ptr); switch (cmd) { case BIO_CTRL_RESET: return 0; case BIO_CTRL_EOF: return b->num; case BIO_CTRL_WPENDING: case BIO_CTRL_PENDING: return 0; case BIO_CTRL_FLUSH: return 1; default: return 0; }}#endif//////////////////////////////////////////////////////////////////////// SocketBIO//////////////////////////////////////////////////////////////////////static int socket_write(BIO* h, const char* buf, int num);static int socket_read(BIO* h, char* buf, int size);static int socket_puts(BIO* h, const char* str);static long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2);static int socket_new(BIO* h);static int socket_free(BIO* data);static BIO_METHOD methods_socket = { BIO_TYPE_BIO, "socket", socket_write, socket_read, socket_puts, 0, socket_ctrl, socket_new, socket_free, NULL,};BIO_METHOD* BIO_s_socket2() { return(&methods_socket); }BIO* BIO_new_socket(talk_base::AsyncSocket* socket) { BIO* ret = BIO_new(BIO_s_socket2()); if (ret == NULL) { return NULL; } ret->ptr = socket; return ret;}static int socket_new(BIO* b) { b->shutdown = 0; b->init = 1; b->num = 0; // 1 means socket closed b->ptr = 0; return 1;}static int socket_free(BIO* b) { if (b == NULL) return 0; return 1;}static int socket_read(BIO* b, char* out, int outl) { if (!out) return -1; talk_base::AsyncSocket* socket = static_cast<talk_base::AsyncSocket*>(b->ptr); BIO_clear_retry_flags(b); int result = socket->Recv(out, outl); if (result > 0) { return result; } else if (result == 0) { b->num = 1; } else if (socket->IsBlocking()) { BIO_set_retry_read(b); } return -1;}static int socket_write(BIO* b, const char* in, int inl) { if (!in) return -1; talk_base::AsyncSocket* socket = static_cast<talk_base::AsyncSocket*>(b->ptr); BIO_clear_retry_flags(b); int result = socket->Send(in, inl); if (result > 0) { return result; } else if (socket->IsBlocking()) { BIO_set_retry_write(b); } return -1;}static int socket_puts(BIO* b, const char* str) { return socket_write(b, str, strlen(str));}static long socket_ctrl(BIO* b, int cmd, long num, void* ptr) { UNUSED(num); UNUSED(ptr); switch (cmd) { case BIO_CTRL_RESET: return 0; case BIO_CTRL_EOF: return b->num; case BIO_CTRL_WPENDING: case BIO_CTRL_PENDING: return 0; case BIO_CTRL_FLUSH: return 1; default: return 0; }}/////////////////////////////////////////////////////////////////////////////// OpenSSLAdapter/////////////////////////////////////////////////////////////////////////////namespace talk_base {OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket) : SSLAdapter(socket), state_(SSL_NONE), ssl_read_needs_write_(false), ssl_write_needs_read_(false), restartable_(false), ssl_(NULL), ssl_ctx_(NULL) {}OpenSSLAdapter::~OpenSSLAdapter() { Cleanup();}intOpenSSLAdapter::StartSSL(const char* hostname, bool restartable) { if (state_ != SSL_NONE) return -1; ssl_host_name_ = hostname; restartable_ = restartable; if (socket_->GetState() != Socket::CS_CONNECTED) { state_ = SSL_WAIT; return 0; } state_ = SSL_CONNECTING; if (int err = BeginSSL()) { Error("BeginSSL", err, false); return err; } return 0;}intOpenSSLAdapter::BeginSSL() { LOG(LS_INFO) << "BeginSSL: " << ssl_host_name_; ASSERT(state_ == SSL_CONNECTING); int err = 0; BIO* bio = NULL; // First set up the context if (!ssl_ctx_) ssl_ctx_ = SetupSSLContext(); if (!ssl_ctx_) { err = -1; goto ssl_error; } bio = BIO_new_socket(static_cast<talk_base::AsyncSocketAdapter*>(socket_)); if (!bio) { err = -1; goto ssl_error; } ssl_ = SSL_new(ssl_ctx_); if (!ssl_) { err = -1; goto ssl_error; } SSL_set_app_data(ssl_, this); SSL_set_bio(ssl_, bio, bio); SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); // the SSL object owns the bio now bio = NULL; // Do the connect err = ContinueSSL(); if (err != 0) goto ssl_error; return err;ssl_error: Cleanup(); if (bio) BIO_free(bio); return err;}intOpenSSLAdapter::ContinueSSL() { LOG(LS_INFO) << "ContinueSSL"; ASSERT(state_ == SSL_CONNECTING); int code = SSL_connect(ssl_); switch (SSL_get_error(ssl_, code)) { case SSL_ERROR_NONE: LOG(LS_INFO) << " -- success"; if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) { LOG(LS_ERROR) << "TLS post connection check failed"; // make sure we close the socket Cleanup(); // The connect failed so return -1 to shut down the socket return -1; } state_ = SSL_CONNECTED; AsyncSocketAdapter::OnConnectEvent(this);#if 0 // TODO: worry about this // Don't let ourselves go away during the callbacks PRefPtr<OpenSSLAdapter> lock(this); LOG(LS_INFO) << " -- onStreamReadable"; AsyncSocketAdapter::OnReadEvent(this); LOG(LS_INFO) << " -- onStreamWriteable"; AsyncSocketAdapter::OnWriteEvent(this);#endif break; case SSL_ERROR_WANT_READ: LOG(LS_INFO) << " -- error want read"; break; case SSL_ERROR_WANT_WRITE: LOG(LS_INFO) << " -- error want write"; break; case SSL_ERROR_ZERO_RETURN: default: LOG(LS_INFO) << " -- error " << code; return (code != 0) ? code : -1; } return 0;}voidOpenSSLAdapter::Error(const char* context, int err, bool signal) { LOG(LS_WARNING) << "SChannelAdapter::Error(" << context << ", " << err << ")"; state_ = SSL_ERROR; SetError(err); if (signal) AsyncSocketAdapter::OnCloseEvent(this, err);}voidOpenSSLAdapter::Cleanup() { LOG(LS_INFO) << "Cleanup"; state_ = SSL_NONE; ssl_read_needs_write_ = false; ssl_write_needs_read_ = false; if (ssl_) { SSL_free(ssl_); ssl_ = NULL; } if (ssl_ctx_) { SSL_CTX_free(ssl_ctx_); ssl_ctx_ = NULL; }}//// AsyncSocket Implementation//intOpenSSLAdapter::Send(const void* pv, size_t cb) { //LOG(LS_INFO) << "OpenSSLAdapter::Send(" << cb << ")"; switch (state_) { case SSL_NONE: return AsyncSocketAdapter::Send(pv, cb); case SSL_WAIT: case SSL_CONNECTING: SetError(EWOULDBLOCK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -