2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2008-2012 Intel Corporation.
5 * Copyright © 2008 Nick Andrew <nick@nick-andrew.net>
7 * Author: David Woodhouse <dwmw2@infradead.org>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * version 2.1, as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to:
21 * Free Software Foundation, Inc.
22 * 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301 USA
35 #include <netinet/tcp.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
39 #include <openssl/ssl.h>
40 #include <openssl/err.h>
42 #include "openconnect-internal.h"
45 * Data packets are encapsulated in the SSL stream as follows:
47 * 0000: Magic "STF\x1"
48 * 0004: Big-endian 16-bit length (not including 8-byte header)
49 * 0006: Byte packet type (see openconnect-internal.h)
53 static char data_hdr[8] = {
56 AC_PKT_DATA, /* Type */
60 static struct pkt keepalive_pkt = {
61 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_KEEPALIVE, 0 },
64 static struct pkt dpd_pkt = {
65 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_OUT, 0 },
68 static struct pkt dpd_resp_pkt = {
69 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 },
72 static int __attribute__ ((format (printf, 3, 4)))
73 buf_append(char *buf, int len, const char *fmt, ...)
75 int start = strlen(buf);
83 ret = vsnprintf(buf + start, len - start, fmt, args);
92 /* Calculate MTU to request. Old servers simply use the X-CSTP-MTU: header,
93 * which represents the tunnel MTU, while new servers do calculations on the
94 * X-CSTP-Base-MTU: header which represents the cleartext MTU between client
97 * If possible, the legacy MTU value should be the TCP MSS less 5 bytes of
98 * TLS and 8 bytes of CSTP overhead. We can get the MSS from either the
99 * TCP_INFO or TCP_MAXSEG sockopts.
101 * The base MTU comes from the TCP_INFO sockopt under Linux, but I don't know
102 * how to work it out on other systems. So leave it blank and do things the
103 * legacy way there. Contributions welcome...
105 * If we don't even have TCP_MAXSEG, then default to sending a legacy MTU of
106 * 1406 which is what we always used to do.
108 static void calculate_mtu(struct openconnect_info *vpninfo, int *base_mtu, int *mtu)
111 *base_mtu = vpninfo->basemtu;
114 if (!*mtu || !*base_mtu) {
116 socklen_t ti_size = sizeof(ti);
118 if (!getsockopt(vpninfo->ssl_fd, SOL_TCP, TCP_INFO,
120 vpn_progress(vpninfo, PRG_TRACE,
121 _("TCP_INFO rcv mss %d, snd mss %d, adv mss %d, pmtu %d\n"),
122 ti.tcpi_rcv_mss, ti.tcpi_snd_mss, ti.tcpi_advmss, ti.tcpi_pmtu);
123 if (!*base_mtu) *base_mtu = ti.tcpi_pmtu;
125 if (ti.tcpi_rcv_mss < ti.tcpi_snd_mss)
126 *mtu = ti.tcpi_rcv_mss - 13;
128 *mtu = ti.tcpi_snd_mss - 13;
136 socklen_t mss_size = sizeof(mss);
137 if (!getsockopt(vpninfo->ssl_fd, SOL_TCP, TCP_MAXSEG,
139 vpn_progress(vpninfo, PRG_TRACE, _("TCP_MAXSEG %d\n"), mss);
150 static int start_cstp_connection(struct openconnect_info *vpninfo)
154 int retried = 0, sessid_found = 0;
155 struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
156 struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
157 struct vpn_option *old_cstp_opts = vpninfo->cstp_options;
158 struct vpn_option *old_dtls_opts = vpninfo->dtls_options;
159 const char *old_addr = vpninfo->vpn_addr;
160 const char *old_netmask = vpninfo->vpn_netmask;
161 const char *old_addr6 = vpninfo->vpn_addr6;
162 const char *old_netmask6 = vpninfo->vpn_netmask6;
163 struct split_include *inc;
166 /* Clear old options which will be overwritten */
167 vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
168 vpninfo->vpn_addr6 = vpninfo->vpn_netmask6 = NULL;
169 vpninfo->cstp_options = vpninfo->dtls_options = NULL;
170 vpninfo->vpn_domain = vpninfo->vpn_proxy_pac = NULL;
171 vpninfo->banner = NULL;
174 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
176 for (inc = vpninfo->split_includes; inc; ) {
177 struct split_include *next = inc->next;
181 for (inc = vpninfo->split_excludes; inc; ) {
182 struct split_include *next = inc->next;
186 vpninfo->split_includes = vpninfo->split_excludes = NULL;
188 /* Create (new) random master key for DTLS connection, if needed */
189 if (vpninfo->dtls_times.last_rekey + vpninfo->dtls_times.rekey <
191 openconnect_random(vpninfo->dtls_secret, sizeof(vpninfo->dtls_secret))) {
192 fprintf(stderr, _("Failed to initialise DTLS secret\n"));
197 calculate_mtu(vpninfo, &base_mtu, &mtu);
200 buf_append(buf, sizeof(buf), "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
201 buf_append(buf, sizeof(buf), "Host: %s\r\n", vpninfo->hostname);
202 buf_append(buf, sizeof(buf), "User-Agent: %s\r\n", vpninfo->useragent);
203 buf_append(buf, sizeof(buf), "Cookie: webvpn=%s\r\n", vpninfo->cookie);
204 buf_append(buf, sizeof(buf), "X-CSTP-Version: 1\r\n");
205 buf_append(buf, sizeof(buf), "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
206 if (vpninfo->deflate && i < sizeof(buf))
207 buf_append(buf, sizeof(buf), "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
209 buf_append(buf, sizeof(buf), "X-CSTP-Base-MTU: %d\r\n", base_mtu);
210 buf_append(buf, sizeof(buf), "X-CSTP-MTU: %d\r\n", mtu);
211 buf_append(buf, sizeof(buf), "X-CSTP-Address-Type: %s\r\n",
212 vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4");
213 buf_append(buf, sizeof(buf), "X-DTLS-Master-Secret: ");
214 for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
215 buf_append(buf, sizeof(buf), "%02X", vpninfo->dtls_secret[i]);
216 buf_append(buf, sizeof(buf), "\r\nX-DTLS-CipherSuite: %s\r\n\r\n",
217 vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA");
219 openconnect_SSL_write(vpninfo, buf, strlen(buf));
221 if ((i = openconnect_SSL_gets(vpninfo, buf, 65536) < 0)) {
224 vpn_progress(vpninfo, PRG_ERR,
225 _("Error fetching HTTPS response\n"));
228 openconnect_close_https(vpninfo);
230 if (openconnect_open_https(vpninfo)) {
231 vpn_progress(vpninfo, PRG_ERR,
232 _("Failed to open HTTPS connection to %s\n"),
241 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
242 if (!strncmp(buf, "HTTP/1.1 503 ", 13)) {
243 /* "Service Unavailable. Why? */
244 const char *reason = "<unknown>";
245 while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
246 if (!strncmp(buf, "X-Reason: ", 10)) {
251 vpn_progress(vpninfo, PRG_ERR,
252 _("VPN service unavailable; reason: %s\n"),
256 vpn_progress(vpninfo, PRG_ERR,
257 _("Got inappropriate HTTP CONNECT response: %s\n"),
259 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
264 vpn_progress(vpninfo, PRG_INFO, _("Got CONNECT response: %s\n"), buf);
266 /* We may have advertised it, but we only do it if the server agrees */
267 vpninfo->deflate = 0;
269 while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
270 struct vpn_option *new_option;
276 colon = strchr(buf, ':');
285 if (strncmp(buf, "X-DTLS-", 7) &&
286 strncmp(buf, "X-CSTP-", 7))
289 new_option = malloc(sizeof(*new_option));
291 vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
294 new_option->option = strdup(buf);
295 new_option->value = strdup(colon);
296 new_option->next = NULL;
298 if (!new_option->option || !new_option->value) {
299 vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
303 vpn_progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
305 if (!strncmp(buf, "X-DTLS-", 7)) {
306 *next_dtls_option = new_option;
307 next_dtls_option = &new_option->next;
309 if (!strcmp(buf + 7, "Session-ID")) {
310 if (strlen(colon) != 64) {
311 vpn_progress(vpninfo, PRG_ERR,
312 _("X-DTLS-Session-ID not 64 characters; is: \"%s\"\n"),
314 vpninfo->dtls_attempt_period = 0;
317 for (i = 0; i < 64; i += 2)
318 vpninfo->dtls_session_id[i/2] = unhex(colon + i);
320 time(&vpninfo->dtls_times.last_rekey);
324 /* CSTP options... */
325 *next_cstp_option = new_option;
326 next_cstp_option = &new_option->next;
329 if (!strcmp(buf + 7, "Keepalive")) {
330 vpninfo->ssl_times.keepalive = atol(colon);
331 } else if (!strcmp(buf + 7, "DPD")) {
333 if (j && (!vpninfo->ssl_times.dpd || j < vpninfo->ssl_times.dpd))
334 vpninfo->ssl_times.dpd = j;
335 } else if (!strcmp(buf + 7, "Rekey-Time")) {
336 vpninfo->ssl_times.rekey = atol(colon);
337 } else if (!strcmp(buf + 7, "Content-Encoding")) {
338 if (!strcmp(colon, "deflate"))
339 vpninfo->deflate = 1;
341 vpn_progress(vpninfo, PRG_ERR,
342 _("Unknown CSTP-Content-Encoding %s\n"),
346 } else if (!strcmp(buf + 7, "MTU")) {
347 vpninfo->mtu = atol(colon);
348 } else if (!strcmp(buf + 7, "Address")) {
349 if (strchr(new_option->value, ':'))
350 vpninfo->vpn_addr6 = new_option->value;
352 vpninfo->vpn_addr = new_option->value;
353 } else if (!strcmp(buf + 7, "Netmask")) {
354 if (strchr(new_option->value, ':'))
355 vpninfo->vpn_netmask6 = new_option->value;
357 vpninfo->vpn_netmask = new_option->value;
358 } else if (!strcmp(buf + 7, "DNS")) {
360 for (j = 0; j < 3; j++) {
361 if (!vpninfo->vpn_dns[j]) {
362 vpninfo->vpn_dns[j] = new_option->value;
366 } else if (!strcmp(buf + 7, "NBNS")) {
368 for (j = 0; j < 3; j++) {
369 if (!vpninfo->vpn_nbns[j]) {
370 vpninfo->vpn_nbns[j] = new_option->value;
374 } else if (!strcmp(buf + 7, "Default-Domain")) {
375 vpninfo->vpn_domain = new_option->value;
376 } else if (!strcmp(buf + 7, "MSIE-Proxy-PAC-URL")) {
377 vpninfo->vpn_proxy_pac = new_option->value;
378 } else if (!strcmp(buf + 7, "Banner")) {
379 vpninfo->banner = new_option->value;
380 } else if (!strcmp(buf + 7, "Split-Include")) {
381 struct split_include *inc = malloc(sizeof(*inc));
384 inc->route = new_option->value;
385 inc->next = vpninfo->split_includes;
386 vpninfo->split_includes = inc;
387 } else if (!strcmp(buf + 7, "Split-Exclude")) {
388 struct split_include *exc = malloc(sizeof(*exc));
391 exc->route = new_option->value;
392 exc->next = vpninfo->split_excludes;
393 vpninfo->split_excludes = exc;
397 if (!vpninfo->vpn_addr && !vpninfo->vpn_addr6) {
398 vpn_progress(vpninfo, PRG_ERR,
399 _("No IP address received. Aborting\n"));
403 if (strcmp(old_addr, vpninfo->vpn_addr)) {
404 vpn_progress(vpninfo, PRG_ERR,
405 _("Reconnect gave different Legacy IP address (%s != %s)\n"),
406 vpninfo->vpn_addr, old_addr);
411 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
412 vpn_progress(vpninfo, PRG_ERR,
413 _("Reconnect gave different Legacy IP netmask (%s != %s)\n"),
414 vpninfo->vpn_netmask, old_netmask);
419 if (strcmp(old_addr6, vpninfo->vpn_addr6)) {
420 vpn_progress(vpninfo, PRG_ERR,
421 _("Reconnect gave different IPv6 address (%s != %s)\n"),
422 vpninfo->vpn_addr6, old_addr6);
427 if (strcmp(old_netmask6, vpninfo->vpn_netmask6)) {
428 vpn_progress(vpninfo, PRG_ERR,
429 _("Reconnect gave different IPv6 netmask (%s != %s)\n"),
430 vpninfo->vpn_netmask6, old_netmask6);
435 while (old_dtls_opts) {
436 struct vpn_option *tmp = old_dtls_opts;
437 old_dtls_opts = old_dtls_opts->next;
442 while (old_cstp_opts) {
443 struct vpn_option *tmp = old_cstp_opts;
444 old_cstp_opts = old_cstp_opts->next;
449 vpn_progress(vpninfo, PRG_INFO, _("CSTP connected. DPD %d, Keepalive %d\n"),
450 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
452 if (vpninfo->select_nfds <= vpninfo->ssl_fd)
453 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
455 FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
456 FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
459 vpninfo->dtls_attempt_period = 0;
461 vpninfo->ssl_times.last_rekey = vpninfo->ssl_times.last_rx =
462 vpninfo->ssl_times.last_tx = time(NULL);
467 int make_cstp_connection(struct openconnect_info *vpninfo)
471 ret = openconnect_open_https(vpninfo);
475 if (vpninfo->deflate) {
476 vpninfo->deflate_adler32 = 1;
477 vpninfo->inflate_adler32 = 1;
479 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
480 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
481 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
482 vpn_progress(vpninfo, PRG_ERR, _("Compression setup failed\n"));
483 vpninfo->deflate = 0;
486 if (!vpninfo->deflate_pkt) {
487 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
488 if (!vpninfo->deflate_pkt) {
489 vpn_progress(vpninfo, PRG_ERR,
490 _("Allocation of deflate buffer failed\n"));
491 inflateEnd(&vpninfo->inflate_strm);
492 deflateEnd(&vpninfo->deflate_strm);
493 vpninfo->deflate = 0;
495 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
496 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
497 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
502 return start_cstp_connection(vpninfo);
505 int cstp_reconnect(struct openconnect_info *vpninfo)
511 openconnect_close_https(vpninfo);
513 /* Requeue the original packet that was deflated */
514 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
515 vpninfo->current_ssl_pkt = NULL;
516 queue_packet(&vpninfo->outgoing_queue, vpninfo->pending_deflated_pkt);
517 vpninfo->pending_deflated_pkt = NULL;
519 if (vpninfo->deflate) {
520 inflateEnd(&vpninfo->inflate_strm);
521 deflateEnd(&vpninfo->deflate_strm);
523 timeout = vpninfo->reconnect_timeout;
524 interval = vpninfo->reconnect_interval;
526 while ((ret = make_cstp_connection(vpninfo))) {
529 vpn_progress(vpninfo, PRG_INFO,
530 _("sleep %ds, remaining timeout %ds\n"),
536 interval += vpninfo->reconnect_interval;
537 if (interval > RECONNECT_INTERVAL_MAX)
538 interval = RECONNECT_INTERVAL_MAX;
540 script_config_tun(vpninfo, "reconnect");
544 static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
545 unsigned char *buf, int len)
547 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
555 vpninfo->inflate_strm.next_in = buf;
556 vpninfo->inflate_strm.avail_in = len - 4;
558 vpninfo->inflate_strm.next_out = new->data;
559 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
560 vpninfo->inflate_strm.total_out = 0;
562 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
563 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
568 new->len = vpninfo->inflate_strm.total_out;
570 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
571 new->data, new->len);
573 pkt_sum = buf[len - 1] | (buf[len - 2] << 8) |
574 (buf[len - 3] << 16) | (buf[len - 4] << 24);
576 if (vpninfo->inflate_adler32 != pkt_sum) {
577 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
580 vpn_progress(vpninfo, PRG_TRACE,
581 _("Received compressed data packet of %ld bytes\n"),
582 (long)vpninfo->inflate_strm.total_out);
584 queue_packet(&vpninfo->incoming_queue, new);
588 #if defined (OPENCONNECT_OPENSSL)
589 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
593 len = SSL_read(vpninfo->https_ssl, buf, maxlen);
597 ret = SSL_get_error(vpninfo->https_ssl, len);
598 if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
599 vpn_progress(vpninfo, PRG_ERR,
600 _("SSL read error %d (server probably closed connection); reconnecting.\n"),
607 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
611 ret = SSL_write(vpninfo->https_ssl, buf, buflen);
615 ret = SSL_get_error(vpninfo->https_ssl, ret);
617 case SSL_ERROR_WANT_WRITE:
618 /* Waiting for the socket to become writable -- it's
619 probably stalled, and/or the buffers are full */
620 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
621 case SSL_ERROR_WANT_READ:
625 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
626 openconnect_report_ssl_errors(vpninfo);
630 #elif defined (OPENCONNECT_GNUTLS)
631 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
635 ret = gnutls_record_recv(vpninfo->https_sess, buf, maxlen);
639 if (ret != GNUTLS_E_AGAIN) {
640 vpn_progress(vpninfo, PRG_ERR,
641 _("SSL read error: %s; reconnecting.\n"),
642 gnutls_strerror(ret));
648 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
652 ret = gnutls_record_send(vpninfo->https_sess, buf, buflen);
656 if (ret == GNUTLS_E_AGAIN) {
657 if (gnutls_record_get_direction(vpninfo->https_sess)) {
658 /* Waiting for the socket to become writable -- it's
659 probably stalled, and/or the buffers are full */
660 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
664 vpn_progress(vpninfo, PRG_ERR, _("SSL send failed: %s\n"),
665 gnutls_strerror(ret));
670 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
672 unsigned char buf[16384];
676 /* FIXME: The poll() handling here is fairly simplistic. Actually,
677 if the SSL connection stalls it could return a WANT_WRITE error
678 on _either_ of the SSL_read() or SSL_write() calls. In that case,
679 we should probably remove POLLIN from the events we're looking for,
680 and add POLLOUT. As it is, though, it'll just chew CPU time in that
681 fairly unlikely situation, until the write backlog clears. */
682 while ( (len = cstp_read(vpninfo, buf, sizeof(buf))) > 0) {
685 if (buf[0] != 'S' || buf[1] != 'T' ||
686 buf[2] != 'F' || buf[3] != 1 || buf[7])
689 payload_len = (buf[4] << 8) + buf[5];
690 if (len != 8 + payload_len) {
691 vpn_progress(vpninfo, PRG_ERR,
692 _("Unexpected packet length. SSL_read returned %d but packet is\n"),
694 vpn_progress(vpninfo, PRG_ERR,
695 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
696 buf[0], buf[1], buf[2], buf[3],
697 buf[4], buf[5], buf[6], buf[7]);
700 vpninfo->ssl_times.last_rx = time(NULL);
703 vpn_progress(vpninfo, PRG_TRACE,
704 _("Got CSTP DPD request\n"));
705 vpninfo->owe_ssl_dpd_response = 1;
708 case AC_PKT_DPD_RESP:
709 vpn_progress(vpninfo, PRG_TRACE,
710 _("Got CSTP DPD response\n"));
713 case AC_PKT_KEEPALIVE:
714 vpn_progress(vpninfo, PRG_TRACE,
715 _("Got CSTP Keepalive\n"));
719 vpn_progress(vpninfo, PRG_TRACE,
720 _("Received uncompressed data packet of %d bytes\n"),
722 queue_new_packet(&vpninfo->incoming_queue, buf + 8,
727 case AC_PKT_DISCONN: {
729 for (i = 0; i < payload_len; i++) {
730 if (!isprint(buf[payload_len + 8 + i]))
731 buf[payload_len + 8 + i] = '.';
733 buf[payload_len + 8] = 0;
734 vpn_progress(vpninfo, PRG_ERR,
735 _("Received server disconnect: %02x '%s'\n"),
737 vpninfo->quit_reason = "Server request";
740 case AC_PKT_COMPRESSED:
741 if (!vpninfo->deflate) {
742 vpn_progress(vpninfo, PRG_ERR,
743 _("Compressed packet received in !deflate mode\n"));
746 inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
750 case AC_PKT_TERM_SERVER:
751 vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
752 vpninfo->quit_reason = "Server request";
757 vpn_progress(vpninfo, PRG_ERR,
758 _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
759 buf[0], buf[1], buf[2], buf[3],
760 buf[4], buf[5], buf[6], buf[7]);
761 vpninfo->quit_reason = "Unknown packet received";
768 /* If SSL_write() fails we are expected to try again. With exactly
769 the same data, at exactly the same location. So we keep the
770 packet we had before.... */
771 if (vpninfo->current_ssl_pkt) {
773 vpninfo->ssl_times.last_tx = time(NULL);
774 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
776 ret = cstp_write(vpninfo,
777 vpninfo->current_ssl_pkt->hdr,
778 vpninfo->current_ssl_pkt->len + 8);
782 else if (!ret && ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
785 if (ret != vpninfo->current_ssl_pkt->len + 8) {
786 vpn_progress(vpninfo, PRG_ERR,
787 _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
788 vpninfo->current_ssl_pkt->len + 8, ret);
789 vpninfo->quit_reason = "Internal error";
792 /* Don't free the 'special' packets */
793 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
794 free(vpninfo->pending_deflated_pkt);
795 else if (vpninfo->current_ssl_pkt != &dpd_pkt &&
796 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
797 vpninfo->current_ssl_pkt != &keepalive_pkt)
798 free(vpninfo->current_ssl_pkt);
800 vpninfo->current_ssl_pkt = NULL;
803 if (vpninfo->owe_ssl_dpd_response) {
804 vpninfo->owe_ssl_dpd_response = 0;
805 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
806 goto handle_outgoing;
809 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
811 /* Not that this will ever happen; we don't even process
812 the setting when we're asked for it. */
813 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
819 vpn_progress(vpninfo, PRG_ERR,
820 _("CSTP Dead Peer Detection detected dead peer!\n"));
822 if (cstp_reconnect(vpninfo)) {
823 vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
824 vpninfo->quit_reason = "CSTP reconnect failed";
827 /* I think we can leave DTLS to its own devices; when we reconnect
828 with the same master secret, we do seem to get the same sessid */
832 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
834 vpninfo->current_ssl_pkt = &dpd_pkt;
835 goto handle_outgoing;
838 /* No need to send an explicit keepalive
839 if we have real data to send */
840 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
843 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
845 vpninfo->current_ssl_pkt = &keepalive_pkt;
846 goto handle_outgoing;
852 /* Service outgoing packet queue, if no DTLS */
853 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
854 struct pkt *this = vpninfo->outgoing_queue;
855 vpninfo->outgoing_queue = this->next;
856 vpninfo->outgoing_qlen--;
858 if (vpninfo->deflate) {
859 unsigned char *adler;
862 vpninfo->deflate_strm.next_in = this->data;
863 vpninfo->deflate_strm.avail_in = this->len;
864 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
865 vpninfo->deflate_strm.avail_out = 2040;
866 vpninfo->deflate_strm.total_out = 0;
868 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
870 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
874 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
875 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
877 /* Add ongoing adler32 to tail of compressed packet */
878 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
879 this->data, this->len);
881 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
882 *(adler++) = vpninfo->deflate_adler32 >> 24;
883 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
884 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
885 *(adler) = vpninfo->deflate_adler32 & 0xff;
887 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
889 vpn_progress(vpninfo, PRG_TRACE,
890 _("Sending compressed data packet of %d bytes\n"),
893 vpninfo->pending_deflated_pkt = this;
894 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
897 memcpy(this->hdr, data_hdr, 8);
898 this->hdr[4] = this->len >> 8;
899 this->hdr[5] = this->len & 0xff;
901 vpn_progress(vpninfo, PRG_TRACE,
902 _("Sending uncompressed data packet of %d bytes\n"),
905 vpninfo->current_ssl_pkt = this;
907 goto handle_outgoing;
910 /* Work is not done if we just got rid of packets off the queue */
914 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
916 unsigned char *bye_pkt;
919 /* already lost connection? */
920 #if defined (OPENCONNECT_OPENSSL)
921 if (!vpninfo->https_ssl)
923 #elif defined (OPENCONNECT_GNUTLS)
924 if (!vpninfo->https_sess)
928 reason_len = strlen(reason);
929 bye_pkt = malloc(reason_len + 9);
933 memcpy(bye_pkt, data_hdr, 8);
934 memcpy(bye_pkt + 9, reason, reason_len);
936 bye_pkt[4] = (reason_len + 1) >> 8;
937 bye_pkt[5] = (reason_len + 1) & 0xff;
938 bye_pkt[6] = AC_PKT_DISCONN;
941 vpn_progress(vpninfo, PRG_INFO,
942 _("Send BYE packet: %s\n"), reason);
944 cstp_write(vpninfo, bye_pkt, reason_len + 9);