1 /* SSL socket workshop */
8 #include <openssl/ssl.h>
10 #elif defined(CONFIG_NSS_COMPAT_OSSL)
11 #include <nss_compat_ossl/nss_compat_ossl.h>
13 #elif defined(CONFIG_GNUTLS)
14 #include <gnutls/gnutls.h>
15 #include <gnutls/x509.h>
17 #error "Huh?! You have SSL enabled, but not OPENSSL nor GNUTLS!! And then you want exactly *what* from me?"
24 #include "config/options.h"
25 #include "main/select.h"
26 #include "network/connection.h"
27 #include "network/socket.h"
28 #include "network/ssl/socket.h"
29 #include "network/ssl/ssl.h"
30 #include "protocol/uri.h"
31 #include "util/memory.h"
36 #define SSL_ERROR_WANT_READ2 9999 /* XXX */
37 #define SSL_ERROR_WANT_WRITE2 SSL_ERROR_WANT_WRITE
38 #define SSL_ERROR_SYSCALL2 SSL_ERROR_SYSCALL
39 #elif defined(CONFIG_GNUTLS)
40 #define SSL_ERROR_NONE GNUTLS_E_SUCCESS
41 #define SSL_ERROR_WANT_READ GNUTLS_E_AGAIN
42 #define SSL_ERROR_WANT_READ2 GNUTLS_E_INTERRUPTED
43 #define SSL_ERROR_WANT_WRITE GNUTLS_E_AGAIN
44 #define SSL_ERROR_WANT_WRITE2 GNUTLS_E_INTERRUPTED
45 #define SSL_ERROR_SYSCALL GNUTLS_E_PUSH_ERROR
46 #define SSL_ERROR_SYSCALL2 GNUTLS_E_PULL_ERROR
51 #define ssl_do_connect(socket) SSL_get_error(socket->ssl, SSL_connect(socket->ssl))
52 #define ssl_do_write(socket, data, len) SSL_write(socket->ssl, data, len)
53 #define ssl_do_read(socket, data, len) SSL_read(socket->ssl, data, len)
54 #define ssl_do_close(socket) /* Hmh? No idea.. */
56 #elif defined(CONFIG_GNUTLS)
58 #define ssl_do_connect(conn) gnutls_handshake(*((ssl_t *) socket->ssl))
59 #define ssl_do_write(socket, data, len) gnutls_record_send(*((ssl_t *) socket->ssl), data, len)
60 #define ssl_do_read(socket, data, len) gnutls_record_recv(*((ssl_t *) socket->ssl), data, len)
61 /* We probably don't handle this entirely correctly.. */
62 #define ssl_do_close(socket) gnutls_bye(*((ssl_t *) socket->ssl), GNUTLS_SHUT_RDWR);
67 /* Refuse to negotiate TLS 1.0 and later protocols on @socket->ssl.
68 * Without this, connecting to <https://www-s.uiuc.edu/> with GnuTLS
69 * 1.3.5 would result in an SSL error. The bug may be in the server
70 * (Netscape-Enterprise/3.6 SP3), in GnuTLS, or in ELinks; please log
71 * your findings to ELinks bug 712. */
73 ssl_set_no_tls(struct socket
*socket
)
76 ((ssl_t
*) socket
->ssl
)->options
|= SSL_OP_NO_TLSv1
;
77 #elif defined(CONFIG_GNUTLS)
78 /* There is another gnutls_priority_set_direct call elsewhere
79 * in ELinks. If you change the priorities here, please check
80 * whether that one needs to be changed as well.
82 * GnuTLS 2.12.x is said to support "-VERS-TLS-ALL" too, but
83 * that version hasn't yet been released as of May 2011. */
84 gnutls_priority_set_direct(*(ssl_t
*) socket
->ssl
,
85 "SECURE:-CTYPE-OPENPGP"
86 ":+VERS-SSL3.0:-VERS-TLS1.0"
87 ":-VERS-TLS1.1:-VERS-TLS1.2"
88 ":%SSL3_RECORD_VERSION",
96 verify_certificates(struct socket
*socket
)
98 gnutls_x509_crt_t cert
;
99 gnutls_session_t session
= *(ssl_t
*)socket
->ssl
;
100 struct connection
*conn
= socket
->conn
;
101 const gnutls_datum_t
*cert_list
;
102 unsigned char *hostname
;
104 unsigned int cert_list_size
, status
;
107 ret
= gnutls_certificate_verify_peers2(session
, &status
);
109 if (status
) return status
;
111 /* If the certificate is of a type for which verification has
112 * not yet been implemented, then reject it. This way, a fake
113 * server cannot avoid verification by using a strange type of
116 * OpenPGP certificates shouldn't even get this far anyway,
117 * because init_ssl_connection() tells GnuTLS to disable
118 * OpenPGP, and ELinks never calls
119 * gnutls_certificate_set_openpgp_keyring_file, so status
120 * should have been GNUTLS_CERT_SIGNER_NOT_FOUND. */
121 if (gnutls_certificate_type_get(session
) != GNUTLS_CRT_X509
)
124 if (gnutls_x509_crt_init(&cert
) < 0) {
128 cert_list
= gnutls_certificate_get_peers(session
, &cert_list_size
);
133 if (gnutls_x509_crt_import(cert
, &cert_list
[0],
134 GNUTLS_X509_FMT_DER
) < 0) {
137 if (gnutls_x509_crt_get_expiration_time(cert
) < time(NULL
)) {
138 gnutls_x509_crt_deinit(cert
);
142 if (gnutls_x509_crt_get_activation_time(cert
) > time(NULL
)) {
143 gnutls_x509_crt_deinit(cert
);
146 hostname
= get_uri_string(conn
->uri
, URI_HOST
);
147 if (!hostname
) return -6;
149 ret
= !gnutls_x509_crt_check_hostname(cert
, hostname
);
150 gnutls_x509_crt_deinit(cert
);
154 #endif /* CONFIG_GNUTLS */
157 ssl_want_read(struct socket
*socket
)
160 ssl_set_no_tls(socket
);
162 switch (ssl_do_connect(socket
)) {
165 if (get_opt_bool("connection.ssl.cert_verify", NULL
)
166 && verify_certificates(socket
)) {
167 socket
->ops
->retry(socket
, connection_state(S_SSL_ERROR
));
172 /* Report successful SSL connection setup. */
173 complete_connect_socket(socket
, NULL
, NULL
);
176 case SSL_ERROR_WANT_READ
:
177 case SSL_ERROR_WANT_READ2
:
181 socket
->no_tls
= !socket
->no_tls
;
182 socket
->ops
->retry(socket
, connection_state(S_SSL_ERROR
));
186 /* Return -1 on error, 0 or success. */
188 ssl_connect(struct socket
*socket
)
191 unsigned char *server_name
;
192 struct connection
*conn
= socket
->conn
;
194 /* TODO: Recode server_name to UTF-8. */
195 server_name
= get_uri_string(conn
->proxied_uri
, URI_HOST
);
197 socket
->ops
->done(socket
, connection_state(S_OUT_OF_MEM
));
201 /* RFC 3546 says literal IPv4 and IPv6 addresses are not allowed. */
202 if (is_ip_address(server_name
, strlen(server_name
)))
203 mem_free_set(&server_name
, NULL
);
205 if (init_ssl_connection(socket
, server_name
) == S_SSL_ERROR
) {
206 mem_free_if(server_name
);
207 socket
->ops
->done(socket
, connection_state(S_SSL_ERROR
));
211 mem_free_if(server_name
);
214 ssl_set_no_tls(socket
);
217 SSL_set_fd(socket
->ssl
, socket
->fd
);
219 if (get_opt_bool("connection.ssl.cert_verify", NULL
))
220 SSL_set_verify(socket
->ssl
, SSL_VERIFY_PEER
221 | SSL_VERIFY_FAIL_IF_NO_PEER_CERT
,
224 if (get_opt_bool("connection.ssl.client_cert.enable", NULL
)) {
225 unsigned char *client_cert
;
227 #ifdef CONFIG_NSS_COMPAT_OSSL
228 client_cert
= get_opt_str(
229 "connection.ssl.client_cert.nickname", NULL
);
231 client_cert
= get_opt_str(
232 "connection.ssl.client_cert.file", NULL
);
235 client_cert
= getenv("X509_CLIENT_CERT");
236 if (client_cert
&& !*client_cert
)
241 #ifdef CONFIG_NSS_COMPAT_OSSL
242 SSL_CTX_use_certificate_chain_file(
246 SSL_CTX
*ctx
= ((SSL
*) socket
->ssl
)->ctx
;
248 SSL_CTX_use_certificate_chain_file(ctx
, client_cert
);
249 SSL_CTX_use_PrivateKey_file(ctx
, client_cert
,
255 #elif defined(CONFIG_GNUTLS)
256 /* GnuTLS uses function pointers for network I/O. The default
257 * functions take a file descriptor, but it must be passed in
258 * as a pointer. GnuTLS uses the GNUTLS_INT_TO_POINTER and
259 * GNUTLS_POINTER_TO_INT macros for these conversions, but
260 * those are unfortunately not in any public header. So
261 * ELinks must just cast the pointer the best it can and hope
262 * that the conversions match. */
263 gnutls_transport_set_ptr(*((ssl_t
*) socket
->ssl
),
264 (gnutls_transport_ptr
) (longptr_T
) socket
->fd
);
266 /* TODO: Some certificates fuss. --pasky */
269 ret
= ssl_do_connect(socket
);
272 case SSL_ERROR_WANT_READ
:
273 case SSL_ERROR_WANT_READ2
:
274 socket
->ops
->set_state(socket
, connection_state(S_SSL_NEG
));
275 set_handlers(socket
->fd
, (select_handler_T
) ssl_want_read
,
276 NULL
, (select_handler_T
) dns_exception
, socket
);
281 if (!get_opt_bool("connection.ssl.cert_verify", NULL
))
284 if (!verify_certificates(socket
))
289 if (ret
!= SSL_ERROR_NONE
) {
290 /* DBG("sslerr %s", gnutls_strerror(ret)); */
291 socket
->no_tls
= !socket
->no_tls
;
294 connect_socket(socket
, connection_state(S_SSL_ERROR
));
301 /* Return enum socket_error on error, bytes written on success. */
303 ssl_write(struct socket
*socket
, unsigned char *data
, int len
)
305 ssize_t wr
= ssl_do_write(socket
, data
, len
);
309 int err
= SSL_get_error(socket
->ssl
, wr
);
310 #elif defined(CONFIG_GNUTLS)
313 if (err
== SSL_ERROR_WANT_WRITE
||
314 err
== SSL_ERROR_WANT_WRITE2
) {
318 if (!wr
) return SOCKET_CANT_WRITE
;
320 if (err
== SSL_ERROR_SYSCALL
)
321 return SOCKET_SYSCALL_ERROR
;
324 return SOCKET_INTERNAL_ERROR
;
330 /* Return enum socket_error on error, bytes read on success. */
332 ssl_read(struct socket
*socket
, unsigned char *data
, int len
)
334 ssize_t rd
= ssl_do_read(socket
, data
, len
);
338 int err
= SSL_get_error(socket
->ssl
, rd
);
339 #elif defined(CONFIG_GNUTLS)
344 if (err
== GNUTLS_E_REHANDSHAKE
)
348 if (err
== SSL_ERROR_WANT_READ
||
349 err
== SSL_ERROR_WANT_READ2
) {
350 return SOCKET_SSL_WANT_READ
;
353 if (!rd
) return SOCKET_CANT_READ
;
355 if (err
== SSL_ERROR_SYSCALL2
)
356 return SOCKET_SYSCALL_ERROR
;
359 return SOCKET_INTERNAL_ERROR
;
366 ssl_close(struct socket
*socket
)
368 ssl_do_close(socket
);
369 done_ssl_connection(socket
);