OpenSSLのアップル携帯電話プッシュでの使用

9026 ワード

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
", 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
"); setallthreadexitflag(); return false; } #ifdef _DEBUG LogExt(LOG_LOG_LEVEL,"Server certificate:
"); #endif char* str = X509_NAME_oneline (X509_get_subject_name (ptserver->server_cert),0,0); if (!str) { writelogimmediatly("[exception]X509_NAME_oneline
"); setallthreadexitflag(); return false; } #ifdef _DEBUG LogExt(LOG_LOG_LEVEL,"\t subject: %s
", 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.
"); setallthreadexitflag(); return false; } #ifdef _DEBUG LogExt(LOG_LOG_LEVEL,"\t issuer: %s
", 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.
"); 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:"!
"); errstr.append("
"); 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.
"); 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
"); 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
"); setallthreadexitflag(); return false; } return true; } // bool CWorker::connectToServer(const char *hostname,int port,APP_SERVER *ptserver) { #ifdef _DEBUG writelogimmediatly("connectToServer start
"); #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
"); //LogExt(LOG_LOG_LEVEL,"Error: %s
", 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
"); 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!
"); 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.
"); #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!
"); 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.
"); } 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!
"); 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
",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,&current_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; }