Close dtls_fd on error returns from connect_dtls_socket()
[platform/upstream/openconnect.git] / dtls.c
1 /*
2  * OpenConnect (SSL + DTLS) VPN client
3  *
4  * Copyright © 2008-2012 Intel Corporation.
5  *
6  * Author: David Woodhouse <dwmw2@infradead.org>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1, as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to:
19  *
20  *   Free Software Foundation, Inc.
21  *   51 Franklin Street, Fifth Floor,
22  *   Boston, MA 02110-1301 USA
23  */
24
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netdb.h>
29 #include <unistd.h>
30 #include <netinet/in.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36
37 #include "openconnect-internal.h"
38
39 static unsigned char nybble(unsigned char n)
40 {
41         if      (n >= '0' && n <= '9') return n - '0';
42         else if (n >= 'A' && n <= 'F') return n - ('A' - 10);
43         else if (n >= 'a' && n <= 'f') return n - ('a' - 10);
44         return 0;
45 }
46
47 unsigned char unhex(const char *data)
48 {
49         return (nybble(data[0]) << 4) | nybble(data[1]);
50 }
51
52 #ifdef HAVE_DTLS
53
54 #if 0
55 /*
56  * Useful for catching test cases, where we want everything to be
57  * reproducible.  *NEVER* do this in the wild.
58  */
59 time_t time(time_t *t)
60 {
61         time_t x = 0x3ab2d948;
62         if (t) *t = x;
63         return x;
64 }
65
66 int RAND_pseudo_bytes(char *buf, int len)
67 {
68         memset(buf, 0x5a, len);
69         printf("FAKE PSEUDO RANDOM!\n");
70         return 1;
71
72 }
73 int RAND_bytes(char *buf, int len)
74 {
75         static int foo = 0x5b;
76         printf("FAKE RANDOM!\n");
77         memset(buf, foo, len);
78         return 1;
79 }
80 #endif
81
82 /*
83  * The master-secret is generated randomly by the client. The server
84  * responds with a DTLS Session-ID. These, done over the HTTPS
85  * connection, are enough to 'resume' a DTLS session, bypassing all
86  * the normal setup of a normal DTLS connection.
87  *
88  * Cisco use a version of the protocol which predates RFC4347, but
89  * isn't quite the same as the pre-RFC version of the protocol which
90  * was in OpenSSL 0.9.8e -- it includes backports of some later
91  * OpenSSL patches.
92  *
93  * The openssl/ directory of this source tree should contain both a
94  * small patch against OpenSSL 0.9.8e to make it support Cisco's
95  * snapshot of the protocol, and a larger patch against newer OpenSSL
96  * which gives us an option to use the old protocol again.
97  *
98  * Cisco's server also seems to respond to the official version of the
99  * protocol, with a change in the ChangeCipherSpec packet which implies
100  * that it does know the difference and isn't just repeating the version
101  * number seen in the ClientHello. But although I can make the handshake
102  * complete by hacking tls1_mac() to use the _old_ protocol version
103  * number when calculating the MAC, the server still seems to be ignoring
104  * my subsequent data packets. So we use the old protocol, which is what
105  * their clients use anyway.
106  */
107
108 #if defined (DTLS_OPENSSL)
109 #define DTLS_SEND SSL_write
110 #define DTLS_RECV SSL_read
111
112 #ifdef HAVE_DTLS1_STOP_TIMER
113 /* OpenSSL doesn't deliberately export this, but we need it to
114    workaround a DTLS bug in versions < 1.0.0e */
115 extern void dtls1_stop_timer (SSL *);
116 #endif
117
118 static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
119 {
120         STACK_OF(SSL_CIPHER) *ciphers;
121         method_const SSL_METHOD *dtls_method;
122         SSL_CIPHER *dtls_cipher;
123         SSL *dtls_ssl;
124         BIO *dtls_bio;
125
126         if (!vpninfo->dtls_ctx) {
127                 dtls_method = DTLSv1_client_method();
128                 vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
129                 if (!vpninfo->dtls_ctx) {
130                         vpn_progress(vpninfo, PRG_ERR,
131                                      _("Initialise DTLSv1 CTX failed\n"));
132                         openconnect_report_ssl_errors(vpninfo);
133                         vpninfo->dtls_attempt_period = 0;
134                         return -EINVAL;
135                 }
136
137                 /* If we don't readahead, then we do short reads and throw
138                    away the tail of data packets. */
139                 SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
140
141                 if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, vpninfo->dtls_cipher)) {
142                         vpn_progress(vpninfo, PRG_ERR,
143                                      _("Set DTLS cipher list failed\n"));
144                         SSL_CTX_free(vpninfo->dtls_ctx);
145                         vpninfo->dtls_ctx = NULL;
146                         vpninfo->dtls_attempt_period = 0;
147                         return -EINVAL;
148                 }
149         }
150
151         if (!vpninfo->dtls_session) {
152                 /* We're going to "resume" a session which never existed. Fake it... */
153                 vpninfo->dtls_session = SSL_SESSION_new();
154                 if (!vpninfo->dtls_session) {
155                         vpn_progress(vpninfo, PRG_ERR,
156                                      _("Initialise DTLSv1 session failed\n"));
157                         vpninfo->dtls_attempt_period = 0;
158                         return -EINVAL;
159                 }
160                 vpninfo->dtls_session->ssl_version = 0x0100; /* DTLS1_BAD_VER */
161         }
162
163         /* Do this every time; it may have changed due to a rekey */
164         vpninfo->dtls_session->master_key_length = sizeof(vpninfo->dtls_secret);
165         memcpy(vpninfo->dtls_session->master_key, vpninfo->dtls_secret,
166                sizeof(vpninfo->dtls_secret));
167
168         vpninfo->dtls_session->session_id_length = sizeof(vpninfo->dtls_session_id);
169         memcpy(vpninfo->dtls_session->session_id, vpninfo->dtls_session_id,
170                sizeof(vpninfo->dtls_session_id));
171
172         dtls_ssl = SSL_new(vpninfo->dtls_ctx);
173         SSL_set_connect_state(dtls_ssl);
174
175         ciphers = SSL_get_ciphers(dtls_ssl);
176         if (sk_SSL_CIPHER_num(ciphers) != 1) {
177                 vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n"));
178                 SSL_CTX_free(vpninfo->dtls_ctx);
179                 SSL_free(dtls_ssl);
180                 SSL_SESSION_free(vpninfo->dtls_session);
181                 vpninfo->dtls_ctx = NULL;
182                 vpninfo->dtls_session = NULL;
183                 vpninfo->dtls_attempt_period = 0;
184                 return -EINVAL;
185         }
186         dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);
187
188         /* Set the appropriate cipher on our session to be resumed */
189         vpninfo->dtls_session->cipher = dtls_cipher;
190         vpninfo->dtls_session->cipher_id = dtls_cipher->id;
191
192         /* Add the generated session to the SSL */
193         if (!SSL_set_session(dtls_ssl, vpninfo->dtls_session)) {
194                 vpn_progress(vpninfo, PRG_ERR,
195                              _("SSL_set_session() failed with old protocol version 0x%x\n"
196                                "Are you using a version of OpenSSL older than 0.9.8m?\n"
197                                "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
198                                "Use the --no-dtls command line option to avoid this message\n"),
199                              vpninfo->dtls_session->ssl_version);
200                 vpninfo->dtls_attempt_period = 0;
201                 return -EINVAL;
202         }
203
204         dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
205         /* Set non-blocking */
206         BIO_set_nbio(dtls_bio, 1);
207         SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);
208
209         SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);
210
211         vpninfo->new_dtls_ssl = dtls_ssl;
212
213         return 0;
214 }
215
216 int dtls_try_handshake(struct openconnect_info *vpninfo)
217 {
218         int ret = SSL_do_handshake(vpninfo->new_dtls_ssl);
219
220         if (ret == 1) {
221                 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection (using OpenSSL)\n"));
222
223                 if (vpninfo->dtls_ssl) {
224                         /* We are replacing an old connection */
225                         SSL_free(vpninfo->dtls_ssl);
226                         close(vpninfo->dtls_fd);
227                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
228                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
229                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
230                 }
231                 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
232                 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
233
234                 vpninfo->new_dtls_ssl = NULL;
235                 vpninfo->new_dtls_fd = -1;
236
237                 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
238
239                 /* From about 8.4.1(11) onwards, the ASA seems to get
240                    very unhappy if we resend ChangeCipherSpec messages
241                    after the initial setup. This was "fixed" in OpenSSL
242                    1.0.0e for RT#2505, but it's not clear if that was
243                    the right fix. What happens if the original packet
244                    *does* get lost? Surely we *wanted* the retransmits,
245                    because without them the server will never be able
246                    to decrypt anything we send?
247                    Oh well, our retransmitted packets upset the server
248                    because we don't get the Cisco-compatibility right
249                    (this is one of the areas in which Cisco's DTLS differs
250                    from the RFC4347 spec), and DPD should help us notice
251                    if *nothing* is getting through. */
252 #if OPENSSL_VERSION_NUMBER >= 0x1000005fL
253                 /* OpenSSL 1.0.0e or above doesn't resend anyway; do nothing.
254                    However, if we were *built* against 1.0.0e or newer, but at
255                    runtime we find that we are being run against an older 
256                    version, warn about it. */
257                 if (SSLeay() < 0x1000005fL) {
258                         vpn_progress(vpninfo, PRG_ERR,
259                                      _("Your OpenSSL is older than the one you built against, so DTLS may fail!"));
260                 }
261 #elif defined (HAVE_DTLS1_STOP_TIMER)
262                 /*
263                  * This works for any normal OpenSSL that supports
264                  * Cisco DTLS compatibility (0.9.8m to 1.0.0d inclusive,
265                  * and even later versions although it isn't needed there.
266                  */
267                 dtls1_stop_timer(vpninfo->dtls_ssl);
268 #elif defined (BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT)
269                 /*
270                  * Debian restricts visibility of dtls1_stop_timer()
271                  * so do it manually. This version also works on all
272                  * sane versions of OpenSSL:
273                  */
274                 memset (&(vpninfo->dtls_ssl->d1->next_timeout), 0,
275                         sizeof((vpninfo->dtls_ssl->d1->next_timeout)));
276                 vpninfo->dtls_ssl->d1->timeout_duration = 1;
277                 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
278                          BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
279                          &(vpninfo->dtls_ssl->d1->next_timeout));
280 #elif defined (BIO_CTRL_DGRAM_SET_TIMEOUT)
281                 /*
282                  * OK, here it gets more fun... this shoul handle the case
283                  * of older OpenSSL which has the Cisco DTLS compatibility
284                  * backported, but *not* the fix for RT#1922.
285                  */
286                 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
287                          BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
288 #else
289                 /*
290                  * And if they don't have any of the above, they probably
291                  * don't have RT#1829 fixed either, but that's OK because
292                  * that's the "fix" that *introduces* the timeout we're
293                  * trying to disable. So do nothing...
294                  */
295 #endif
296                 return 0;
297         }
298
299         ret = SSL_get_error(vpninfo->new_dtls_ssl, ret);
300         if (ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) {
301                 if (time(NULL) < vpninfo->new_dtls_started + 5)
302                         return 0;
303                 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
304         }
305
306         vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %d\n"), ret);
307         openconnect_report_ssl_errors(vpninfo);
308
309         /* Kill the new (failed) connection... */
310         SSL_free(vpninfo->new_dtls_ssl);
311         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
312         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
313         close(vpninfo->new_dtls_fd);
314         vpninfo->new_dtls_ssl = NULL;
315         vpninfo->new_dtls_fd = -1;
316
317         /* ... and kill the old one too. The only time there'll be a valid
318            existing session is when it was a rekey, and in that case it's
319            time for the old one to die. */
320         if (vpninfo->dtls_ssl) {
321                 SSL_free(vpninfo->dtls_ssl);
322                 close(vpninfo->dtls_fd);
323                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
324                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
325                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
326                 vpninfo->dtls_ssl = NULL;
327                 vpninfo->dtls_fd = -1;
328         }
329
330         time(&vpninfo->new_dtls_started);
331         return -EINVAL;
332 }
333
334 #elif defined (DTLS_GNUTLS)
335 #include <gnutls/dtls.h>
336
337 struct {
338         const char *name;
339         gnutls_cipher_algorithm_t cipher;
340         gnutls_mac_algorithm_t mac;
341         const char *prio;
342 } gnutls_dtls_ciphers[] = {
343         { "AES128-SHA", GNUTLS_CIPHER_AES_128_CBC, GNUTLS_MAC_SHA1,
344           "NONE:+VERS-DTLS0.9:+COMP-NULL:+AES-128-CBC:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION" },
345         { "DES-CBC3-SHA", GNUTLS_CIPHER_3DES_CBC, GNUTLS_MAC_SHA1,
346           "NONE:+VERS-DTLS0.9:+COMP-NULL:+3DES-CBC:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION" },
347 };
348
349 #define DTLS_SEND gnutls_record_send
350 #define DTLS_RECV gnutls_record_recv
351 static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
352 {
353         gnutls_session_t dtls_ssl;
354         gnutls_datum_t master_secret, session_id;
355         int err;
356         int cipher;
357
358         for (cipher = 0; cipher < sizeof(gnutls_dtls_ciphers)/sizeof(gnutls_dtls_ciphers[0]); cipher++) {
359                 if (!strcmp(vpninfo->dtls_cipher, gnutls_dtls_ciphers[cipher].name))
360                         goto found_cipher;
361         }
362         vpn_progress(vpninfo, PRG_ERR, _("Unknown DTLS parameters for requested CipherSuite '%s'\n"),
363                      vpninfo->dtls_cipher);
364         vpninfo->dtls_attempt_period = 0;
365
366         return -EINVAL;
367
368  found_cipher:
369         gnutls_init(&dtls_ssl, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
370         err = gnutls_priority_set_direct(dtls_ssl,
371                                          gnutls_dtls_ciphers[cipher].prio,
372                                          NULL);
373         if (err) {
374                 vpn_progress(vpninfo, PRG_ERR,
375                              _("Failed to set DTLS priority: %s\n"),
376                              gnutls_strerror(err));
377                 gnutls_deinit(dtls_ssl);
378                 vpninfo->dtls_attempt_period = 0;
379                 return -EINVAL;
380         }
381         gnutls_transport_set_ptr(dtls_ssl,
382                                  (gnutls_transport_ptr_t)(long) dtls_fd);
383         gnutls_record_disable_padding(dtls_ssl);
384         master_secret.data = vpninfo->dtls_secret;
385         master_secret.size = sizeof(vpninfo->dtls_secret);
386         session_id.data = vpninfo->dtls_session_id;
387         session_id.size = sizeof(vpninfo->dtls_session_id);
388         err = gnutls_session_set_premaster(dtls_ssl, GNUTLS_CLIENT, GNUTLS_DTLS0_9,
389                                            GNUTLS_KX_RSA, gnutls_dtls_ciphers[cipher].cipher,
390                                            gnutls_dtls_ciphers[cipher].mac, GNUTLS_COMP_NULL,
391                                            &master_secret, &session_id);
392         if (err) {
393                 vpn_progress(vpninfo, PRG_ERR,
394                              _("Failed to set DTLS session parameters: %s\n"),
395                              gnutls_strerror(err));
396                 gnutls_deinit(dtls_ssl);
397                 vpninfo->dtls_attempt_period = 0;
398                 return -EINVAL;
399         }
400
401         vpninfo->new_dtls_ssl = dtls_ssl;
402         return 0;
403 }
404
405 int dtls_try_handshake(struct openconnect_info *vpninfo)
406 {
407         int err = gnutls_handshake(vpninfo->new_dtls_ssl);
408
409         if (!err) {
410 #ifdef HAVE_GNUTLS_DTLS_SET_DATA_MTU
411                 /* Make sure GnuTLS's idea of the MTU is sufficient to take
412                    a full VPN MTU (with 1-byte header) in a data record. */
413                 err = gnutls_dtls_set_data_mtu(vpninfo->new_dtls_ssl, vpninfo->actual_mtu + 1);
414                 if (err) {
415                         vpn_progress(vpninfo, PRG_ERR,
416                                      _("Failed to set DTLS MTU: %s\n"),
417                                      gnutls_strerror(err));
418                         goto error;
419                 }
420 #else
421                 /* If we don't have gnutls_dtls_set_data_mtu() then make sure
422                    we leave enough headroom by adding the worst-case overhead.
423                    We only support AES128-CBC and DES-CBC3-SHA anyway, so
424                    working out the worst case isn't hard. */
425                 gnutls_dtls_set_mtu(vpninfo->new_dtls_ssl,
426                                     vpninfo->actual_mtu + 1 /* packet + header */
427                                     + 13 /* DTLS header */
428                                     + 20 /* biggest supported MAC (SHA1) */
429                                     + 16 /* biggest supported IV (AES-128) */
430                                     + 16 /* max padding */);
431 #endif
432
433                 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection (using GnuTLS)\n"));
434
435                 if (vpninfo->dtls_ssl) {
436                         /* We are replacing an old connection */
437                         gnutls_deinit(vpninfo->dtls_ssl);
438                         close(vpninfo->dtls_fd);
439                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
440                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
441                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
442                 }
443                 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
444                 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
445
446                 vpninfo->new_dtls_ssl = NULL;
447                 vpninfo->new_dtls_fd = -1;
448
449                 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
450
451                 /* XXX: For OpenSSL we explicitly prevent retransmits here. */
452                 return 0;
453         }
454
455         if (err == GNUTLS_E_AGAIN) {
456                 if (time(NULL) < vpninfo->new_dtls_started + 5)
457                         return 0;
458                 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
459         }
460
461         vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %s\n"),
462                      gnutls_strerror(err));
463
464         goto error;
465  error:
466         /* Kill the new (failed) connection... */
467         gnutls_deinit(vpninfo->new_dtls_ssl);
468         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
469         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
470         close(vpninfo->new_dtls_fd);
471         vpninfo->new_dtls_ssl = NULL;
472         vpninfo->new_dtls_fd = -1;
473
474         /* ... and kill the old one too. The only time there'll be a valid
475            existing session is when it was a rekey, and in that case it's
476            time for the old one to die. */
477         if (vpninfo->dtls_ssl) {
478                 gnutls_deinit(vpninfo->dtls_ssl);
479                 close(vpninfo->dtls_fd);
480                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
481                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
482                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
483                 vpninfo->dtls_ssl = NULL;
484                 vpninfo->dtls_fd = -1;
485         }
486
487         time(&vpninfo->new_dtls_started);
488         return -EINVAL;
489 }
490 #endif
491
492 int connect_dtls_socket(struct openconnect_info *vpninfo)
493 {
494         int dtls_fd, ret;
495
496         if (!vpninfo->dtls_addr) {
497                 vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n"));
498                 vpninfo->dtls_attempt_period = 0;
499                 return -EINVAL;
500         }
501
502         if (!vpninfo->dtls_cipher) {
503                 /* We probably didn't offer it any ciphers it liked */
504                 vpn_progress(vpninfo, PRG_ERR, _("Server offered no DTLS cipher option\n"));
505                 vpninfo->dtls_attempt_period = 0;
506                 return -EINVAL;
507         }
508
509         if (vpninfo->proxy) {
510                 /* XXX: Theoretically, SOCKS5 proxies can do UDP too */
511                 vpn_progress(vpninfo, PRG_ERR, _("No DTLS when connected via proxy\n"));
512                 vpninfo->dtls_attempt_period = 0;
513                 return -EINVAL;
514         }
515
516         dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
517         if (dtls_fd < 0) {
518                 perror(_("Open UDP socket for DTLS:"));
519                 return -EINVAL;
520         }
521
522         if (vpninfo->dtls_local_port) {
523                 union {
524                         struct sockaddr_in in;
525                         struct sockaddr_in6 in6;
526                 } dtls_bind_addr;
527                 int dtls_bind_addrlen;
528                 memset(&dtls_bind_addr, 0, sizeof(dtls_bind_addr));
529
530                 if (vpninfo->peer_addr->sa_family == AF_INET) {
531                         struct sockaddr_in *addr = &dtls_bind_addr.in;
532                         dtls_bind_addrlen = sizeof(*addr);
533                         addr->sin_family = AF_INET;
534                         addr->sin_addr.s_addr = INADDR_ANY;
535                         addr->sin_port = htons(vpninfo->dtls_local_port);
536                 } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
537                         struct sockaddr_in6 *addr = &dtls_bind_addr.in6;
538                         dtls_bind_addrlen = sizeof(*addr);
539                         addr->sin6_family = AF_INET6;
540                         addr->sin6_addr = in6addr_any;
541                         addr->sin6_port = htons(vpninfo->dtls_local_port);
542                 } else {
543                         vpn_progress(vpninfo, PRG_ERR,
544                                      _("Unknown protocol family %d. Cannot do DTLS\n"),
545                                      vpninfo->peer_addr->sa_family);
546                         vpninfo->dtls_attempt_period = 0;
547                         close(dtls_fd);
548                         return -EINVAL;
549                 }
550
551                 if (bind(dtls_fd, (struct sockaddr *)&dtls_bind_addr, dtls_bind_addrlen)) {
552                         perror(_("Bind UDP socket for DTLS"));
553                         close(dtls_fd);
554                         return -EINVAL;
555                 }
556         }
557
558         if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
559                 perror(_("UDP (DTLS) connect:\n"));
560                 close(dtls_fd);
561                 return -EINVAL;
562         }
563
564         fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
565         fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
566
567         ret = start_dtls_handshake(vpninfo, dtls_fd);
568         if (ret) {
569                 close(dtls_fd);
570                 return ret;
571         }
572
573         vpninfo->new_dtls_fd = dtls_fd;
574         if (vpninfo->select_nfds <= dtls_fd)
575                 vpninfo->select_nfds = dtls_fd + 1;
576
577         FD_SET(dtls_fd, &vpninfo->select_rfds);
578         FD_SET(dtls_fd, &vpninfo->select_efds);
579
580         time(&vpninfo->new_dtls_started);
581
582         return dtls_try_handshake(vpninfo);
583 }
584
585 static int dtls_restart(struct openconnect_info *vpninfo)
586 {
587         if (vpninfo->dtls_ssl) {
588 #if defined (DTLS_OPENSSL)
589                 SSL_free(vpninfo->dtls_ssl);
590 #elif defined (DTLS_GNUTLS)
591                 gnutls_deinit(vpninfo->dtls_ssl);
592 #endif
593                 close(vpninfo->dtls_fd);
594                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
595                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
596                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
597                 vpninfo->dtls_ssl = NULL;
598                 vpninfo->dtls_fd = -1;
599         }
600
601         return connect_dtls_socket(vpninfo);
602 }
603
604
605 int setup_dtls(struct openconnect_info *vpninfo)
606 {
607         struct vpn_option *dtls_opt = vpninfo->dtls_options;
608         int dtls_port = 0;
609
610 #if defined (OPENCONNECT_GNUTLS) && defined (DTLS_OPENSSL)
611         /* If we're using GnuTLS for authentication but OpenSSL for DTLS,
612            we'll need to initialise OpenSSL now... */
613         SSL_library_init ();
614         ERR_clear_error ();
615         SSL_load_error_strings ();
616         OpenSSL_add_all_algorithms ();
617 #endif
618
619         while (dtls_opt) {
620                 vpn_progress(vpninfo, PRG_TRACE,
621                              _("DTLS option %s : %s\n"),
622                              dtls_opt->option, dtls_opt->value);
623
624                 if (!strcmp(dtls_opt->option + 7, "Port")) {
625                         dtls_port = atol(dtls_opt->value);
626                 } else if (!strcmp(dtls_opt->option + 7, "Keepalive")) {
627                         vpninfo->dtls_times.keepalive = atol(dtls_opt->value);
628                 } else if (!strcmp(dtls_opt->option + 7, "DPD")) {
629                         int j = atol(dtls_opt->value);
630                         if (j && (!vpninfo->dtls_times.dpd || j < vpninfo->dtls_times.dpd))
631                                 vpninfo->dtls_times.dpd = j;
632                 } else if (!strcmp(dtls_opt->option + 7, "Rekey-Time")) {
633                         vpninfo->dtls_times.rekey = atol(dtls_opt->value);
634                 } else if (!strcmp(dtls_opt->option + 7, "CipherSuite")) {
635                         vpninfo->dtls_cipher = strdup(dtls_opt->value);
636                 }
637
638                 dtls_opt = dtls_opt->next;
639         }
640         if (!dtls_port) {
641                 vpninfo->dtls_attempt_period = 0;
642                 return -EINVAL;
643         }
644
645         vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
646         if (!vpninfo->dtls_addr) {
647                 vpninfo->dtls_attempt_period = 0;
648                 return -ENOMEM;
649         }
650         memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
651
652         if (vpninfo->peer_addr->sa_family == AF_INET) {
653                 struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
654                 sin->sin_port = htons(dtls_port);
655         } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
656                 struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
657                 sin->sin6_port = htons(dtls_port);
658         } else {
659                 vpn_progress(vpninfo, PRG_ERR,
660                              _("Unknown protocol family %d. Cannot do DTLS\n"),
661                              vpninfo->peer_addr->sa_family);
662                 vpninfo->dtls_attempt_period = 0;
663                 return -EINVAL;
664         }
665
666         if (connect_dtls_socket(vpninfo))
667                 return -EINVAL;
668
669         vpn_progress(vpninfo, PRG_TRACE,
670                      _("DTLS connected. DPD %d, Keepalive %d\n"),
671                      vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
672
673         return 0;
674 }
675
676 static struct pkt *dtls_pkt;
677
678 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
679 {
680         int work_done = 0;
681         char magic_pkt;
682
683         while (1) {
684                 int len = vpninfo->actual_mtu;
685                 unsigned char *buf;
686
687                 if (!dtls_pkt) {
688                         dtls_pkt = malloc(sizeof(struct pkt) + len);
689                         if (!dtls_pkt) {
690                                 vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n");
691                                 break;
692                         }
693                 }
694
695                 buf = dtls_pkt->data - 1;
696                 len = DTLS_RECV(vpninfo->dtls_ssl, buf, len + 1);
697                 if (len <= 0)
698                         break;
699
700                 vpn_progress(vpninfo, PRG_TRACE,
701                              _("Received DTLS packet 0x%02x of %d bytes\n"),
702                              buf[0], len);
703
704                 vpninfo->dtls_times.last_rx = time(NULL);
705
706                 switch(buf[0]) {
707                 case AC_PKT_DATA:
708                         dtls_pkt->len = len - 1;
709                         queue_packet(&vpninfo->incoming_queue, dtls_pkt);
710                         dtls_pkt = NULL;
711                         work_done = 1;
712                         break;
713
714                 case AC_PKT_DPD_OUT:
715                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));
716
717                         /* FIXME: What if the packet doesn't get through? */
718                         magic_pkt = AC_PKT_DPD_RESP;
719                         if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
720                                 vpn_progress(vpninfo, PRG_ERR,
721                                              _("Failed to send DPD response. Expect disconnect\n"));
722                         continue;
723
724                 case AC_PKT_DPD_RESP:
725                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
726                         break;
727
728                 case AC_PKT_KEEPALIVE:
729                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
730                         break;
731
732                 default:
733                         vpn_progress(vpninfo, PRG_ERR,
734                                      _("Unknown DTLS packet type %02x, len %d\n"),
735                                      buf[0], len);
736                         if (1) {
737                                 /* Some versions of OpenSSL have bugs with receiving out-of-order
738                                  * packets. Not only do they wrongly decide to drop packets if
739                                  * two packets get swapped in transit, but they also _fail_ to
740                                  * drop the packet in non-blocking mode; instead they return
741                                  * the appropriate length of garbage. So don't abort... for now. */
742                                 break;
743                         } else {
744                                 vpninfo->quit_reason = "Unknown packet received";
745                                 return 1;
746                         }
747
748                 }
749         }
750
751         switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
752         case KA_REKEY:
753                 vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));
754
755                 /* There ought to be a method of rekeying DTLS without tearing down
756                    the CSTP session and restarting, but we don't (yet) know it */
757                 if (cstp_reconnect(vpninfo)) {
758                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
759                         vpninfo->quit_reason = "CSTP reconnect failed";
760                         return 1;
761                 }
762
763                 if (dtls_restart(vpninfo)) {
764                         vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
765                         return 1;
766                 }
767                 work_done = 1;
768                 break;
769
770
771         case KA_DPD_DEAD:
772                 vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n"));
773                 /* Fall back to SSL, and start a new DTLS connection */
774                 dtls_restart(vpninfo);
775                 return 1;
776
777         case KA_DPD:
778                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));
779
780                 magic_pkt = AC_PKT_DPD_OUT;
781                 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
782                         vpn_progress(vpninfo, PRG_ERR,
783                                      _("Failed to send DPD request. Expect disconnect\n"));
784
785                 /* last_dpd will just have been set */
786                 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
787                 work_done = 1;
788                 break;
789
790         case KA_KEEPALIVE:
791                 /* No need to send an explicit keepalive
792                    if we have real data to send */
793                 if (vpninfo->outgoing_queue)
794                         break;
795
796                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));
797
798                 magic_pkt = AC_PKT_KEEPALIVE;
799                 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
800                         vpn_progress(vpninfo, PRG_ERR,
801                                      _("Failed to send keepalive request. Expect disconnect\n"));
802                 time(&vpninfo->dtls_times.last_tx);
803                 work_done = 1;
804                 break;
805
806         case KA_NONE:
807                 ;
808         }
809
810         /* Service outgoing packet queue */
811         while (vpninfo->outgoing_queue) {
812                 struct pkt *this = vpninfo->outgoing_queue;
813                 int ret;
814
815                 vpninfo->outgoing_queue = this->next;
816                 vpninfo->outgoing_qlen--;
817
818                 /* One byte of header */
819                 this->hdr[7] = AC_PKT_DATA;
820
821 #if defined(DTLS_OPENSSL)
822                 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
823                 if (ret <= 0) {
824                         ret = SSL_get_error(vpninfo->dtls_ssl, ret);
825
826                         /* If it's a real error, kill the DTLS connection and
827                            requeue the packet to be sent over SSL */
828                         if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
829                                 vpn_progress(vpninfo, PRG_ERR,
830                                              _("DTLS got write error %d. Falling back to SSL\n"),
831                                              ret);
832                                 openconnect_report_ssl_errors(vpninfo);
833                                 dtls_restart(vpninfo);
834                                 vpninfo->outgoing_queue = this;
835                                 vpninfo->outgoing_qlen++;
836                         }
837                         return 1;
838                 }
839 #elif defined (DTLS_GNUTLS)
840                 ret = gnutls_record_send(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
841                 if (ret <= 0) {
842                         if (ret != GNUTLS_E_AGAIN) {
843                                 vpn_progress(vpninfo, PRG_ERR,
844                                              _("DTLS got write error: %s. Falling back to SSL\n"),
845                                              gnutls_strerror(ret));
846                                 dtls_restart(vpninfo);
847                                 vpninfo->outgoing_queue = this;
848                                 vpninfo->outgoing_qlen++;
849                         }
850                         return 1;
851                 }
852 #endif
853                 time(&vpninfo->dtls_times.last_tx);
854                 vpn_progress(vpninfo, PRG_TRACE,
855                              _("Sent DTLS packet of %d bytes; DTLS send returned %d\n"),
856                              this->len, ret);
857                 free(this);
858         }
859
860         return work_done;
861 }
862 #else /* !HAVE_DTLS */
863 #warning Your SSL library does not seem to support Cisco DTLS compatibility
864  int setup_dtls(struct openconnect_info *vpninfo)
865 {
866         vpn_progress(vpninfo, PRG_ERR,
867                      _("Built against SSL library with no Cisco DTLS support\n"));
868         return -EINVAL;
869 }
870 #endif
871