www.codeproject.com/internet/wininet_ssl___certificate.asp Connecting to a HTTPS server with SSL using Wininet, sending client certificate and reading response
int confd=socket(AF_INET,SOCK_STREAM,0); if(confd > 0) { //cerr<<"socket create OK for 80 port."<<endl; } else { return -3; } struct sockaddr_in dest_addr; unsigned int port = GetURLPort(url); if(!port) return -2; cout<<port<<endl; dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(port); dest_addr.sin_addr.S_un.S_addr=inet_addr(IP); memset(dest_addr.sin_zero,0,8); string str="";str="\ GET "; str+=url; str+=" HTTP/1.1\n\ Accept: */*\n\ Accept-Language: zh-cn\n\ Accept-Encoding: gzip, deflate\n\ If-Modified-Since: Fri, 08 Jul 1970 09:12:08 GMT\n\ If-None-Match: \"00000\"\n\ User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon)\n\ Host: "; str+=host; str+="\n\ Connection: Keep-Alive\n\ Cookie: 0\n\n\ ";cout<<str.c_str()<<endl;
int con_ret=connect(confd,(struct sockaddr*)&dest_addr,sizeof(sockaddr)); if(con_ret!=0) { //cerr<<"connect 61.235.170.17 port 80 error!"<<endl; return -4; }else { //cerr<<"connect 61.235.170.17 port 80 sucess!"<<endl; } char write_buf[1024] = { 0 }; if(send(confd,str.c_str(),strlen(str.c_str()),0)<0) return -4; ret = GetFile(confd, FileName); return ret;
WSACleanup(); return 0; }
给你一个吧,肯定可用的 CSslClientSocket::CSslClientSocket() { m_Ctx=NULL; m_Ssl=NULL; m_pList=NULL; }CSslClientSocket::~CSslClientSocket() { } // Do not edit the following lines, which are needed by ClassWizard. #if 0 BEGIN_MESSAGE_MAP(CSslClientSocket, CAsyncSocket) //{{AFX_MSG_MAP(CSslClientSocket) //}}AFX_MSG_MAP END_MESSAGE_MAP() #endif // 0///////////////////////////////////////////////////////////////////////////// // CSslClientSocket member functions X509 * CSslClientSocket::load_cert(BIO *cert/*输入BIO*/, int format/*格式*/,char * pwd,/*P12密码*/char * outMsg) { ASN1_HEADER *ah=NULL; BUF_MEM *buf=NULL; X509 *x=NULL; if (format == DER) x=d2i_X509_bio(cert,NULL); else if (format == PEM) x=PEM_read_bio_X509(cert,NULL,NULL,NULL);//PEM_read_bio_X509_AUX else if (format == P12) { PKCS12 *p12 = d2i_PKCS12_bio(cert, NULL); PKCS12_parse(p12, pwd, NULL, &x, NULL); PKCS12_free(p12); p12 = NULL; } else { sprintf(outMsg,"bad input format specified for input cert\n"); goto end; } end: if (x == NULL) { sprintf(outMsg,"unable to load certificate\n"); } if (ah != NULL) ASN1_HEADER_free(ah); if (buf != NULL) BUF_MEM_free(buf); return(x); }X509 * CSslClientSocket::LoadCert(char * cert,int certlen,char * outMsg)//枚举DER/PEM格式 { BIO * in=NULL; X509 * x509=NULL; if(certlen==0)//输入为磁盘文件 { if((in=BIO_new_file(cert, "r")) == NULL) { sprintf(outMsg,"open CA certificate file error"); return NULL; } } else//输入为内存中文件 { if((in=BIO_new_mem_buf(cert,certlen))== NULL)//只读类型 { sprintf(outMsg,"Make Mem Bio Error"); return NULL; } } if((x509=load_cert(in,DER,NULL,outMsg))==NULL)//尝试DER { BIO_reset(in);//恢复bio x509=load_cert(in,PEM,NULL,outMsg);//尝试PEM } if (in != NULL) BIO_free(in); return x509; }EVP_PKEY * CSslClientSocket::load_key(BIO *bio, int format, char *pass,char * outMsg) { EVP_PKEY *pkey=NULL; if (format == DER) { pkey=d2i_PrivateKey_bio(bio, NULL); } else if (format == PEM) { pkey=PEM_read_bio_PrivateKey(bio,NULL,NULL,pass); } else if (format == P12) { PKCS12 *p12 = d2i_PKCS12_bio(bio, NULL); PKCS12_parse(p12, pass, &pkey, NULL, NULL); PKCS12_free(p12); p12 = NULL; } else { sprintf(outMsg,"bad input format specified for key\n"); goto end; } end: if (pkey == NULL) sprintf(outMsg,"unable to load Private Key\n"); return(pkey); }EVP_PKEY * CSslClientSocket::LoadKey(char * key,int keylen,char * pass,char * outMsg) { EVP_PKEY *pkey=NULL; BIO * in=NULL; if(keylen==0)//输入为磁盘文件 { if((in=BIO_new_file(key, "r")) == NULL) { sprintf(outMsg,"open CA certificate file error"); return NULL; } } else//输入为内存中文件 { if((in=BIO_new_mem_buf(key,keylen))== NULL)//只读类型 { sprintf(outMsg,"Make Mem Bio Error"); return NULL; } } if((pkey=load_key(in,DER,pass,outMsg))==NULL)//尝试DER { BIO_reset(in);//BIO是可读写的,那么该BIO所有数据都会被清空; //如果该BIO是只读的,那么该操作只会简单将指 //针指向原始位置,里面的数据可以再读. pkey=load_key(in,PEM,pass,outMsg);//尝试PEM } if (in != NULL) BIO_free(in); return pkey; }
int CSslClientSocket::Rand(const char *file,int dont_warn,char * outMsg) { int consider_randfile = (file == NULL); char buffer[200];
#ifdef WINDOWS // BIO_flush(bio_e); RAND_screen(); #endif
if (file == NULL) file = RAND_file_name(buffer, sizeof buffer); else if (RAND_egd(file) > 0) { /* we try if the given filename is an EGD socket. if it is, we don't write anything back to the file. */ return 1; } if (file == NULL || !RAND_load_file(file, -1)) { if (RAND_status() == 0 && !dont_warn) { sprintf(outMsg,"unable to load 'random state'\n"); sprintf(outMsg,"This means that the random number generator has not been seeded\n"); if (consider_randfile) /* explanation does not apply when a file is explicitly named */ { sprintf(outMsg,"Consider setting the RANDFILE environment variable to point at a file that\n"); sprintf(outMsg,"'random' data can be kept in (the file will be overwritten).\n"); } } return 0; } return 1; }void CSslClientSocket::GetPeerInfo(SSL * ssl,stuSERVERINFO * stu) {
sk=SSL_get_peer_cert_chain(ssl);//returns a pointer to STACKOF(X509) certificates if (sk != NULL) { got_a_chain = 1; /* we don't have it for SSL2 (yet) */
sk2=SSL_get_client_CA_list(ssl); if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) { // BIO_printf(bio,"---\nAcceptable client certificate CA names\n"); for (i=0; i<sk_X509_NAME_num(sk2); i++) { xn=sk_X509_NAME_value(sk2,i); X509_NAME_oneline(xn,stu->selfChain,BUFSIZ); // BIO_write(bio,buf,strlen(buf)); // BIO_write(bio,"\n",1); } } else { strcpy(stu->selfChain,"No client certificate CA names sent"); }
p=SSL_get_shared_ciphers(ssl,buf,BUFSIZ); if (p != NULL) { /* This works only for SSL 2. In later protocol * versions, the client does not know what other * ciphers (in addition to the one to be used * in the current connection) the server supports. */
// BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n"); j=i=0; while (*p) { if (*p == ':') { BIO_write(bio,space,15-j%25); i++; j=0; BIO_write(bio,((i%3)?" ":"\n"),1); } else { BIO_write(bio,p,1); j++; } p++; } BIO_write(bio,"\n",1); }
//SSL handshake has read %ld bytes and written %ld bytes\n", stu->read=BIO_number_read(SSL_get_rbio(ssl)); stu->written=BIO_number_written(SSL_get_wbio(ssl));
// BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, ")); c=SSL_get_current_cipher(ssl); //BIO_printf(bio,"%s, Cipher is %s\n", strcpy(stu->CiphersVer,SSL_CIPHER_get_version(c)); strcpy(stu->CiphersName,SSL_CIPHER_get_name(c)); if (peer != NULL) { EVP_PKEY *pktmp; pktmp = X509_get_pubkey(peer); //Server public key bit stu->CertBit=EVP_PKEY_bits(pktmp); EVP_PKEY_free(pktmp); } SSL_SESSION_print(bio,SSL_get_session(ssl)); BIO_read(bio,stu->Session,4*BUFSIZ); /* flush, or debugging output gets mixed with http response */ BIO_flush(bio); if (peer != NULL) X509_free(peer); BIO_free(bio); }
if (!SSL_CTX_check_private_key(m_Ctx)) { strcpy(out,"Private key does not match the certificate public key"); SSL_CTX_free(m_Ctx); m_Ctx=NULL; goto err; }
Connecting to a HTTPS server with SSL using Wininet, sending client certificate and reading response
long
GetURLFile( char *url, const char *FileName, const char* IP, char *host)
{
//url 要下载文件地址。 例:http://www.yxt.cc/down/23.exe
//FileName 保存文件路径
//IP 服务器IP
//host 主机地址:例: www.yxt.cc
int ret= -1;
if(!url || !FileName || !IP || !host)
{
return -2;
} int hlen = strlen(host)+8, ulen = strlen(url);
if(ulen>1024) return -2;
if((hlen<8) || (hlen>ulen))
{
return -2;
}
WSADATA ws;
WSAStartup(0x101,&ws);
int confd=socket(AF_INET,SOCK_STREAM,0);
if(confd > 0)
{
//cerr<<"socket create OK for 80 port."<<endl;
}
else
{
return -3;
}
struct sockaddr_in dest_addr;
unsigned int port = GetURLPort(url);
if(!port) return -2;
cout<<port<<endl;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
dest_addr.sin_addr.S_un.S_addr=inet_addr(IP);
memset(dest_addr.sin_zero,0,8);
string str="";str="\
GET ";
str+=url;
str+=" HTTP/1.1\n\
Accept: */*\n\
Accept-Language: zh-cn\n\
Accept-Encoding: gzip, deflate\n\
If-Modified-Since: Fri, 08 Jul 1970 09:12:08 GMT\n\
If-None-Match: \"00000\"\n\
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon)\n\
Host: ";
str+=host;
str+="\n\
Connection: Keep-Alive\n\
Cookie: 0\n\n\
";cout<<str.c_str()<<endl;
int con_ret=connect(confd,(struct sockaddr*)&dest_addr,sizeof(sockaddr));
if(con_ret!=0)
{
//cerr<<"connect 61.235.170.17 port 80 error!"<<endl;
return -4;
}else
{
//cerr<<"connect 61.235.170.17 port 80 sucess!"<<endl;
}
char write_buf[1024] = { 0 };
if(send(confd,str.c_str(),strlen(str.c_str()),0)<0) return -4;
ret = GetFile(confd, FileName);
return ret;
WSACleanup();
return 0;
}
CSslClientSocket::CSslClientSocket()
{
m_Ctx=NULL;
m_Ssl=NULL;
m_pList=NULL;
}CSslClientSocket::~CSslClientSocket()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CSslClientSocket, CAsyncSocket)
//{{AFX_MSG_MAP(CSslClientSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0/////////////////////////////////////////////////////////////////////////////
// CSslClientSocket member functions
X509 * CSslClientSocket::load_cert(BIO *cert/*输入BIO*/, int format/*格式*/,char * pwd,/*P12密码*/char * outMsg)
{
ASN1_HEADER *ah=NULL;
BUF_MEM *buf=NULL;
X509 *x=NULL; if (format == DER)
x=d2i_X509_bio(cert,NULL);
else if (format == PEM)
x=PEM_read_bio_X509(cert,NULL,NULL,NULL);//PEM_read_bio_X509_AUX
else if (format == P12)
{
PKCS12 *p12 = d2i_PKCS12_bio(cert, NULL);
PKCS12_parse(p12, pwd, NULL, &x, NULL);
PKCS12_free(p12);
p12 = NULL;
}
else
{
sprintf(outMsg,"bad input format specified for input cert\n");
goto end;
}
end:
if (x == NULL)
{
sprintf(outMsg,"unable to load certificate\n");
}
if (ah != NULL) ASN1_HEADER_free(ah);
if (buf != NULL) BUF_MEM_free(buf);
return(x);
}X509 * CSslClientSocket::LoadCert(char * cert,int certlen,char * outMsg)//枚举DER/PEM格式
{
BIO * in=NULL;
X509 * x509=NULL; if(certlen==0)//输入为磁盘文件
{
if((in=BIO_new_file(cert, "r")) == NULL)
{
sprintf(outMsg,"open CA certificate file error");
return NULL;
}
}
else//输入为内存中文件
{
if((in=BIO_new_mem_buf(cert,certlen))== NULL)//只读类型
{
sprintf(outMsg,"Make Mem Bio Error");
return NULL;
}
}
if((x509=load_cert(in,DER,NULL,outMsg))==NULL)//尝试DER
{
BIO_reset(in);//恢复bio
x509=load_cert(in,PEM,NULL,outMsg);//尝试PEM
}
if (in != NULL) BIO_free(in);
return x509;
}EVP_PKEY * CSslClientSocket::load_key(BIO *bio, int format, char *pass,char * outMsg)
{
EVP_PKEY *pkey=NULL; if (format == DER)
{
pkey=d2i_PrivateKey_bio(bio, NULL);
}
else if (format == PEM)
{
pkey=PEM_read_bio_PrivateKey(bio,NULL,NULL,pass);
}
else if (format == P12)
{
PKCS12 *p12 = d2i_PKCS12_bio(bio, NULL);
PKCS12_parse(p12, pass, &pkey, NULL, NULL);
PKCS12_free(p12);
p12 = NULL;
}
else
{
sprintf(outMsg,"bad input format specified for key\n");
goto end;
}
end:
if (pkey == NULL)
sprintf(outMsg,"unable to load Private Key\n");
return(pkey);
}EVP_PKEY * CSslClientSocket::LoadKey(char * key,int keylen,char * pass,char * outMsg)
{
EVP_PKEY *pkey=NULL;
BIO * in=NULL; if(keylen==0)//输入为磁盘文件
{
if((in=BIO_new_file(key, "r")) == NULL)
{
sprintf(outMsg,"open CA certificate file error");
return NULL;
}
}
else//输入为内存中文件
{
if((in=BIO_new_mem_buf(key,keylen))== NULL)//只读类型
{
sprintf(outMsg,"Make Mem Bio Error");
return NULL;
}
} if((pkey=load_key(in,DER,pass,outMsg))==NULL)//尝试DER
{
BIO_reset(in);//BIO是可读写的,那么该BIO所有数据都会被清空;
//如果该BIO是只读的,那么该操作只会简单将指
//针指向原始位置,里面的数据可以再读.
pkey=load_key(in,PEM,pass,outMsg);//尝试PEM
}
if (in != NULL) BIO_free(in);
return pkey;
}
{
int consider_randfile = (file == NULL);
char buffer[200];
#ifdef WINDOWS
// BIO_flush(bio_e);
RAND_screen();
#endif
if (file == NULL)
file = RAND_file_name(buffer, sizeof buffer);
else if (RAND_egd(file) > 0)
{
/* we try if the given filename is an EGD socket.
if it is, we don't write anything back to the file. */
return 1;
}
if (file == NULL || !RAND_load_file(file, -1))
{
if (RAND_status() == 0 && !dont_warn)
{
sprintf(outMsg,"unable to load 'random state'\n");
sprintf(outMsg,"This means that the random number generator has not been seeded\n");
if (consider_randfile) /* explanation does not apply when a file is explicitly named */
{
sprintf(outMsg,"Consider setting the RANDFILE environment variable to point at a file that\n");
sprintf(outMsg,"'random' data can be kept in (the file will be overwritten).\n");
}
}
return 0;
}
return 1;
}void CSslClientSocket::GetPeerInfo(SSL * ssl,stuSERVERINFO * stu)
{
X509 *peer=NULL;
char *p;
static char *space=" ";
char buf[BUFSIZ];//512
STACK_OF(X509) *sk;
STACK_OF(X509_NAME) *sk2;
SSL_CIPHER *c;
X509_NAME *xn;
int j,i;
BIO *bio=BIO_new(BIO_s_mem());
char bufout[1024]={0};
int got_a_chain = 0;
sk=SSL_get_peer_cert_chain(ssl);//returns a pointer to STACKOF(X509) certificates
if (sk != NULL)
{
got_a_chain = 1; /* we don't have it for SSL2 (yet) */
for (i=0; i<sk_X509_num(sk); i++)
{
X509_NAME_oneline(X509_get_subject_name(sk_X509_value(sk,i)),
stu->peerChain.sub,BUFSIZ);
X509_NAME_oneline(X509_get_issuer_name(sk_X509_value(sk,i)),
stu->peerChain.iss,BUFSIZ);
// PEM_write_bio_X509(bio,sk_X509_value(sk,i));
// BIO_read(bio,bufout,4*BUFSIZ);
}
}
peer=SSL_get_peer_certificate(ssl);
if (peer != NULL)
{
// Server certificate
PEM_write_bio_X509(bio,peer);
BIO_read(bio,stu->Cert,4*BUFSIZ);
BIO_flush(bio);
X509_NAME_oneline(X509_get_subject_name(peer),
stu->peerCert.sub,BUFSIZ);
X509_NAME_oneline(X509_get_issuer_name(peer),
stu->peerCert.iss,BUFSIZ);
}
else
strcpy(stu->Cert,"no peer certificate available");
sk2=SSL_get_client_CA_list(ssl);
if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0))
{
// BIO_printf(bio,"---\nAcceptable client certificate CA names\n");
for (i=0; i<sk_X509_NAME_num(sk2); i++)
{
xn=sk_X509_NAME_value(sk2,i);
X509_NAME_oneline(xn,stu->selfChain,BUFSIZ);
// BIO_write(bio,buf,strlen(buf));
// BIO_write(bio,"\n",1);
}
}
else
{
strcpy(stu->selfChain,"No client certificate CA names sent");
}
p=SSL_get_shared_ciphers(ssl,buf,BUFSIZ);
if (p != NULL)
{
/* This works only for SSL 2. In later protocol
* versions, the client does not know what other
* ciphers (in addition to the one to be used
* in the current connection) the server supports. */
// BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n");
j=i=0;
while (*p)
{
if (*p == ':')
{
BIO_write(bio,space,15-j%25);
i++;
j=0;
BIO_write(bio,((i%3)?" ":"\n"),1);
}
else
{
BIO_write(bio,p,1);
j++;
}
p++;
}
BIO_write(bio,"\n",1);
}
//SSL handshake has read %ld bytes and written %ld bytes\n",
stu->read=BIO_number_read(SSL_get_rbio(ssl));
stu->written=BIO_number_written(SSL_get_wbio(ssl));
// BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, "));
c=SSL_get_current_cipher(ssl);
//BIO_printf(bio,"%s, Cipher is %s\n",
strcpy(stu->CiphersVer,SSL_CIPHER_get_version(c));
strcpy(stu->CiphersName,SSL_CIPHER_get_name(c));
if (peer != NULL)
{
EVP_PKEY *pktmp;
pktmp = X509_get_pubkey(peer);
//Server public key bit
stu->CertBit=EVP_PKEY_bits(pktmp);
EVP_PKEY_free(pktmp);
}
SSL_SESSION_print(bio,SSL_get_session(ssl));
BIO_read(bio,stu->Session,4*BUFSIZ);
/* flush, or debugging output gets mixed with http response */
BIO_flush(bio);
if (peer != NULL)
X509_free(peer);
BIO_free(bio);
}
char * cafile, char * capath,CColorListBox * plist,LPCTSTR lpszHostAddress, UINT nHostPort,char * out)
{
EVP_PKEY *pkey=NULL;
X509 *x509=NULL;
CString str;
unsigned long l=1;
BIO * sbio=NULL;
struct hostent *hp;
struct sockaddr_in addr;
int sock,i=0; m_pList=plist;///////////////////// OpenSSL_add_ssl_algorithms(); m_Ctx=SSL_CTX_new(meth);
if (m_Ctx == NULL)
{
strcpy(out,"Create ctx error");
return FALSE;
}
SSL_CTX_set_options(m_Ctx,SSL_OP_ALL);
pkey=LoadKey(keyfile,keylen,NULL,out);
if (pkey == NULL)
{
sprintf(out,"unable to load CA private key\n");
m_Ctx=NULL;
goto err;
}
if(!(SSL_CTX_use_PrivateKey(m_Ctx,pkey)))
{
strcpy(out,"adds private key to ctx error");
SSL_CTX_free(m_Ctx);
m_Ctx=NULL;
goto err;
}
x509=LoadCert(certfile,certlen,out);
if (x509 == NULL)
{
sprintf(out,"unable to load CA certificate\n");
SSL_CTX_free(m_Ctx);
m_Ctx=NULL;
goto err;
}
if(!(SSL_CTX_use_certificate(m_Ctx,x509)))
{
strcpy(out,"loads certificate into ctx error");
SSL_CTX_free(m_Ctx);
m_Ctx=NULL;
goto err;
}
if (!SSL_CTX_check_private_key(m_Ctx))
{
strcpy(out,"Private key does not match the certificate public key");
SSL_CTX_free(m_Ctx);
m_Ctx=NULL;
goto err;
}
/* Load the CAs we trust*/
if(!(SSL_CTX_load_verify_locations(m_Ctx,cafile,/*capath*/NULL)))
{
strcpy(out,"Couldn't read CA list");
SSL_CTX_free(m_Ctx);
m_Ctx=NULL;
goto err;
}
SSL_CTX_set_verify_depth(m_Ctx,1);
SSL_CTX_set_client_CA_list(m_Ctx,SSL_load_client_CA_file(cafile));
m_Ssl=SSL_new(m_Ctx);
if(m_Ssl==NULL)
{
strcpy(out,"Make SSL Error");
goto err;
}
/* Load randomness */
Rand(NULL,1,out); /*连接服务器*/ if(!(hp=gethostbyname(lpszHostAddress)))
{
strcpy(out,"Couldn't resolve host");
return FALSE;
}
memset(&addr,0,sizeof(addr));
addr.sin_addr=*(struct in_addr*)hp->h_addr_list[0];
addr.sin_family=AF_INET;
addr.sin_port=htons(nHostPort);
sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
strcpy(out,"create socket error");
return FALSE;
}
i=setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
if (i < 0)
{
strcpy(out,"setsockopt error");
return FALSE;
}
if (connect(sock,(struct sockaddr *)&addr,sizeof(addr)) == SOCKET_ERROR)
{
SSlShouDown();
strcpy(out,"connect error");
return FALSE;
} /* Connect the SSL socket */
if (BIO_socket_ioctl(sock,FIONBIO,&l) < 0)
{
strcpy(out,"io set error");
shutdown(sock,2);
closesocket(sock);
SSlShouDown();
return FALSE;
}
sbio=BIO_new_socket(sock,BIO_NOCLOSE);
SSL_set_bio(m_Ssl,sbio,sbio);
SSL_set_connect_state(m_Ssl);
Attach(sock,FD_WRITE|FD_CLOSE);
str.Format("%d接入服务器%s,等待握手....",m_hSocket,inet_ntoa(addr.sin_addr));
m_pList->AddMsg(str,M_WARING);
return TRUE;err:
EVP_PKEY_free(pkey);
X509_free(x509);
SSlShouDown();
return FALSE;
}int CSslClientSocket::SSlConnect(stuSERVERINFO * stu,char * out)
{
if(m_Ssl==NULL)
{
strcpy(out,"SSL没有正确初始化");
return -1;
}
int err=0;
if ((err = SSL_connect(m_Ssl)) <= 0)
{
if (BIO_sock_should_retry(err))
{
return 0;//重试
}
else
{
strcpy(out,"SSL连接失败");//ERR_clear_error
return -1;
}
}
GetPeerInfo(m_Ssl,stu);
return 1;
}void CSslClientSocket::SSlShouDown()
{
if(m_Ctx!=NULL)
{
SSL_CTX_free(m_Ctx);
m_Ctx=NULL;
}
if(m_Ssl!=NULL)
{
SSL_shutdown(m_Ssl);
SSL_free(m_Ssl);
m_Ssl=NULL;
}
if(m_hSocket != INVALID_SOCKET)
{
ShutDown(0);//receives
Close();
}
}int CSslClientSocket::SSlSend(char *buf, int len)
{
if(m_Ssl==NULL)
return -1;
int k=0;
for(;;)
{
k = SSL_write(m_Ssl,buf,len);
if (k <= 0)
{
if (BIO_sock_should_retry(k))
{
Sleep(100);
continue;//重试
}
return k;//出错
}
break;
}
AsyncSelect(FD_READ|FD_CLOSE);
return k;
}int CSslClientSocket::SSlReceive(char *buf, int len)
{
if(m_Ssl==NULL)
return 0;
int k=0;
do
{
for(;;)
{
k = SSL_read(m_Ssl,buf,len);
if (k <=0)
{
if (BIO_sock_should_retry(k))
{
Sleep(100);
continue;//重试
}
return k;//错误退出
}
m_pList->AddMsg(buf);
break;
}
}while (SSL_pending(m_Ssl)); return k;
}void CSslClientSocket::OnClose(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CString serverIp,str;
unsigned int port;
GetPeerName(serverIp,port);//得到用户ip,port
str.Format("%d被服务器%s断开",m_hSocket,serverIp);
m_pList->AddMsg(str,M_WARING);
SSlShouDown();
CAsyncSocket::OnClose(nErrorCode);
}void CSslClientSocket::OnReceive(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
char buf[1024]={0};
SSlReceive(buf,1024);
CAsyncSocket::OnReceive(nErrorCode);
}