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 static unsigned char nybble(unsigned char n)
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);
47 unsigned char unhex(const char *data)
49 return (nybble(data[0]) << 4) | nybble(data[1]);
56 * Useful for catching test cases, where we want everything to be
57 * reproducible. *NEVER* do this in the wild.
59 time_t time(time_t *t)
61 time_t x = 0x3ab2d948;
66 int RAND_pseudo_bytes(char *buf, int len)
68 memset(buf, 0x5a, len);
69 printf("FAKE PSEUDO RANDOM!\n");
73 int RAND_bytes(char *buf, int len)
75 static int foo = 0x5b;
76 printf("FAKE RANDOM!\n");
77 memset(buf, foo, len);
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.
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
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.
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.
108 #if defined (DTLS_OPENSSL)
109 #define DTLS_SEND SSL_write
110 #define DTLS_RECV SSL_read
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 *);
118 static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
120 STACK_OF(SSL_CIPHER) *ciphers;
121 method_const SSL_METHOD *dtls_method;
122 SSL_CIPHER *dtls_cipher;
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;
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);
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;
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;
160 vpninfo->dtls_session->ssl_version = 0x0100; /* DTLS1_BAD_VER */
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));
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));
172 dtls_ssl = SSL_new(vpninfo->dtls_ctx);
173 SSL_set_connect_state(dtls_ssl);
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);
180 SSL_SESSION_free(vpninfo->dtls_session);
181 vpninfo->dtls_ctx = NULL;
182 vpninfo->dtls_session = NULL;
183 vpninfo->dtls_attempt_period = 0;
186 dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);
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;
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;
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);
209 SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);
211 vpninfo->new_dtls_ssl = dtls_ssl;
216 int dtls_try_handshake(struct openconnect_info *vpninfo)
218 int ret = SSL_do_handshake(vpninfo->new_dtls_ssl);
221 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection (using OpenSSL)\n"));
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);
231 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
232 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
234 vpninfo->new_dtls_ssl = NULL;
235 vpninfo->new_dtls_fd = -1;
237 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
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!"));
261 #elif defined (HAVE_DTLS1_STOP_TIMER)
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.
267 dtls1_stop_timer(vpninfo->dtls_ssl);
268 #elif defined (BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT)
270 * Debian restricts visibility of dtls1_stop_timer()
271 * so do it manually. This version also works on all
272 * sane versions of OpenSSL:
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)
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.
286 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
287 BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
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...
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)
303 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
306 vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %d\n"), ret);
307 openconnect_report_ssl_errors(vpninfo);
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;
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;
330 time(&vpninfo->new_dtls_started);
334 #elif defined (DTLS_GNUTLS)
335 #include <gnutls/dtls.h>
339 gnutls_cipher_algorithm_t cipher;
340 gnutls_mac_algorithm_t mac;
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" },
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)
353 gnutls_session_t dtls_ssl;
354 gnutls_datum_t master_secret, session_id;
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))
362 vpn_progress(vpninfo, PRG_ERR, _("Unknown DTLS parameters for requested CipherSuite '%s'\n"),
363 vpninfo->dtls_cipher);
364 vpninfo->dtls_attempt_period = 0;
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,
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;
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);
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;
401 vpninfo->new_dtls_ssl = dtls_ssl;
405 int dtls_try_handshake(struct openconnect_info *vpninfo)
407 int err = gnutls_handshake(vpninfo->new_dtls_ssl);
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);
415 vpn_progress(vpninfo, PRG_ERR,
416 _("Failed to set DTLS MTU: %s\n"),
417 gnutls_strerror(err));
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 */);
433 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection (using GnuTLS)\n"));
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);
443 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
444 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
446 vpninfo->new_dtls_ssl = NULL;
447 vpninfo->new_dtls_fd = -1;
449 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
451 /* XXX: For OpenSSL we explicitly prevent retransmits here. */
455 if (err == GNUTLS_E_AGAIN) {
456 if (time(NULL) < vpninfo->new_dtls_started + 5)
458 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
461 vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %s\n"),
462 gnutls_strerror(err));
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;
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;
487 time(&vpninfo->new_dtls_started);
492 int connect_dtls_socket(struct openconnect_info *vpninfo)
496 if (!vpninfo->dtls_addr) {
497 vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n"));
498 vpninfo->dtls_attempt_period = 0;
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;
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;
516 dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
518 perror(_("Open UDP socket for DTLS:"));
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));
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);
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;
547 if (bind(dtls_fd, (struct sockaddr *)&dtls_bind_addr, dtls_bind_addrlen)) {
548 perror(_("Bind UDP socket for DTLS"));
553 if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
554 perror(_("UDP (DTLS) connect:\n"));
559 fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
560 fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
562 ret = start_dtls_handshake(vpninfo, dtls_fd);
568 vpninfo->new_dtls_fd = dtls_fd;
569 if (vpninfo->select_nfds <= dtls_fd)
570 vpninfo->select_nfds = dtls_fd + 1;
572 FD_SET(dtls_fd, &vpninfo->select_rfds);
573 FD_SET(dtls_fd, &vpninfo->select_efds);
575 time(&vpninfo->new_dtls_started);
577 return dtls_try_handshake(vpninfo);
580 static int dtls_restart(struct openconnect_info *vpninfo)
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);
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;
596 return connect_dtls_socket(vpninfo);
600 int setup_dtls(struct openconnect_info *vpninfo)
602 struct vpn_option *dtls_opt = vpninfo->dtls_options;
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... */
610 SSL_load_error_strings ();
611 OpenSSL_add_all_algorithms ();
615 vpn_progress(vpninfo, PRG_TRACE,
616 _("DTLS option %s : %s\n"),
617 dtls_opt->option, dtls_opt->value);
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);
633 dtls_opt = dtls_opt->next;
636 vpninfo->dtls_attempt_period = 0;
640 vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
641 if (!vpninfo->dtls_addr) {
642 vpninfo->dtls_attempt_period = 0;
645 memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
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);
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;
661 if (connect_dtls_socket(vpninfo))
664 vpn_progress(vpninfo, PRG_TRACE,
665 _("DTLS connected. DPD %d, Keepalive %d\n"),
666 vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
671 static struct pkt *dtls_pkt;
673 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
679 int len = vpninfo->actual_mtu;
683 dtls_pkt = malloc(sizeof(struct pkt) + len);
685 vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n");
690 buf = dtls_pkt->data - 1;
691 len = DTLS_RECV(vpninfo->dtls_ssl, buf, len + 1);
695 vpn_progress(vpninfo, PRG_TRACE,
696 _("Received DTLS packet 0x%02x of %d bytes\n"),
699 vpninfo->dtls_times.last_rx = time(NULL);
703 dtls_pkt->len = len - 1;
704 queue_packet(&vpninfo->incoming_queue, dtls_pkt);
710 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));
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"));
719 case AC_PKT_DPD_RESP:
720 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
723 case AC_PKT_KEEPALIVE:
724 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
728 vpn_progress(vpninfo, PRG_ERR,
729 _("Unknown DTLS packet type %02x, len %d\n"),
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. */
739 vpninfo->quit_reason = "Unknown packet received";
746 switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
748 vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));
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";
758 if (dtls_restart(vpninfo)) {
759 vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
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);
773 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));
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"));
780 /* last_dpd will just have been set */
781 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
786 /* No need to send an explicit keepalive
787 if we have real data to send */
788 if (vpninfo->outgoing_queue)
791 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));
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);
805 /* Service outgoing packet queue */
806 while (vpninfo->outgoing_queue) {
807 struct pkt *this = vpninfo->outgoing_queue;
810 vpninfo->outgoing_queue = this->next;
811 vpninfo->outgoing_qlen--;
813 /* One byte of header */
814 this->hdr[7] = AC_PKT_DATA;
816 #if defined(DTLS_OPENSSL)
817 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
819 ret = SSL_get_error(vpninfo->dtls_ssl, ret);
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"),
827 openconnect_report_ssl_errors(vpninfo);
828 dtls_restart(vpninfo);
829 vpninfo->outgoing_queue = this;
830 vpninfo->outgoing_qlen++;
834 #elif defined (DTLS_GNUTLS)
835 ret = gnutls_record_send(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
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++;
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"),
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)
861 vpn_progress(vpninfo, PRG_ERR,
862 _("Built against SSL library with no Cisco DTLS support\n"));