如何做一个用于测试SSL版本的客户端

最近由于工作的需要,需要升级建链过程中SSL的版本,因此有了这篇博文。

科普:

  版本排序,从小到大:SSLv2, SSLv3, TLSv1, TLSv1.1 and TLSv1.2

SSL_CTX_new:creates a new SSL_CTX object as framework to establish TLS/SSL enabled connections.
 #include <openssl/ssl.h>

 SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);

其中,要想知道 SSL_METHOD有多少个可以用的方法,参见:http://openssl.cs.utah.edu/docs/ssl/SSL_CTX_new.html

SSL_CTX_set_options() or SSL_set_options():该方法是用来禁止使用什么协议来建链的。其中有以下选项可以填写:

SSL_OP_NO_SSLv2, SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1_1 and SSL_OP_NO_TLSv1_2

通过字面意思,我们可以知道其用法。

Demo

  1 #include <sys/socket.h>
  2 #include <resolv.h>
  3 #include <netdb.h>
  4 #include <netinet/in.h>
  5 #include <arpa/inet.h>
  6 #include <string.h>
  7 
  8 #include <openssl/bio.h>
  9 #include <openssl/ssl.h>
 10 #include <openssl/err.h>
 11 #include <openssl/pem.h>
 12 #include <openssl/x509.h>
 13 #include <openssl/x509_vfy.h>
 14 
 15 int create_socket(char[], BIO *);
 16 
 17 int main() {
 18 
 19     char dest_url[] = "https://www.baidu.com";
 20     BIO *certbio = NULL;
 21     BIO *outbio = NULL;
 22     X509 *cert = NULL;
 23     X509_NAME *certname = NULL;
 24     const SSL_METHOD *method;
 25     SSL_CTX *ctx;
 26     SSL *ssl;
 27     int server = 0;
 28     int ret, i;
 29 
 30     /* ---------------------------------------------------------- *
 31      * 初始化OpenSSL                                                *
 32      * ---------------------------------------------------------- */
 33     OpenSSL_add_all_algorithms();
 34     ERR_load_BIO_strings();
 35     ERR_load_crypto_strings();
 36     SSL_load_error_strings();
 37 
 38     /* ---------------------------------------------------------- *
 39      * 创建一个BIO的输入和输出.                                   *
 40      * ---------------------------------------------------------- */
 41     certbio = BIO_new(BIO_s_file());
 42     outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
 43 
 44     /* ---------------------------------------------------------- *
 45      * 初始化SSL库和注册算法                                      *
 46      * ---------------------------------------------------------- */
 47     if (SSL_library_init() < 0)
 48         BIO_printf(outbio, "Could not initialize the OpenSSL library !\n");
 49 
 50     /* ---------------------------------------------------------- *
 51      * 发送SSL2 SSL3 TLS 1.0 TLS 2.0 TLS 3.0 与服务器建链         *
 52      * ---------------------------------------------------------- */
 53     method = SSLv23_client_method();
 54 
 55     /* ---------------------------------------------------------- *
 56      * 创建一个新的SSL上下文                                      *
 57      * ---------------------------------------------------------- */
 58     if ((ctx = SSL_CTX_new(method)) == NULL)
 59         BIO_printf(outbio, "Unable to create a new SSL context structure.\n");
 60 
 61     /* ---------------------------------------------------------- *
 62      * 禁止使用SSLv3建链                                          *
 63      * ---------------------------------------------------------- */
 64     SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
 65 
 66     /* ---------------------------------------------------------- *
 67      * 创建一个新的SSL的状态                                      *
 68      * ---------------------------------------------------------- */
 69     ssl = SSL_new(ctx);
 70 
 71     /* ---------------------------------------------------------- *
 72      * 创建一个优先的SSL TCP 链接                                 *
 73      * ---------------------------------------------------------- */
 74     server = create_socket(dest_url, outbio);
 75     if (server != 0)
 76         BIO_printf(outbio, "Successfully made the TCP connection to: %s.\n",
 77                 dest_url);
 78 
 79     /* ---------------------------------------------------------- *
 80      * 关联socket的会话                                           *
 81      * ---------------------------------------------------------- */
 82     SSL_set_fd(ssl, server);
 83 
 84     /* ---------------------------------------------------------- *
 85      * 建立SSL 链接,返回1成功                                    *
 86      * ---------------------------------------------------------- */
 87     if (SSL_connect(ssl) != 1)
 88         BIO_printf(outbio, "Error: Could not build a SSL session to: %s.\n",
 89                 dest_url);
 90     else
 91         BIO_printf(outbio, "Successfully enabled SSL/TLS session to: %s.\n",
 92                 dest_url);
 93 
 94     /* ---------------------------------------------------------- *
 95      * 得到服务端的证书到X509结构体                               *
 96      * ---------------------------------------------------------- */
 97     cert = SSL_get_peer_certificate(ssl);
 98     if (cert == NULL)
 99         BIO_printf(outbio, "Error: Could not get a certificate from: %s.\n",
100                 dest_url);
101     else
102         BIO_printf(outbio, "Retrieved the server's certificate from: %s.\n",
103                 dest_url);
104 
105     /* ---------------------------------------------------------- *
106      * 提取各种证书信息                    *
107      * -----------------------------------------------------------*/
108     certname = X509_NAME_new();
109     certname = X509_get_subject_name(cert);
110 
111     /* ---------------------------------------------------------- *
112      * 这里显示证书的主题                                         *
113      * -----------------------------------------------------------*/
114     BIO_printf(outbio, "Displaying the certificate subject data:\n");
115     X509_NAME_print_ex(outbio, certname, 0, 0);
116     BIO_printf(outbio, "\n");
117 
118     /* ---------------------------------------------------------- *
119      * 释放不再使用的结构体                  *
120      * -----------------------------------------------------------*/
121     SSL_free(ssl);
122     close(server);
123     X509_free(cert);
124     SSL_CTX_free(ctx);
125     BIO_printf(outbio, "Finished SSL/TLS connection with server: %s.\n",
126             dest_url);
127     return (0);
128 }
129 
130 /* ---------------------------------------------------------- *
131  * create_socket() 和服务端建立TCP的socket链接                *
132  * ---------------------------------------------------------- */
133 int create_socket(char url_str[], BIO *out) {
134     int sockfd;
135     char hostname[256] = "";
136     char portnum[6] = "443";
137     char proto[6] = "";
138     char *tmp_ptr = NULL;
139     int port;
140     struct hostent *host;
141     struct sockaddr_in dest_addr;
142 
143     /* ---------------------------------------------------------- *
144      * 移除url_str的末尾 /                                        *
145      * ---------------------------------------------------------- */
146     if (url_str[strlen(url_str)] == '/')
147         url_str[strlen(url_str)] = '\0';
148 
149     /* ---------------------------------------------------------- *
150      * the first : ends the protocol string, i.e. http            *
151      * ---------------------------------------------------------- */
152     strncpy(proto, url_str, (strchr(url_str, ':') - url_str));
153 
154     /* ---------------------------------------------------------- *
155      * the hostname starts after the "://" part                   *
156      * ---------------------------------------------------------- */
157     strncpy(hostname, strstr(url_str, "://") + 3, sizeof(hostname));
158 
159     /* ---------------------------------------------------------- *
160      * if the hostname contains a colon :, we got a port number   *
161      * ---------------------------------------------------------- */
162     if (strchr(hostname, ':')) {
163         tmp_ptr = strchr(hostname, ':');
164         /* the last : starts the port number, if avail, i.e. 8443 */
165         strncpy(portnum, tmp_ptr + 1, sizeof(portnum));
166         *tmp_ptr = '\0';
167     }
168 
169     port = atoi(portnum);
170 
171     if ((host = gethostbyname(hostname)) == NULL) {
172         BIO_printf(out, "Error: Cannot resolve hostname %s.\n", hostname);
173         abort();
174     }
175 
176     /* ---------------------------------------------------------- *
177      * create the basic TCP socket                                *
178      * ---------------------------------------------------------- */
179     sockfd = socket(AF_INET, SOCK_STREAM, 0);
180 
181     dest_addr.sin_family = AF_INET;
182     dest_addr.sin_port = htons(port);
183     dest_addr.sin_addr.s_addr = *(long*) (host->h_addr);
184 
185     /* ---------------------------------------------------------- *
186      * Zeroing the rest of the struct                             *
187      * ---------------------------------------------------------- */
188     memset(&(dest_addr.sin_zero), '\0', 8);
189 
190     tmp_ptr = inet_ntoa(dest_addr.sin_addr);
191 
192     /* ---------------------------------------------------------- *
193      * Try to make the host connect here                          *
194      * ---------------------------------------------------------- */
195     if (connect(sockfd, (struct sockaddr *) &dest_addr, sizeof(struct sockaddr))
196             == -1) {
197         BIO_printf(out, "Error: Cannot connect to host %s [%s] on port %d.\n",
198                 hostname, tmp_ptr, port);
199     }
200 
201     return sockfd;
202 }
View Code

 

posted @ 2016-11-20 16:48  天天AC  阅读(3171)  评论(1编辑  收藏  举报