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>
31 #include <openssl/err.h>
32 #include <openssl/ssl.h>
36 #include "openconnect-internal.h"
38 #ifdef HAVE_DTLS1_STOP_TIMER
39 /* OpenSSL doesn't deliberately export this, but we need it to
40 workaround a DTLS bug in versions < 1.0.0e */
41 extern void dtls1_stop_timer (SSL *);
44 static unsigned char nybble(unsigned char n)
46 if (n >= '0' && n <= '9') return n - '0';
47 else if (n >= 'A' && n <= 'F') return n - ('A' - 10);
48 else if (n >= 'a' && n <= 'f') return n - ('a' - 10);
52 unsigned char unhex(const char *data)
54 return (nybble(data[0]) << 4) | nybble(data[1]);
61 * Useful for catching test cases, where we want everything to be
62 * reproducible. *NEVER* do this in the wild.
64 time_t time(time_t *t)
66 time_t x = 0x3ab2d948;
71 int RAND_pseudo_bytes(char *buf, int len)
73 memset(buf, 0x5a, len);
74 printf("FAKE PSEUDO RANDOM!\n");
78 int RAND_bytes(char *buf, int len)
80 static int foo = 0x5b;
81 printf("FAKE RANDOM!\n");
82 memset(buf, foo, len);
88 * The master-secret is generated randomly by the client. The server
89 * responds with a DTLS Session-ID. These, done over the HTTPS
90 * connection, are enough to 'resume' a DTLS session, bypassing all
91 * the normal setup of a normal DTLS connection.
93 * Cisco use a version of the protocol which predates RFC4347, but
94 * isn't quite the same as the pre-RFC version of the protocol which
95 * was in OpenSSL 0.9.8e -- it includes backports of some later
98 * The openssl/ directory of this source tree should contain both a
99 * small patch against OpenSSL 0.9.8e to make it support Cisco's
100 * snapshot of the protocol, and a larger patch against newer OpenSSL
101 * which gives us an option to use the old protocol again.
103 * Cisco's server also seems to respond to the official version of the
104 * protocol, with a change in the ChangeCipherSpec packet which implies
105 * that it does know the difference and isn't just repeating the version
106 * number seen in the ClientHello. But although I can make the handshake
107 * complete by hacking tls1_mac() to use the _old_ protocol version
108 * number when calculating the MAC, the server still seems to be ignoring
109 * my subsequent data packets. So we use the old protocol, which is what
110 * their clients use anyway.
113 #if defined (OPENCONNECT_OPENSSL)
114 #define DTLS_SEND SSL_write
115 #define DTLS_RECV SSL_read
116 static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
118 STACK_OF(SSL_CIPHER) *ciphers;
119 method_const SSL_METHOD *dtls_method;
120 SSL_CIPHER *dtls_cipher;
124 if (!vpninfo->dtls_ctx) {
125 dtls_method = DTLSv1_client_method();
126 vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
127 if (!vpninfo->dtls_ctx) {
128 vpn_progress(vpninfo, PRG_ERR,
129 _("Initialise DTLSv1 CTX failed\n"));
130 vpninfo->dtls_attempt_period = 0;
134 /* If we don't readahead, then we do short reads and throw
135 away the tail of data packets. */
136 SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
138 if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, vpninfo->dtls_cipher)) {
139 vpn_progress(vpninfo, PRG_ERR,
140 _("Set DTLS cipher list failed\n"));
141 SSL_CTX_free(vpninfo->dtls_ctx);
142 vpninfo->dtls_ctx = NULL;
143 vpninfo->dtls_attempt_period = 0;
148 if (!vpninfo->dtls_session) {
149 /* We're going to "resume" a session which never existed. Fake it... */
150 vpninfo->dtls_session = SSL_SESSION_new();
151 if (!vpninfo->dtls_session) {
152 vpn_progress(vpninfo, PRG_ERR,
153 _("Initialise DTLSv1 session failed\n"));
154 vpninfo->dtls_attempt_period = 0;
157 vpninfo->dtls_session->ssl_version = 0x0100; /* DTLS1_BAD_VER */
160 /* Do this every time; it may have changed due to a rekey */
161 vpninfo->dtls_session->master_key_length = sizeof(vpninfo->dtls_secret);
162 memcpy(vpninfo->dtls_session->master_key, vpninfo->dtls_secret,
163 sizeof(vpninfo->dtls_secret));
165 vpninfo->dtls_session->session_id_length = sizeof(vpninfo->dtls_session_id);
166 memcpy(vpninfo->dtls_session->session_id, vpninfo->dtls_session_id,
167 sizeof(vpninfo->dtls_session_id));
169 dtls_ssl = SSL_new(vpninfo->dtls_ctx);
170 SSL_set_connect_state(dtls_ssl);
172 ciphers = SSL_get_ciphers(dtls_ssl);
173 if (sk_SSL_CIPHER_num(ciphers) != 1) {
174 vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n"));
175 SSL_CTX_free(vpninfo->dtls_ctx);
177 SSL_SESSION_free(vpninfo->dtls_session);
178 vpninfo->dtls_ctx = NULL;
179 vpninfo->dtls_session = NULL;
180 vpninfo->dtls_attempt_period = 0;
183 dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);
185 /* Set the appropriate cipher on our session to be resumed */
186 vpninfo->dtls_session->cipher = dtls_cipher;
187 vpninfo->dtls_session->cipher_id = dtls_cipher->id;
189 /* Add the generated session to the SSL */
190 if (!SSL_set_session(dtls_ssl, vpninfo->dtls_session)) {
191 vpn_progress(vpninfo, PRG_ERR,
192 _("SSL_set_session() failed with old protocol version 0x%x\n"
193 "Are you using a version of OpenSSL older than 0.9.8m?\n"
194 "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
195 "Use the --no-dtls command line option to avoid this message\n"),
196 vpninfo->dtls_session->ssl_version);
197 vpninfo->dtls_attempt_period = 0;
201 dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
202 /* Set non-blocking */
203 BIO_set_nbio(dtls_bio, 1);
204 SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);
206 SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);
208 vpninfo->new_dtls_ssl = dtls_ssl;
213 int dtls_try_handshake(struct openconnect_info *vpninfo)
215 int ret = SSL_do_handshake(vpninfo->new_dtls_ssl);
218 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection\n"));
220 if (vpninfo->dtls_ssl) {
221 /* We are replacing an old connection */
222 SSL_free(vpninfo->dtls_ssl);
223 close(vpninfo->dtls_fd);
224 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
225 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
226 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
228 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
229 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
231 vpninfo->new_dtls_ssl = NULL;
232 vpninfo->new_dtls_fd = -1;
234 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
236 /* From about 8.4.1(11) onwards, the ASA seems to get
237 very unhappy if we resend ChangeCipherSpec messages
238 after the initial setup. This was "fixed" in OpenSSL
239 1.0.0e for RT#2505, but it's not clear if that was
240 the right fix. What happens if the original packet
241 *does* get lost? Surely we *wanted* the retransmits,
242 because without them the server will never be able
243 to decrypt anything we send?
244 Oh well, our retransmitted packets upset the server
245 because we don't get the Cisco-compatibility right
246 (this is one of the areas in which Cisco's DTLS differs
247 from the RFC4347 spec), and DPD should help us notice
248 if *nothing* is getting through. */
249 #if OPENSSL_VERSION_NUMBER >= 0x1000005fL
250 /* OpenSSL 1.0.0e or above doesn't resend anyway; do nothing.
251 However, if we were *built* against 1.0.0e or newer, but at
252 runtime we find that we are being run against an older
253 version, warn about it. */
254 if (SSLeay() < 0x1000005fL) {
255 vpn_progress(vpninfo, PRG_ERR,
256 _("Your OpenSSL is older than the one you built against, so DTLS may fail!"));
258 #elif defined (HAVE_DTLS1_STOP_TIMER)
260 * This works for any normal OpenSSL that supports
261 * Cisco DTLS compatibility (0.9.8m to 1.0.0d inclusive,
262 * and even later versions although it isn't needed there.
264 dtls1_stop_timer(vpninfo->dtls_ssl);
265 #elif defined (BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT)
267 * Debian restricts visibility of dtls1_stop_timer()
268 * so do it manually. This version also works on all
269 * sane versions of OpenSSL:
271 memset (&(vpninfo->dtls_ssl->d1->next_timeout), 0,
272 sizeof((vpninfo->dtls_ssl->d1->next_timeout)));
273 vpninfo->dtls_ssl->d1->timeout_duration = 1;
274 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
275 BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
276 &(vpninfo->dtls_ssl->d1->next_timeout));
277 #elif defined (BIO_CTRL_DGRAM_SET_TIMEOUT)
279 * OK, here it gets more fun... this shoul handle the case
280 * of older OpenSSL which has the Cisco DTLS compatibility
281 * backported, but *not* the fix for RT#1922.
283 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
284 BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
287 * And if they don't have any of the above, they probably
288 * don't have RT#1829 fixed either, but that's OK because
289 * that's the "fix" that *introduces* the timeout we're
290 * trying to disable. So do nothing...
296 ret = SSL_get_error(vpninfo->new_dtls_ssl, ret);
297 if (ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) {
298 if (time(NULL) < vpninfo->new_dtls_started + 5)
300 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
303 vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %d\n"), ret);
304 openconnect_report_ssl_errors(vpninfo);
306 /* Kill the new (failed) connection... */
307 SSL_free(vpninfo->new_dtls_ssl);
308 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
309 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
310 close(vpninfo->new_dtls_fd);
311 vpninfo->new_dtls_ssl = NULL;
312 vpninfo->new_dtls_fd = -1;
314 /* ... and kill the old one too. The only time there'll be a valid
315 existing session is when it was a rekey, and in that case it's
316 time for the old one to die. */
317 if (vpninfo->dtls_ssl) {
318 SSL_free(vpninfo->dtls_ssl);
319 close(vpninfo->dtls_fd);
320 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
321 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
322 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
323 vpninfo->dtls_ssl = NULL;
324 vpninfo->dtls_fd = -1;
327 time(&vpninfo->new_dtls_started);
331 #elif defined (OPENCONNECT_GNUTLS)
332 #define DTLS_SEND gnutls_record_send
333 #define DTLS_RECV gnutls_record_recv
334 static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
336 gnutls_session_t dtls_ssl;
337 gnutls_datum_t master_secret, session_id;
340 gnutls_init(&dtls_ssl, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
341 err = gnutls_priority_set_direct(dtls_ssl,
342 "NONE:+VERS-DTLS0.9:+COMP-NULL:+AES-128-CBC:+SHA1:+RSA:%COMPAT:%DISABLE_SAFE_RENEGOTIATION",
345 vpn_progress(vpninfo, PRG_ERR,
346 _("Failed to set DTLS priority: %s\n"),
347 gnutls_strerror(err));
348 gnutls_deinit(dtls_ssl);
349 vpninfo->dtls_attempt_period = 0;
352 gnutls_transport_set_ptr(dtls_ssl,
353 (gnutls_transport_ptr_t)(long) dtls_fd);
354 gnutls_record_disable_padding(dtls_ssl);
355 master_secret.data = vpninfo->dtls_secret;
356 master_secret.size = sizeof(vpninfo->dtls_secret);
357 session_id.data = vpninfo->dtls_session_id;
358 session_id.size = sizeof(vpninfo->dtls_session_id);
359 err = gnutls_session_set_master(dtls_ssl, GNUTLS_CLIENT, GNUTLS_DTLS0_9,
360 GNUTLS_KX_RSA, GNUTLS_CIPHER_AES_128_CBC,
361 GNUTLS_MAC_SHA1, GNUTLS_COMP_NULL,
362 &master_secret, &session_id);
364 vpn_progress(vpninfo, PRG_ERR,
365 _("Failed to set DTLS session parameters: %s\n"),
366 gnutls_strerror(err));
367 gnutls_deinit(dtls_ssl);
368 vpninfo->dtls_attempt_period = 0;
372 vpninfo->new_dtls_ssl = dtls_ssl;
376 int dtls_try_handshake(struct openconnect_info *vpninfo)
378 int err = gnutls_handshake(vpninfo->new_dtls_ssl);
381 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection\n"));
383 if (vpninfo->dtls_ssl) {
384 /* We are replacing an old connection */
385 gnutls_deinit(vpninfo->dtls_ssl);
386 close(vpninfo->dtls_fd);
387 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
388 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
389 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
391 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
392 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
394 vpninfo->new_dtls_ssl = NULL;
395 vpninfo->new_dtls_fd = -1;
397 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
399 /* XXX: For OpenSSL we explicitly prevent retransmits here. */
403 if (err == GNUTLS_E_AGAIN) {
404 if (time(NULL) < vpninfo->new_dtls_started + 5)
406 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
409 vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %s\n"),
410 gnutls_strerror(err));
412 /* Kill the new (failed) connection... */
413 gnutls_deinit(vpninfo->new_dtls_ssl);
414 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
415 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
416 close(vpninfo->new_dtls_fd);
417 vpninfo->new_dtls_ssl = NULL;
418 vpninfo->new_dtls_fd = -1;
420 /* ... and kill the old one too. The only time there'll be a valid
421 existing session is when it was a rekey, and in that case it's
422 time for the old one to die. */
423 if (vpninfo->dtls_ssl) {
424 gnutls_deinit(vpninfo->dtls_ssl);
425 close(vpninfo->dtls_fd);
426 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
427 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
428 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
429 vpninfo->dtls_ssl = NULL;
430 vpninfo->dtls_fd = -1;
433 time(&vpninfo->new_dtls_started);
438 int connect_dtls_socket(struct openconnect_info *vpninfo)
442 if (!vpninfo->dtls_addr) {
443 vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n"));
444 vpninfo->dtls_attempt_period = 0;
448 if (!vpninfo->dtls_cipher) {
449 /* We probably didn't offer it any ciphers it liked */
450 vpn_progress(vpninfo, PRG_ERR, _("Server offered no DTLS cipher option\n"));
451 vpninfo->dtls_attempt_period = 0;
455 if (vpninfo->proxy) {
456 /* XXX: Theoretically, SOCKS5 proxies can do UDP too */
457 vpn_progress(vpninfo, PRG_ERR, _("No DTLS when connected via proxy\n"));
458 vpninfo->dtls_attempt_period = 0;
462 dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
464 perror(_("Open UDP socket for DTLS:"));
468 if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
469 perror(_("UDP (DTLS) connect:\n"));
474 fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
475 fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
477 ret = start_dtls_handshake(vpninfo, dtls_fd);
483 vpninfo->new_dtls_fd = dtls_fd;
484 if (vpninfo->select_nfds <= dtls_fd)
485 vpninfo->select_nfds = dtls_fd + 1;
487 FD_SET(dtls_fd, &vpninfo->select_rfds);
488 FD_SET(dtls_fd, &vpninfo->select_efds);
490 time(&vpninfo->new_dtls_started);
492 return dtls_try_handshake(vpninfo);
495 static int dtls_restart(struct openconnect_info *vpninfo)
497 if (vpninfo->dtls_ssl) {
498 #if defined (OPENCONNECT_OPENSSL)
499 SSL_free(vpninfo->dtls_ssl);
500 #elif defined (OPENCONNECT_GNUTLS)
501 gnutls_deinit(vpninfo->dtls_ssl);
503 close(vpninfo->dtls_fd);
504 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
505 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
506 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
507 vpninfo->dtls_ssl = NULL;
508 vpninfo->dtls_fd = -1;
511 return connect_dtls_socket(vpninfo);
515 int setup_dtls(struct openconnect_info *vpninfo)
517 struct vpn_option *dtls_opt = vpninfo->dtls_options;
521 vpn_progress(vpninfo, PRG_TRACE,
522 _("DTLS option %s : %s\n"),
523 dtls_opt->option, dtls_opt->value);
525 if (!strcmp(dtls_opt->option + 7, "Port")) {
526 dtls_port = atol(dtls_opt->value);
527 } else if (!strcmp(dtls_opt->option + 7, "Keepalive")) {
528 vpninfo->dtls_times.keepalive = atol(dtls_opt->value);
529 } else if (!strcmp(dtls_opt->option + 7, "DPD")) {
530 int j = atol(dtls_opt->value);
531 if (j && (!vpninfo->dtls_times.dpd || j < vpninfo->dtls_times.dpd))
532 vpninfo->dtls_times.dpd = j;
533 } else if (!strcmp(dtls_opt->option + 7, "Rekey-Time")) {
534 vpninfo->dtls_times.rekey = atol(dtls_opt->value);
535 } else if (!strcmp(dtls_opt->option + 7, "CipherSuite")) {
536 vpninfo->dtls_cipher = strdup(dtls_opt->value);
539 dtls_opt = dtls_opt->next;
542 vpninfo->dtls_attempt_period = 0;
546 vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
547 if (!vpninfo->dtls_addr) {
548 vpninfo->dtls_attempt_period = 0;
551 memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
553 if (vpninfo->peer_addr->sa_family == AF_INET) {
554 struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
555 sin->sin_port = htons(dtls_port);
556 } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
557 struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
558 sin->sin6_port = htons(dtls_port);
560 vpn_progress(vpninfo, PRG_ERR,
561 _("Unknown protocol family %d. Cannot do DTLS\n"),
562 vpninfo->peer_addr->sa_family);
563 vpninfo->dtls_attempt_period = 0;
567 if (connect_dtls_socket(vpninfo))
570 vpn_progress(vpninfo, PRG_TRACE,
571 _("DTLS connected. DPD %d, Keepalive %d\n"),
572 vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
577 static struct pkt *dtls_pkt;
579 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
585 int len = vpninfo->mtu;
589 dtls_pkt = malloc(sizeof(struct pkt) + len);
591 vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n");
596 buf = dtls_pkt->data - 1;
597 len = DTLS_RECV(vpninfo->dtls_ssl, buf, len + 1);
601 vpn_progress(vpninfo, PRG_TRACE,
602 _("Received DTLS packet 0x%02x of %d bytes\n"),
605 vpninfo->dtls_times.last_rx = time(NULL);
609 dtls_pkt->len = len - 1;
610 queue_packet(&vpninfo->incoming_queue, dtls_pkt);
616 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));
618 /* FIXME: What if the packet doesn't get through? */
619 magic_pkt = AC_PKT_DPD_RESP;
620 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
621 vpn_progress(vpninfo, PRG_ERR,
622 _("Failed to send DPD response. Expect disconnect\n"));
625 case AC_PKT_DPD_RESP:
626 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
629 case AC_PKT_KEEPALIVE:
630 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
634 vpn_progress(vpninfo, PRG_ERR,
635 _("Unknown DTLS packet type %02x, len %d\n"),
638 /* Some versions of OpenSSL have bugs with receiving out-of-order
639 * packets. Not only do they wrongly decide to drop packets if
640 * two packets get swapped in transit, but they also _fail_ to
641 * drop the packet in non-blocking mode; instead they return
642 * the appropriate length of garbage. So don't abort... for now. */
645 vpninfo->quit_reason = "Unknown packet received";
652 switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
654 vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));
656 /* There ought to be a method of rekeying DTLS without tearing down
657 the CSTP session and restarting, but we don't (yet) know it */
658 if (cstp_reconnect(vpninfo)) {
659 vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
660 vpninfo->quit_reason = "CSTP reconnect failed";
664 if (dtls_restart(vpninfo)) {
665 vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
673 vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n"));
674 /* Fall back to SSL, and start a new DTLS connection */
675 dtls_restart(vpninfo);
679 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));
681 magic_pkt = AC_PKT_DPD_OUT;
682 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
683 vpn_progress(vpninfo, PRG_ERR,
684 _("Failed to send DPD request. Expect disconnect\n"));
686 /* last_dpd will just have been set */
687 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
692 /* No need to send an explicit keepalive
693 if we have real data to send */
694 if (vpninfo->outgoing_queue)
697 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));
699 magic_pkt = AC_PKT_KEEPALIVE;
700 if (DTLS_SEND(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
701 vpn_progress(vpninfo, PRG_ERR,
702 _("Failed to send keepalive request. Expect disconnect\n"));
703 time(&vpninfo->dtls_times.last_tx);
711 /* Service outgoing packet queue */
712 while (vpninfo->outgoing_queue) {
713 struct pkt *this = vpninfo->outgoing_queue;
716 vpninfo->outgoing_queue = this->next;
717 vpninfo->outgoing_qlen--;
719 /* One byte of header */
720 this->hdr[7] = AC_PKT_DATA;
722 #if defined(OPENCONNECT_OPENSSL)
723 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
725 ret = SSL_get_error(vpninfo->dtls_ssl, ret);
727 /* If it's a real error, kill the DTLS connection and
728 requeue the packet to be sent over SSL */
729 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
730 vpn_progress(vpninfo, PRG_ERR,
731 _("DTLS got write error %d. Falling back to SSL\n"),
733 openconnect_report_ssl_errors(vpninfo);
734 dtls_restart(vpninfo);
735 vpninfo->outgoing_queue = this;
736 vpninfo->outgoing_qlen++;
740 #elif defined (OPENCONNECT_GNUTLS)
741 ret = gnutls_record_send(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
743 if (ret != GNUTLS_E_AGAIN) {
744 vpn_progress(vpninfo, PRG_ERR,
745 _("DTLS got write error: %s. Falling back to SSL\n"),
746 gnutls_strerror(ret));
747 dtls_restart(vpninfo);
748 vpninfo->outgoing_queue = this;
749 vpninfo->outgoing_qlen++;
754 time(&vpninfo->dtls_times.last_tx);
755 vpn_progress(vpninfo, PRG_TRACE,
756 _("Sent DTLS packet of %d bytes; DTLS send returned %d\n"),
763 #else /* !HAVE_DTLS */
764 #warning Your SSL library does not seem to support Cisco DTLS compatibility
765 int setup_dtls(struct openconnect_info *vpninfo)
767 vpn_progress(vpninfo, PRG_ERR,
768 _("Built against SSL library with no Cisco DTLS support\n"));