废话不多说,代码中使用了两种https客户端的实现方式。
cpp
#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;
}