opensssl BIO方式https客户端

发布时间:2024年01月18日

废话不多说,代码中使用了两种https客户端的实现方式。




#include <windows.h>
#include <WinSock.h>

#pragma comment(lib,"ws2_32.lib")
#include "../include/openssl\ssl.h"
#include "../include/openssl\err.h"


#pragma comment ( lib, "../lib/libeay32.lib" )
#pragma comment ( lib, "../lib/ssleay32.lib" )


#define HTTPS_PORT 443


DWORD BIOSendRecvData(sockaddr_in stBaiduPassPortAddr,char * pSendData,int iSendSize,char * pRecvData,int iRecvSize)
{
	//ERR_load_crypto_strings();
	//ERR_load_SSL_strings();
	//OPENSSL_add_all_algorithms_noconf();

	//如果系统平台不支持自动进行随机数种子的设置,这里应该进行设置(seed PRNG)
	SSL_CTX * ctxClient = SSL_CTX_new(SSLv3_client_method());

	//通常应该在这里设置一些验证路径和模式等,因为这里没有设置,所以该例子可以跟使用任意CA签发证书的任意服务器建立连接
	BIO * stBio = BIO_new_ssl_connect(ctxClient);

	SSL * sslClient = FALSE;
	int iRet = BIO_get_ssl(stBio,&sslClient);
	if(sslClient == FALSE)
	{
		fprintf(stderr,"Can't locate SSL pointer\n");
		//ERR_print_errors_fp(stderr);
		//SSL_free(sslClient);
		SSL_CTX_free(ctxClient);
		BIO_free_all(stBio);
		return FALSE;
	}
	/* 不需要任何重试请求*/
	iRet = SSL_set_mode(sslClient,SSL_MODE_AUTO_RETRY);
	//这里你可以添加对SSL的其它一些设置

	char szBioConnectAddrFormat[] = "%s:%u";
	char szBioConnectAddr[64];
	int iLen = wsprintfA(szBioConnectAddr,szBioConnectAddrFormat,inet_ntoa(stBaiduPassPortAddr.sin_addr),HTTPS_PORT);
	iRet = BIO_set_conn_hostname(stBio,szBioConnectAddr);		//"passport.baidu.com"
	//BIO * out=BIO_new_fp(stdout,BIO_NOCLOSE);
	if(BIO_do_handshake(stBio)<=0)
	{
		//SSL_free(sslClient);
		SSL_CTX_free(ctxClient);
		fprintf(stderr,"Error connecting to server\n");
		ERR_print_errors_fp(stderr);
		return FALSE;
	}

	X509 * stCert = SSL_get_peer_certificate(sslClient);
	char * strServerName = X509_NAME_oneline(X509_get_subject_name(stCert),0,0);
	OPENSSL_free(strServerName);
	strServerName = X509_NAME_oneline(X509_get_issuer_name(stCert),0,0);
	OPENSSL_free(strServerName);
	X509_free(stCert);

	iRet = BIO_write(stBio,pSendData,iSendSize);
	if (iRet <= 0)
	{
		//SSL_free(sslClient);
		SSL_CTX_free(ctxClient);
		BIO_free_all(stBio);
		return FALSE;
	}
	char * pRecvPtr = pRecvData;
	iRet = BIO_read(stBio,pRecvPtr,iRecvSize);
	if (iRet <= 0)
	{
		//SSL_free(sslClient);
		SSL_CTX_free(ctxClient);
		BIO_free_all(stBio);
		return FALSE;
	}
	while(iRet == 1)
	{
		pRecvPtr ++;
		iRet = BIO_read(stBio,pRecvPtr,iRecvSize);
	}

	if (iRet > 0)
	{
		*(pRecvPtr + iRet) = 0;
	}

	BIO_free_all(stBio);

	SSL_CTX_free(ctxClient);
	//SSL_free(sslClient);
	//BIO_free(out);
	return TRUE;
}










DWORD SendAndRecvHttpsPacket(sockaddr_in stBaiduPassPortAddr,char * pSendData,int iSendSize,char * pRecvData,int iRecvSize)
{
	SOCKET sockClient = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (sockClient == INVALID_SOCKET)
	{
		return FALSE;
	}

	int iRet = connect(sockClient,(sockaddr*)&stBaiduPassPortAddr,sizeof(sockaddr_in));
	if (iRet == INVALID_SOCKET)
	{
		closesocket(sockClient);
		return FALSE;
	}

	SSL_CTX * pctxClient = SSL_CTX_new( SSLv23_client_method() );
	if (pctxClient == 0)
	{
		iRet = GetLastError();
		closesocket(sockClient);
		return FALSE;
	}

	SSL * pSSLClient = SSL_new(pctxClient);
	if (pSSLClient == 0)
	{
		closesocket(sockClient);
		return FALSE;
	}

	iRet = SSL_set_fd(pSSLClient,sockClient);
	if (iRet <= 0)
	{
		iRet = GetLastError();
		closesocket(sockClient);
		return FALSE;
	}

	iRet = SSL_connect(pSSLClient);
	if (iRet <= 0)
	{
		iRet = GetLastError();
		//return FALSE;
	}

	iRet = SSL_write(pSSLClient,pSendData,iSendSize);
	if (iRet <= 0)
	{
		iRet = GetLastError();
		//return FALSE;
	}

	char * pRecvBuf = pRecvData;
	int iSize = iRecvSize;
	do
	{
		iRet = SSL_read(pSSLClient,pRecvBuf,1);
		if (iRet > 0)
		{
			pRecvBuf ++;
			iSize --;
		}
	} while (iRet > 0);
	*pRecvBuf = 0;

	SSL_free(pSSLClient);
	SSL_CTX_free(pctxClient);
	closesocket(sockClient);
	return (pRecvBuf - pRecvData);
}



/*
DWORD BIOServerSample()
{
    BIO *sbio, *bbio, *acpt, *out;
    int len;
    char tmpbuf[1024];
    SSL_CTX *ctx;
    SSL *ssl;

    ERR_load_crypto_strings();
    ERR_load_SSL_strings();
    OpenSSL_add_all_algorithms();

    //Might seed PRNG here 

    ctx = SSL_CTX_new(SSLv23_server_method());

    if (!SSL_CTX_use_certificate_file(ctx,"server.pem",SSL_FILETYPE_PEM)
           || !SSL_CTX_use_PrivateKey_file(ctx,"server.pem",SSL_FILETYPE_PEM)
           || !SSL_CTX_check_private_key(ctx)) {

           fprintf(stderr, "Error setting up SSL_CTX\n");
           ERR_print_errors_fp(stderr);
           return 0;
    }

	//Might do other things here like setting verify locations and
	//DH and/or RSA temporary key callbacks
     

    // New SSL BIO setup as server 
    sbio=BIO_new_ssl(ctx,0);

    BIO_get_ssl(sbio, &ssl);

    if(!ssl) {
      fprintf(stderr, "Can't locate SSL pointer\n");
      // whatever ... 
    }

    // Don't want any retries 
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

    // Create the buffering BIO 

    bbio = BIO_new(BIO_f_buffer());

    //Add to chain 
    sbio = BIO_push(bbio, sbio);

    acpt=BIO_new_accept("433");

   //  By doing this when a new connection is established
   //  we automatically have sbio inserted into it. The
   //  BIO chain is now 'swallowed' by the accept BIO and
   //  will be freed when the accept BIO is freed.
     

    BIO_set_accept_bios(acpt,sbio);

    out = BIO_new_fp(stdout, BIO_NOCLOSE);

    // Setup accept BIO 
    if(BIO_do_accept(acpt) <= 0) {
           fprintf(stderr, "Error setting up accept BIO\n");
           ERR_print_errors_fp(stderr);
           return 0;
    }

    // Now wait for incoming connection 
    if(BIO_do_accept(acpt) <= 0) {
           fprintf(stderr, "Error in connection\n");
           ERR_print_errors_fp(stderr);
           return 0;
    }

    // We only want one connection so remove and free
    // accept BIO
    //

    sbio = BIO_pop(acpt);

    BIO_free_all(acpt);

    if(BIO_do_handshake(sbio) <= 0) {
           fprintf(stderr, "Error in SSL handshake\n");
           ERR_print_errors_fp(stderr);
           return 0;
    }

    BIO_puts(sbio, "HTTP/1.0 200 OK\r\nContent-type: text/plain\r\n\r\n");
    BIO_puts(sbio, "\r\nConnection Established\r\nRequest headers:\r\n");
    BIO_puts(sbio, "--------------------------------------------------\r\n");

    for(;;) {
           len = BIO_gets(sbio, tmpbuf, 1024);
           if(len <= 0) break;
           BIO_write(sbio, tmpbuf, len);
           BIO_write(out, tmpbuf, len);
           // Look for blank line signifying end of headers
           if((tmpbuf[0] == '\r') || (tmpbuf[0] == '\n')) break;
    }

    BIO_puts(sbio, "--------------------------------------------------\r\n");
    BIO_puts(sbio, "\r\n");

    // Since there is a buffering BIO present we had better flush it 
    BIO_flush(sbio);

    BIO_free_all(sbio);
	return TRUE;
}
*/





int __stdcall WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd ){

	WSAData wsa;

	int ret = WSAStartup(0x0202,&wsa);
	if (ret )
	{
		return FALSE;
	}


	SSL_library_init( );			
	SSL_load_error_strings( );
	OpenSSL_add_all_algorithms();

	char szdata[0x4000];
	for (int i =0;i < sizeof(szdata); i ++)
	{
		szdata[i] = 'a';
	}
	szdata[0] = '/';
	szdata[1] = 0;

	hostent * lphost= gethostbyname("www.baidu.com");
	DWORD lpip = *(DWORD*)(lphost->h_addr_list);
	DWORD ip= *(DWORD*)lpip;

	sockaddr_in sa = {0};
	sa.sin_family = AF_INET;
	sa.sin_port = ntohs(443);
	sa.sin_addr.S_un.S_addr = ip;


	char szrecv[0x4000];
	ret=BIOSendRecvData(sa,szdata, lstrlenA(szdata),szrecv, sizeof(szdata));
	//ret=SendAndRecvHttpsPacket(sa,szdata,0x10000,szrecv,0x10000);

	// 	SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	// 	if (s == INVALID_SOCKET)
	// 	{
	// 		return FALSE;
	// 	}

	return TRUE;
}
文章来源:https://blog.csdn.net/m0_37567738/article/details/135685466
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。