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