Fix build failure on systems without GnuTLS v3
[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         /* +1 for packet header, +13 for DTLS overhead */
382         gnutls_dtls_set_mtu(dtls_ssl, vpninfo->mtu + 14);
383         gnutls_transport_set_ptr(dtls_ssl,
384                                  (gnutls_transport_ptr_t)(long) dtls_fd);
385         gnutls_record_disable_padding(dtls_ssl);
386         master_secret.data = vpninfo->dtls_secret;
387         master_secret.size = sizeof(vpninfo->dtls_secret);
388         session_id.data = vpninfo->dtls_session_id;
389         session_id.size = sizeof(vpninfo->dtls_session_id);
390         err = gnutls_session_set_premaster(dtls_ssl, GNUTLS_CLIENT, GNUTLS_DTLS0_9,
391                                            GNUTLS_KX_RSA, gnutls_dtls_ciphers[cipher].cipher,
392                                            gnutls_dtls_ciphers[cipher].mac, GNUTLS_COMP_NULL,
393                                            &master_secret, &session_id);
394         if (err) {
395                 vpn_progress(vpninfo, PRG_ERR,
396                              _("Failed to set DTLS session parameters: %s\n"),
397                              gnutls_strerror(err));
398                 gnutls_deinit(dtls_ssl);
399                 vpninfo->dtls_attempt_period = 0;
400                 return -EINVAL;
401         }
402
403         vpninfo->new_dtls_ssl = dtls_ssl;
404         return 0;
405 }
406
407 int dtls_try_handshake(struct openconnect_info *vpninfo)
408 {
409         int err = gnutls_handshake(vpninfo->new_dtls_ssl);
410
411         if (!err) {
412                 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection (using GnuTLS)\n"));
413
414                 if (vpninfo->dtls_ssl) {
415                         /* We are replacing an old connection */
416                         gnutls_deinit(vpninfo->dtls_ssl);
417                         close(vpninfo->dtls_fd);
418                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
419                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
420                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
421                 }
422                 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
423                 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
424
425                 vpninfo->new_dtls_ssl = NULL;
426                 vpninfo->new_dtls_fd = -1;
427
428                 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
429
430                 /* XXX: For OpenSSL we explicitly prevent retransmits here. */
431                 return 0;
432         }
433
434         if (err == GNUTLS_E_AGAIN) {
435                 if (time(NULL) < vpninfo->new_dtls_started + 5)
436                         return 0;
437                 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
438         }
439
440         vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %s\n"),
441                      gnutls_strerror(err));
442
443         /* Kill the new (failed) connection... */
444         gnutls_deinit(vpninfo->new_dtls_ssl);
445         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
446         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
447         close(vpninfo->new_dtls_fd);
448         vpninfo->new_dtls_ssl = NULL;
449         vpninfo->new_dtls_fd = -1;
450
451         /* ... and kill the old one too. The only time there'll be a valid
452            existing session is when it was a rekey, and in that case it's
453            time for the old one to die. */
454         if (vpninfo->dtls_ssl) {
455                 gnutls_deinit(vpninfo->dtls_ssl);
456                 close(vpninfo->dtls_fd);
457                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
458                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
459                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
460                 vpninfo->dtls_ssl = NULL;
461                 vpninfo->dtls_fd = -1;
462         }
463
464         time(&vpninfo->new_dtls_started);
465         return -EINVAL;
466 }
467 #endif
468
469 int connect_dtls_socket(struct openconnect_info *vpninfo)
470 {
471         int dtls_fd, ret;
472
473         if (!vpninfo->dtls_addr) {
474                 vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n"));
475                 vpninfo->dtls_attempt_period = 0;
476                 return -EINVAL;
477         }
478
479         if (!vpninfo->dtls_cipher) {
480                 /* We probably didn't offer it any ciphers it liked */
481                 vpn_progress(vpninfo, PRG_ERR, _("Server offered no DTLS cipher option\n"));
482                 vpninfo->dtls_attempt_period = 0;
483                 return -EINVAL;
484         }
485
486         if (vpninfo->proxy) {
487                 /* XXX: Theoretically, SOCKS5 proxies can do UDP too */
488                 vpn_progress(vpninfo, PRG_ERR, _("No DTLS when connected via proxy\n"));
489                 vpninfo->dtls_attempt_period = 0;
490                 return -EINVAL;
491         }
492
493         dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
494         if (dtls_fd < 0) {
495                 perror(_("Open UDP socket for DTLS:"));
496                 return -EINVAL;
497         }
498
499         if (vpninfo->dtls_local_port) {
500                 struct sockaddr_storage dtls_bind_addr;
501                 int dtls_bind_addrlen;
502                 memset(&dtls_bind_addr, 0, sizeof(dtls_bind_addr));
503
504                 if (vpninfo->peer_addr->sa_family == AF_INET) {
505                         struct sockaddr_in *addr = (struct sockaddr_in *)&dtls_bind_addr;
506                         dtls_bind_addrlen = sizeof(*addr);
507                         addr->sin_family = AF_INET;
508                         addr->sin_addr.s_addr = INADDR_ANY;
509                         addr->sin_port = htons(vpninfo->dtls_local_port);
510                 } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
511                         struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&dtls_bind_addr;
512                         dtls_bind_addrlen = sizeof(*addr);
513                         addr->sin6_family = AF_INET6;
514                         addr->sin6_addr = in6addr_any;
515                         addr->sin6_port = htons(vpninfo->dtls_local_port);
516                 } else {
517                         vpn_progress(vpninfo, PRG_ERR,
518                                      _("Unknown protocol family %d. Cannot do DTLS\n"),
519                                      vpninfo->peer_addr->sa_family);
520                         vpninfo->dtls_attempt_period = 0;
521                         return -EINVAL;
522                 }
523
524                 if (bind(dtls_fd, (struct sockaddr *)&dtls_bind_addr, dtls_bind_addrlen)) {
525                         perror(_("Bind UDP socket for DTLS"));
526                         return -EINVAL;
527                 }
528         }
529
530         if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
531                 perror(_("UDP (DTLS) connect:\n"));
532                 close(dtls_fd);
533                 return -EINVAL;
534         }
535
536         fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
537         fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
538
539         ret = start_dtls_handshake(vpninfo, dtls_fd);
540         if (ret) {
541                 close(dtls_fd);
542                 return ret;
543         }
544
545         vpninfo->new_dtls_fd = dtls_fd;
546         if (vpninfo->select_nfds <= dtls_fd)
547                 vpninfo->select_nfds = dtls_fd + 1;
548
549         FD_SET(dtls_fd, &vpninfo->select_rfds);
550         FD_SET(dtls_fd, &vpninfo->select_efds);
551
552         time(&vpninfo->new_dtls_started);
553
554         return dtls_try_handshake(vpninfo);
555 }
556
557 static int dtls_restart(struct openconnect_info *vpninfo)
558 {
559         if (vpninfo->dtls_ssl) {
560 #if defined (DTLS_OPENSSL)
561                 SSL_free(vpninfo->dtls_ssl);
562 #elif defined (DTLS_GNUTLS)
563                 gnutls_deinit(vpninfo->dtls_ssl);
564 #endif
565                 close(vpninfo->dtls_fd);
566                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
567                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
568                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
569                 vpninfo->dtls_ssl = NULL;
570                 vpninfo->dtls_fd = -1;
571         }
572
573         return connect_dtls_socket(vpninfo);
574 }
575
576
577 int setup_dtls(struct openconnect_info *vpninfo)
578 {
579         struct vpn_option *dtls_opt = vpninfo->dtls_options;
580         int dtls_port = 0;
581
582 #if defined (OPENCONNECT_GNUTLS) && defined (DTLS_OPENSSL)
583         /* If we're using GnuTLS for authentication but OpenSSL for DTLS,
584            we'll need to initialise OpenSSL now... */
585         SSL_library_init ();
586         ERR_clear_error ();
587         SSL_load_error_strings ();
588         OpenSSL_add_all_algorithms ();
589 #endif
590
591         while (dtls_opt) {
592                 vpn_progress(vpninfo, PRG_TRACE,
593                              _("DTLS option %s : %s\n"),
594                              dtls_opt->option, dtls_opt->value);
595
596                 if (!strcmp(dtls_opt->option + 7, "Port")) {
597                         dtls_port = atol(dtls_opt->value);
598                 } else if (!strcmp(dtls_opt->option + 7, "Keepalive")) {
599                         vpninfo->dtls_times.keepalive = atol(dtls_opt->value);
600                 } else if (!strcmp(dtls_opt->option + 7, "DPD")) {
601                         int j = atol(dtls_opt->value);
602                         if (j && (!vpninfo->dtls_times.dpd || j < vpninfo->dtls_times.dpd))
603                                 vpninfo->dtls_times.dpd = j;
604                 } else if (!strcmp(dtls_opt->option + 7, "Rekey-Time")) {
605                         vpninfo->dtls_times.rekey = atol(dtls_opt->value);
606                 } else if (!strcmp(dtls_opt->option + 7, "CipherSuite")) {
607                         vpninfo->dtls_cipher = strdup(dtls_opt->value);
608                 }
609
610                 dtls_opt = dtls_opt->next;
611         }
612         if (!dtls_port) {
613                 vpninfo->dtls_attempt_period = 0;
614                 return -EINVAL;
615         }
616
617         vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
618         if (!vpninfo->dtls_addr) {
619                 vpninfo->dtls_attempt_period = 0;
620                 return -ENOMEM;
621         }
622         memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
623
624         if (vpninfo->peer_addr->sa_family == AF_INET) {
625                 struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
626                 sin->sin_port = htons(dtls_port);
627         } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
628                 struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
629                 sin->sin6_port = htons(dtls_port);
630         } else {
631                 vpn_progress(vpninfo, PRG_ERR,
632                              _("Unknown protocol family %d. Cannot do DTLS\n"),
633                              vpninfo->peer_addr->sa_family);
634                 vpninfo->dtls_attempt_period = 0;
635                 return -EINVAL;
636         }
637
638         if (connect_dtls_socket(vpninfo))
639                 return -EINVAL;
640
641         vpn_progress(vpninfo, PRG_TRACE,
642                      _("DTLS connected. DPD %d, Keepalive %d\n"),
643                      vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
644
645         return 0;
646 }
647
648 static struct pkt *dtls_pkt;
649
650 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
651 {
652         int work_done = 0;
653         char magic_pkt;
654
655         while (1) {
656                 int len = vpninfo->mtu;
657                 unsigned char *buf;
658
659                 if (!dtls_pkt) {
660                         dtls_pkt = malloc(sizeof(struct pkt) + len);
661                         if (!dtls_pkt) {
662                                 vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n");
663                                 break;
664                         }
665                 }
666
667                 buf = dtls_pkt->data - 1;
668                 len = DTLS_RECV(vpninfo->dtls_ssl, buf, len + 1);
669                 if (len <= 0)
670                         break;
671
672                 vpn_progress(vpninfo, PRG_TRACE,
673                              _("Received DTLS packet 0x%02x of %d bytes\n"),
674                              buf[0], len);
675
676                 vpninfo->dtls_times.last_rx = time(NULL);
677
678                 switch(buf[0]) {
679                 case AC_PKT_DATA:
680                         dtls_pkt->len = len - 1;
681                         queue_packet(&vpninfo->incoming_queue, dtls_pkt);
682                         dtls_pkt = NULL;
683                         work_done = 1;
684                         break;
685
686                 case AC_PKT_DPD_OUT:
687                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));
688
689                         /* FIXME: What if the packet doesn't get through? */
690                         magic_pkt = AC_PKT_DPD_RESP;
691                         if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
692                                 vpn_progress(vpninfo, PRG_ERR,
693                                              _("Failed to send DPD response. Expect disconnect\n"));
694                         continue;
695
696                 case AC_PKT_DPD_RESP:
697                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
698                         break;
699
700                 case AC_PKT_KEEPALIVE:
701                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
702                         break;
703
704                 default:
705                         vpn_progress(vpninfo, PRG_ERR,
706                                      _("Unknown DTLS packet type %02x, len %d\n"),
707                                      buf[0], len);
708                         if (1) {
709                                 /* Some versions of OpenSSL have bugs with receiving out-of-order
710                                  * packets. Not only do they wrongly decide to drop packets if
711                                  * two packets get swapped in transit, but they also _fail_ to
712                                  * drop the packet in non-blocking mode; instead they return
713                                  * the appropriate length of garbage. So don't abort... for now. */
714                                 break;
715                         } else {
716                                 vpninfo->quit_reason = "Unknown packet received";
717                                 return 1;
718                         }
719
720                 }
721         }
722
723         switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
724         case KA_REKEY:
725                 vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));
726
727                 /* There ought to be a method of rekeying DTLS without tearing down
728                    the CSTP session and restarting, but we don't (yet) know it */
729                 if (cstp_reconnect(vpninfo)) {
730                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
731                         vpninfo->quit_reason = "CSTP reconnect failed";
732                         return 1;
733                 }
734
735                 if (dtls_restart(vpninfo)) {
736                         vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
737                         return 1;
738                 }
739                 work_done = 1;
740                 break;
741
742
743         case KA_DPD_DEAD:
744                 vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n"));
745                 /* Fall back to SSL, and start a new DTLS connection */
746                 dtls_restart(vpninfo);
747                 return 1;
748
749         case KA_DPD:
750                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));
751
752                 magic_pkt = AC_PKT_DPD_OUT;
753                 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
754                         vpn_progress(vpninfo, PRG_ERR,
755                                      _("Failed to send DPD request. Expect disconnect\n"));
756
757                 /* last_dpd will just have been set */
758                 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
759                 work_done = 1;
760                 break;
761
762         case KA_KEEPALIVE:
763                 /* No need to send an explicit keepalive
764                    if we have real data to send */
765                 if (vpninfo->outgoing_queue)
766                         break;
767
768                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));
769
770                 magic_pkt = AC_PKT_KEEPALIVE;
771                 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
772                         vpn_progress(vpninfo, PRG_ERR,
773                                      _("Failed to send keepalive request. Expect disconnect\n"));
774                 time(&vpninfo->dtls_times.last_tx);
775                 work_done = 1;
776                 break;
777
778         case KA_NONE:
779                 ;
780         }
781
782         /* Service outgoing packet queue */
783         while (vpninfo->outgoing_queue) {
784                 struct pkt *this = vpninfo->outgoing_queue;
785                 int ret;
786
787                 vpninfo->outgoing_queue = this->next;
788                 vpninfo->outgoing_qlen--;
789
790                 /* One byte of header */
791                 this->hdr[7] = AC_PKT_DATA;
792
793 #if defined(DTLS_OPENSSL)
794                 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
795                 if (ret <= 0) {
796                         ret = SSL_get_error(vpninfo->dtls_ssl, ret);
797
798                         /* If it's a real error, kill the DTLS connection and
799                            requeue the packet to be sent over SSL */
800                         if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
801                                 vpn_progress(vpninfo, PRG_ERR,
802                                              _("DTLS got write error %d. Falling back to SSL\n"),
803                                              ret);
804                                 openconnect_report_ssl_errors(vpninfo);
805                                 dtls_restart(vpninfo);
806                                 vpninfo->outgoing_queue = this;
807                                 vpninfo->outgoing_qlen++;
808                         }
809                         return 1;
810                 }
811 #elif defined (DTLS_GNUTLS)
812                 ret = gnutls_record_send(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
813                 if (ret <= 0) {
814                         if (ret != GNUTLS_E_AGAIN) {
815                                 vpn_progress(vpninfo, PRG_ERR,
816                                              _("DTLS got write error: %s. Falling back to SSL\n"),
817                                              gnutls_strerror(ret));
818                                 dtls_restart(vpninfo);
819                                 vpninfo->outgoing_queue = this;
820                                 vpninfo->outgoing_qlen++;
821                         }
822                         return 1;
823                 }
824 #endif
825                 time(&vpninfo->dtls_times.last_tx);
826                 vpn_progress(vpninfo, PRG_TRACE,
827                              _("Sent DTLS packet of %d bytes; DTLS send returned %d\n"),
828                              this->len, ret);
829                 free(this);
830         }
831
832         return work_done;
833 }
834 #else /* !HAVE_DTLS */
835 #warning Your SSL library does not seem to support Cisco DTLS compatibility
836  int setup_dtls(struct openconnect_info *vpninfo)
837 {
838         vpn_progress(vpninfo, PRG_ERR,
839                      _("Built against SSL library with no Cisco DTLS support\n"));
840         return -EINVAL;
841 }
842 #endif
843