opensslshiy流程:
1.初始化;
SSLv23_client_method();建立SSL上下文環境 SSL_CTX_new ()
2.建立socket,connect;校驗證書;
3.socket綁定SSL:SSL_new,SSL_connect;
4.校驗服務器證書;
5.SSL_write,SSL_read;
6.釋放資源 SSL_shutdown等;
////openssl
//author:jordan.sg QQ:87895224
//2012.7
//初始化部分
SSL_library_init();
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
//校驗服務器
bool CWorker::verifyServer(APP_SERVER *ptserver)
{
/* Following two steps are optional and not required for
data exchange to be successful. */
/* Set for server verification*/
SSL_CTX_set_verify(ptserver->psslctx,SSL_VERIFY_PEER,NULL);
/* Get the cipher - opt */
#ifdef _DEBUG
LogExt(LOG_LOG_LEVEL,"SSL connection using %s\n", SSL_get_cipher(ptserver->ssl));
#endif
/* Get server's certificate (note: beware of dynamic allocation) - opt */
ptserver->server_cert = SSL_get_peer_certificate (ptserver->ssl);
if (!ptserver->server_cert)
{
writelogimmediatly("[exception]SSL_get_peer_certificate \n");
setallthreadexitflag();
return false;
}
#ifdef _DEBUG
LogExt(LOG_LOG_LEVEL,"Server certificate:\n");
#endif
char* str = X509_NAME_oneline (X509_get_subject_name (ptserver->server_cert),0,0);
if (!str)
{
writelogimmediatly("[exception]X509_NAME_oneline\n");
setallthreadexitflag();
return false;
}
#ifdef _DEBUG
LogExt(LOG_LOG_LEVEL,"\t subject: %s\n", str);
//subject: /C=US/ST=California/L=Cupertino/O=Apple Inc./OU=iTMS Engineering/CN=gateway.sandbox.push.apple.com
//issuer: /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
#endif
OPENSSL_free (str);
str = X509_NAME_oneline (X509_get_issuer_name(ptserver->server_cert),0,0);
if (!str)
{
writelogimmediatly("[exception]X509_NAME_oneline.\n");
setallthreadexitflag();
return false;
}
#ifdef _DEBUG
LogExt(LOG_LOG_LEVEL,"\t issuer: %s\n", str);
#endif
OPENSSL_free (str);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
X509_free (ptserver->server_cert);
return true;
}
//本機校驗
bool CWorker::caVerify(APP_SERVER *ptserver)
{
/* define HOME to be dir for key and certificate files... */
//#define HOME "/certs/"
/* Make these what you want for certificate & key files */
#define CERT_FILE ptserver->pemfile ///// HOME "1024ccert.pem"
#define KEY_FILE ptserver->pemfile
/*Cipher list to be used*/
#define CIPHER_LIST "AES128-SHA"
/*Trusted CAs location*/
#define CA_FILE ptserver->pemfile ////"/certs/1024ccert.pem"
#define CA_DIR NULL
/*Set cipher list*/
if (SSL_CTX_set_cipher_list(ptserver->psslctx,CIPHER_LIST) <= 0)
{
writelogimmediatly("[exception][CWorker][SSL]Error setting the cipher list.\n");
setallthreadexitflag();
return false ;
}
/*Indicate the certificate file to be used*/
string pathfile=getExePath();
pathfile+="\\";
pathfile+=ptserver->pemfile;
if (SSL_CTX_use_certificate_file(ptserver->psslctx, pathfile.c_str(), SSL_FILETYPE_PEM) <= 0)
{
string errstr("[err][SSL]Error setting the certificate file");
const char * pc=ERR_reason_error_string(ERR_get_error());
errstr.append(pc?pc:"!\n");
errstr.append("\n");
writelogimmediatly(errstr.c_str() );
setallthreadexitflag();
return false;
}
/*Load the password for the Private Key*/
SSL_CTX_set_default_passwd_cb_userdata(ptserver->psslctx, (void*)g_cfg.pem_psw.c_str());
pathfile=getExePath();
pathfile+= "\\";
pathfile+=KEY_FILE;
/*Indicate the key file to be used*/
if (SSL_CTX_use_PrivateKey_file(ptserver->psslctx, pathfile.c_str(), SSL_FILETYPE_PEM) <= 0)
{
writelogimmediatly("[exception][CWorker][SSL]Error setting the key file.\n");
setallthreadexitflag();
return false;
}
/*Make sure the key and certificate file match*/
if (SSL_CTX_check_private_key(ptserver->psslctx) == 0) {
writelogimmediatly("[log][CWorker][SSL]Private key does not match the certificate public key\n");
setallthreadexitflag();
return false;
}
/* Set the list of trusted CAs based on the file and/or directory provided*/
pathfile=getExePath();
pathfile+= "\\";
pathfile+=CA_FILE;
if(SSL_CTX_load_verify_locations(ptserver->psslctx, pathfile.c_str(), CA_DIR)<1) {
writelogimmediatly("[log][CWorker][SSL]Error setting verify location\n");
setallthreadexitflag();
return false;
}
return true;
}
//鏈接到蘋果的服務器
bool CWorker::connectToServer(const char *hostname,int port,APP_SERVER *ptserver)
{
#ifdef _DEBUG
writelogimmediatly("connectToServer start\n");
#endif
//set client using SSL version
ptserver->meth = (SSL_METHOD *)SSLv23_client_method();
//建立SSL上下文環境
ptserver->psslctx = SSL_CTX_new (ptserver->meth);
if(!ptserver->psslctx)
{
writelogimmediatly("[err]SSL_CTX_new: NULL\n");
//LogExt(LOG_LOG_LEVEL,"Error: %s\n", ERR_reason_error_string(ERR_get_error()));
return false;
}
caVerify(ptserver);
/* ----------------------------------------------- */
/* Create a socket and connect to server using normal socket calls. */
ptserver->sd = socket (AF_INET, SOCK_STREAM, 0);
if(SOCKET_ERROR == ptserver->sd)
{
writelogimmediatly("[err][connectToServer]socket\n");
return false;
}
if(!nonblock_connect(ptserver->sd,ptserver->sa,hostname,port))
{
return false;
}
/* ----------------------------------------------- */
/* Now we have TCP conncetion. Start SSL negotiation. */
ptserver->ssl = SSL_new (ptserver->psslctx);
if(!ptserver->ssl)
{
string errstr("[err][SSL_new]");
const char * pc=ERR_reason_error_string(ERR_get_error());
errstr.append(pc?pc:"fail!\n");
writelogimmediatly(errstr.c_str() );
return false;
}
SSL_set_fd (ptserver->ssl, ptserver->sd);
SSL_set_mode(ptserver->ssl, SSL_MODE_AUTO_RETRY);
#ifdef NONEBLOCK_SOCKET
CONN_RE:
ptserver->err = SSL_connect (ptserver->ssl);
if(1 == ptserver->err)
{
#ifdef _DEBUG
LogExt(LOG_LOG_LEVEL,"The TLS/SSL handshake was successfully completed, a TLS/SSL connection has been established.\n");
#endif
}
else if(-1 == ptserver->err)
{
ptserver->err = SSL_get_error(ptserver->ssl,ptserver->err);
if (SSL_ERROR_WANT_READ==ptserver->err || SSL_ERROR_WANT_WRITE==ptserver->err)
{
goto CONN_RE;
}
string errstr("[err][SSL_connect]fail!\n");
writelogimmediatly(errstr.c_str() );
return false;
}
#else
ptserver->err = SSL_connect (ptserver->ssl);
if(1 == ptserver->err)
{
LogExt(LOG_LOG_LEVEL,"The TLS/SSL handshake was successfully completed, a TLS/SSL connection has been established.\n");
}
else if(-1 == ptserver->err)
{
string errstr("[err][SSL_connect]");
const char * pc=ERR_reason_error_string(ERR_get_error());
errstr.append(pc?pc:"fail!\n");
writelogimmediatly(errstr.c_str() );
return false;
}
#endif
// 檢查證書是否有效
//20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate
// the issuer certificate could not be found: this occurs if the issuer certificate of an untrusted certificate cannot be found.
int ret_ssl=0;
if(X509_V_OK != ( ret_ssl=SSL_get_verify_result(ptserver->ssl)))
{
LogExt(LOG_LOG_LEVEL,"SSL_get_verify_result =>%d\n",ret_ssl);
}
return true;
}
//鏈接到Feedback沙盒測試服務器
bool CWorker::connectToFeedbackSandBoxServer()
{
bool ret = connectToServer(g_cfg.feedback_sandbox_www.c_str(),g_cfg.feedback_sandbox_port,&this->feed);
if (ret)
{
verifyServer(&this->feed);
}
return ret;
}
//讀取Feedback
void CWorker::getFeedback()
{
bool ret = false;
if ( IsSandBox())
{
ret = connectToFeedbackSandBoxServer();
}
else
{
ret = connectToFeedbackServer();
}
//讀feedback
if (ret)
{
readFeedbackSub();
}
stopSSLFeed();
}
//發送推送信息
void CWorker::sendtoAPNs()
{
bool ret = false;
if ( IsSandBox())
{
ret = connectToAPNsSandBox();
}
else
{
ret = connectToAPNs();
}
if (ret)
{
//找到開始的一條信息,開始的一個設備
string current_info_id("");//send_id char12
UINT current_device_id=0;
string current_device_token("");
StartSend(current_info_id,current_device_token,¤t_device_id);
if (!current_info_id.empty() && !current_device_token.empty() )
{
batchSendtoApns(current_info_id,current_device_token,current_device_id);
}
//
}
stopSSLApns();
}
void CWorker::stopSSLFeed()
{
if (feed.ssl)
{
SSL_shutdown (feed.ssl); /* send SSL/TLS close_notify */
close (feed.sd);
SSL_free (feed.ssl);
SSL_CTX_free (feed.psslctx);
}
feed.ssl=NULL;
}