?? sslserversocket.cpp
字號:
// SslServerSocket.cpp : implementation file
//
#include "stdafx.h"
#include "UsbKey.h"
#include "SslServerSocket.h"
#include <openssl/err.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSslServerSocket
CSslServerSocket::CSslServerSocket()
{
m_Ctx=NULL;
m_Ssl=NULL;
m_pSocket=NULL;
m_pList=NULL;
m_type=0;//www
m_pObSock=NULL;
}
CSslServerSocket::CSslServerSocket(int type)
{
m_Ctx=NULL;
m_Ssl=NULL;
m_pSocket=NULL;
m_pList=NULL;
m_type=1;//ra
m_pObSock=NULL;
}
CSslServerSocket::~CSslServerSocket()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CSslServerSocket, CAsyncSocket)
//{{AFX_MSG_MAP(CSslServerSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/////////////////////////////////////////////////////////////////////////////
// CSslServerSocket member functions
X509 * CSslServerSocket::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 * CSslServerSocket::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 * CSslServerSocket::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 * CSslServerSocket::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 CSslServerSocket::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;
}
BOOL CSslServerSocket::GetPeerInfo(SSL * ssl,stuCLIENTINFO * stu)
{
X509 *peer;
BIO *bio=BIO_new(BIO_s_mem());
const char *str=NULL;
SSL_SESSION_print(bio,SSL_get_session(ssl));
peer=SSL_get_peer_certificate(ssl);
if (peer != NULL)
{
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);
X509_free(peer);
}
if (SSL_get_shared_ciphers(ssl,stu->Shared_ciphers,BUFSIZ) != NULL)
{
int bits2=0;
SSL_CIPHER *sc=SSL_get_current_cipher(ssl);
if(ssl==NULL) strcpy(stu->Current_cipher,"No current cipher?\n");
else
{
int bits=SSL_CIPHER_get_bits(sc, &bits2);
sprintf(stu->Current_cipher,"Version=%s Cipher=%s Bits=%d\n", SSL_get_version(ssl),
SSL_CIPHER_get_name(sc), bits);
}
}
if(strlen(stu->Cert))
m_pList->AddMsg(stu->Cert);
if(strlen(stu->Current_cipher))
m_pList->AddMsg(stu->Current_cipher);
if(strlen(stu->peerCert.iss))
m_pList->AddMsg(stu->peerCert.iss);
if(strlen(stu->peerCert.sub))
m_pList->AddMsg(stu->peerCert.sub);
if(strlen((char *)stu->Session))
m_pList->AddMsg(stu->Session);
if(strlen(stu->Shared_ciphers))
m_pList->AddMsg(stu->Shared_ciphers);
return TRUE;
/* if (s->hit) BIO_printf(bio,"Reused session-id\n");
if (SSL_ctrl(s,SSL_CTRL_GET_FLAGS,0,NULL) &
TLS1_FLAGS_TLS_PADDING_BUG)
BIO_printf(bio,"Peer has incorrect TLSv1 block padding\n");*/
}
SSL_CTX * CSslServerSocket::InitCtx(SSL_METHOD *meth,char *certfile,int certlen,
char *keyfile,int keylen,char * cafile, char * capath,
int VerType/*對于客戶端驗證模式*/,CColorListBox * plist,
CObList * pObSock/*連接列表*/,
_ConnectionPtr pConnection/*數據庫連接*/,char * out)
{
EVP_PKEY *pkey=NULL;
X509 *x509=NULL;
OpenSSL_add_ssl_algorithms();
SSL_load_error_strings();
m_pList=plist;/////////////////////
m_pConnection=pConnection;/////////
m_pObSock=pObSock;
m_Ctx=SSL_CTX_new(meth);
if (m_Ctx == NULL)
{
strcpy(out,"Create ctx error");
return NULL;
}
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));
switch(VerType)
{
case 1:
SSL_CTX_set_verify(m_Ctx,SSL_VERIFY_PEER,Verify);//要求對方證書
break;
case 2:
SSL_CTX_set_verify(m_Ctx,SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,Verify);
break;
case 3:
SSL_CTX_set_verify(m_Ctx,SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,Verify);
break;
default:
SSL_CTX_set_verify(m_Ctx,SSL_VERIFY_NONE,Verify);//不要求對方證書
break;
}
/* Load randomness */
Rand(NULL,1,out);
err:
EVP_PKEY_free(pkey);
X509_free(x509);
return m_Ctx;
}
BOOL CSslServerSocket::CreateLisenSock(UINT nSocketPort, long lEvent)
{
int sock;
char out[100]={0};
struct sockaddr_in sin;
int val=1;
memset(&sin,0,sizeof(sin));
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_family=AF_INET;
sin.sin_port=htons(nSocketPort);
if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
{
GetSockError(GetLastError(),out);
return FALSE;
}
val=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val));
if (val < 0)
{
GetSockError(GetLastError(),out);
return FALSE;
}
if(bind(sock,(struct sockaddr *)&sin,sizeof(sin))<0)//If no error occurs, bind returns zero
{
GetSockError(GetLastError(),out);
return FALSE;
}
if(listen(sock,5))//return 0 no error
{
GetSockError(GetLastError(),out);
return FALSE;
}
Attach(sock,lEvent);
return TRUE;
}
void CSslServerSocket::OnAccept(int nErrorCode) //只有偵聽sock執行
{
// TODO: Add your specialized code here and/or call the base class
BIO * sbio=NULL;
int err;
char out[100]={0};
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -