版本排序,从小到大: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
通过字面意思,我们可以知道其用法。
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>
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>
15 int create_socket(char[], BIO *);
17 int main() {
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;
30 /* ---------------------------------------------------------- *
31 * 初始化OpenSSL *
32 * ---------------------------------------------------------- */
33 OpenSSL_add_all_algorithms();
34 ERR_load_BIO_strings();
35 ERR_load_crypto_strings();
36 SSL_load_error_strings();
38 /* ---------------------------------------------------------- *
39 * 创建一个BIO的输入和输出. *
40 * ---------------------------------------------------------- */
41 certbio = BIO_new(BIO_s_file());
42 outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
44 /* ---------------------------------------------------------- *
45 * 初始化SSL库和注册算法 *
46 * ---------------------------------------------------------- */
47 if (SSL_library_init() < 0)
48 BIO_printf(outbio, "Could not initialize the OpenSSL library !\n");
50 /* ---------------------------------------------------------- *
51 * 发送SSL2 SSL3 TLS 1.0 TLS 2.0 TLS 3.0 与服务器建链 *
52 * ---------------------------------------------------------- */
53 method = SSLv23_client_method();
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");
61 /* ---------------------------------------------------------- *
62 * 禁止使用SSLv3建链 *
63 * ---------------------------------------------------------- */
64 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
66 /* ---------------------------------------------------------- *
67 * 创建一个新的SSL的状态 *
68 * ---------------------------------------------------------- */
69 ssl = SSL_new(ctx);
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);
79 /* ---------------------------------------------------------- *
80 * 关联socket的会话 *
81 * ---------------------------------------------------------- */
82 SSL_set_fd(ssl, server);
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);
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);
105 /* ---------------------------------------------------------- *
106 * 提取各种证书信息 *
107 * -----------------------------------------------------------*/
108 certname = X509_NAME_new();
109 certname = X509_get_subject_name(cert);
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");
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 }
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;
143 /* ---------------------------------------------------------- *
144 * 移除url_str的末尾 / *
145 * ---------------------------------------------------------- */
146 if (url_str[strlen(url_str)] == '/')
147 url_str[strlen(url_str)] = '\0';
149 /* ---------------------------------------------------------- *
150 * the first : ends the protocol string, i.e. http *
151 * ---------------------------------------------------------- */
152 strncpy(proto, url_str, (strchr(url_str, ':') - url_str));
154 /* ---------------------------------------------------------- *
155 * the hostname starts after the "://" part *
156 * ---------------------------------------------------------- */
157 strncpy(hostname, strstr(url_str, "://") + 3, sizeof(hostname));
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 }
169 port = atoi(portnum);
171 if ((host = gethostbyname(hostname)) == NULL) {
172 BIO_printf(out, "Error: Cannot resolve hostname %s.\n", hostname);
173 abort();
174 }
176 /* ---------------------------------------------------------- *
177 * create the basic TCP socket *
178 * ---------------------------------------------------------- */
179 sockfd = socket(AF_INET, SOCK_STREAM, 0);
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);
185 /* ---------------------------------------------------------- *
186 * Zeroing the rest of the struct *
187 * ---------------------------------------------------------- */
188 memset(&(dest_addr.sin_zero), '\0', 8);
190 tmp_ptr = inet_ntoa(dest_addr.sin_addr);
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 }
201 return sockfd;
202 }
View Code