织梦CMS - 轻松建站从此开始!

罗索

SSL双方系统时间不一致导致的SSL连接失败及其解决方案

jackyhwei 发布于 2016-07-18 16:48 点击:次 
通过用wireshake抓包分析SSL建立连接的过程,发现在SSL握手过程中,会向对方传送本机的系统时间.因此一个显而易见的办法就是获取对方的时间,然后在必要时将本机的系统时间改为对方的系统时间,失败后再连一次.
TAG: OpenSSL  

 在 产品使用中,实施人员常常报告服务器与客户端无法连接.究其原因是因为客户端机器与服务端机器系统时间不一致.原因在于系统使用了OpenSSL,证书中 有一个有效时间段,当客户端或服务器的系统时间不在这个时间段内时SSL会因证书验证失败而无法连接.在实施中系统时间错误是很常见的,因不能上网而未开 时间自动同步,bios没电了,客户疏忽等原因都会导致系统时间设置有误.如果连接失败后再查看系统时间设置总是一项麻烦的事情,那么有哪些办法可以自动 避免这个问题呢?
一,将证书的有效期设得够大:如:1970-2099
这样估计可以在一定程度上解决这个问题,不过这也是个馊主意.
二,检测及必要时自动同步客户端与服务器的时间

通过用wireshake抓包分析SSL建立连接的过程,发现在SSL握手过程中,会向对方传送本机的系统时间.因此一个显而易见的办法就是获取对方的时间,然后在必要时将本机的系统时间改为对方的系统时间,失败后再连一次.下面是具体的示例代码:

  1. #include <openssl/ssl.h> 
  2. #include <openssl/bio.h> 
  3. #include <openssl/err.h> 
  4. #include <winsock2.h> 
  5. #include <stdio.h> 
  6. #include <string.h> 
  7. #include <time.h> 
  8.  
  9. typedef struct _TimeInfo 
  10.     time_t client;  /*客户端的时间*/ 
  11.     time_t server;  /*服务器的时间*/ 
  12. } TimeInfo; 
  13.  
  14. /** 
  15. * 同步系统时间. 
  16. */ 
  17. BOOL syncSystemTime(time_t t) 
  18.     SYSTEMTIME st; 
  19.     FILETIME   ft;   
  20.     LONGLONG   ll;   
  21.      
  22.     ll = Int32x32To64(t, 10000000) + 116444736000000000; //1970.01.01   
  23.      
  24.     ft.dwLowDateTime  = (DWORD)ll;   
  25.     ft.dwHighDateTime = (DWORD)(ll >> 32);   
  26.      
  27.     return FileTimeToSystemTime(&ft, &st) && SetSystemTime(&st); 
  28.  
  29. /** 
  30. * 获取SSL握手过程中服务器与客户端双方的系统时间. 
  31. */ 
  32. void getSSLHandleShakeTimeInfo(int write_p, 
  33.                                int version, 
  34.                                int content_type, 
  35.                                const unsigned char* buf, 
  36.                                size_t len, 
  37.                                SSL *ssl, 
  38.                                TimeInfo *ti) 
  39.     if(content_type != 22)   //require handshake message 
  40.         return
  41.     if(len < 42) 
  42.         return
  43.     if(buf[0] == 1)          //ClientHello Message send from client to server 
  44.         ti->client = htonl(*((u_long*)(buf + 6))); 
  45.     else if(buf[0] == 2)     //ServerHello Message send from server to client 
  46.         ti->server = htonl(*((u_long*)(buf + 6))); 
  47.     else 
  48.         return
  49.  
  50. int main() 
  51.     BIO * bio; 
  52.     SSL * ssl; 
  53.     SSL_CTX * ctx; 
  54.     TimeInfo timeInfo = {-1, -1}; 
  55.     BOOL timeSynced = FALSE; 
  56.     long result; 
  57.  
  58.     /* Set up the library */ 
  59.     SSL_library_init(); 
  60.     ERR_load_BIO_strings(); 
  61.     SSL_load_error_strings(); 
  62.  
  63.     /* Set up the SSL context */ 
  64.     ctx = SSL_CTX_new(SSLv3_client_method()); 
  65.     if(ctx == NULL) 
  66.     { 
  67.         fprintf(stderr, "Error new SSL_CTX\n"); 
  68.         ERR_print_errors_fp(stderr); 
  69.         SSL_CTX_free(ctx); 
  70.         return 0; 
  71.     } 
  72.  
  73.     /* Get Server and Client system time via SSL Handshake */ 
  74.     SSL_CTX_set_msg_callback(ctx, getSSLHandleShakeTimeInfo); 
  75.     SSL_CTX_set_msg_callback_arg(ctx, &timeInfo); 
  76.      
  77.     /* Load the trust store */ 
  78.     if(! SSL_CTX_load_verify_locations(ctx, ".\\certs\\cacert.pem", NULL)) 
  79.     { 
  80.         fprintf(stderr, "Error loading trust store\n"); 
  81.         ERR_print_errors_fp(stderr); 
  82.         SSL_CTX_free(ctx); 
  83.         return 0; 
  84.     } 
  85.  
  86.     /* Setup the connection */ 
  87.     bio = BIO_new_ssl_connect(ctx); 
  88.  
  89.     /* Set the SSL_MODE_AUTO_RETRY flag */ 
  90.     BIO_get_ssl(bio, & ssl); 
  91.     SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 
  92.  
  93.     /* Create and setup the connection */ 
  94.     BIO_set_conn_hostname(bio, "192.168.1.5:5555"); 
  95.     if(BIO_do_connect(bio) <= 0) 
  96.     { 
  97.         fprintf(stderr, "Error attempting to connect\n"); 
  98.         ERR_print_errors_fp(stderr); 
  99.         BIO_free_all(bio); 
  100.         SSL_CTX_free(ctx); 
  101.         return 0; 
  102.     } 
  103.      
  104.     /* Check the certificate */ 
  105.     switch(SSL_get_verify_result(ssl)) 
  106.     { 
  107.     case X509_V_OK: 
  108.         break
  109.     case X509_V_ERR_CERT_NOT_YET_VALID: 
  110.     case X509_V_ERR_CERT_HAS_EXPIRED: 
  111.         if(timeInfo.server != -1 && timeInfo.client != -1) 
  112.         { 
  113.             printf("当前客户端时间: %s", ctime(&timeInfo.client)); 
  114.             printf("当前服务器时间: %s", ctime(&timeInfo.server)); 
  115.             printf("尝试与服务器时间同步"); 
  116.              
  117.             if(syncSystemTime(timeInfo.server)) 
  118.                 printf("成功\n"); 
  119.             else 
  120.                 printf("失败\n"); 
  121.             printf("请重试连接服务器!\n"); 
  122.         } 
  123.     default
  124. fprintf(stderr, "Certificate verification error: %i\n", SSL_get_verify_result(ssl)); 
  125.         BIO_free_all(bio); 
  126.         SSL_CTX_free(ctx); 
  127.         return 0; 
  128.     } 
  129.  
  130.     /* Close the connection and free the context */ 
  131.     BIO_free_all(bio); 
  132.     SSL_CTX_free(ctx); 
  133.     return 0; 

 

(zqt520)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201607/17458.html]
本文出处:CSDN博客 作者:zqt520 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容