Let users retry connection in case of error. Especially SSL error.
[elinks.git] / src / network / ssl / socket.c
bloba19ffd4f62bdddd7840e155816e983f05ac6b35f
1 /* SSL socket workshop */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #ifdef CONFIG_OPENSSL
8 #include <openssl/ssl.h>
9 #include <openssl/x509v3.h>
10 #define USE_OPENSSL
11 #elif defined(CONFIG_NSS_COMPAT_OSSL)
12 #include <nss_compat_ossl/nss_compat_ossl.h>
13 #define USE_OPENSSL
14 #elif defined(CONFIG_GNUTLS)
15 #include <gnutls/gnutls.h>
16 #include <gnutls/x509.h>
17 #else
18 #error "Huh?! You have SSL enabled, but not OPENSSL nor GNUTLS!! And then you want exactly *what* from me?"
19 #endif
21 #ifdef HAVE_ARPA_INET_H
22 #include <arpa/inet.h>
23 #endif
24 #include <errno.h>
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h>
27 #endif
29 #include "elinks.h"
31 #include "config/options.h"
32 #include "main/select.h"
33 #include "network/connection.h"
34 #include "network/socket.h"
35 #include "network/ssl/match-hostname.h"
36 #include "network/ssl/socket.h"
37 #include "network/ssl/ssl.h"
38 #include "protocol/uri.h"
39 #include "util/memory.h"
42 /* SSL errors */
43 #ifdef USE_OPENSSL
44 #define SSL_ERROR_WANT_READ2 9999 /* XXX */
45 #define SSL_ERROR_WANT_WRITE2 SSL_ERROR_WANT_WRITE
46 #define SSL_ERROR_SYSCALL2 SSL_ERROR_SYSCALL
47 #elif defined(CONFIG_GNUTLS)
48 #define SSL_ERROR_NONE GNUTLS_E_SUCCESS
49 #define SSL_ERROR_WANT_READ GNUTLS_E_AGAIN
50 #define SSL_ERROR_WANT_READ2 GNUTLS_E_INTERRUPTED
51 #define SSL_ERROR_WANT_WRITE GNUTLS_E_AGAIN
52 #define SSL_ERROR_WANT_WRITE2 GNUTLS_E_INTERRUPTED
53 #define SSL_ERROR_SYSCALL GNUTLS_E_PUSH_ERROR
54 #define SSL_ERROR_SYSCALL2 GNUTLS_E_PULL_ERROR
55 #endif
57 #ifdef USE_OPENSSL
59 #define ssl_do_connect(socket) SSL_get_error(socket->ssl, SSL_connect(socket->ssl))
60 #define ssl_do_write(socket, data, len) SSL_write(socket->ssl, data, len)
61 #define ssl_do_read(socket, data, len) SSL_read(socket->ssl, data, len)
62 #define ssl_do_close(socket) /* Hmh? No idea.. */
64 #elif defined(CONFIG_GNUTLS)
66 #define ssl_do_connect(conn) gnutls_handshake(*((ssl_t *) socket->ssl))
67 #define ssl_do_write(socket, data, len) gnutls_record_send(*((ssl_t *) socket->ssl), data, len)
68 #define ssl_do_read(socket, data, len) gnutls_record_recv(*((ssl_t *) socket->ssl), data, len)
69 /* We probably don't handle this entirely correctly.. */
70 #define ssl_do_close(socket) gnutls_bye(*((ssl_t *) socket->ssl), GNUTLS_SHUT_RDWR);
72 #endif
75 /* Refuse to negotiate TLS 1.0 and later protocols on @socket->ssl.
76 * Without this, connecting to <https://www-s.uiuc.edu/> with GnuTLS
77 * 1.3.5 would result in an SSL error. The bug may be in the server
78 * (Netscape-Enterprise/3.6 SP3), in GnuTLS, or in ELinks; please log
79 * your findings to ELinks bug 712. */
80 static void
81 ssl_set_no_tls(struct socket *socket)
83 #ifdef CONFIG_OPENSSL
84 #ifdef SSL_OP_NO_TLSv1
85 SSL_set_options((ssl_t *)socket->ssl, SSL_OP_NO_TLSv1);
86 #endif
87 #elif defined(CONFIG_GNUTLS)
88 /* There is another gnutls_priority_set_direct call elsewhere
89 * in ELinks. If you change the priorities here, please check
90 * whether that one needs to be changed as well.
92 * GnuTLS 2.12.x is said to support "-VERS-TLS-ALL" too, but
93 * that version hasn't yet been released as of May 2011. */
94 gnutls_priority_set_direct(*(ssl_t *) socket->ssl,
95 "SECURE:-CTYPE-OPENPGP"
96 ":-VERS-SSL3.0:-VERS-TLS1.0"
97 ":-VERS-TLS1.1:-VERS-TLS1.2"
98 ":%SSL3_RECORD_VERSION",
99 NULL);
100 #endif
104 #ifdef CONFIG_GNUTLS
105 static int
106 verify_certificates(struct socket *socket)
108 gnutls_x509_crt_t cert;
109 gnutls_session_t session = *(ssl_t *)socket->ssl;
110 struct connection *conn = socket->conn;
111 const gnutls_datum_t *cert_list;
112 unsigned char *hostname;
113 int ret;
114 unsigned int cert_list_size, status;
117 ret = gnutls_certificate_verify_peers2(session, &status);
118 if (ret) return ret;
119 if (status) return status;
121 /* If the certificate is of a type for which verification has
122 * not yet been implemented, then reject it. This way, a fake
123 * server cannot avoid verification by using a strange type of
124 * certificate.
126 * OpenPGP certificates shouldn't even get this far anyway,
127 * because init_ssl_connection() tells GnuTLS to disable
128 * OpenPGP, and ELinks never calls
129 * gnutls_certificate_set_openpgp_keyring_file, so status
130 * should have been GNUTLS_CERT_SIGNER_NOT_FOUND. */
131 if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509)
132 return -7;
134 if (gnutls_x509_crt_init(&cert) < 0) {
135 return -1;
138 cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
139 if (!cert_list) {
140 return -2;
143 if (gnutls_x509_crt_import(cert, &cert_list[0],
144 GNUTLS_X509_FMT_DER) < 0) {
145 return -3;
147 if (gnutls_x509_crt_get_expiration_time(cert) < time(NULL)) {
148 gnutls_x509_crt_deinit(cert);
149 return -4;
152 if (gnutls_x509_crt_get_activation_time(cert) > time(NULL)) {
153 gnutls_x509_crt_deinit(cert);
154 return -5;
157 /* Because RFC 5280 defines dNSName as an IA5String, it can
158 * only contain ASCII characters. Internationalized domain
159 * names must thus be in Punycode form. Because GnuTLS 2.8.6
160 * does not itself support IDN, ELinks must convert. */
161 hostname = get_uri_string(conn->proxied_uri, URI_HOST | URI_IDN);
162 if (!hostname) return -6;
164 ret = !gnutls_x509_crt_check_hostname(cert, hostname);
165 gnutls_x509_crt_deinit(cert);
166 mem_free(hostname);
167 return ret;
169 #endif /* CONFIG_GNUTLS */
171 #ifdef USE_OPENSSL
173 /** Checks whether the host component of a URI matches a host name in
174 * the server certificate.
176 * @param[in] uri_host
177 * The host name (or IP address) to which the user wanted to connect.
178 * Should be in UTF-8.
179 * @param[in] cert_host_asn1
180 * A host name found in the server certificate: either as commonName
181 * in the subject field, or as a dNSName in the subjectAltName
182 * extension. This may contain wildcards, as specified in RFC 2818
183 * section 3.1.
185 * @return
186 * Nonzero if the host matches. Zero if it doesn't, or on error.
188 * If @a uri_host is an IP address literal rather than a host name,
189 * then this function returns 0, meaning that the host name does not match.
190 * According to RFC 2818, if the certificate is intended to match an
191 * IP address, then it must have that IP address as an iPAddress
192 * SubjectAltName, rather than in commonName. For comparing those,
193 * match_uri_host_ip() must be used instead of this function. */
194 static int
195 match_uri_host_name(const unsigned char *uri_host,
196 ASN1_STRING *cert_host_asn1)
198 const size_t uri_host_len = strlen(uri_host);
199 unsigned char *cert_host = NULL;
200 int cert_host_len;
201 int matched = 0;
203 if (is_ip_address(uri_host, uri_host_len))
204 goto mismatch;
206 /* This function is used for both dNSName and commonName.
207 * Although dNSName is always an IA5 string, commonName allows
208 * many other encodings too. Normalize all to UTF-8. */
209 cert_host_len = ASN1_STRING_to_UTF8(&cert_host,
210 cert_host_asn1);
211 if (cert_host_len < 0)
212 goto mismatch;
214 matched = match_hostname_pattern(uri_host, uri_host_len,
215 cert_host, cert_host_len);
217 mismatch:
218 if (cert_host)
219 OPENSSL_free(cert_host);
220 return matched;
223 /** Checks whether the host component of a URI matches an IP address
224 * in the server certificate.
226 * @param[in] uri_host
227 * The IP address (or host name) to which the user wanted to connect.
228 * Should be in UTF-8.
229 * @param[in] cert_host_asn1
230 * An IP address found as iPAddress in the subjectAltName extension
231 * of the server certificate. According to RFC 5280 section 4.2.1.6,
232 * that is an octet string in network byte order. According to
233 * RFC 2818 section 3.1, wildcards are not allowed.
235 * @return
236 * Nonzero if the host matches. Zero if it doesn't, or on error.
238 * If @a uri_host is a host name rather than an IP address literal,
239 * then this function returns 0, meaning that the address does not match.
240 * This function does not try to resolve the host name to an IP address
241 * and compare that to @a cert_host_asn1, because such an approach would
242 * be vulnerable to DNS spoofing.
244 * This function does not support the address-and-netmask format used
245 * in the name constraints extension of a CA certificate (RFC 5280
246 * section 4.2.1.10). */
247 static int
248 match_uri_host_ip(const unsigned char *uri_host,
249 ASN1_OCTET_STRING *cert_host_asn1)
251 const unsigned char *cert_host_addr = ASN1_STRING_data(cert_host_asn1);
252 struct in_addr uri_host_in;
253 #ifdef CONFIG_IPV6
254 struct in6_addr uri_host_in6;
255 #endif
257 /* RFC 5280 defines the iPAddress alternative of GeneralName
258 * as an OCTET STRING. Verify that the type is indeed that.
259 * This is an assertion because, if someone puts the wrong
260 * type of data there, then it will not even be recognized as
261 * an iPAddress, and this function will not be called.
263 * (Because GeneralName is defined in an implicitly tagged
264 * ASN.1 module, the OCTET STRING tag is not part of the DER
265 * encoding. BER also allows a constructed encoding where
266 * each substring begins with the OCTET STRING tag; but ITU-T
267 * Rec. X.690 (07/2002) subclause 8.21 says those would be
268 * OCTET STRING even if the outer string were of some other
269 * type. "A Layman's Guide to a Subset of ASN.1, BER, and
270 * DER" (Kaliski, 1993) claims otherwise, though.) */
271 assert(ASN1_STRING_type(cert_host_asn1) == V_ASN1_OCTET_STRING);
272 if_assert_failed return 0;
274 /* cert_host_addr, url_host_in, and url_host_in6 are all in
275 * network byte order. */
276 switch (ASN1_STRING_length(cert_host_asn1)) {
277 case 4:
278 return inet_aton(uri_host, &uri_host_in) != 0
279 && memcmp(cert_host_addr, &uri_host_in.s_addr, 4) == 0;
281 #ifdef CONFIG_IPV6
282 case 16:
283 return inet_pton(AF_INET6, uri_host, &uri_host_in6) == 1
284 && memcmp(cert_host_addr, &uri_host_in6.s6_addr, 16) == 0;
285 #endif
287 default:
288 return 0;
292 /** Verify one certificate in the server certificate chain.
293 * This callback is documented in SSL_set_verify(3). */
294 static int
295 verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
297 X509 *cert;
298 SSL *ssl;
299 struct socket *socket;
300 struct connection *conn;
301 unsigned char *host_in_uri;
302 GENERAL_NAMES *alts;
303 int saw_dns_name = 0;
304 int matched = 0;
306 /* If OpenSSL already found a problem, keep that. */
307 if (!preverify_ok)
308 return 0;
310 /* Examine only the server certificate, not CA certificates. */
311 if (X509_STORE_CTX_get_error_depth(ctx) != 0)
312 return preverify_ok;
314 cert = X509_STORE_CTX_get_current_cert(ctx);
315 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
316 socket = SSL_get_ex_data(ssl, socket_SSL_ex_data_idx);
317 conn = socket->conn;
318 host_in_uri = get_uri_string(conn->proxied_uri, URI_HOST | URI_IDN);
319 if (!host_in_uri)
320 return 0;
322 /* RFC 5280 section 4.2.1.6 describes the subjectAltName extension.
323 * RFC 2818 section 3.1 says Common Name must not be used
324 * if dNSName is present. */
325 alts = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
326 if (alts != NULL) {
327 int alt_count;
328 int alt_pos;
329 GENERAL_NAME *alt;
331 alt_count = sk_GENERAL_NAME_num(alts);
332 for (alt_pos = 0; !matched && alt_pos < alt_count; ++alt_pos) {
333 alt = sk_GENERAL_NAME_value(alts, alt_pos);
334 if (alt->type == GEN_DNS) {
335 saw_dns_name = 1;
336 matched = match_uri_host_name(host_in_uri,
337 alt->d.dNSName);
338 } else if (alt->type == GEN_IPADD) {
339 matched = match_uri_host_ip(host_in_uri,
340 alt->d.iPAddress);
344 /* Free the GENERAL_NAMES list and each element. */
345 sk_GENERAL_NAME_pop_free(alts, GENERAL_NAME_free);
348 if (!matched && !saw_dns_name) {
349 X509_NAME *name;
350 int cn_index;
351 X509_NAME_ENTRY *entry = NULL;
353 name = X509_get_subject_name(cert);
354 cn_index = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
355 if (cn_index >= 0)
356 entry = X509_NAME_get_entry(name, cn_index);
357 if (entry != NULL)
358 matched = match_uri_host_name(host_in_uri,
359 X509_NAME_ENTRY_get_data(entry));
362 mem_free(host_in_uri);
363 return matched;
366 #endif /* USE_OPENSSL */
368 static void
369 ssl_want_read(struct socket *socket)
371 if (socket->no_tls)
372 ssl_set_no_tls(socket);
374 switch (ssl_do_connect(socket)) {
375 case SSL_ERROR_NONE:
376 #ifdef CONFIG_GNUTLS
377 if (socket->verify && get_opt_bool("connection.ssl.cert_verify", NULL)
378 && verify_certificates(socket)) {
379 socket->ops->retry(socket, connection_state(S_SSL_ERROR));
380 return;
382 #endif
384 /* Report successful SSL connection setup. */
385 complete_connect_socket(socket, NULL, NULL);
386 break;
388 case SSL_ERROR_WANT_READ:
389 case SSL_ERROR_WANT_READ2:
390 break;
392 default:
393 socket->no_tls = !socket->no_tls;
394 socket->ops->retry(socket, connection_state(S_SSL_ERROR));
398 /* Return -1 on error, 0 or success. */
400 ssl_connect(struct socket *socket)
402 int ret;
403 unsigned char *server_name;
404 struct connection *conn = socket->conn;
406 /* TODO: Recode server_name to UTF-8. */
407 server_name = get_uri_string(conn->proxied_uri, URI_HOST);
408 if (!server_name) {
409 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
410 return -1;
413 /* RFC 3546 says literal IPv4 and IPv6 addresses are not allowed. */
414 if (is_ip_address(server_name, strlen(server_name)))
415 mem_free_set(&server_name, NULL);
417 if (init_ssl_connection(socket, server_name) == S_SSL_ERROR) {
418 mem_free_if(server_name);
419 socket->ops->done(socket, connection_state(S_SSL_ERROR));
420 return -1;
423 mem_free_if(server_name);
425 if (socket->no_tls)
426 ssl_set_no_tls(socket);
428 #ifdef USE_OPENSSL
429 SSL_set_fd(socket->ssl, socket->fd);
431 if (socket->verify && get_opt_bool("connection.ssl.cert_verify", NULL))
432 SSL_set_verify(socket->ssl, SSL_VERIFY_PEER
433 | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
434 verify_callback);
436 if (get_opt_bool("connection.ssl.client_cert.enable", NULL)) {
437 unsigned char *client_cert;
439 #ifdef CONFIG_NSS_COMPAT_OSSL
440 client_cert = get_opt_str(
441 "connection.ssl.client_cert.nickname", NULL);
442 #else
443 client_cert = get_opt_str(
444 "connection.ssl.client_cert.file", NULL);
445 #endif
446 if (!*client_cert) {
447 client_cert = getenv("X509_CLIENT_CERT");
448 if (client_cert && !*client_cert)
449 client_cert = NULL;
452 if (client_cert) {
453 #ifdef CONFIG_NSS_COMPAT_OSSL
454 SSL_CTX_use_certificate_chain_file(
455 (SSL *) socket->ssl,
456 client_cert);
457 #else
458 SSL_CTX *ctx = SSL_get_SSL_CTX((SSL *) socket->ssl);
460 SSL_CTX_use_certificate_chain_file(ctx, client_cert);
461 SSL_CTX_use_PrivateKey_file(ctx, client_cert,
462 SSL_FILETYPE_PEM);
463 #endif
467 #elif defined(CONFIG_GNUTLS)
468 /* GnuTLS uses function pointers for network I/O. The default
469 * functions take a file descriptor, but it must be passed in
470 * as a pointer. GnuTLS uses the GNUTLS_INT_TO_POINTER and
471 * GNUTLS_POINTER_TO_INT macros for these conversions, but
472 * those are unfortunately not in any public header. So
473 * ELinks must just cast the pointer the best it can and hope
474 * that the conversions match. */
475 gnutls_transport_set_ptr(*((ssl_t *) socket->ssl),
476 (gnutls_transport_ptr_t) (longptr_T) socket->fd);
478 /* TODO: Some certificates fuss. --pasky */
479 #endif
481 ret = ssl_do_connect(socket);
483 switch (ret) {
484 case SSL_ERROR_WANT_READ:
485 case SSL_ERROR_WANT_READ2:
486 socket->ops->set_state(socket, connection_state(S_SSL_NEG));
487 set_handlers(socket->fd, (select_handler_T) ssl_want_read,
488 NULL, (select_handler_T) dns_exception, socket);
489 return -1;
491 case SSL_ERROR_NONE:
492 #ifdef CONFIG_GNUTLS
493 if (!socket->verify || !get_opt_bool("connection.ssl.cert_verify", NULL))
494 break;
496 if (!verify_certificates(socket))
497 #endif
498 break;
500 default:
501 if (ret != SSL_ERROR_NONE) {
502 /* DBG("sslerr %s", gnutls_strerror(ret)); */
503 socket->no_tls = !socket->no_tls;
505 connect_socket(socket, connection_state(S_SSL_ERROR));
506 return -1;
509 return 0;
512 /* Return enum socket_error on error, bytes written on success. */
513 ssize_t
514 ssl_write(struct socket *socket, unsigned char *data, int len)
516 ssize_t wr = ssl_do_write(socket, data, len);
518 if (wr <= 0) {
519 #ifdef USE_OPENSSL
520 int err = SSL_get_error(socket->ssl, wr);
521 #elif defined(CONFIG_GNUTLS)
522 int err = wr;
523 #endif
524 if (err == SSL_ERROR_WANT_WRITE ||
525 err == SSL_ERROR_WANT_WRITE2) {
526 return -1;
529 if (!wr) return SOCKET_CANT_WRITE;
531 if (err == SSL_ERROR_SYSCALL)
532 return SOCKET_SYSCALL_ERROR;
534 errno = S_SSL_ERROR;
535 return SOCKET_INTERNAL_ERROR;
538 return wr;
541 /* Return enum socket_error on error, bytes read on success. */
542 ssize_t
543 ssl_read(struct socket *socket, unsigned char *data, int len)
545 ssize_t rd = ssl_do_read(socket, data, len);
547 if (rd <= 0) {
548 #ifdef USE_OPENSSL
549 int err = SSL_get_error(socket->ssl, rd);
550 #elif defined(CONFIG_GNUTLS)
551 int err = rd;
552 #endif
554 #ifdef CONFIG_GNUTLS
555 if (err == GNUTLS_E_REHANDSHAKE)
556 return -1;
557 #endif
559 if (err == SSL_ERROR_WANT_READ ||
560 err == SSL_ERROR_WANT_READ2) {
561 return SOCKET_SSL_WANT_READ;
564 if (!rd) return SOCKET_CANT_READ;
566 if (err == SSL_ERROR_SYSCALL2)
567 return SOCKET_SYSCALL_ERROR;
569 errno = S_SSL_ERROR;
570 return SOCKET_INTERNAL_ERROR;
573 return rd;
577 ssl_close(struct socket *socket)
579 ssl_do_close(socket);
580 done_ssl_connection(socket);
582 return 0;