Separate requested from received MTU settings
[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                 struct sockaddr_storage dtls_bind_addr;
524                 int dtls_bind_addrlen;
525                 memset(&dtls_bind_addr, 0, sizeof(dtls_bind_addr));
526
527                 if (vpninfo->peer_addr->sa_family == AF_INET) {
528                         struct sockaddr_in *addr = (struct sockaddr_in *)&dtls_bind_addr;
529                         dtls_bind_addrlen = sizeof(*addr);
530                         addr->sin_family = AF_INET;
531                         addr->sin_addr.s_addr = INADDR_ANY;
532                         addr->sin_port = htons(vpninfo->dtls_local_port);
533                 } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
534                         struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&dtls_bind_addr;
535                         dtls_bind_addrlen = sizeof(*addr);
536                         addr->sin6_family = AF_INET6;
537                         addr->sin6_addr = in6addr_any;
538                         addr->sin6_port = htons(vpninfo->dtls_local_port);
539                 } else {
540                         vpn_progress(vpninfo, PRG_ERR,
541                                      _("Unknown protocol family %d. Cannot do DTLS\n"),
542                                      vpninfo->peer_addr->sa_family);
543                         vpninfo->dtls_attempt_period = 0;
544                         return -EINVAL;
545                 }
546
547                 if (bind(dtls_fd, (struct sockaddr *)&dtls_bind_addr, dtls_bind_addrlen)) {
548                         perror(_("Bind UDP socket for DTLS"));
549                         return -EINVAL;
550                 }
551         }
552
553         if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
554                 perror(_("UDP (DTLS) connect:\n"));
555                 close(dtls_fd);
556                 return -EINVAL;
557         }
558
559         fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
560         fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
561
562         ret = start_dtls_handshake(vpninfo, dtls_fd);
563         if (ret) {
564                 close(dtls_fd);
565                 return ret;
566         }
567
568         vpninfo->new_dtls_fd = dtls_fd;
569         if (vpninfo->select_nfds <= dtls_fd)
570                 vpninfo->select_nfds = dtls_fd + 1;
571
572         FD_SET(dtls_fd, &vpninfo->select_rfds);
573         FD_SET(dtls_fd, &vpninfo->select_efds);
574
575         time(&vpninfo->new_dtls_started);
576
577         return dtls_try_handshake(vpninfo);
578 }
579
580 static int dtls_restart(struct openconnect_info *vpninfo)
581 {
582         if (vpninfo->dtls_ssl) {
583 #if defined (DTLS_OPENSSL)
584                 SSL_free(vpninfo->dtls_ssl);
585 #elif defined (DTLS_GNUTLS)
586                 gnutls_deinit(vpninfo->dtls_ssl);
587 #endif
588                 close(vpninfo->dtls_fd);
589                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
590                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
591                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
592                 vpninfo->dtls_ssl = NULL;
593                 vpninfo->dtls_fd = -1;
594         }
595
596         return connect_dtls_socket(vpninfo);
597 }
598
599
600 int setup_dtls(struct openconnect_info *vpninfo)
601 {
602         struct vpn_option *dtls_opt = vpninfo->dtls_options;
603         int dtls_port = 0;
604
605 #if defined (OPENCONNECT_GNUTLS) && defined (DTLS_OPENSSL)
606         /* If we're using GnuTLS for authentication but OpenSSL for DTLS,
607            we'll need to initialise OpenSSL now... */
608         SSL_library_init ();
609         ERR_clear_error ();
610         SSL_load_error_strings ();
611         OpenSSL_add_all_algorithms ();
612 #endif
613
614         while (dtls_opt) {
615                 vpn_progress(vpninfo, PRG_TRACE,
616                              _("DTLS option %s : %s\n"),
617                              dtls_opt->option, dtls_opt->value);
618
619                 if (!strcmp(dtls_opt->option + 7, "Port")) {
620                         dtls_port = atol(dtls_opt->value);
621                 } else if (!strcmp(dtls_opt->option + 7, "Keepalive")) {
622                         vpninfo->dtls_times.keepalive = atol(dtls_opt->value);
623                 } else if (!strcmp(dtls_opt->option + 7, "DPD")) {
624                         int j = atol(dtls_opt->value);
625                         if (j && (!vpninfo->dtls_times.dpd || j < vpninfo->dtls_times.dpd))
626                                 vpninfo->dtls_times.dpd = j;
627                 } else if (!strcmp(dtls_opt->option + 7, "Rekey-Time")) {
628                         vpninfo->dtls_times.rekey = atol(dtls_opt->value);
629                 } else if (!strcmp(dtls_opt->option + 7, "CipherSuite")) {
630                         vpninfo->dtls_cipher = strdup(dtls_opt->value);
631                 }
632
633                 dtls_opt = dtls_opt->next;
634         }
635         if (!dtls_port) {
636                 vpninfo->dtls_attempt_period = 0;
637                 return -EINVAL;
638         }
639
640         vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
641         if (!vpninfo->dtls_addr) {
642                 vpninfo->dtls_attempt_period = 0;
643                 return -ENOMEM;
644         }
645         memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
646
647         if (vpninfo->peer_addr->sa_family == AF_INET) {
648                 struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
649                 sin->sin_port = htons(dtls_port);
650         } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
651                 struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
652                 sin->sin6_port = htons(dtls_port);
653         } else {
654                 vpn_progress(vpninfo, PRG_ERR,
655                              _("Unknown protocol family %d. Cannot do DTLS\n"),
656                              vpninfo->peer_addr->sa_family);
657                 vpninfo->dtls_attempt_period = 0;
658                 return -EINVAL;
659         }
660
661         if (connect_dtls_socket(vpninfo))
662                 return -EINVAL;
663
664         vpn_progress(vpninfo, PRG_TRACE,
665                      _("DTLS connected. DPD %d, Keepalive %d\n"),
666                      vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
667
668         return 0;
669 }
670
671 static struct pkt *dtls_pkt;
672
673 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
674 {
675         int work_done = 0;
676         char magic_pkt;
677
678         while (1) {
679                 int len = vpninfo->actual_mtu;
680                 unsigned char *buf;
681
682                 if (!dtls_pkt) {
683                         dtls_pkt = malloc(sizeof(struct pkt) + len);
684                         if (!dtls_pkt) {
685                                 vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n");
686                                 break;
687                         }
688                 }
689
690                 buf = dtls_pkt->data - 1;
691                 len = DTLS_RECV(vpninfo->dtls_ssl, buf, len + 1);
692                 if (len <= 0)
693                         break;
694
695                 vpn_progress(vpninfo, PRG_TRACE,
696                              _("Received DTLS packet 0x%02x of %d bytes\n"),
697                              buf[0], len);
698
699                 vpninfo->dtls_times.last_rx = time(NULL);
700
701                 switch(buf[0]) {
702                 case AC_PKT_DATA:
703                         dtls_pkt->len = len - 1;
704                         queue_packet(&vpninfo->incoming_queue, dtls_pkt);
705                         dtls_pkt = NULL;
706                         work_done = 1;
707                         break;
708
709                 case AC_PKT_DPD_OUT:
710                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));
711
712                         /* FIXME: What if the packet doesn't get through? */
713                         magic_pkt = AC_PKT_DPD_RESP;
714                         if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
715                                 vpn_progress(vpninfo, PRG_ERR,
716                                              _("Failed to send DPD response. Expect disconnect\n"));
717                         continue;
718
719                 case AC_PKT_DPD_RESP:
720                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
721                         break;
722
723                 case AC_PKT_KEEPALIVE:
724                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
725                         break;
726
727                 default:
728                         vpn_progress(vpninfo, PRG_ERR,
729                                      _("Unknown DTLS packet type %02x, len %d\n"),
730                                      buf[0], len);
731                         if (1) {
732                                 /* Some versions of OpenSSL have bugs with receiving out-of-order
733                                  * packets. Not only do they wrongly decide to drop packets if
734                                  * two packets get swapped in transit, but they also _fail_ to
735                                  * drop the packet in non-blocking mode; instead they return
736                                  * the appropriate length of garbage. So don't abort... for now. */
737                                 break;
738                         } else {
739                                 vpninfo->quit_reason = "Unknown packet received";
740                                 return 1;
741                         }
742
743                 }
744         }
745
746         switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
747         case KA_REKEY:
748                 vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));
749
750                 /* There ought to be a method of rekeying DTLS without tearing down
751                    the CSTP session and restarting, but we don't (yet) know it */
752                 if (cstp_reconnect(vpninfo)) {
753                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
754                         vpninfo->quit_reason = "CSTP reconnect failed";
755                         return 1;
756                 }
757
758                 if (dtls_restart(vpninfo)) {
759                         vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
760                         return 1;
761                 }
762                 work_done = 1;
763                 break;
764
765
766         case KA_DPD_DEAD:
767                 vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n"));
768                 /* Fall back to SSL, and start a new DTLS connection */
769                 dtls_restart(vpninfo);
770                 return 1;
771
772         case KA_DPD:
773                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));
774
775                 magic_pkt = AC_PKT_DPD_OUT;
776                 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
777                         vpn_progress(vpninfo, PRG_ERR,
778                                      _("Failed to send DPD request. Expect disconnect\n"));
779
780                 /* last_dpd will just have been set */
781                 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
782                 work_done = 1;
783                 break;
784
785         case KA_KEEPALIVE:
786                 /* No need to send an explicit keepalive
787                    if we have real data to send */
788                 if (vpninfo->outgoing_queue)
789                         break;
790
791                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));
792
793                 magic_pkt = AC_PKT_KEEPALIVE;
794                 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
795                         vpn_progress(vpninfo, PRG_ERR,
796                                      _("Failed to send keepalive request. Expect disconnect\n"));
797                 time(&vpninfo->dtls_times.last_tx);
798                 work_done = 1;
799                 break;
800
801         case KA_NONE:
802                 ;
803         }
804
805         /* Service outgoing packet queue */
806         while (vpninfo->outgoing_queue) {
807                 struct pkt *this = vpninfo->outgoing_queue;
808                 int ret;
809
810                 vpninfo->outgoing_queue = this->next;
811                 vpninfo->outgoing_qlen--;
812
813                 /* One byte of header */
814                 this->hdr[7] = AC_PKT_DATA;
815
816 #if defined(DTLS_OPENSSL)
817                 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
818                 if (ret <= 0) {
819                         ret = SSL_get_error(vpninfo->dtls_ssl, ret);
820
821                         /* If it's a real error, kill the DTLS connection and
822                            requeue the packet to be sent over SSL */
823                         if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
824                                 vpn_progress(vpninfo, PRG_ERR,
825                                              _("DTLS got write error %d. Falling back to SSL\n"),
826                                              ret);
827                                 openconnect_report_ssl_errors(vpninfo);
828                                 dtls_restart(vpninfo);
829                                 vpninfo->outgoing_queue = this;
830                                 vpninfo->outgoing_qlen++;
831                         }
832                         return 1;
833                 }
834 #elif defined (DTLS_GNUTLS)
835                 ret = gnutls_record_send(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
836                 if (ret <= 0) {
837                         if (ret != GNUTLS_E_AGAIN) {
838                                 vpn_progress(vpninfo, PRG_ERR,
839                                              _("DTLS got write error: %s. Falling back to SSL\n"),
840                                              gnutls_strerror(ret));
841                                 dtls_restart(vpninfo);
842                                 vpninfo->outgoing_queue = this;
843                                 vpninfo->outgoing_qlen++;
844                         }
845                         return 1;
846                 }
847 #endif
848                 time(&vpninfo->dtls_times.last_tx);
849                 vpn_progress(vpninfo, PRG_TRACE,
850                              _("Sent DTLS packet of %d bytes; DTLS send returned %d\n"),
851                              this->len, ret);
852                 free(this);
853         }
854
855         return work_done;
856 }
857 #else /* !HAVE_DTLS */
858 #warning Your SSL library does not seem to support Cisco DTLS compatibility
859  int setup_dtls(struct openconnect_info *vpninfo)
860 {
861         vpn_progress(vpninfo, PRG_ERR,
862                      _("Built against SSL library with no Cisco DTLS support\n"));
863         return -EINVAL;
864 }
865 #endif
866