1 /* SSL socket workshop */
8 #include <openssl/ssl.h>
9 #include <openssl/x509v3.h>
11 #elif defined(CONFIG_NSS_COMPAT_OSSL)
12 #include <nss_compat_ossl/nss_compat_ossl.h>
14 #elif defined(CONFIG_GNUTLS)
15 #include <gnutls/gnutls.h>
16 #include <gnutls/x509.h>
18 #error "Huh?! You have SSL enabled, but not OPENSSL nor GNUTLS!! And then you want exactly *what* from me?"
21 #ifdef HAVE_ARPA_INET_H
22 #include <arpa/inet.h>
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.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"
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
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);
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. */
81 ssl_set_no_tls(struct socket
*socket
)
84 #ifdef SSL_OP_NO_TLSv1
85 SSL_set_options((ssl_t
*)socket
->ssl
, SSL_OP_NO_TLSv1
);
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",
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
;
114 unsigned int cert_list_size
, status
;
117 ret
= gnutls_certificate_verify_peers2(session
, &status
);
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
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
)
134 if (gnutls_x509_crt_init(&cert
) < 0) {
138 cert_list
= gnutls_certificate_get_peers(session
, &cert_list_size
);
143 if (gnutls_x509_crt_import(cert
, &cert_list
[0],
144 GNUTLS_X509_FMT_DER
) < 0) {
147 if (gnutls_x509_crt_get_expiration_time(cert
) < time(NULL
)) {
148 gnutls_x509_crt_deinit(cert
);
152 if (gnutls_x509_crt_get_activation_time(cert
) > time(NULL
)) {
153 gnutls_x509_crt_deinit(cert
);
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
);
169 #endif /* CONFIG_GNUTLS */
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
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. */
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
;
203 if (is_ip_address(uri_host
, uri_host_len
))
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
,
211 if (cert_host_len
< 0)
214 matched
= match_hostname_pattern(uri_host
, uri_host_len
,
215 cert_host
, cert_host_len
);
219 OPENSSL_free(cert_host
);
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.
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). */
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
;
254 struct in6_addr uri_host_in6
;
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
)) {
278 return inet_aton(uri_host
, &uri_host_in
) != 0
279 && memcmp(cert_host_addr
, &uri_host_in
.s_addr
, 4) == 0;
283 return inet_pton(AF_INET6
, uri_host
, &uri_host_in6
) == 1
284 && memcmp(cert_host_addr
, &uri_host_in6
.s6_addr
, 16) == 0;
292 /** Verify one certificate in the server certificate chain.
293 * This callback is documented in SSL_set_verify(3). */
295 verify_callback(int preverify_ok
, X509_STORE_CTX
*ctx
)
299 struct socket
*socket
;
300 struct connection
*conn
;
301 unsigned char *host_in_uri
;
303 int saw_dns_name
= 0;
306 /* If OpenSSL already found a problem, keep that. */
310 /* Examine only the server certificate, not CA certificates. */
311 if (X509_STORE_CTX_get_error_depth(ctx
) != 0)
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
);
318 host_in_uri
= get_uri_string(conn
->proxied_uri
, URI_HOST
| URI_IDN
);
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
);
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
) {
336 matched
= match_uri_host_name(host_in_uri
,
338 } else if (alt
->type
== GEN_IPADD
) {
339 matched
= match_uri_host_ip(host_in_uri
,
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
) {
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);
356 entry
= X509_NAME_get_entry(name
, cn_index
);
358 matched
= match_uri_host_name(host_in_uri
,
359 X509_NAME_ENTRY_get_data(entry
));
362 mem_free(host_in_uri
);
366 #endif /* USE_OPENSSL */
369 ssl_want_read(struct socket
*socket
)
372 ssl_set_no_tls(socket
);
374 switch (ssl_do_connect(socket
)) {
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
));
384 /* Report successful SSL connection setup. */
385 complete_connect_socket(socket
, NULL
, NULL
);
388 case SSL_ERROR_WANT_READ
:
389 case SSL_ERROR_WANT_READ2
:
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
)
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
);
409 socket
->ops
->done(socket
, connection_state(S_OUT_OF_MEM
));
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
));
423 mem_free_if(server_name
);
426 ssl_set_no_tls(socket
);
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
,
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
);
443 client_cert
= get_opt_str(
444 "connection.ssl.client_cert.file", NULL
);
447 client_cert
= getenv("X509_CLIENT_CERT");
448 if (client_cert
&& !*client_cert
)
453 #ifdef CONFIG_NSS_COMPAT_OSSL
454 SSL_CTX_use_certificate_chain_file(
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
,
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 */
481 ret
= ssl_do_connect(socket
);
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
);
493 if (!socket
->verify
|| !get_opt_bool("connection.ssl.cert_verify", NULL
))
496 if (!verify_certificates(socket
))
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
));
512 /* Return enum socket_error on error, bytes written on success. */
514 ssl_write(struct socket
*socket
, unsigned char *data
, int len
)
516 ssize_t wr
= ssl_do_write(socket
, data
, len
);
520 int err
= SSL_get_error(socket
->ssl
, wr
);
521 #elif defined(CONFIG_GNUTLS)
524 if (err
== SSL_ERROR_WANT_WRITE
||
525 err
== SSL_ERROR_WANT_WRITE2
) {
529 if (!wr
) return SOCKET_CANT_WRITE
;
531 if (err
== SSL_ERROR_SYSCALL
)
532 return SOCKET_SYSCALL_ERROR
;
535 return SOCKET_INTERNAL_ERROR
;
541 /* Return enum socket_error on error, bytes read on success. */
543 ssl_read(struct socket
*socket
, unsigned char *data
, int len
)
545 ssize_t rd
= ssl_do_read(socket
, data
, len
);
549 int err
= SSL_get_error(socket
->ssl
, rd
);
550 #elif defined(CONFIG_GNUTLS)
555 if (err
== GNUTLS_E_REHANDSHAKE
)
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
;
570 return SOCKET_INTERNAL_ERROR
;
577 ssl_close(struct socket
*socket
)
579 ssl_do_close(socket
);
580 done_ssl_connection(socket
);