⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asyncsslsocketlayer.cpp

📁 AsynSocketDemo.rar网络代码,可以设置代理,ssl加密. AsynSocketDemo.rar网络代码,可以设置代理,ssl加密. AsynSocketDemo.rar网络代码,
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*CAsyncSslSocketLayer by Tim Kosse (Tim.Kosse@gmx.de)
               Version 1.0 (2003-04-05)
------------------------------------------------------

Introduction
------------

CAsyncSslSocketLayer is a layer class for CAsyncSocketEx which allows you to establish SSL secured
connections to servers.

How to use
----------

Using this class is really simple. In the easiest case, just add an instance of
CAsyncSslSocketLayer to your socket and call InitClientSsl after creation of the socket.

This class only has three new public functions:
- InitClientSsl();
  This functions establishes an SSL connection to the server. You can call it at any
  time one the socket has been created.
  Most likely you want to call this function right after calling Create for the socket.
  But sometimes, you'll need to call this function later. One example is for an FTP connection
  with explicit SSL: In this case you would have to call InitClientSsl after receiving the reply
  to an 'AUTH SSL' command.
- Is UsingSSL();
  Returns true if you've previously called InitClientSsl()
- SetNotifyReply(SetNotifyReply(int nID, int nCode, int result);
  You can call this function only after receiving a layerspecific callback with the SSL_VERIFY_CERT 
  id. See below for details.

This layer sends some layerspecific notifications to your socket instance, you can handle them in
OnLayerCallback of your socket class.
Valid notification IDs are:
- SSL_INFO 0
  There are two possible values for param2:
	SSL_INFO_ESTABLISHED 0 - You'll get this notification if the SSL negotiation was successful
	SSL_INFO_SHUTDOWNCOMPLETE 1 - You'll get this notification if the SSL connection has been shut 
                                  down sucessfully. See below for details.
- SSL_FAILURE 1
  This notification is sent if the SSL connection could not be established or if an existing 
  connection failed. Valid values for param2 are:
  - SSL_FAILURE_UNKNOWN 0 - Details may have been sent with a SSL_VERBOSE_* notification.
  - SSL_FAILURE_ESTABLISH 1 - Problem during SSL negotiation
  - SSL_FAILURE_LOADDLLS 2
  - SSL_FAILURE_INITSSL 4
  - SSL_FAILURE_VERIFYCERT 8 - The remote SSL certificate was invalid
- SSL_VERBOSE_WARNING 3
  SSL_VERBOSE_INFO 4
  This two notifications contain some additional information. The value given by param2 is a 
  pointer to a null-terminated char string (char *) with some useful information.
- SSL_VERIFY_CERT 2
  This notification is sent each time a remote certificate has to be verified.
  param2 is a pointer to a t_SslCertData structure which contains some information
  about the remote certificate.
  Return 1 if you trust the certificate and 0 if you don't trust it. If you're unsure so that the
  user has to choose to trust the certificate return 2.
  In this case, you have to call SetNotifyReply later to resume the SSL connection. nID has to be
  the priv_data element of the t_SslCertData structure and nCode has to be SSL_VERIFY_CERT.
  Set nAction to 1 if you trust the certificate and 0 if you don't trust it.

Be careful with closing the connection after sending data, not all data may have been sent already.
Before closing the connection, you should call Shutdown() and wait for the SSL_INFO_SHUTDOWNCOMPLETE
notification. This assures that all encrypted data really has been sent.

License
-------

Feel free to use this class, as long as you don't claim that you wrote it
and this copyright notice stays intact in the source files.
If you use this class in commercial applications, please send a short message
to tim.kosse@gmx.de

This product includes software developed by the OpenSSL Project
for use in the OpenSSL Toolkit. (http://www.openssl.org/)
*/

#include "stdafx.h"
#include "AsyncSslSocketLayer.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//The following functions from the SSL libraries are used:
typedef int			(*tSSL_state)					(SSL *s);
typedef char*		(*tSSL_state_string_long)		(SSL *s);
typedef void		(*tSSL_set_info_callback)		(SSL *ssl, void(*cb)());
typedef void		(*tSSL_set_bio)					(SSL *s, BIO *rbio, BIO *wbio);
typedef void		(*tSSL_set_connect_state)		(SSL *s);
typedef int			(*tSSL_set_session)				(SSL *to, SSL_SESSION *session);
typedef BIO_METHOD*	(*tBIO_f_ssl)					(void);
typedef SSL*		(*tSSL_new)						(SSL_CTX *ctx);
typedef SSL_CTX*	(*tSSL_CTX_new)					(SSL_METHOD *meth);
typedef SSL_METHOD*	(*tSSLv23_method)				(void);
typedef void		(*tSSL_load_error_strings)		(void);
typedef int			(*tSSL_library_init)			(void);
typedef void		(*tSSL_CTX_free)				(SSL_CTX *);
typedef void		(*tSSL_free)					(SSL *ssl);
typedef int			(*tSSL_get_error)				(SSL *s, int retcode);
typedef int			(*tSSL_shutdown)				(SSL *s);
typedef char*		(*tSSL_alert_type_string_long)	(int VALUE);
typedef char*		(*tSSL_alert_desc_string_long)	(int value);
typedef void		(*tSSL_CTX_set_verify)			(SSL_CTX *ctx, int mode, int (*callback)(int, X509_STORE_CTX *));
typedef X509_STORE*	(*tSSL_CTX_get_cert_store)		(SSL_CTX *);
typedef long		(*tSSL_get_verify_result)		(SSL *ssl);
typedef X509*		(*tSSL_get_peer_certificate)	(SSL *s);
typedef const char*	(*tSSL_get_version)				(SSL *ssl);
typedef SSL_CIPHER*	(*tSSL_get_current_cipher)		(SSL *ssl);
typedef const char*	(*tSSL_CIPHER_get_name)			(SSL_CIPHER *cipher);
typedef char*		(*tSSL_CIPHER_get_version)		(SSL_CIPHER *cipher);

typedef size_t				(*tBIO_ctrl_pending)				(BIO *b);
typedef int					(*tBIO_read)						(BIO *b, void *data, int len);
typedef long				(*tBIO_ctrl)						(BIO *bp, int cmd, long larg, void *parg);
typedef int					(*tBIO_write)						(BIO *b, const void *data, int len);
typedef size_t				(*tBIO_ctrl_get_write_guarantee)	(BIO *b);
typedef int					(*tBIO_new_bio_pair)				(BIO **bio1, size_t writebuf1, BIO **bio2, size_t writebuf2);
typedef BIO*				(*tBIO_new)							(BIO_METHOD *type);
typedef int					(*tBIO_free)						(BIO *a);
typedef int					(*ti2t_ASN1_OBJECT)					(char *buf, int buf_len, ASN1_OBJECT *a);
typedef int					(*tOBJ_obj2nid)						(ASN1_OBJECT *o);
typedef ASN1_OBJECT*		(*tX509_NAME_ENTRY_get_object)		(X509_NAME_ENTRY *ne);
typedef X509_NAME_ENTRY*	(*tX509_NAME_get_entry)				(X509_NAME *name, int loc);
typedef int					(*tX509_NAME_entry_count)			(X509_NAME *name);
typedef X509_NAME*			(*tX509_get_subject_name)			(X509 *a);
typedef X509_NAME*			(*tX509_get_issuer_name)			(X509 *a);
typedef const char*			(*tOBJ_nid2sn)						(int n);
typedef ASN1_STRING*		(*tX509_NAME_ENTRY_get_data)		(X509_NAME_ENTRY *ne);
typedef void				(*tX509_STORE_CTX_set_error)		(X509_STORE_CTX *ctx, int s);
typedef int					(*tX509_digest)						(const X509 *data, const EVP_MD *type, unsigned char *md, unsigned int *len);
typedef EVP_MD*				(*tEVP_sha1)						(void);
typedef X509*				(*tX509_STORE_CTX_get_current_cert)	(X509_STORE_CTX *ctx);
typedef int					(*tX509_STORE_CTX_get_error)		(X509_STORE_CTX *ctx);
typedef void				(*tX509_free)						(X509 *a);
typedef EVP_PKEY*			(*tX509_get_pubkey)					(X509 *x);
typedef int					(*tBN_num_bits)						(const BIGNUM *a);
typedef void				(*tEVP_PKEY_free)					(EVP_PKEY *pkey);

static tSSL_state_string_long		pSSL_state_string_long;
static tSSL_state					pSSL_state;
static tSSL_set_info_callback		pSSL_set_info_callback;
static tSSL_set_bio					pSSL_set_bio;
static tSSL_set_connect_state		pSSL_set_connect_state;
static tSSL_set_session				pSSL_set_session;
static tBIO_f_ssl					pBIO_f_ssl;
static tSSL_new						pSSL_new;
static tSSL_CTX_new					pSSL_CTX_new;
static tSSLv23_method				pSSLv23_method;
static tSSL_load_error_strings		pSSL_load_error_strings;
static tSSL_library_init			pSSL_library_init;
static tSSL_CTX_free				pSSL_CTX_free;
static tSSL_free					pSSL_free;
static tSSL_get_error				pSSL_get_error;
static tSSL_shutdown				pSSL_shutdown;
static tSSL_alert_type_string_long	pSSL_alert_type_string_long;
static tSSL_alert_desc_string_long	pSSL_alert_desc_string_long;
static tSSL_CTX_set_verify			pSSL_CTX_set_verify;
static tSSL_CTX_get_cert_store		pSSL_CTX_get_cert_store;
static tSSL_get_verify_result		pSSL_get_verify_result;
static tSSL_get_peer_certificate	pSSL_get_peer_certificate;
static tSSL_get_version				pSSL_get_version;
static tSSL_get_current_cipher		pSSL_get_current_cipher;
static tSSL_CIPHER_get_name			pSSL_CIPHER_get_name;
static tSSL_CIPHER_get_version		pSSL_CIPHER_get_version;

static tBIO_ctrl_pending				pBIO_ctrl_pending;
static tBIO_read						pBIO_read;
static tBIO_ctrl						pBIO_ctrl;
static tBIO_write						pBIO_write;
static tBIO_ctrl_get_write_guarantee	pBIO_ctrl_get_write_guarantee;
static tBIO_new_bio_pair				pBIO_new_bio_pair;
static tBIO_new							pBIO_new;
static tBIO_free						pBIO_free;
static ti2t_ASN1_OBJECT					pi2t_ASN1_OBJECT;
static tOBJ_obj2nid						pOBJ_obj2nid;
static tX509_NAME_ENTRY_get_object		pX509_NAME_ENTRY_get_object;
static tX509_NAME_get_entry				pX509_NAME_get_entry;
static tX509_NAME_entry_count			pX509_NAME_entry_count;
static tX509_get_subject_name			pX509_get_subject_name;
static tX509_get_issuer_name			pX509_get_issuer_name;
static tOBJ_nid2sn						pOBJ_nid2sn;
static tX509_NAME_ENTRY_get_data		pX509_NAME_ENTRY_get_data;
static tX509_STORE_CTX_set_error		pX509_STORE_CTX_set_error;
static tX509_digest						pX509_digest;
static tEVP_sha1						pEVP_sha1;
static tX509_STORE_CTX_get_current_cert	pX509_STORE_CTX_get_current_cert;
static tX509_STORE_CTX_get_error		pX509_STORE_CTX_get_error;
static tX509_free						pX509_free;
static tX509_get_pubkey					pX509_get_pubkey;
static tBN_num_bits						pBN_num_bits;
static tEVP_PKEY_free					pEVP_PKEY_free;

// Critical section wrapper class
#ifndef CCRITICALSECTIONWRAPPERINCLUDED
class CCriticalSectionWrapper
{
public:
	CCriticalSectionWrapper()
	{
		InitializeCriticalSection(&m_criticalSection);
	}

	~CCriticalSectionWrapper()
	{
		DeleteCriticalSection(&m_criticalSection);
	}

	void Lock()
	{
		EnterCriticalSection(&m_criticalSection);
	}
	void Unlock()
	{
		LeaveCriticalSection(&m_criticalSection);
	}
protected:
	CRITICAL_SECTION m_criticalSection;
};
#define CCRITICALSECTIONWRAPPERINCLUDED
#endif

/////////////////////////////////////////////////////////////////////////////
// CAsyncSslSocketLayer
CCriticalSectionWrapper CAsyncSslSocketLayer::m_sCriticalSection;

CAsyncSslSocketLayer::t_SslLayerList* CAsyncSslSocketLayer::m_pSslLayerList = 0;
int CAsyncSslSocketLayer::m_nSslRefCount = 0;
HMODULE CAsyncSslSocketLayer::m_hSslDll1 = 0;
HMODULE CAsyncSslSocketLayer::m_hSslDll2 = 0;
SSL_CTX* CAsyncSslSocketLayer::m_ssl_ctx = 0;

CAsyncSslSocketLayer::CAsyncSslSocketLayer()
{
	m_ssl = 0;
	m_sslbio = 0;
	m_ibio = 0;
	m_nbio = 0;

	m_bUseSSL = false;
	m_bSslInitialized = FALSE;
	m_bSslEstablished = FALSE;
	m_nNetworkSendBufferLen = 0;
	m_pNetworkSendBuffer = 0;
	m_nNetworkError = 0;
	m_nShutDown = 0;

	m_bBlocking = FALSE;
	m_nSslAsyncNotifyId = 0;
	m_bFailureSent = FALSE;
}

CAsyncSslSocketLayer::~CAsyncSslSocketLayer()
{
	UnloadSSL();
}

void CAsyncSslSocketLayer::OnReceive(int nErrorCode)
{
	if (m_bUseSSL)
	{
		if (m_bBlocking)
			return;
		if (m_nNetworkError)
			return;

		char buffer[16384];
		
		//Get number of bytes we can receive and store in the network input bio
		int len = pBIO_ctrl_get_write_guarantee(m_nbio);
		
		int numread = 0;
		if (len)
			// Receive data
			numread = ReceiveNext(buffer,len);
		while (numread>0)
		{
			//Store it in the network input bio and process data
			pBIO_write(m_nbio, buffer, numread);
			pBIO_ctrl(m_nbio, BIO_CTRL_FLUSH, 0, NULL);

			//Look if input data was valid
			int res = pBIO_read(m_sslbio, (void *)1, 0);
			if (res<0)
			{
				if (!BIO_should_retry(m_sslbio))
				{
					m_nNetworkError = WSAECONNABORTED;
					WSASetLastError(WSAECONNABORTED);
					if (!m_bFailureSent)
					{
						m_bFailureSent = TRUE;
						DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_FAILURE, m_bSslEstablished ? SSL_FAILURE_UNKNOWN : SSL_FAILURE_ESTABLISH);
					}
					TriggerEvent(FD_CLOSE, 0);
					return;
				}
			}
			if (numread<len)
				break;

			//Get number of bytes we can receive and store in the input network bio
			len = pBIO_ctrl_get_write_guarantee(m_nbio);
			numread = ReceiveNext(buffer, len);
		}
		if (numread==SOCKET_ERROR)
		{
			int nError = GetLastError();
			if (nError!=WSAEWOULDBLOCK && nError!=WSAENOTCONN)
			{
				m_nNetworkError = GetLastError();
				TriggerEvent(FD_CLOSE, 0);
				return;
			}
		}

		if (ShutDownComplete() && m_nShutDown == 1)
		{
			//Send shutdown notification if all pending data has been sent
			DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_INFO, SSL_INFO_SHUTDOWNCOMPLETE);
			m_nShutDown++;
		}

		if (pBIO_ctrl(m_sslbio, BIO_CTRL_PENDING, 0, NULL) && nErrorCode!=1)
			TriggerEvent(FD_READ, nErrorCode, TRUE);

		//Try to send encrypted data waiting in the network bio
		if (pBIO_ctrl_pending(m_nbio))
			OnSend(nErrorCode);
	}
	else
		TriggerEvent(FD_READ, nErrorCode, TRUE);
}

void CAsyncSslSocketLayer::OnSend(int nErrorCode)
{
	if (m_bUseSSL)
	{
		if (m_nNetworkError)
			return;

		//Send data in the send buffer
		if (m_pNetworkSendBuffer)
		{
			int numsent = SendNext(m_pNetworkSendBuffer, m_nNetworkSendBufferLen);
			if (numsent == SOCKET_ERROR)
			{
				int nError=GetLastError();
				if (nError!=WSAEWOULDBLOCK && nError!=WSAENOTCONN)
				{
					m_nNetworkError=nError;
					TriggerEvent(FD_CLOSE, 0);
				}
				return;
			}
			if (numsent==m_nNetworkSendBufferLen)
			{
				delete [] m_pNetworkSendBuffer;
				m_pNetworkSendBuffer = 0;
				m_nNetworkSendBufferLen = 0;
			}
			else
			{
				char *tmp = m_pNetworkSendBuffer;
				m_pNetworkSendBuffer = new char[m_nNetworkSendBufferLen-numsent];
				memcpy(m_pNetworkSendBuffer+numsent, tmp, m_nNetworkSendBufferLen-numsent);
				m_nNetworkSendBufferLen -= numsent;
				delete [] tmp;
				return;
			}
		}

		//Send the data waiting in the network bio
		char buffer[16384];
		int len = pBIO_ctrl_pending(m_nbio);
		int numread=pBIO_read(m_nbio, buffer, len);
		while(numread>0)
		{
			int numsent = SendNext(buffer, numread);
			if (numsent==SOCKET_ERROR || numsent<numread)
			{
				if (numsent==SOCKET_ERROR)
					if (GetLastError()!=WSAEWOULDBLOCK && GetLastError()!=WSAENOTCONN)
					{
						m_nNetworkError = GetLastError();
						TriggerEvent(FD_CLOSE, 0);
						return;
					}
					else
						numsent = 0;

				//Add all data that was retrieved from the network bio but could not be sent to the send buffer.
				if (!m_pNetworkSendBuffer)
					m_pNetworkSendBuffer = new char[numread-numsent];
				else
				{
					char *tmp = m_pNetworkSendBuffer;
					m_pNetworkSendBuffer = new char[m_nNetworkSendBufferLen+numread-numsent];
					memcpy(m_pNetworkSendBuffer, tmp, m_nNetworkSendBufferLen);
					delete [] tmp;
				}
				memcpy(m_pNetworkSendBuffer+m_nNetworkSendBufferLen, buffer, numread-numsent);
				m_nNetworkSendBufferLen += numread-numsent;
			}
			len = pBIO_ctrl_pending(m_nbio);
			if (!len)
				break;
			numread = pBIO_read(m_nbio,buffer,len);
		}
		if (ShutDownComplete() && m_nShutDown == 1)
		{
			DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_INFO, SSL_INFO_SHUTDOWNCOMPLETE);
			m_nShutDown++;
		}
	}
	else
		TriggerEvent(FD_WRITE, nErrorCode, TRUE);
}

int CAsyncSslSocketLayer::Send(const void* lpBuf, int nBufLen, int nFlags)
{
	if (m_bUseSSL)
	{
		if (!lpBuf)
			return 0;
		if (m_bBlocking)
		{
			SetLastError(WSAEWOULDBLOCK);
			return SOCKET_ERROR;
		}
		if (m_nNetworkError)
		{
			SetLastError(m_nNetworkError);
			return SOCKET_ERROR;
		}
		if (m_nShutDown)
		{
			SetLastError(WSAESHUTDOWN);
			return SOCKET_ERROR;
		}
		if (!nBufLen)
			return 0;

		int numwrite = pBIO_write(m_sslbio, lpBuf, nBufLen);
		pBIO_ctrl(m_sslbio, BIO_CTRL_FLUSH, 0, NULL);

		if (pBIO_ctrl_pending(m_nbio))
			CAsyncSslSocketLayer::OnSend(0);
		if (numwrite==-1)
			if (BIO_should_retry(m_sslbio))
			{
				TriggerEvent(FD_WRITE, 0);
				SetLastError(WSAEWOULDBLOCK);
			}
			else
				SetLastError(WSAECONNABORTED);

		return numwrite;
	}
	else
		return SendNext(lpBuf, nBufLen, nFlags);
}

int CAsyncSslSocketLayer::Receive(void* lpBuf, int nBufLen, int nFlags)
{
	if (m_bUseSSL)
	{
		if (m_bBlocking)
		{
			SetLastError(WSAEWOULDBLOCK);
			return SOCKET_ERROR;
		}
		if (m_nNetworkError)
		{
			if (pBIO_ctrl(m_sslbio, BIO_CTRL_PENDING, 0, NULL) && !m_nShutDown)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -