2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2008-2012 Intel Corporation.
6 * Author: David Woodhouse <dwmw2@infradead.org>
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.
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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA
26 #include <sys/types.h>
27 #include <sys/socket.h>
30 #include <netinet/in.h>
37 #include "openconnect-internal.h"
39 #ifdef HAVE_DTLS1_STOP_TIMER
40 /* OpenSSL doesn't deliberately export this, but we need it to
41 workaround a DTLS bug in versions < 1.0.0e */
42 extern void dtls1_stop_timer (SSL *);
45 static unsigned char nybble(unsigned char n)
47 if (n >= '0' && n <= '9') return n - '0';
48 else if (n >= 'A' && n <= 'F') return n - ('A' - 10);
49 else if (n >= 'a' && n <= 'f') return n - ('a' - 10);
53 unsigned char unhex(const char *data)
55 return (nybble(data[0]) << 4) | nybble(data[1]);
62 * Useful for catching test cases, where we want everything to be
63 * reproducible. *NEVER* do this in the wild.
65 time_t time(time_t *t)
67 time_t x = 0x3ab2d948;
72 int RAND_pseudo_bytes(char *buf, int len)
74 memset(buf, 0x5a, len);
75 printf("FAKE PSEUDO RANDOM!\n");
79 int RAND_bytes(char *buf, int len)
81 static int foo = 0x5b;
82 printf("FAKE RANDOM!\n");
83 memset(buf, foo, len);
89 * The master-secret is generated randomly by the client. The server
90 * responds with a DTLS Session-ID. These, done over the HTTPS
91 * connection, are enough to 'resume' a DTLS session, bypassing all
92 * the normal setup of a normal DTLS connection.
94 * Cisco use a version of the protocol which predates RFC4347, but
95 * isn't quite the same as the pre-RFC version of the protocol which
96 * was in OpenSSL 0.9.8e -- it includes backports of some later
99 * The openssl/ directory of this source tree should contain both a
100 * small patch against OpenSSL 0.9.8e to make it support Cisco's
101 * snapshot of the protocol, and a larger patch against newer OpenSSL
102 * which gives us an option to use the old protocol again.
104 * Cisco's server also seems to respond to the official version of the
105 * protocol, with a change in the ChangeCipherSpec packet which implies
106 * that it does know the difference and isn't just repeating the version
107 * number seen in the ClientHello. But although I can make the handshake
108 * complete by hacking tls1_mac() to use the _old_ protocol version
109 * number when calculating the MAC, the server still seems to be ignoring
110 * my subsequent data packets. So we use the old protocol, which is what
111 * their clients use anyway.
114 #if defined (DTLS_OPENSSL)
115 #define DTLS_SEND SSL_write
116 #define DTLS_RECV SSL_read
117 static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
119 STACK_OF(SSL_CIPHER) *ciphers;
120 method_const SSL_METHOD *dtls_method;
121 SSL_CIPHER *dtls_cipher;
125 if (!vpninfo->dtls_ctx) {
126 dtls_method = DTLSv1_client_method();
127 vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
128 if (!vpninfo->dtls_ctx) {
129 vpn_progress(vpninfo, PRG_ERR,
130 _("Initialise DTLSv1 CTX failed\n"));
131 openconnect_report_ssl_errors(vpninfo);
132 vpninfo->dtls_attempt_period = 0;
136 /* If we don't readahead, then we do short reads and throw
137 away the tail of data packets. */
138 SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
140 if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, vpninfo->dtls_cipher)) {
141 vpn_progress(vpninfo, PRG_ERR,
142 _("Set DTLS cipher list failed\n"));
143 SSL_CTX_free(vpninfo->dtls_ctx);
144 vpninfo->dtls_ctx = NULL;
145 vpninfo->dtls_attempt_period = 0;
150 if (!vpninfo->dtls_session) {
151 /* We're going to "resume" a session which never existed. Fake it... */
152 vpninfo->dtls_session = SSL_SESSION_new();
153 if (!vpninfo->dtls_session) {
154 vpn_progress(vpninfo, PRG_ERR,
155 _("Initialise DTLSv1 session failed\n"));
156 vpninfo->dtls_attempt_period = 0;
159 vpninfo->dtls_session->ssl_version = 0x0100; /* DTLS1_BAD_VER */
162 /* Do this every time; it may have changed due to a rekey */
163 vpninfo->dtls_session->master_key_length = sizeof(vpninfo->dtls_secret);
164 memcpy(vpninfo->dtls_session->master_key, vpninfo->dtls_secret,
165 sizeof(vpninfo->dtls_secret));
167 vpninfo->dtls_session->session_id_length = sizeof(vpninfo->dtls_session_id);
168 memcpy(vpninfo->dtls_session->session_id, vpninfo->dtls_session_id,
169 sizeof(vpninfo->dtls_session_id));
171 dtls_ssl = SSL_new(vpninfo->dtls_ctx);
172 SSL_set_connect_state(dtls_ssl);
174 ciphers = SSL_get_ciphers(dtls_ssl);
175 if (sk_SSL_CIPHER_num(ciphers) != 1) {
176 vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n"));
177 SSL_CTX_free(vpninfo->dtls_ctx);
179 SSL_SESSION_free(vpninfo->dtls_session);
180 vpninfo->dtls_ctx = NULL;
181 vpninfo->dtls_session = NULL;
182 vpninfo->dtls_attempt_period = 0;
185 dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);
187 /* Set the appropriate cipher on our session to be resumed */
188 vpninfo->dtls_session->cipher = dtls_cipher;
189 vpninfo->dtls_session->cipher_id = dtls_cipher->id;
191 /* Add the generated session to the SSL */
192 if (!SSL_set_session(dtls_ssl, vpninfo->dtls_session)) {
193 vpn_progress(vpninfo, PRG_ERR,
194 _("SSL_set_session() failed with old protocol version 0x%x\n"
195 "Are you using a version of OpenSSL older than 0.9.8m?\n"
196 "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
197 "Use the --no-dtls command line option to avoid this message\n"),
198 vpninfo->dtls_session->ssl_version);
199 vpninfo->dtls_attempt_period = 0;
203 dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
204 /* Set non-blocking */
205 BIO_set_nbio(dtls_bio, 1);
206 SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);
208 SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);
210 vpninfo->new_dtls_ssl = dtls_ssl;
215 int dtls_try_handshake(struct openconnect_info *vpninfo)
217 int ret = SSL_do_handshake(vpninfo->new_dtls_ssl);
220 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection (using OpenSSL)\n"));
222 if (vpninfo->dtls_ssl) {
223 /* We are replacing an old connection */
224 SSL_free(vpninfo->dtls_ssl);
225 close(vpninfo->dtls_fd);
226 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
227 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
228 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
230 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
231 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
233 vpninfo->new_dtls_ssl = NULL;
234 vpninfo->new_dtls_fd = -1;
236 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
238 /* From about 8.4.1(11) onwards, the ASA seems to get
239 very unhappy if we resend ChangeCipherSpec messages
240 after the initial setup. This was "fixed" in OpenSSL
241 1.0.0e for RT#2505, but it's not clear if that was
242 the right fix. What happens if the original packet
243 *does* get lost? Surely we *wanted* the retransmits,
244 because without them the server will never be able
245 to decrypt anything we send?
246 Oh well, our retransmitted packets upset the server
247 because we don't get the Cisco-compatibility right
248 (this is one of the areas in which Cisco's DTLS differs
249 from the RFC4347 spec), and DPD should help us notice
250 if *nothing* is getting through. */
251 #if OPENSSL_VERSION_NUMBER >= 0x1000005fL
252 /* OpenSSL 1.0.0e or above doesn't resend anyway; do nothing.
253 However, if we were *built* against 1.0.0e or newer, but at
254 runtime we find that we are being run against an older
255 version, warn about it. */
256 if (SSLeay() < 0x1000005fL) {
257 vpn_progress(vpninfo, PRG_ERR,
258 _("Your OpenSSL is older than the one you built against, so DTLS may fail!"));
260 #elif defined (HAVE_DTLS1_STOP_TIMER)
262 * This works for any normal OpenSSL that supports
263 * Cisco DTLS compatibility (0.9.8m to 1.0.0d inclusive,
264 * and even later versions although it isn't needed there.
266 dtls1_stop_timer(vpninfo->dtls_ssl);
267 #elif defined (BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT)
269 * Debian restricts visibility of dtls1_stop_timer()
270 * so do it manually. This version also works on all
271 * sane versions of OpenSSL:
273 memset (&(vpninfo->dtls_ssl->d1->next_timeout), 0,
274 sizeof((vpninfo->dtls_ssl->d1->next_timeout)));
275 vpninfo->dtls_ssl->d1->timeout_duration = 1;
276 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
277 BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
278 &(vpninfo->dtls_ssl->d1->next_timeout));
279 #elif defined (BIO_CTRL_DGRAM_SET_TIMEOUT)
281 * OK, here it gets more fun... this shoul handle the case
282 * of older OpenSSL which has the Cisco DTLS compatibility
283 * backported, but *not* the fix for RT#1922.
285 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
286 BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
289 * And if they don't have any of the above, they probably
290 * don't have RT#1829 fixed either, but that's OK because
291 * that's the "fix" that *introduces* the timeout we're
292 * trying to disable. So do nothing...
298 ret = SSL_get_error(vpninfo->new_dtls_ssl, ret);
299 if (ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) {
300 if (time(NULL) < vpninfo->new_dtls_started + 5)
302 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
305 vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %d\n"), ret);
306 openconnect_report_ssl_errors(vpninfo);
308 /* Kill the new (failed) connection... */
309 SSL_free(vpninfo->new_dtls_ssl);
310 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
311 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
312 close(vpninfo->new_dtls_fd);
313 vpninfo->new_dtls_ssl = NULL;
314 vpninfo->new_dtls_fd = -1;
316 /* ... and kill the old one too. The only time there'll be a valid
317 existing session is when it was a rekey, and in that case it's
318 time for the old one to die. */
319 if (vpninfo->dtls_ssl) {
320 SSL_free(vpninfo->dtls_ssl);
321 close(vpninfo->dtls_fd);
322 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
323 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
324 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
325 vpninfo->dtls_ssl = NULL;
326 vpninfo->dtls_fd = -1;
329 time(&vpninfo->new_dtls_started);
333 #elif defined (DTLS_GNUTLS)
336 gnutls_cipher_algorithm_t cipher;
337 gnutls_mac_algorithm_t mac;
339 } gnutls_dtls_ciphers[] = {
340 { "AES128-SHA", GNUTLS_CIPHER_AES_128_CBC, GNUTLS_MAC_SHA1,
341 "NONE:+VERS-DTLS0.9:+COMP-NULL:+AES-128-CBC:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION" },
342 { "DES-CBC3-SHA", GNUTLS_CIPHER_3DES_CBC, GNUTLS_MAC_SHA1,
343 "NONE:+VERS-DTLS0.9:+COMP-NULL:+3DES-CBC:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION" },
346 #define DTLS_SEND gnutls_record_send
347 #define DTLS_RECV gnutls_record_recv
348 static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
350 gnutls_session_t dtls_ssl;
351 gnutls_datum_t master_secret, session_id;
355 for (cipher = 0; cipher < sizeof(gnutls_dtls_ciphers)/sizeof(gnutls_dtls_ciphers[0]); cipher++) {
356 if (!strcmp(vpninfo->dtls_cipher, gnutls_dtls_ciphers[cipher].name))
359 vpn_progress(vpninfo, PRG_ERR, _("Unknown DTLS parameters for requested CipherSuite '%s'\n"),
360 vpninfo->dtls_cipher);
361 vpninfo->dtls_attempt_period = 0;
366 gnutls_init(&dtls_ssl, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
367 err = gnutls_priority_set_direct(dtls_ssl,
368 gnutls_dtls_ciphers[cipher].prio,
371 vpn_progress(vpninfo, PRG_ERR,
372 _("Failed to set DTLS priority: %s\n"),
373 gnutls_strerror(err));
374 gnutls_deinit(dtls_ssl);
375 vpninfo->dtls_attempt_period = 0;
378 gnutls_transport_set_ptr(dtls_ssl,
379 (gnutls_transport_ptr_t)(long) dtls_fd);
380 gnutls_record_disable_padding(dtls_ssl);
381 master_secret.data = vpninfo->dtls_secret;
382 master_secret.size = sizeof(vpninfo->dtls_secret);
383 session_id.data = vpninfo->dtls_session_id;
384 session_id.size = sizeof(vpninfo->dtls_session_id);
385 err = gnutls_session_set_premaster(dtls_ssl, GNUTLS_CLIENT, GNUTLS_DTLS0_9,
386 GNUTLS_KX_RSA, gnutls_dtls_ciphers[cipher].cipher,
387 gnutls_dtls_ciphers[cipher].mac, GNUTLS_COMP_NULL,
388 &master_secret, &session_id);
390 vpn_progress(vpninfo, PRG_ERR,
391 _("Failed to set DTLS session parameters: %s\n"),
392 gnutls_strerror(err));
393 gnutls_deinit(dtls_ssl);
394 vpninfo->dtls_attempt_period = 0;
398 vpninfo->new_dtls_ssl = dtls_ssl;
402 int dtls_try_handshake(struct openconnect_info *vpninfo)
404 int err = gnutls_handshake(vpninfo->new_dtls_ssl);
407 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection (using GnuTLS)\n"));
409 if (vpninfo->dtls_ssl) {
410 /* We are replacing an old connection */
411 gnutls_deinit(vpninfo->dtls_ssl);
412 close(vpninfo->dtls_fd);
413 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
414 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
415 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
417 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
418 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
420 vpninfo->new_dtls_ssl = NULL;
421 vpninfo->new_dtls_fd = -1;
423 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
425 /* XXX: For OpenSSL we explicitly prevent retransmits here. */
429 if (err == GNUTLS_E_AGAIN) {
430 if (time(NULL) < vpninfo->new_dtls_started + 5)
432 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
435 vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %s\n"),
436 gnutls_strerror(err));
438 /* Kill the new (failed) connection... */
439 gnutls_deinit(vpninfo->new_dtls_ssl);
440 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
441 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
442 close(vpninfo->new_dtls_fd);
443 vpninfo->new_dtls_ssl = NULL;
444 vpninfo->new_dtls_fd = -1;
446 /* ... and kill the old one too. The only time there'll be a valid
447 existing session is when it was a rekey, and in that case it's
448 time for the old one to die. */
449 if (vpninfo->dtls_ssl) {
450 gnutls_deinit(vpninfo->dtls_ssl);
451 close(vpninfo->dtls_fd);
452 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
453 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
454 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
455 vpninfo->dtls_ssl = NULL;
456 vpninfo->dtls_fd = -1;
459 time(&vpninfo->new_dtls_started);
464 int connect_dtls_socket(struct openconnect_info *vpninfo)
468 if (!vpninfo->dtls_addr) {
469 vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n"));
470 vpninfo->dtls_attempt_period = 0;
474 if (!vpninfo->dtls_cipher) {
475 /* We probably didn't offer it any ciphers it liked */
476 vpn_progress(vpninfo, PRG_ERR, _("Server offered no DTLS cipher option\n"));
477 vpninfo->dtls_attempt_period = 0;
481 if (vpninfo->proxy) {
482 /* XXX: Theoretically, SOCKS5 proxies can do UDP too */
483 vpn_progress(vpninfo, PRG_ERR, _("No DTLS when connected via proxy\n"));
484 vpninfo->dtls_attempt_period = 0;
488 dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
490 perror(_("Open UDP socket for DTLS:"));
494 if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
495 perror(_("UDP (DTLS) connect:\n"));
500 fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
501 fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
503 ret = start_dtls_handshake(vpninfo, dtls_fd);
509 vpninfo->new_dtls_fd = dtls_fd;
510 if (vpninfo->select_nfds <= dtls_fd)
511 vpninfo->select_nfds = dtls_fd + 1;
513 FD_SET(dtls_fd, &vpninfo->select_rfds);
514 FD_SET(dtls_fd, &vpninfo->select_efds);
516 time(&vpninfo->new_dtls_started);
518 return dtls_try_handshake(vpninfo);
521 static int dtls_restart(struct openconnect_info *vpninfo)
523 if (vpninfo->dtls_ssl) {
524 #if defined (DTLS_OPENSSL)
525 SSL_free(vpninfo->dtls_ssl);
526 #elif defined (DTLS_GNUTLS)
527 gnutls_deinit(vpninfo->dtls_ssl);
529 close(vpninfo->dtls_fd);
530 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
531 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
532 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
533 vpninfo->dtls_ssl = NULL;
534 vpninfo->dtls_fd = -1;
537 return connect_dtls_socket(vpninfo);
541 int setup_dtls(struct openconnect_info *vpninfo)
543 struct vpn_option *dtls_opt = vpninfo->dtls_options;
546 #if defined (OPENCONNECT_GNUTLS) && defined (DTLS_OPENSSL)
547 /* If we're using GnuTLS for authentication but OpenSSL for DTLS,
548 we'll need to initialise OpenSSL now... */
551 SSL_load_error_strings ();
552 OpenSSL_add_all_algorithms ();
556 vpn_progress(vpninfo, PRG_TRACE,
557 _("DTLS option %s : %s\n"),
558 dtls_opt->option, dtls_opt->value);
560 if (!strcmp(dtls_opt->option + 7, "Port")) {
561 dtls_port = atol(dtls_opt->value);
562 } else if (!strcmp(dtls_opt->option + 7, "Keepalive")) {
563 vpninfo->dtls_times.keepalive = atol(dtls_opt->value);
564 } else if (!strcmp(dtls_opt->option + 7, "DPD")) {
565 int j = atol(dtls_opt->value);
566 if (j && (!vpninfo->dtls_times.dpd || j < vpninfo->dtls_times.dpd))
567 vpninfo->dtls_times.dpd = j;
568 } else if (!strcmp(dtls_opt->option + 7, "Rekey-Time")) {
569 vpninfo->dtls_times.rekey = atol(dtls_opt->value);
570 } else if (!strcmp(dtls_opt->option + 7, "CipherSuite")) {
571 vpninfo->dtls_cipher = strdup(dtls_opt->value);
574 dtls_opt = dtls_opt->next;
577 vpninfo->dtls_attempt_period = 0;
581 vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
582 if (!vpninfo->dtls_addr) {
583 vpninfo->dtls_attempt_period = 0;
586 memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
588 if (vpninfo->peer_addr->sa_family == AF_INET) {
589 struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
590 sin->sin_port = htons(dtls_port);
591 } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
592 struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
593 sin->sin6_port = htons(dtls_port);
595 vpn_progress(vpninfo, PRG_ERR,
596 _("Unknown protocol family %d. Cannot do DTLS\n"),
597 vpninfo->peer_addr->sa_family);
598 vpninfo->dtls_attempt_period = 0;
602 if (connect_dtls_socket(vpninfo))
605 vpn_progress(vpninfo, PRG_TRACE,
606 _("DTLS connected. DPD %d, Keepalive %d\n"),
607 vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
612 static struct pkt *dtls_pkt;
614 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
620 int len = vpninfo->mtu;
624 dtls_pkt = malloc(sizeof(struct pkt) + len);
626 vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n");
631 buf = dtls_pkt->data - 1;
632 len = DTLS_RECV(vpninfo->dtls_ssl, buf, len + 1);
636 vpn_progress(vpninfo, PRG_TRACE,
637 _("Received DTLS packet 0x%02x of %d bytes\n"),
640 vpninfo->dtls_times.last_rx = time(NULL);
644 dtls_pkt->len = len - 1;
645 queue_packet(&vpninfo->incoming_queue, dtls_pkt);
651 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));
653 /* FIXME: What if the packet doesn't get through? */
654 magic_pkt = AC_PKT_DPD_RESP;
655 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
656 vpn_progress(vpninfo, PRG_ERR,
657 _("Failed to send DPD response. Expect disconnect\n"));
660 case AC_PKT_DPD_RESP:
661 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
664 case AC_PKT_KEEPALIVE:
665 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
669 vpn_progress(vpninfo, PRG_ERR,
670 _("Unknown DTLS packet type %02x, len %d\n"),
673 /* Some versions of OpenSSL have bugs with receiving out-of-order
674 * packets. Not only do they wrongly decide to drop packets if
675 * two packets get swapped in transit, but they also _fail_ to
676 * drop the packet in non-blocking mode; instead they return
677 * the appropriate length of garbage. So don't abort... for now. */
680 vpninfo->quit_reason = "Unknown packet received";
687 switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
689 vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));
691 /* There ought to be a method of rekeying DTLS without tearing down
692 the CSTP session and restarting, but we don't (yet) know it */
693 if (cstp_reconnect(vpninfo)) {
694 vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
695 vpninfo->quit_reason = "CSTP reconnect failed";
699 if (dtls_restart(vpninfo)) {
700 vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
708 vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n"));
709 /* Fall back to SSL, and start a new DTLS connection */
710 dtls_restart(vpninfo);
714 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));
716 magic_pkt = AC_PKT_DPD_OUT;
717 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
718 vpn_progress(vpninfo, PRG_ERR,
719 _("Failed to send DPD request. Expect disconnect\n"));
721 /* last_dpd will just have been set */
722 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
727 /* No need to send an explicit keepalive
728 if we have real data to send */
729 if (vpninfo->outgoing_queue)
732 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));
734 magic_pkt = AC_PKT_KEEPALIVE;
735 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
736 vpn_progress(vpninfo, PRG_ERR,
737 _("Failed to send keepalive request. Expect disconnect\n"));
738 time(&vpninfo->dtls_times.last_tx);
746 /* Service outgoing packet queue */
747 while (vpninfo->outgoing_queue) {
748 struct pkt *this = vpninfo->outgoing_queue;
751 vpninfo->outgoing_queue = this->next;
752 vpninfo->outgoing_qlen--;
754 /* One byte of header */
755 this->hdr[7] = AC_PKT_DATA;
757 #if defined(DTLS_OPENSSL)
758 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
760 ret = SSL_get_error(vpninfo->dtls_ssl, ret);
762 /* If it's a real error, kill the DTLS connection and
763 requeue the packet to be sent over SSL */
764 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
765 vpn_progress(vpninfo, PRG_ERR,
766 _("DTLS got write error %d. Falling back to SSL\n"),
768 openconnect_report_ssl_errors(vpninfo);
769 dtls_restart(vpninfo);
770 vpninfo->outgoing_queue = this;
771 vpninfo->outgoing_qlen++;
775 #elif defined (DTLS_GNUTLS)
776 ret = gnutls_record_send(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
778 if (ret != GNUTLS_E_AGAIN) {
779 vpn_progress(vpninfo, PRG_ERR,
780 _("DTLS got write error: %s. Falling back to SSL\n"),
781 gnutls_strerror(ret));
782 dtls_restart(vpninfo);
783 vpninfo->outgoing_queue = this;
784 vpninfo->outgoing_qlen++;
789 time(&vpninfo->dtls_times.last_tx);
790 vpn_progress(vpninfo, PRG_TRACE,
791 _("Sent DTLS packet of %d bytes; DTLS send returned %d\n"),
798 #else /* !HAVE_DTLS */
799 #warning Your SSL library does not seem to support Cisco DTLS compatibility
800 int setup_dtls(struct openconnect_info *vpninfo)
802 vpn_progress(vpninfo, PRG_ERR,
803 _("Built against SSL library with no Cisco DTLS support\n"));