OpenSSL在苹果手机推送中的使用

来源:互联网 发布:二次元站源码 编辑:程序博客网 时间:2024/05/01 14:36

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等;


view source
print?
001    ////openssl
002    //author:jordan.sg  QQ:87895224
003    //2012.7
004    //初始化部分
005    SSL_library_init();
006    SSL_load_error_strings();
007    SSLeay_add_ssl_algorithms();
008
009    //校验服务器
010    bool CWorker::verifyServer(APP_SERVER *ptserver)
011    {
012        /* Following two steps are optional and not required for
013         data exchange to be successful. */
014
015        /* Set for server verification*/
016        SSL_CTX_set_verify(ptserver->psslctx,SSL_VERIFY_PEER,NULL);
017
018        /* Get the cipher – opt */
019    #ifdef _DEBUG
020        LogExt(LOG_LOG_LEVEL,”SSL connection using %s\n”, SSL_get_cipher(ptserver->ssl));
021    #endif
022        /* Get server’s certificate (note: beware of dynamic allocation) – opt */
023
024        ptserver->server_cert = SSL_get_peer_certificate (ptserver->ssl);
025        if (!ptserver->server_cert)
026        {
027            writelogimmediatly(“[exception]SSL_get_peer_certificate \n”);
028            setallthreadexitflag();
029            return false;
030        }
031    #ifdef _DEBUG
032        LogExt(LOG_LOG_LEVEL,”Server certificate:\n”);
033    #endif
034        char*  str = X509_NAME_oneline (X509_get_subject_name (ptserver->server_cert),0,0);
035        if (!str)
036        {
037            writelogimmediatly(“[exception]X509_NAME_oneline\n”);
038            setallthreadexitflag();
039            return false;
040        }
041
042    #ifdef _DEBUG
043        LogExt(LOG_LOG_LEVEL,”\t subject: %s\n”, str);
044    //subject: /C=US/ST=California/L=Cupertino/O=Apple Inc./OU=iTMS Engineering/CN=gateway.sandbox.push.apple.com
045    //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
046    #endif
047
048        OPENSSL_free (str);
049
050        str = X509_NAME_oneline (X509_get_issuer_name(ptserver->server_cert),0,0);
051        if (!str)
052        {
053            writelogimmediatly(“[exception]X509_NAME_oneline.\n”);
054            setallthreadexitflag();
055            return false;
056        }
057
058    #ifdef _DEBUG
059        LogExt(LOG_LOG_LEVEL,”\t issuer: %s\n”, str);
060    #endif
061
062        OPENSSL_free (str);
063
064        /* We could do all sorts of certificate verification stuff here before
065         deallocating the certificate. */
066
067        X509_free (ptserver->server_cert);
068
069        return true;
070    }
071    //本机校验
072    bool CWorker::caVerify(APP_SERVER *ptserver)
073    {
074        /* define HOME to be dir for key and certificate files… */
075        //#define HOME “/certs/”
076        /* Make these what you want for certificate & key files */
077        #define CERT_FILE  ptserver->pemfile   ///// HOME “1024ccert.pem”
078        #define KEY_FILE   ptserver->pemfile
079
080            /*Cipher list to be used*/
081        #define CIPHER_LIST “AES128-SHA”
082
083            /*Trusted CAs location*/
084        #define CA_FILE  ptserver->pemfile   ////”/certs/1024ccert.pem”
085        #define CA_DIR  NULL
086
087        /*Set cipher list*/
088        if (SSL_CTX_set_cipher_list(ptserver->psslctx,CIPHER_LIST) <= 0)
089        {
090            writelogimmediatly(“[exception][CWorker][SSL]Error setting the cipher list.\n”);
091            setallthreadexitflag();
092            return false ;
093        }
094
095        /*Indicate the certificate file to be used*/
096
097    string pathfile=getExePath();
098        pathfile+=”\\”;
099        pathfile+=ptserver->pemfile;
100        if (SSL_CTX_use_certificate_file(ptserver->psslctx, pathfile.c_str(), SSL_FILETYPE_PEM) <= 0)
101        {
102
103            string errstr(“[err][SSL]Error setting the certificate file”);
104            const char * pc=ERR_reason_error_string(ERR_get_error());
105            errstr.append(pc?pc:”!\n”);
106            errstr.append(“\n”);
107            writelogimmediatly(errstr.c_str() );
108
109            setallthreadexitflag();
110            return false;
111        }
112
113
114        /*Load the password for the Private Key*/
115        SSL_CTX_set_default_passwd_cb_userdata(ptserver->psslctx, (void*)g_cfg.pem_psw.c_str());
116
117        pathfile=getExePath();
118        pathfile+= “\\”;
119        pathfile+=KEY_FILE;
120        /*Indicate the key file to be used*/
121        if (SSL_CTX_use_PrivateKey_file(ptserver->psslctx, pathfile.c_str(), SSL_FILETYPE_PEM) <= 0)
122        {
123            writelogimmediatly(“[exception][CWorker][SSL]Error setting the key file.\n”);
124            setallthreadexitflag();
125            return false;
126        }
127
128        /*Make sure the key and certificate file match*/
129        if (SSL_CTX_check_private_key(ptserver->psslctx) == 0) {
130            writelogimmediatly(“[log][CWorker][SSL]Private key does not match the certificate public key\n”);
131            setallthreadexitflag();
132            return false;
133        }
134
135        /* Set the list of trusted CAs based on the file and/or directory provided*/
136        pathfile=getExePath();
137        pathfile+= “\\”;
138        pathfile+=CA_FILE;
139        if(SSL_CTX_load_verify_locations(ptserver->psslctx, pathfile.c_str(), CA_DIR)<1) {
140            writelogimmediatly(“[log][CWorker][SSL]Error setting verify location\n”);
141            setallthreadexitflag();
142            return false;
143        }
144
145        return true;
146
147    }
148    //连接到苹果的服务器
149    bool CWorker::connectToServer(const char *hostname,int port,APP_SERVER *ptserver)
150    {
151    #ifdef _DEBUG
152        writelogimmediatly(“connectToServer start\n”);
153    #endif
154
155        //set client using SSL version
156        ptserver->meth = (SSL_METHOD *)SSLv23_client_method();
157
158
159        //创建SSL上下文环境
160        ptserver->psslctx = SSL_CTX_new (ptserver->meth);
161        if(!ptserver->psslctx)
162        {
163           writelogimmediatly(“[err]SSL_CTX_new: NULL\n”);
164           //LogExt(LOG_LOG_LEVEL,”Error: %s\n”, ERR_reason_error_string(ERR_get_error()));
165           return false;
166        }
167
168        caVerify(ptserver);
169        /* ———————————————– */
170        /* Create a socket and connect to server using normal socket calls. */
171
172        ptserver->sd = socket (AF_INET, SOCK_STREAM, 0);
173        if(SOCKET_ERROR == ptserver->sd)
174        {
175            writelogimmediatly(“[err][connectToServer]socket\n”);
176            return false;
177        }
178
179        if(!nonblock_connect(ptserver->sd,ptserver->sa,hostname,port))
180        {
181            return false;
182        }
183
184        /* ———————————————– */
185        /* Now we have TCP conncetion. Start SSL negotiation. */
186        ptserver->ssl = SSL_new (ptserver->psslctx);
187        if(!ptserver->ssl)
188        {
189            string errstr(“[err][SSL_new]“);
190            const char * pc=ERR_reason_error_string(ERR_get_error());
191            errstr.append(pc?pc:”fail!\n”);
192            writelogimmediatly(errstr.c_str() );
193            return false;
194        }
195        SSL_set_fd (ptserver->ssl, ptserver->sd);
196        SSL_set_mode(ptserver->ssl, SSL_MODE_AUTO_RETRY);
197
198    #ifdef NONEBLOCK_SOCKET
199
200    CONN_RE:
201
202        ptserver->err = SSL_connect (ptserver->ssl);
203        if(1 == ptserver->err)
204        {
205    #ifdef _DEBUG
206            LogExt(LOG_LOG_LEVEL,”The TLS/SSL handshake was successfully completed, a TLS/SSL connection has been established.\n”);
207    #endif
208        }
209        else if(-1 == ptserver->err)
210        {
211            ptserver->err = SSL_get_error(ptserver->ssl,ptserver->err);
212            if (SSL_ERROR_WANT_READ==ptserver->err || SSL_ERROR_WANT_WRITE==ptserver->err)
213            {
214                goto CONN_RE;
215            }
216            string errstr(“[err][SSL_connect]fail!\n”);
217            writelogimmediatly(errstr.c_str() );
218            return false;
219        }
220
221    #else
222
223        ptserver->err = SSL_connect (ptserver->ssl);
224        if(1 == ptserver->err)
225        {
226            LogExt(LOG_LOG_LEVEL,”The TLS/SSL handshake was successfully completed, a TLS/SSL connection has been established.\n”);
227        }
228        else if(-1 == ptserver->err)
229        {
230            string errstr(“[err][SSL_connect]“);
231            const char * pc=ERR_reason_error_string(ERR_get_error());
232            errstr.append(pc?pc:”fail!\n”);
233            writelogimmediatly(errstr.c_str() );
234            return false;
235        }
236    #endif
237        // 检查证书是否有效
238        //20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate
239        //  the issuer certificate could not be found: this occurs if the issuer certificate of an untrusted certificate cannot be found.
240
241        int ret_ssl=0;
242        if(X509_V_OK !=  ( ret_ssl=SSL_get_verify_result(ptserver->ssl)))
243        {
244            LogExt(LOG_LOG_LEVEL,”SSL_get_verify_result =>%d\n”,ret_ssl);
245        }
246
247        return true;
248    }
249
250    //连接到Feedback沙盒测试服务器
251    bool CWorker::connectToFeedbackSandBoxServer()
252    {
253        bool ret = connectToServer(g_cfg.feedback_sandbox_www.c_str(),g_cfg.feedback_sandbox_port,&this->feed);
254        if (ret)
255        {
256            verifyServer(&this->feed);
257        }
258
259        return ret;
260    }
261
262    //读取Feedback
263    void CWorker::getFeedback()
264    {
265        bool ret = false;
266        if ( IsSandBox())
267        {
268            ret = connectToFeedbackSandBoxServer();
269        }
270        else
271        {
272            ret = connectToFeedbackServer();
273        }
274
275        //读feedback
276        if (ret)
277        {
278            readFeedbackSub();
279        }
280
281        stopSSLFeed();
282    }
283    //发送推送信息
284    void CWorker::sendtoAPNs()
285    {
286        bool ret = false;
287        if ( IsSandBox())
288        {
289            ret = connectToAPNsSandBox();
290        }
291        else
292        {
293            ret = connectToAPNs();
294        }
295
296        if (ret)
297        {
298            //找到开始的一条信息,开始的一个设备
299            string current_info_id(“”);//send_id char12
300            UINT   current_device_id=0;
301            string current_device_token(“”);
302
303            StartSend(current_info_id,current_device_token,&current_device_id);
304            if (!current_info_id.empty() && !current_device_token.empty() )
305            {
306                batchSendtoApns(current_info_id,current_device_token,current_device_id);
307            }
308
309            //
310
311        }
312        stopSSLApns();
313
314    }
315
316    void CWorker::stopSSLFeed()
317    {
318
319        if (feed.ssl)
320        {
321            SSL_shutdown (feed.ssl);  /* send SSL/TLS close_notify */
322
323            close (feed.sd);
324            SSL_free (feed.ssl);
325            SSL_CTX_free (feed.psslctx);
326        }
327        feed.ssl=NULL;
328
329
330    }

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等;
view sourceprint?
001////openssl
002//author:jordan.sg  QQ:87895224 
003//2012.7
004//初始化部分
005SSL_library_init();
006SSL_load_error_strings();
007SSLeay_add_ssl_algorithms();
008 
009//校验服务器
010bool CWorker::verifyServer(APP_SERVER *ptserver)
011{
012    /* Following two steps are optional and not required for
013     data exchange to be successful. */
014 
015    /* Set for server verification*/
016    SSL_CTX_set_verify(ptserver->psslctx,SSL_VERIFY_PEER,NULL);
017 
018    /* Get the cipher - opt */
019#ifdef _DEBUG
020    LogExt(LOG_LOG_LEVEL,"SSL connection using %s\n", SSL_get_cipher(ptserver->ssl));
021#endif
022    /* Get server's certificate (note: beware of dynamic allocation) - opt */
023 
024    ptserver->server_cert = SSL_get_peer_certificate (ptserver->ssl);      
025    if (!ptserver->server_cert)
026    {
027        writelogimmediatly("[exception]SSL_get_peer_certificate \n");
028        setallthreadexitflag();
029        return false;
030    }
031#ifdef _DEBUG
032    LogExt(LOG_LOG_LEVEL,"Server certificate:\n");
033#endif
034    char*  str = X509_NAME_oneline (X509_get_subject_name (ptserver->server_cert),0,0);
035    if (!str)
036    {
037        writelogimmediatly("[exception]X509_NAME_oneline\n");
038        setallthreadexitflag();
039        return false;
040    }
041 
042#ifdef _DEBUG
043    LogExt(LOG_LOG_LEVEL,"\t subject: %s\n", str);
044//subject: /C=US/ST=California/L=Cupertino/O=Apple Inc./OU=iTMS Engineering/CN=gateway.sandbox.push.apple.com
045//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
046#endif
047 
048    OPENSSL_free (str);
049 
050    str = X509_NAME_oneline (X509_get_issuer_name(ptserver->server_cert),0,0);
051    if (!str)
052    {
053        writelogimmediatly("[exception]X509_NAME_oneline.\n");
054        setallthreadexitflag();
055        return false;
056    }
057 
058#ifdef _DEBUG
059    LogExt(LOG_LOG_LEVEL,"\t issuer: %s\n", str);
060#endif
061 
062    OPENSSL_free (str);
063 
064    /* We could do all sorts of certificate verification stuff here before
065     deallocating the certificate. */
066 
067    X509_free (ptserver->server_cert);
068 
069    return true;
070}
071//本机校验
072bool CWorker::caVerify(APP_SERVER *ptserver)
073{
074    /* define HOME to be dir for key and certificate files... */
075    //#define HOME "/certs/"
076    /* Make these what you want for certificate & key files */
077    #define CERT_FILE  ptserver->pemfile   ///// HOME "1024ccert.pem"
078    #define KEY_FILE   ptserver->pemfile
079        
080        /*Cipher list to be used*/
081    #define CIPHER_LIST "AES128-SHA"
082        
083        /*Trusted CAs location*/
084    #define CA_FILE  ptserver->pemfile   ////"/certs/1024ccert.pem"
085    #define CA_DIR  NULL
086    
087    /*Set cipher list*/
088    if (SSL_CTX_set_cipher_list(ptserver->psslctx,CIPHER_LIST) <= 0)
089    {
090        writelogimmediatly("[exception][CWorker][SSL]Error setting the cipher list.\n");
091        setallthreadexitflag();
092        return false ;
093    }
094 
095    /*Indicate the certificate file to be used*/
096 
097string pathfile=getExePath();
098    pathfile+="\\";
099    pathfile+=ptserver->pemfile;
100    if (SSL_CTX_use_certificate_file(ptserver->psslctx, pathfile.c_str(), SSL_FILETYPE_PEM) <= 0)
101    {
102 
103        string errstr("[err][SSL]Error setting the certificate file");
104        const char * pc=ERR_reason_error_string(ERR_get_error());
105        errstr.append(pc?pc:"!\n");
106        errstr.append("\n");
107        writelogimmediatly(errstr.c_str() );
108 
109        setallthreadexitflag();
110        return false;
111    }
112 
113 
114    /*Load the password for the Private Key*/
115    SSL_CTX_set_default_passwd_cb_userdata(ptserver->psslctx, (void*)g_cfg.pem_psw.c_str());
116 
117    pathfile=getExePath();
118    pathfile+= "\\";
119    pathfile+=KEY_FILE;
120    /*Indicate the key file to be used*/
121    if (SSL_CTX_use_PrivateKey_file(ptserver->psslctx, pathfile.c_str(), SSL_FILETYPE_PEM) <= 0)
122    {
123        writelogimmediatly("[exception][CWorker][SSL]Error setting the key file.\n");
124        setallthreadexitflag();
125        return false;
126    }
127 
128    /*Make sure the key and certificate file match*/
129    if (SSL_CTX_check_private_key(ptserver->psslctx) == 0) {
130        writelogimmediatly("[log][CWorker][SSL]Private key does not match the certificate public key\n");
131        setallthreadexitflag();
132        return false;
133    }
134 
135    /* Set the list of trusted CAs based on the file and/or directory provided*/
136    pathfile=getExePath();
137    pathfile+= "\\";
138    pathfile+=CA_FILE;
139    if(SSL_CTX_load_verify_locations(ptserver->psslctx, pathfile.c_str(), CA_DIR)<1) {
140        writelogimmediatly("[log][CWorker][SSL]Error setting verify location\n");
141        setallthreadexitflag();
142        return false;
143    }
144 
145    return true;
146 
147}
148//连接到苹果的服务器
149bool CWorker::connectToServer(const char *hostname,int port,APP_SERVER *ptserver)
150{
151#ifdef _DEBUG
152    writelogimmediatly("connectToServer start\n");
153#endif
154 
155    //set client using SSL version
156    ptserver->meth = (SSL_METHOD *)SSLv23_client_method();
157    
158 
159    //创建SSL上下文环境
160    ptserver->psslctx = SSL_CTX_new (ptserver->meth);
161    if(!ptserver->psslctx)
162    {
163       writelogimmediatly("[err]SSL_CTX_new: NULL\n");
164       //LogExt(LOG_LOG_LEVEL,"Error: %s\n", ERR_reason_error_string(ERR_get_error()));
165       return false;
166    }
167 
168    caVerify(ptserver);
169    /* ----------------------------------------------- */
170    /* Create a socket and connect to server using normal socket calls. */
171    
172    ptserver->sd = socket (AF_INET, SOCK_STREAM, 0);      
173    if(SOCKET_ERROR == ptserver->sd)
174    {
175        writelogimmediatly("[err][connectToServer]socket\n");
176        return false;
177    }
178 
179    if(!nonblock_connect(ptserver->sd,ptserver->sa,hostname,port))
180    {
181        return false;
182    }
183    
184    /* ----------------------------------------------- */
185    /* Now we have TCP conncetion. Start SSL negotiation. */
186    ptserver->ssl = SSL_new (ptserver->psslctx); 
187    if(!ptserver->ssl)
188    {  
189        string errstr("[err][SSL_new]");
190        const char * pc=ERR_reason_error_string(ERR_get_error());
191        errstr.append(pc?pc:"fail!\n");    
192        writelogimmediatly(errstr.c_str() );
193        return false;
194    }
195    SSL_set_fd (ptserver->ssl, ptserver->sd);
196    SSL_set_mode(ptserver->ssl, SSL_MODE_AUTO_RETRY);
197 
198#ifdef NONEBLOCK_SOCKET
199 
200CONN_RE:
201 
202    ptserver->err = SSL_connect (ptserver->ssl);
203    if(1 == ptserver->err)
204    {
205#ifdef _DEBUG
206        LogExt(LOG_LOG_LEVEL,"The TLS/SSL handshake was successfully completed, a TLS/SSL connection has been established.\n");
207#endif
208    }
209    else if(-1 == ptserver->err)
210    {      
211        ptserver->err = SSL_get_error(ptserver->ssl,ptserver->err);
212        if (SSL_ERROR_WANT_READ==ptserver->err || SSL_ERROR_WANT_WRITE==ptserver->err)
213        {
214            goto CONN_RE;
215        }
216        string errstr("[err][SSL_connect]fail!\n");
217        writelogimmediatly(errstr.c_str() );
218        return false;
219    }
220 
221#else
222 
223    ptserver->err = SSL_connect (ptserver->ssl);
224    if(1 == ptserver->err)
225    {
226        LogExt(LOG_LOG_LEVEL,"The TLS/SSL handshake was successfully completed, a TLS/SSL connection has been established.\n");
227    }
228    else if(-1 == ptserver->err)
229    {      
230        string errstr("[err][SSL_connect]");
231        const char * pc=ERR_reason_error_string(ERR_get_error());
232        errstr.append(pc?pc:"fail!\n");
233        writelogimmediatly(errstr.c_str() );
234        return false;
235    }
236#endif
237    // 检查证书是否有效
238    //20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate
239    //  the issuer certificate could not be found: this occurs if the issuer certificate of an untrusted certificate cannot be found.
240 
241    int ret_ssl=0;
242    if(X509_V_OK !=  ( ret_ssl=SSL_get_verify_result(ptserver->ssl)))
243    {
244        LogExt(LOG_LOG_LEVEL,"SSL_get_verify_result =>%d\n",ret_ssl);
245    }
246    
247    return true;
248}
249 
250//连接到Feedback沙盒测试服务器
251bool CWorker::connectToFeedbackSandBoxServer()
252{  
253    bool ret = connectToServer(g_cfg.feedback_sandbox_www.c_str(),g_cfg.feedback_sandbox_port,&this->feed);
254    if (ret)
255    {
256        verifyServer(&this->feed);
257    }
258 
259    return ret;
260}
261 
262//读取Feedback
263void CWorker::getFeedback()
264{
265    bool ret = false;
266    if ( IsSandBox())
267    {
268        ret = connectToFeedbackSandBoxServer();
269    }
270    else
271    {
272        ret = connectToFeedbackServer();
273    }
274    
275    //读feedback
276    if (ret)
277    {
278        readFeedbackSub();
279    }
280         
281    stopSSLFeed();
282}
283//发送推送信息
284void CWorker::sendtoAPNs()
285{
286    bool ret = false;
287    if ( IsSandBox())
288    {
289        ret = connectToAPNsSandBox();  
290    }
291    else
292    {
293        ret = connectToAPNs();
294    }
295    
296    if (ret)
297    {
298        //找到开始的一条信息,开始的一个设备
299        string current_info_id("");//send_id char12
300        UINT   current_device_id=0;
301        string current_device_token("");
302        
303        StartSend(current_info_id,current_device_token,&current_device_id);
304        if (!current_info_id.empty() && !current_device_token.empty() )
305        {
306            batchSendtoApns(current_info_id,current_device_token,current_device_id);
307        }
308        
309        //
310        
311    }
312    stopSSLApns();
313    
314}
315 
316void CWorker::stopSSLFeed()
317{
318 
319    if (feed.ssl)
320    {
321        SSL_shutdown (feed.ssl);  /* send SSL/TLS close_notify */
322        
323        close (feed.sd);
324        SSL_free (feed.ssl);
325        SSL_CTX_free (feed.psslctx);
326    }
327    feed.ssl=NULL;
328 
329 
330}

原创粉丝点击