1 /* SSL socket workshop */
2 
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 
7 #ifdef CONFIG_OPENSSL
8 #include <openssl/ssl.h>
9 #elif defined(CONFIG_GNUTLS)
10 #include <gnutls/gnutls.h>
11 #else
12 #error "Huh?! You have SSL enabled, but not OPENSSL nor GNUTLS!! And then you want exactly *what* from me?"
13 #endif
14 
15 #include <errno.h>
16 
17 #include "elinks.h"
18 
19 #include "config/options.h"
20 #include "main/select.h"
21 #include "network/connection.h"
22 #include "network/socket.h"
23 #include "network/ssl/socket.h"
24 #include "network/ssl/ssl.h"
25 #include "util/memory.h"
26 
27 
28 /* SSL errors */
29 #ifdef CONFIG_OPENSSL
30 #define	SSL_ERROR_WANT_READ2	9999 /* XXX */
31 #define	SSL_ERROR_WANT_WRITE2	SSL_ERROR_WANT_WRITE
32 #define	SSL_ERROR_SYSCALL2	SSL_ERROR_SYSCALL
33 #elif defined(CONFIG_GNUTLS)
34 #define	SSL_ERROR_NONE		GNUTLS_E_SUCCESS
35 #define	SSL_ERROR_WANT_READ	GNUTLS_E_AGAIN
36 #define	SSL_ERROR_WANT_READ2	GNUTLS_E_INTERRUPTED
37 #define	SSL_ERROR_WANT_WRITE	GNUTLS_E_AGAIN
38 #define	SSL_ERROR_WANT_WRITE2	GNUTLS_E_INTERRUPTED
39 #define	SSL_ERROR_SYSCALL	GNUTLS_E_PUSH_ERROR
40 #define	SSL_ERROR_SYSCALL2	GNUTLS_E_PULL_ERROR
41 #endif
42 
43 #ifdef CONFIG_OPENSSL
44 
45 #define ssl_do_connect(socket)		SSL_get_error(socket->ssl, SSL_connect(socket->ssl))
46 #define ssl_do_write(socket, data, len)	SSL_write(socket->ssl, data, len)
47 #define ssl_do_read(socket, data, len)	SSL_read(socket->ssl, data, len)
48 #define ssl_do_close(socket)		/* Hmh? No idea.. */
49 
50 #elif defined(CONFIG_GNUTLS)
51 
52 #define ssl_do_connect(conn)		gnutls_handshake(*((ssl_t *) socket->ssl))
53 #define ssl_do_write(socket, data, len)	gnutls_record_send(*((ssl_t *) socket->ssl), data, len)
54 #define ssl_do_read(socket, data, len)	gnutls_record_recv(*((ssl_t *) socket->ssl), data, len)
55 /* We probably don't handle this entirely correctly.. */
56 #define ssl_do_close(socket)		gnutls_bye(*((ssl_t *) socket->ssl), GNUTLS_SHUT_RDWR);
57 
58 #endif
59 
60 
61 /* Refuse to negotiate TLS 1.0 and later protocols on @socket->ssl.
62  * Without this, connecting to <https://www-s.uiuc.edu/> with GnuTLS
63  * 1.3.5 would result in an SSL error.  The bug may be in the server
64  * (Netscape-Enterprise/3.6 SP3), in GnuTLS, or in ELinks; please log
65  * your findings to ELinks bug 712.  */
66 static void
ssl_set_no_tls(struct socket * socket)67 ssl_set_no_tls(struct socket *socket)
68 {
69 #ifdef CONFIG_OPENSSL
70 	SSL_set_options((ssl_t *) socket->ssl, SSL_OP_NO_TLSv1);
71 #elif defined(CONFIG_GNUTLS)
72 	{
73 		/* GnuTLS does not support SSLv2 because it is "insecure".
74 		 * That leaves only SSLv3.  */
75 		static const int protocol_priority[] = {
76 			GNUTLS_SSL3,
77 			0
78 		};
79 
80 		gnutls_protocol_set_priority(*(ssl_t *) socket->ssl, protocol_priority);
81 	}
82 #endif
83 }
84 
85 static void
ssl_want_read(struct socket * socket)86 ssl_want_read(struct socket *socket)
87 {
88 	if (socket->no_tls)
89 		ssl_set_no_tls(socket);
90 
91 	switch (ssl_do_connect(socket)) {
92 		case SSL_ERROR_NONE:
93 #ifdef CONFIG_GNUTLS
94 			if (get_opt_bool("connection.ssl.cert_verify")
95 			    && gnutls_certificate_verify_peers(*((ssl_t *) socket->ssl))) {
96 				socket->ops->retry(socket, S_SSL_ERROR);
97 				return;
98 			}
99 #endif
100 
101 			/* Report successful SSL connection setup. */
102 			complete_connect_socket(socket, NULL, NULL);
103 			break;
104 
105 		case SSL_ERROR_WANT_READ:
106 		case SSL_ERROR_WANT_READ2:
107 			break;
108 
109 		default:
110 			socket->no_tls = 1;
111 			socket->ops->retry(socket, S_SSL_ERROR);
112 	}
113 }
114 
115 /* Return -1 on error, 0 or success. */
116 int
ssl_connect(struct socket * socket)117 ssl_connect(struct socket *socket)
118 {
119 	int ret;
120 
121 	if (init_ssl_connection(socket) == S_SSL_ERROR) {
122 		socket->ops->done(socket, S_SSL_ERROR);
123 		return -1;
124 	}
125 
126 	if (socket->no_tls)
127 		ssl_set_no_tls(socket);
128 
129 #ifdef CONFIG_OPENSSL
130 	SSL_set_fd(socket->ssl, socket->fd);
131 
132 	if (get_opt_bool("connection.ssl.cert_verify"))
133 		SSL_set_verify(socket->ssl, SSL_VERIFY_PEER
134 					  | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
135 				NULL);
136 
137 	if (get_opt_bool("connection.ssl.client_cert.enable")) {
138 		unsigned char *client_cert;
139 
140 		client_cert = get_opt_str("connection.ssl.client_cert.file");
141 		if (!*client_cert) {
142 			client_cert = getenv("X509_CLIENT_CERT");
143 			if (client_cert && !*client_cert)
144 				client_cert = NULL;
145 		}
146 
147 		if (client_cert) {
148 			SSL_CTX *ctx = SSL_get_SSL_CTX(socket->ssl);
149 
150 			SSL_CTX_use_certificate_chain_file(ctx, client_cert);
151 			SSL_CTX_use_PrivateKey_file(ctx, client_cert,
152 						    SSL_FILETYPE_PEM);
153 		}
154 	}
155 
156 #elif defined(CONFIG_GNUTLS)
157 	gnutls_transport_set_ptr(*((ssl_t *) socket->ssl),
158 				 (gnutls_transport_ptr) socket->fd);
159 
160 	/* TODO: Some certificates fuss. --pasky */
161 #endif
162 
163 	ret = ssl_do_connect(socket);
164 
165 	switch (ret) {
166 		case SSL_ERROR_WANT_READ:
167 		case SSL_ERROR_WANT_READ2:
168 			socket->ops->set_state(socket, S_SSL_NEG);
169 			set_handlers(socket->fd, (select_handler_T) ssl_want_read,
170 				     NULL, (select_handler_T) dns_exception, socket);
171 			return -1;
172 
173 		case SSL_ERROR_NONE:
174 #ifdef CONFIG_GNUTLS
175 			if (!get_opt_bool("connection.ssl.cert_verify"))
176 				break;
177 
178 			if (!gnutls_certificate_verify_peers(*((ssl_t *) socket->ssl)))
179 #endif
180 				break;
181 
182 		default:
183 			if (ret != SSL_ERROR_NONE) {
184 				/* DBG("sslerr %s", gnutls_strerror(ret)); */
185 				socket->no_tls = 1;
186 			}
187 
188 			connect_socket(socket, S_SSL_ERROR);
189 			return -1;
190 	}
191 
192 	return 0;
193 }
194 
195 /* Return -1 on error, bytes written on success. */
196 ssize_t
ssl_write(struct socket * socket,unsigned char * data,int len)197 ssl_write(struct socket *socket, unsigned char *data, int len)
198 {
199 	ssize_t wr = ssl_do_write(socket, data, len);
200 
201 	if (wr <= 0) {
202 #ifdef CONFIG_OPENSSL
203 		int err = SSL_get_error(socket->ssl, wr);
204 #elif defined(CONFIG_GNUTLS)
205 		int err = wr;
206 #endif
207 		if (err == SSL_ERROR_WANT_WRITE ||
208 		    err == SSL_ERROR_WANT_WRITE2) {
209 			return -1;
210 		}
211 
212 		if (!wr) return SOCKET_CANT_WRITE;
213 
214 		if (err == SSL_ERROR_SYSCALL)
215 			return SOCKET_SYSCALL_ERROR;
216 
217 		errno = -S_SSL_ERROR;
218 
219 		return SOCKET_INTERNAL_ERROR;
220 	}
221 
222 	return wr;
223 }
224 
225 /* Return -1 on error, rd or success. */
226 ssize_t
ssl_read(struct socket * socket,unsigned char * data,int len)227 ssl_read(struct socket *socket, unsigned char *data, int len)
228 {
229 	ssize_t rd = ssl_do_read(socket, data, len);
230 
231 	if (rd <= 0) {
232 #ifdef CONFIG_OPENSSL
233 		int err = SSL_get_error(socket->ssl, rd);
234 #elif defined(CONFIG_GNUTLS)
235 		int err = rd;
236 #endif
237 
238 #ifdef CONFIG_GNUTLS
239 		if (err == GNUTLS_E_REHANDSHAKE)
240 			return -1;
241 #endif
242 
243 		if (err == SSL_ERROR_WANT_READ ||
244 		    err == SSL_ERROR_WANT_READ2) {
245 			return SOCKET_SSL_WANT_READ;
246 		}
247 
248 		if (!rd) return SOCKET_CANT_READ;
249 
250 		if (err == SSL_ERROR_SYSCALL2)
251 			return SOCKET_SYSCALL_ERROR;
252 
253 		errno = -S_SSL_ERROR;
254 
255 		return SOCKET_INTERNAL_ERROR;
256 	}
257 
258 	return rd;
259 }
260 
261 int
ssl_close(struct socket * socket)262 ssl_close(struct socket *socket)
263 {
264 	ssl_do_close(socket);
265 	done_ssl_connection(socket);
266 
267 	return 0;
268 }
269