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]);
57 #if defined (OPENCONNECT_OPENSSL) && defined (SSL_OP_CISCO_ANYCONNECT)
60 * Useful for catching test cases, where we want everything to be
61 * reproducible. *NEVER* do this in the wild.
63 time_t time(time_t *t)
65 time_t x = 0x3ab2d948;
70 int RAND_pseudo_bytes(char *buf, int len)
72 memset(buf, 0x5a, len);
73 printf("FAKE PSEUDO RANDOM!\n");
77 int RAND_bytes(char *buf, int len)
79 static int foo = 0x5b;
80 printf("FAKE RANDOM!\n");
81 memset(buf, foo, len);
87 * The master-secret is generated randomly by the client. The server
88 * responds with a DTLS Session-ID. These, done over the HTTPS
89 * connection, are enough to 'resume' a DTLS session, bypassing all
90 * the normal setup of a normal DTLS connection.
92 * Cisco use a version of the protocol which predates RFC4347, but
93 * isn't quite the same as the pre-RFC version of the protocol which
94 * was in OpenSSL 0.9.8e -- it includes backports of some later
97 * The openssl/ directory of this source tree should contain both a
98 * small patch against OpenSSL 0.9.8e to make it support Cisco's
99 * snapshot of the protocol, and a larger patch against newer OpenSSL
100 * which gives us an option to use the old protocol again.
102 * Cisco's server also seems to respond to the official version of the
103 * protocol, with a change in the ChangeCipherSpec packet which implies
104 * that it does know the difference and isn't just repeating the version
105 * number seen in the ClientHello. But although I can make the handshake
106 * complete by hacking tls1_mac() to use the _old_ protocol version
107 * number when calculating the MAC, the server still seems to be ignoring
108 * my subsequent data packets. So we use the old protocol, which is what
109 * their clients use anyway.
112 int connect_dtls_socket(struct openconnect_info *vpninfo)
114 STACK_OF(SSL_CIPHER) *ciphers;
115 method_const SSL_METHOD *dtls_method;
116 SSL_CIPHER *dtls_cipher;
121 if (!vpninfo->dtls_addr) {
122 vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n"));
123 vpninfo->dtls_attempt_period = 0;
127 if (!vpninfo->dtls_cipher) {
128 /* We probably didn't offer it any ciphers it liked */
129 vpn_progress(vpninfo, PRG_ERR, _("Server offered no DTLS cipher option\n"));
130 vpninfo->dtls_attempt_period = 0;
134 if (vpninfo->proxy) {
135 /* XXX: Theoretically, SOCKS5 proxies can do UDP too */
136 vpn_progress(vpninfo, PRG_ERR, _("No DTLS when connected via proxy\n"));
137 vpninfo->dtls_attempt_period = 0;
141 dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
143 perror(_("Open UDP socket for DTLS:"));
147 if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
148 perror(_("UDP (DTLS) connect:\n"));
153 fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
155 if (!vpninfo->dtls_ctx) {
156 dtls_method = DTLSv1_client_method();
157 vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
158 if (!vpninfo->dtls_ctx) {
159 vpn_progress(vpninfo, PRG_ERR,
160 _("Initialise DTLSv1 CTX failed\n"));
161 vpninfo->dtls_attempt_period = 0;
165 /* If we don't readahead, then we do short reads and throw
166 away the tail of data packets. */
167 SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
169 if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, vpninfo->dtls_cipher)) {
170 vpn_progress(vpninfo, PRG_ERR,
171 _("Set DTLS cipher list failed\n"));
172 SSL_CTX_free(vpninfo->dtls_ctx);
173 vpninfo->dtls_ctx = NULL;
174 vpninfo->dtls_attempt_period = 0;
179 if (!vpninfo->dtls_session) {
180 /* We're going to "resume" a session which never existed. Fake it... */
181 vpninfo->dtls_session = SSL_SESSION_new();
182 if (!vpninfo->dtls_session) {
183 vpn_progress(vpninfo, PRG_ERR,
184 _("Initialise DTLSv1 session failed\n"));
185 vpninfo->dtls_attempt_period = 0;
188 vpninfo->dtls_session->ssl_version = 0x0100; /* DTLS1_BAD_VER */
191 /* Do this every time; it may have changed due to a rekey */
192 vpninfo->dtls_session->master_key_length = sizeof(vpninfo->dtls_secret);
193 memcpy(vpninfo->dtls_session->master_key, vpninfo->dtls_secret,
194 sizeof(vpninfo->dtls_secret));
196 vpninfo->dtls_session->session_id_length = sizeof(vpninfo->dtls_session_id);
197 memcpy(vpninfo->dtls_session->session_id, vpninfo->dtls_session_id,
198 sizeof(vpninfo->dtls_session_id));
200 dtls_ssl = SSL_new(vpninfo->dtls_ctx);
201 SSL_set_connect_state(dtls_ssl);
203 ciphers = SSL_get_ciphers(dtls_ssl);
204 if (sk_SSL_CIPHER_num(ciphers) != 1) {
205 vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n"));
206 SSL_CTX_free(vpninfo->dtls_ctx);
208 SSL_SESSION_free(vpninfo->dtls_session);
209 vpninfo->dtls_ctx = NULL;
210 vpninfo->dtls_session = NULL;
211 vpninfo->dtls_attempt_period = 0;
214 dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);
216 /* Set the appropriate cipher on our session to be resumed */
217 vpninfo->dtls_session->cipher = dtls_cipher;
218 vpninfo->dtls_session->cipher_id = dtls_cipher->id;
220 /* Add the generated session to the SSL */
221 if (!SSL_set_session(dtls_ssl, vpninfo->dtls_session)) {
222 vpn_progress(vpninfo, PRG_ERR,
223 _("SSL_set_session() failed with old protocol version 0x%x\n"
224 "Are you using a version of OpenSSL older than 0.9.8m?\n"
225 "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
226 "Use the --no-dtls command line option to avoid this message\n"),
227 vpninfo->dtls_session->ssl_version);
228 vpninfo->dtls_attempt_period = 0;
233 fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
235 dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
236 /* Set non-blocking */
237 BIO_set_nbio(dtls_bio, 1);
238 SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);
240 SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);
242 vpninfo->new_dtls_fd = dtls_fd;
243 vpninfo->new_dtls_ssl = dtls_ssl;
245 if (vpninfo->select_nfds <= dtls_fd)
246 vpninfo->select_nfds = dtls_fd + 1;
248 FD_SET(dtls_fd, &vpninfo->select_rfds);
249 FD_SET(dtls_fd, &vpninfo->select_efds);
251 time(&vpninfo->new_dtls_started);
252 return dtls_try_handshake(vpninfo);
255 int dtls_try_handshake(struct openconnect_info *vpninfo)
257 int ret = SSL_do_handshake(vpninfo->new_dtls_ssl);
260 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection\n"));
262 if (vpninfo->dtls_ssl) {
263 /* We are replacing an old connection */
264 SSL_free(vpninfo->dtls_ssl);
265 close(vpninfo->dtls_fd);
266 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
267 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
268 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
270 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
271 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
273 vpninfo->new_dtls_ssl = NULL;
274 vpninfo->new_dtls_fd = -1;
276 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
278 /* From about 8.4.1(11) onwards, the ASA seems to get
279 very unhappy if we resend ChangeCipherSpec messages
280 after the initial setup. This was "fixed" in OpenSSL
281 1.0.0e for RT#2505, but it's not clear if that was
282 the right fix. What happens if the original packet
283 *does* get lost? Surely we *wanted* the retransmits,
284 because without them the server will never be able
285 to decrypt anything we send?
286 Oh well, our retransmitted packets upset the server
287 because we don't get the Cisco-compatibility right
288 (this is one of the areas in which Cisco's DTLS differs
289 from the RFC4347 spec), and DPD should help us notice
290 if *nothing* is getting through. */
291 #if OPENSSL_VERSION_NUMBER >= 0x1000005fL
292 /* OpenSSL 1.0.0e or above doesn't resend anyway; do nothing.
293 However, if we were *built* against 1.0.0e or newer, but at
294 runtime we find that we are being run against an older
295 version, warn about it. */
296 if (SSLeay() < 0x1000005fL) {
297 vpn_progress(vpninfo, PRG_ERR,
298 _("Your OpenSSL is older than the one you built against, so DTLS may fail!"));
300 #elif defined (HAVE_DTLS1_STOP_TIMER)
302 * This works for any normal OpenSSL that supports
303 * Cisco DTLS compatibility (0.9.8m to 1.0.0d inclusive,
304 * and even later versions although it isn't needed there.
306 dtls1_stop_timer(vpninfo->dtls_ssl);
307 #elif defined (BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT)
309 * Debian restricts visibility of dtls1_stop_timer()
310 * so do it manually. This version also works on all
311 * sane versions of OpenSSL:
313 memset (&(vpninfo->dtls_ssl->d1->next_timeout), 0,
314 sizeof((vpninfo->dtls_ssl->d1->next_timeout)));
315 vpninfo->dtls_ssl->d1->timeout_duration = 1;
316 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
317 BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
318 &(vpninfo->dtls_ssl->d1->next_timeout));
319 #elif defined (BIO_CTRL_DGRAM_SET_TIMEOUT)
321 * OK, here it gets more fun... this shoul handle the case
322 * of older OpenSSL which has the Cisco DTLS compatibility
323 * backported, but *not* the fix for RT#1922.
325 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
326 BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
329 * And if they don't have any of the above, they probably
330 * don't have RT#1829 fixed either, but that's OK because
331 * that's the "fix" that *introduces* the timeout we're
332 * trying to disable. So do nothing...
338 ret = SSL_get_error(vpninfo->new_dtls_ssl, ret);
339 if (ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) {
340 if (time(NULL) < vpninfo->new_dtls_started + 5)
342 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
345 vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %d\n"), ret);
346 openconnect_report_ssl_errors(vpninfo);
348 /* Kill the new (failed) connection... */
349 SSL_free(vpninfo->new_dtls_ssl);
350 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
351 FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
352 close(vpninfo->new_dtls_fd);
353 vpninfo->new_dtls_ssl = NULL;
354 vpninfo->new_dtls_fd = -1;
356 /* ... and kill the old one too. The only time there'll be a valid
357 existing session is when it was a rekey, and in that case it's
358 time for the old one to die. */
359 if (vpninfo->dtls_ssl) {
360 SSL_free(vpninfo->dtls_ssl);
361 close(vpninfo->dtls_fd);
362 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
363 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
364 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
365 vpninfo->dtls_ssl = NULL;
366 vpninfo->dtls_fd = -1;
369 time(&vpninfo->new_dtls_started);
373 static int dtls_restart(struct openconnect_info *vpninfo)
375 if (vpninfo->dtls_ssl) {
376 SSL_free(vpninfo->dtls_ssl);
377 close(vpninfo->dtls_fd);
378 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
379 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
380 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
381 vpninfo->dtls_ssl = NULL;
382 vpninfo->dtls_fd = -1;
385 return connect_dtls_socket(vpninfo);
389 int setup_dtls(struct openconnect_info *vpninfo)
391 struct vpn_option *dtls_opt = vpninfo->dtls_options;
395 vpn_progress(vpninfo, PRG_TRACE,
396 _("DTLS option %s : %s\n"),
397 dtls_opt->option, dtls_opt->value);
399 if (!strcmp(dtls_opt->option + 7, "Port")) {
400 dtls_port = atol(dtls_opt->value);
401 } else if (!strcmp(dtls_opt->option + 7, "Keepalive")) {
402 vpninfo->dtls_times.keepalive = atol(dtls_opt->value);
403 } else if (!strcmp(dtls_opt->option + 7, "DPD")) {
404 int j = atol(dtls_opt->value);
405 if (j && (!vpninfo->dtls_times.dpd || j < vpninfo->dtls_times.dpd))
406 vpninfo->dtls_times.dpd = j;
407 } else if (!strcmp(dtls_opt->option + 7, "Rekey-Time")) {
408 vpninfo->dtls_times.rekey = atol(dtls_opt->value);
409 } else if (!strcmp(dtls_opt->option + 7, "CipherSuite")) {
410 vpninfo->dtls_cipher = strdup(dtls_opt->value);
413 dtls_opt = dtls_opt->next;
416 vpninfo->dtls_attempt_period = 0;
420 vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
421 if (!vpninfo->dtls_addr) {
422 vpninfo->dtls_attempt_period = 0;
425 memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
427 if (vpninfo->peer_addr->sa_family == AF_INET) {
428 struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
429 sin->sin_port = htons(dtls_port);
430 } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
431 struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
432 sin->sin6_port = htons(dtls_port);
434 vpn_progress(vpninfo, PRG_ERR,
435 _("Unknown protocol family %d. Cannot do DTLS\n"),
436 vpninfo->peer_addr->sa_family);
437 vpninfo->dtls_attempt_period = 0;
441 if (connect_dtls_socket(vpninfo))
444 vpn_progress(vpninfo, PRG_TRACE,
445 _("DTLS connected. DPD %d, Keepalive %d\n"),
446 vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
451 static struct pkt *dtls_pkt;
453 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
459 int len = vpninfo->mtu;
463 dtls_pkt = malloc(sizeof(struct pkt) + len);
465 vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n");
470 buf = dtls_pkt->data - 1;
471 len = SSL_read(vpninfo->dtls_ssl, buf, len + 1);
475 vpn_progress(vpninfo, PRG_TRACE,
476 _("Received DTLS packet 0x%02x of %d bytes\n"),
479 vpninfo->dtls_times.last_rx = time(NULL);
483 dtls_pkt->len = len - 1;
484 queue_packet(&vpninfo->incoming_queue, dtls_pkt);
490 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));
492 /* FIXME: What if the packet doesn't get through? */
493 magic_pkt = AC_PKT_DPD_RESP;
494 if (SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
495 vpn_progress(vpninfo, PRG_ERR,
496 _("Failed to send DPD response. Expect disconnect\n"));
499 case AC_PKT_DPD_RESP:
500 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
503 case AC_PKT_KEEPALIVE:
504 vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
508 vpn_progress(vpninfo, PRG_ERR,
509 _("Unknown DTLS packet type %02x, len %d\n"),
512 /* Some versions of OpenSSL have bugs with receiving out-of-order
513 * packets. Not only do they wrongly decide to drop packets if
514 * two packets get swapped in transit, but they also _fail_ to
515 * drop the packet in non-blocking mode; instead they return
516 * the appropriate length of garbage. So don't abort... for now. */
519 vpninfo->quit_reason = "Unknown packet received";
526 switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
528 vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));
530 /* There ought to be a method of rekeying DTLS without tearing down
531 the CSTP session and restarting, but we don't (yet) know it */
532 if (cstp_reconnect(vpninfo)) {
533 vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
534 vpninfo->quit_reason = "CSTP reconnect failed";
538 if (dtls_restart(vpninfo)) {
539 vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
547 vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n"));
548 /* Fall back to SSL, and start a new DTLS connection */
549 dtls_restart(vpninfo);
553 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));
555 magic_pkt = AC_PKT_DPD_OUT;
556 SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
557 /* last_dpd will just have been set */
558 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
563 /* No need to send an explicit keepalive
564 if we have real data to send */
565 if (vpninfo->outgoing_queue)
568 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));
570 magic_pkt = AC_PKT_KEEPALIVE;
571 SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
572 time(&vpninfo->dtls_times.last_tx);
580 /* Service outgoing packet queue */
581 while (vpninfo->outgoing_queue) {
582 struct pkt *this = vpninfo->outgoing_queue;
585 vpninfo->outgoing_queue = this->next;
586 vpninfo->outgoing_qlen--;
588 /* One byte of header */
589 this->hdr[7] = AC_PKT_DATA;
591 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
593 ret = SSL_get_error(vpninfo->dtls_ssl, ret);
595 /* If it's a real error, kill the DTLS connection and
596 requeue the packet to be sent over SSL */
597 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
598 vpn_progress(vpninfo, PRG_ERR,
599 _("DTLS got write error %d. Falling back to SSL\n"),
601 openconnect_report_ssl_errors(vpninfo);
602 dtls_restart(vpninfo);
603 vpninfo->outgoing_queue = this;
604 vpninfo->outgoing_qlen++;
608 time(&vpninfo->dtls_times.last_tx);
609 vpn_progress(vpninfo, PRG_TRACE,
610 _("Sent DTLS packet of %d bytes; SSL_write() returned %d\n"),
617 #else /* No DTLS support in OpenSSL */
618 #warning Your version of OpenSSL does not seem to support Cisco DTLS compatibility
619 int setup_dtls(struct openconnect_info *vpninfo)
621 vpn_progress(vpninfo, PRG_ERR,
622 _("Built against OpenSSL with no Cisco DTLS support\n"));