Split out OpenSSL_specific start_dtls_handshake() function
[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 <openssl/err.h>
32 #include <openssl/ssl.h>
33 #include <fcntl.h>
34 #include <string.h>
35
36 #include "openconnect-internal.h"
37
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 *);
42 #endif
43
44 static unsigned char nybble(unsigned char n)
45 {
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);
49         return 0;
50 }
51
52 unsigned char unhex(const char *data)
53 {
54         return (nybble(data[0]) << 4) | nybble(data[1]);
55 }
56
57 #if defined (OPENCONNECT_OPENSSL) && defined (SSL_OP_CISCO_ANYCONNECT)
58 #if 0
59 /*
60  * Useful for catching test cases, where we want everything to be
61  * reproducible.  *NEVER* do this in the wild.
62  */
63 time_t time(time_t *t)
64 {
65         time_t x = 0x3ab2d948;
66         if (t) *t = x;
67         return x;
68 }
69
70 int RAND_pseudo_bytes(char *buf, int len)
71 {
72         memset(buf, 0x5a, len);
73         printf("FAKE PSEUDO RANDOM!\n");
74         return 1;
75
76 }
77 int RAND_bytes(char *buf, int len)
78 {
79         static int foo = 0x5b;
80         printf("FAKE RANDOM!\n");
81         memset(buf, foo, len);
82         return 1;
83 }
84 #endif
85
86 /*
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.
91  *
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
95  * OpenSSL patches.
96  *
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.
101  *
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.
110  */
111
112 static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
113 {
114         STACK_OF(SSL_CIPHER) *ciphers;
115         method_const SSL_METHOD *dtls_method;
116         SSL_CIPHER *dtls_cipher;
117         SSL *dtls_ssl;
118         BIO *dtls_bio;
119
120         if (!vpninfo->dtls_ctx) {
121                 dtls_method = DTLSv1_client_method();
122                 vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
123                 if (!vpninfo->dtls_ctx) {
124                         vpn_progress(vpninfo, PRG_ERR,
125                                      _("Initialise DTLSv1 CTX failed\n"));
126                         vpninfo->dtls_attempt_period = 0;
127                         return -EINVAL;
128                 }
129
130                 /* If we don't readahead, then we do short reads and throw
131                    away the tail of data packets. */
132                 SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);
133
134                 if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, vpninfo->dtls_cipher)) {
135                         vpn_progress(vpninfo, PRG_ERR,
136                                      _("Set DTLS cipher list failed\n"));
137                         SSL_CTX_free(vpninfo->dtls_ctx);
138                         vpninfo->dtls_ctx = NULL;
139                         vpninfo->dtls_attempt_period = 0;
140                         return -EINVAL;
141                 }
142         }
143
144         if (!vpninfo->dtls_session) {
145                 /* We're going to "resume" a session which never existed. Fake it... */
146                 vpninfo->dtls_session = SSL_SESSION_new();
147                 if (!vpninfo->dtls_session) {
148                         vpn_progress(vpninfo, PRG_ERR,
149                                      _("Initialise DTLSv1 session failed\n"));
150                         vpninfo->dtls_attempt_period = 0;
151                         return -EINVAL;
152                 }
153                 vpninfo->dtls_session->ssl_version = 0x0100; /* DTLS1_BAD_VER */
154         }
155
156         /* Do this every time; it may have changed due to a rekey */
157         vpninfo->dtls_session->master_key_length = sizeof(vpninfo->dtls_secret);
158         memcpy(vpninfo->dtls_session->master_key, vpninfo->dtls_secret,
159                sizeof(vpninfo->dtls_secret));
160
161         vpninfo->dtls_session->session_id_length = sizeof(vpninfo->dtls_session_id);
162         memcpy(vpninfo->dtls_session->session_id, vpninfo->dtls_session_id,
163                sizeof(vpninfo->dtls_session_id));
164
165         dtls_ssl = SSL_new(vpninfo->dtls_ctx);
166         SSL_set_connect_state(dtls_ssl);
167
168         ciphers = SSL_get_ciphers(dtls_ssl);
169         if (sk_SSL_CIPHER_num(ciphers) != 1) {
170                 vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n"));
171                 SSL_CTX_free(vpninfo->dtls_ctx);
172                 SSL_free(dtls_ssl);
173                 SSL_SESSION_free(vpninfo->dtls_session);
174                 vpninfo->dtls_ctx = NULL;
175                 vpninfo->dtls_session = NULL;
176                 vpninfo->dtls_attempt_period = 0;
177                 return -EINVAL;
178         }
179         dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);
180
181         /* Set the appropriate cipher on our session to be resumed */
182         vpninfo->dtls_session->cipher = dtls_cipher;
183         vpninfo->dtls_session->cipher_id = dtls_cipher->id;
184
185         /* Add the generated session to the SSL */
186         if (!SSL_set_session(dtls_ssl, vpninfo->dtls_session)) {
187                 vpn_progress(vpninfo, PRG_ERR,
188                              _("SSL_set_session() failed with old protocol version 0x%x\n"
189                                "Are you using a version of OpenSSL older than 0.9.8m?\n"
190                                "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
191                                "Use the --no-dtls command line option to avoid this message\n"),
192                              vpninfo->dtls_session->ssl_version);
193                 vpninfo->dtls_attempt_period = 0;
194                 return -EINVAL;
195         }
196
197         dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
198         /* Set non-blocking */
199         BIO_set_nbio(dtls_bio, 1);
200         SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);
201
202         SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);
203
204         vpninfo->new_dtls_ssl = dtls_ssl;
205
206         return 0;
207 }
208
209 int dtls_try_handshake(struct openconnect_info *vpninfo)
210 {
211         int ret = SSL_do_handshake(vpninfo->new_dtls_ssl);
212
213         if (ret == 1) {
214                 vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection\n"));
215
216                 if (vpninfo->dtls_ssl) {
217                         /* We are replacing an old connection */
218                         SSL_free(vpninfo->dtls_ssl);
219                         close(vpninfo->dtls_fd);
220                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
221                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
222                         FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
223                 }
224                 vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
225                 vpninfo->dtls_fd = vpninfo->new_dtls_fd;
226
227                 vpninfo->new_dtls_ssl = NULL;
228                 vpninfo->new_dtls_fd = -1;
229
230                 vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);
231
232                 /* From about 8.4.1(11) onwards, the ASA seems to get
233                    very unhappy if we resend ChangeCipherSpec messages
234                    after the initial setup. This was "fixed" in OpenSSL
235                    1.0.0e for RT#2505, but it's not clear if that was
236                    the right fix. What happens if the original packet
237                    *does* get lost? Surely we *wanted* the retransmits,
238                    because without them the server will never be able
239                    to decrypt anything we send?
240                    Oh well, our retransmitted packets upset the server
241                    because we don't get the Cisco-compatibility right
242                    (this is one of the areas in which Cisco's DTLS differs
243                    from the RFC4347 spec), and DPD should help us notice
244                    if *nothing* is getting through. */
245 #if OPENSSL_VERSION_NUMBER >= 0x1000005fL
246                 /* OpenSSL 1.0.0e or above doesn't resend anyway; do nothing.
247                    However, if we were *built* against 1.0.0e or newer, but at
248                    runtime we find that we are being run against an older 
249                    version, warn about it. */
250                 if (SSLeay() < 0x1000005fL) {
251                         vpn_progress(vpninfo, PRG_ERR,
252                                      _("Your OpenSSL is older than the one you built against, so DTLS may fail!"));
253                 }
254 #elif defined (HAVE_DTLS1_STOP_TIMER)
255                 /*
256                  * This works for any normal OpenSSL that supports
257                  * Cisco DTLS compatibility (0.9.8m to 1.0.0d inclusive,
258                  * and even later versions although it isn't needed there.
259                  */
260                 dtls1_stop_timer(vpninfo->dtls_ssl);
261 #elif defined (BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT)
262                 /*
263                  * Debian restricts visibility of dtls1_stop_timer()
264                  * so do it manually. This version also works on all
265                  * sane versions of OpenSSL:
266                  */
267                 memset (&(vpninfo->dtls_ssl->d1->next_timeout), 0,
268                         sizeof((vpninfo->dtls_ssl->d1->next_timeout)));
269                 vpninfo->dtls_ssl->d1->timeout_duration = 1;
270                 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
271                          BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
272                          &(vpninfo->dtls_ssl->d1->next_timeout));
273 #elif defined (BIO_CTRL_DGRAM_SET_TIMEOUT)
274                 /*
275                  * OK, here it gets more fun... this shoul handle the case
276                  * of older OpenSSL which has the Cisco DTLS compatibility
277                  * backported, but *not* the fix for RT#1922.
278                  */
279                 BIO_ctrl(SSL_get_rbio(vpninfo->dtls_ssl),
280                          BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
281 #else
282                 /*
283                  * And if they don't have any of the above, they probably
284                  * don't have RT#1829 fixed either, but that's OK because
285                  * that's the "fix" that *introduces* the timeout we're
286                  * trying to disable. So do nothing...
287                  */
288 #endif
289                 return 0;
290         }
291
292         ret = SSL_get_error(vpninfo->new_dtls_ssl, ret);
293         if (ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) {
294                 if (time(NULL) < vpninfo->new_dtls_started + 5)
295                         return 0;
296                 vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
297         }
298
299         vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %d\n"), ret);
300         openconnect_report_ssl_errors(vpninfo);
301
302         /* Kill the new (failed) connection... */
303         SSL_free(vpninfo->new_dtls_ssl);
304         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
305         FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
306         close(vpninfo->new_dtls_fd);
307         vpninfo->new_dtls_ssl = NULL;
308         vpninfo->new_dtls_fd = -1;
309
310         /* ... and kill the old one too. The only time there'll be a valid
311            existing session is when it was a rekey, and in that case it's
312            time for the old one to die. */
313         if (vpninfo->dtls_ssl) {
314                 SSL_free(vpninfo->dtls_ssl);
315                 close(vpninfo->dtls_fd);
316                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
317                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
318                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
319                 vpninfo->dtls_ssl = NULL;
320                 vpninfo->dtls_fd = -1;
321         }
322
323         time(&vpninfo->new_dtls_started);
324         return -EINVAL;
325 }
326
327 int connect_dtls_socket(struct openconnect_info *vpninfo)
328 {
329         int dtls_fd, ret;
330
331         if (!vpninfo->dtls_addr) {
332                 vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n"));
333                 vpninfo->dtls_attempt_period = 0;
334                 return -EINVAL;
335         }
336
337         if (!vpninfo->dtls_cipher) {
338                 /* We probably didn't offer it any ciphers it liked */
339                 vpn_progress(vpninfo, PRG_ERR, _("Server offered no DTLS cipher option\n"));
340                 vpninfo->dtls_attempt_period = 0;
341                 return -EINVAL;
342         }
343
344         if (vpninfo->proxy) {
345                 /* XXX: Theoretically, SOCKS5 proxies can do UDP too */
346                 vpn_progress(vpninfo, PRG_ERR, _("No DTLS when connected via proxy\n"));
347                 vpninfo->dtls_attempt_period = 0;
348                 return -EINVAL;
349         }
350
351         dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
352         if (dtls_fd < 0) {
353                 perror(_("Open UDP socket for DTLS:"));
354                 return -EINVAL;
355         }
356
357         if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
358                 perror(_("UDP (DTLS) connect:\n"));
359                 close(dtls_fd);
360                 return -EINVAL;
361         }
362
363         fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
364         fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
365
366         ret = start_dtls_handshake(vpninfo, dtls_fd);
367         if (ret) {
368                 close(dtls_fd);
369                 return ret;
370         }
371
372         vpninfo->new_dtls_fd = dtls_fd;
373         if (vpninfo->select_nfds <= dtls_fd)
374                 vpninfo->select_nfds = dtls_fd + 1;
375
376         FD_SET(dtls_fd, &vpninfo->select_rfds);
377         FD_SET(dtls_fd, &vpninfo->select_efds);
378
379         time(&vpninfo->new_dtls_started);
380
381         return dtls_try_handshake(vpninfo);
382 }
383
384 static int dtls_restart(struct openconnect_info *vpninfo)
385 {
386         if (vpninfo->dtls_ssl) {
387                 SSL_free(vpninfo->dtls_ssl);
388                 close(vpninfo->dtls_fd);
389                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
390                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
391                 FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
392                 vpninfo->dtls_ssl = NULL;
393                 vpninfo->dtls_fd = -1;
394         }
395
396         return connect_dtls_socket(vpninfo);
397 }
398
399
400 int setup_dtls(struct openconnect_info *vpninfo)
401 {
402         struct vpn_option *dtls_opt = vpninfo->dtls_options;
403         int dtls_port = 0;
404
405         while (dtls_opt) {
406                 vpn_progress(vpninfo, PRG_TRACE,
407                              _("DTLS option %s : %s\n"),
408                              dtls_opt->option, dtls_opt->value);
409
410                 if (!strcmp(dtls_opt->option + 7, "Port")) {
411                         dtls_port = atol(dtls_opt->value);
412                 } else if (!strcmp(dtls_opt->option + 7, "Keepalive")) {
413                         vpninfo->dtls_times.keepalive = atol(dtls_opt->value);
414                 } else if (!strcmp(dtls_opt->option + 7, "DPD")) {
415                         int j = atol(dtls_opt->value);
416                         if (j && (!vpninfo->dtls_times.dpd || j < vpninfo->dtls_times.dpd))
417                                 vpninfo->dtls_times.dpd = j;
418                 } else if (!strcmp(dtls_opt->option + 7, "Rekey-Time")) {
419                         vpninfo->dtls_times.rekey = atol(dtls_opt->value);
420                 } else if (!strcmp(dtls_opt->option + 7, "CipherSuite")) {
421                         vpninfo->dtls_cipher = strdup(dtls_opt->value);
422                 }
423
424                 dtls_opt = dtls_opt->next;
425         }
426         if (!dtls_port) {
427                 vpninfo->dtls_attempt_period = 0;
428                 return -EINVAL;
429         }
430
431         vpninfo->dtls_addr = malloc(vpninfo->peer_addrlen);
432         if (!vpninfo->dtls_addr) {
433                 vpninfo->dtls_attempt_period = 0;
434                 return -ENOMEM;
435         }
436         memcpy(vpninfo->dtls_addr, vpninfo->peer_addr, vpninfo->peer_addrlen);
437
438         if (vpninfo->peer_addr->sa_family == AF_INET) {
439                 struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
440                 sin->sin_port = htons(dtls_port);
441         } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
442                 struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
443                 sin->sin6_port = htons(dtls_port);
444         } else {
445                 vpn_progress(vpninfo, PRG_ERR,
446                              _("Unknown protocol family %d. Cannot do DTLS\n"),
447                              vpninfo->peer_addr->sa_family);
448                 vpninfo->dtls_attempt_period = 0;
449                 return -EINVAL;
450         }
451
452         if (connect_dtls_socket(vpninfo))
453                 return -EINVAL;
454
455         vpn_progress(vpninfo, PRG_TRACE,
456                      _("DTLS connected. DPD %d, Keepalive %d\n"),
457                      vpninfo->dtls_times.dpd, vpninfo->dtls_times.keepalive);
458
459         return 0;
460 }
461
462 static struct pkt *dtls_pkt;
463
464 int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
465 {
466         int work_done = 0;
467         char magic_pkt;
468
469         while (1) {
470                 int len = vpninfo->mtu;
471                 unsigned char *buf;
472
473                 if (!dtls_pkt) {
474                         dtls_pkt = malloc(sizeof(struct pkt) + len);
475                         if (!dtls_pkt) {
476                                 vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n");
477                                 break;
478                         }
479                 }
480
481                 buf = dtls_pkt->data - 1;
482                 len = SSL_read(vpninfo->dtls_ssl, buf, len + 1);
483                 if (len <= 0)
484                         break;
485
486                 vpn_progress(vpninfo, PRG_TRACE,
487                              _("Received DTLS packet 0x%02x of %d bytes\n"),
488                              buf[0], len);
489
490                 vpninfo->dtls_times.last_rx = time(NULL);
491
492                 switch(buf[0]) {
493                 case AC_PKT_DATA:
494                         dtls_pkt->len = len - 1;
495                         queue_packet(&vpninfo->incoming_queue, dtls_pkt);
496                         dtls_pkt = NULL;
497                         work_done = 1;
498                         break;
499
500                 case AC_PKT_DPD_OUT:
501                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));
502
503                         /* FIXME: What if the packet doesn't get through? */
504                         magic_pkt = AC_PKT_DPD_RESP;
505                         if (SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
506                                 vpn_progress(vpninfo, PRG_ERR,
507                                              _("Failed to send DPD response. Expect disconnect\n"));
508                         continue;
509
510                 case AC_PKT_DPD_RESP:
511                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
512                         break;
513
514                 case AC_PKT_KEEPALIVE:
515                         vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
516                         break;
517
518                 default:
519                         vpn_progress(vpninfo, PRG_ERR,
520                                      _("Unknown DTLS packet type %02x, len %d\n"),
521                                      buf[0], len);
522                         if (1) {
523                                 /* Some versions of OpenSSL have bugs with receiving out-of-order
524                                  * packets. Not only do they wrongly decide to drop packets if
525                                  * two packets get swapped in transit, but they also _fail_ to
526                                  * drop the packet in non-blocking mode; instead they return
527                                  * the appropriate length of garbage. So don't abort... for now. */
528                                 break;
529                         } else {
530                                 vpninfo->quit_reason = "Unknown packet received";
531                                 return 1;
532                         }
533
534                 }
535         }
536
537         switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
538         case KA_REKEY:
539                 vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));
540
541                 /* There ought to be a method of rekeying DTLS without tearing down
542                    the CSTP session and restarting, but we don't (yet) know it */
543                 if (cstp_reconnect(vpninfo)) {
544                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
545                         vpninfo->quit_reason = "CSTP reconnect failed";
546                         return 1;
547                 }
548
549                 if (dtls_restart(vpninfo)) {
550                         vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
551                         return 1;
552                 }
553                 work_done = 1;
554                 break;
555
556
557         case KA_DPD_DEAD:
558                 vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n"));
559                 /* Fall back to SSL, and start a new DTLS connection */
560                 dtls_restart(vpninfo);
561                 return 1;
562
563         case KA_DPD:
564                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));
565
566                 magic_pkt = AC_PKT_DPD_OUT;
567                 SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
568                 /* last_dpd will just have been set */
569                 vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
570                 work_done = 1;
571                 break;
572
573         case KA_KEEPALIVE:
574                 /* No need to send an explicit keepalive
575                    if we have real data to send */
576                 if (vpninfo->outgoing_queue)
577                         break;
578
579                 vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));
580
581                 magic_pkt = AC_PKT_KEEPALIVE;
582                 SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
583                 time(&vpninfo->dtls_times.last_tx);
584                 work_done = 1;
585                 break;
586
587         case KA_NONE:
588                 ;
589         }
590
591         /* Service outgoing packet queue */
592         while (vpninfo->outgoing_queue) {
593                 struct pkt *this = vpninfo->outgoing_queue;
594                 int ret;
595
596                 vpninfo->outgoing_queue = this->next;
597                 vpninfo->outgoing_qlen--;
598
599                 /* One byte of header */
600                 this->hdr[7] = AC_PKT_DATA;
601
602                 ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
603                 if (ret <= 0) {
604                         ret = SSL_get_error(vpninfo->dtls_ssl, ret);
605
606                         /* If it's a real error, kill the DTLS connection and
607                            requeue the packet to be sent over SSL */
608                         if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
609                                 vpn_progress(vpninfo, PRG_ERR,
610                                              _("DTLS got write error %d. Falling back to SSL\n"),
611                                              ret);
612                                 openconnect_report_ssl_errors(vpninfo);
613                                 dtls_restart(vpninfo);
614                                 vpninfo->outgoing_queue = this;
615                                 vpninfo->outgoing_qlen++;
616                         }
617                         return 1;
618                 }
619                 time(&vpninfo->dtls_times.last_tx);
620                 vpn_progress(vpninfo, PRG_TRACE,
621                              _("Sent DTLS packet of %d bytes; SSL_write() returned %d\n"),
622                              this->len, ret);
623                 free(this);
624         }
625
626         return work_done;
627 }
628 #else /* No DTLS support in OpenSSL */
629 #warning Your version of OpenSSL does not seem to support Cisco DTLS compatibility
630  int setup_dtls(struct openconnect_info *vpninfo)
631 {
632         vpn_progress(vpninfo, PRG_ERR,
633                      _("Built against OpenSSL with no Cisco DTLS support\n"));
634         return -EINVAL;
635 }
636 #endif
637