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 for (inc = vpninfo->split_dns; inc; ) {
187 struct split_include *next = inc->next;
191 vpninfo->split_dns = vpninfo->split_includes = vpninfo->split_excludes = NULL;
193 /* Create (new) random master key for DTLS connection, if needed */
194 if (vpninfo->dtls_times.last_rekey + vpninfo->dtls_times.rekey <
196 openconnect_random(vpninfo->dtls_secret, sizeof(vpninfo->dtls_secret))) {
197 fprintf(stderr, _("Failed to initialise DTLS secret\n"));
202 calculate_mtu(vpninfo, &base_mtu, &mtu);
205 buf_append(buf, sizeof(buf), "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
206 buf_append(buf, sizeof(buf), "Host: %s\r\n", vpninfo->hostname);
207 buf_append(buf, sizeof(buf), "User-Agent: %s\r\n", vpninfo->useragent);
208 buf_append(buf, sizeof(buf), "Cookie: webvpn=%s\r\n", vpninfo->cookie);
209 buf_append(buf, sizeof(buf), "X-CSTP-Version: 1\r\n");
210 buf_append(buf, sizeof(buf), "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
211 if (vpninfo->deflate && i < sizeof(buf))
212 buf_append(buf, sizeof(buf), "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
214 buf_append(buf, sizeof(buf), "X-CSTP-Base-MTU: %d\r\n", base_mtu);
215 buf_append(buf, sizeof(buf), "X-CSTP-MTU: %d\r\n", mtu);
216 buf_append(buf, sizeof(buf), "X-CSTP-Address-Type: %s\r\n",
217 vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4");
218 buf_append(buf, sizeof(buf), "X-DTLS-Master-Secret: ");
219 for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
220 buf_append(buf, sizeof(buf), "%02X", vpninfo->dtls_secret[i]);
221 buf_append(buf, sizeof(buf), "\r\nX-DTLS-CipherSuite: %s\r\n\r\n",
222 vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA");
224 openconnect_SSL_write(vpninfo, buf, strlen(buf));
226 if ((i = openconnect_SSL_gets(vpninfo, buf, 65536) < 0)) {
229 vpn_progress(vpninfo, PRG_ERR,
230 _("Error fetching HTTPS response\n"));
233 openconnect_close_https(vpninfo);
235 if (openconnect_open_https(vpninfo)) {
236 vpn_progress(vpninfo, PRG_ERR,
237 _("Failed to open HTTPS connection to %s\n"),
246 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
247 if (!strncmp(buf, "HTTP/1.1 503 ", 13)) {
248 /* "Service Unavailable. Why? */
249 const char *reason = "<unknown>";
250 while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
251 if (!strncmp(buf, "X-Reason: ", 10)) {
256 vpn_progress(vpninfo, PRG_ERR,
257 _("VPN service unavailable; reason: %s\n"),
261 vpn_progress(vpninfo, PRG_ERR,
262 _("Got inappropriate HTTP CONNECT response: %s\n"),
264 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
269 vpn_progress(vpninfo, PRG_INFO, _("Got CONNECT response: %s\n"), buf);
271 /* We may have advertised it, but we only do it if the server agrees */
272 vpninfo->deflate = 0;
274 while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
275 struct vpn_option *new_option;
281 colon = strchr(buf, ':');
290 if (strncmp(buf, "X-DTLS-", 7) &&
291 strncmp(buf, "X-CSTP-", 7))
294 new_option = malloc(sizeof(*new_option));
296 vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
299 new_option->option = strdup(buf);
300 new_option->value = strdup(colon);
301 new_option->next = NULL;
303 if (!new_option->option || !new_option->value) {
304 vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
308 vpn_progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
310 if (!strncmp(buf, "X-DTLS-", 7)) {
311 *next_dtls_option = new_option;
312 next_dtls_option = &new_option->next;
314 if (!strcmp(buf + 7, "Session-ID")) {
315 if (strlen(colon) != 64) {
316 vpn_progress(vpninfo, PRG_ERR,
317 _("X-DTLS-Session-ID not 64 characters; is: \"%s\"\n"),
319 vpninfo->dtls_attempt_period = 0;
322 for (i = 0; i < 64; i += 2)
323 vpninfo->dtls_session_id[i/2] = unhex(colon + i);
325 time(&vpninfo->dtls_times.last_rekey);
329 /* CSTP options... */
330 *next_cstp_option = new_option;
331 next_cstp_option = &new_option->next;
334 if (!strcmp(buf + 7, "Keepalive")) {
335 vpninfo->ssl_times.keepalive = atol(colon);
336 } else if (!strcmp(buf + 7, "DPD")) {
338 if (j && (!vpninfo->ssl_times.dpd || j < vpninfo->ssl_times.dpd))
339 vpninfo->ssl_times.dpd = j;
340 } else if (!strcmp(buf + 7, "Rekey-Time")) {
341 vpninfo->ssl_times.rekey = atol(colon);
342 } else if (!strcmp(buf + 7, "Content-Encoding")) {
343 if (!strcmp(colon, "deflate"))
344 vpninfo->deflate = 1;
346 vpn_progress(vpninfo, PRG_ERR,
347 _("Unknown CSTP-Content-Encoding %s\n"),
351 } else if (!strcmp(buf + 7, "MTU")) {
352 vpninfo->mtu = atol(colon);
353 } else if (!strcmp(buf + 7, "Address")) {
354 if (strchr(new_option->value, ':'))
355 vpninfo->vpn_addr6 = new_option->value;
357 vpninfo->vpn_addr = new_option->value;
358 } else if (!strcmp(buf + 7, "Netmask")) {
359 if (strchr(new_option->value, ':'))
360 vpninfo->vpn_netmask6 = new_option->value;
362 vpninfo->vpn_netmask = new_option->value;
363 } else if (!strcmp(buf + 7, "DNS")) {
365 for (j = 0; j < 3; j++) {
366 if (!vpninfo->vpn_dns[j]) {
367 vpninfo->vpn_dns[j] = new_option->value;
371 } else if (!strcmp(buf + 7, "NBNS")) {
373 for (j = 0; j < 3; j++) {
374 if (!vpninfo->vpn_nbns[j]) {
375 vpninfo->vpn_nbns[j] = new_option->value;
379 } else if (!strcmp(buf + 7, "Default-Domain")) {
380 vpninfo->vpn_domain = new_option->value;
381 } else if (!strcmp(buf + 7, "MSIE-Proxy-PAC-URL")) {
382 vpninfo->vpn_proxy_pac = new_option->value;
383 } else if (!strcmp(buf + 7, "Banner")) {
384 vpninfo->banner = new_option->value;
385 } else if (!strcmp(buf + 7, "Split-DNS")) {
386 struct split_include *dns = malloc(sizeof(*dns));
389 dns->route = new_option->value;
390 dns->next = vpninfo->split_dns;
391 vpninfo->split_dns = dns;
392 } else if (!strcmp(buf + 7, "Split-Include")) {
393 struct split_include *inc = malloc(sizeof(*inc));
396 inc->route = new_option->value;
397 inc->next = vpninfo->split_includes;
398 vpninfo->split_includes = inc;
399 } else if (!strcmp(buf + 7, "Split-Exclude")) {
400 struct split_include *exc = malloc(sizeof(*exc));
403 exc->route = new_option->value;
404 exc->next = vpninfo->split_excludes;
405 vpninfo->split_excludes = exc;
409 if (!vpninfo->vpn_addr && !vpninfo->vpn_addr6) {
410 vpn_progress(vpninfo, PRG_ERR,
411 _("No IP address received. Aborting\n"));
415 if (strcmp(old_addr, vpninfo->vpn_addr)) {
416 vpn_progress(vpninfo, PRG_ERR,
417 _("Reconnect gave different Legacy IP address (%s != %s)\n"),
418 vpninfo->vpn_addr, old_addr);
423 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
424 vpn_progress(vpninfo, PRG_ERR,
425 _("Reconnect gave different Legacy IP netmask (%s != %s)\n"),
426 vpninfo->vpn_netmask, old_netmask);
431 if (strcmp(old_addr6, vpninfo->vpn_addr6)) {
432 vpn_progress(vpninfo, PRG_ERR,
433 _("Reconnect gave different IPv6 address (%s != %s)\n"),
434 vpninfo->vpn_addr6, old_addr6);
439 if (strcmp(old_netmask6, vpninfo->vpn_netmask6)) {
440 vpn_progress(vpninfo, PRG_ERR,
441 _("Reconnect gave different IPv6 netmask (%s != %s)\n"),
442 vpninfo->vpn_netmask6, old_netmask6);
447 while (old_dtls_opts) {
448 struct vpn_option *tmp = old_dtls_opts;
449 old_dtls_opts = old_dtls_opts->next;
454 while (old_cstp_opts) {
455 struct vpn_option *tmp = old_cstp_opts;
456 old_cstp_opts = old_cstp_opts->next;
461 vpn_progress(vpninfo, PRG_INFO, _("CSTP connected. DPD %d, Keepalive %d\n"),
462 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
464 if (vpninfo->select_nfds <= vpninfo->ssl_fd)
465 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
467 FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
468 FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
471 vpninfo->dtls_attempt_period = 0;
473 vpninfo->ssl_times.last_rekey = vpninfo->ssl_times.last_rx =
474 vpninfo->ssl_times.last_tx = time(NULL);
479 int make_cstp_connection(struct openconnect_info *vpninfo)
483 ret = openconnect_open_https(vpninfo);
487 if (vpninfo->deflate) {
488 vpninfo->deflate_adler32 = 1;
489 vpninfo->inflate_adler32 = 1;
491 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
492 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
493 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
494 vpn_progress(vpninfo, PRG_ERR, _("Compression setup failed\n"));
495 vpninfo->deflate = 0;
498 if (!vpninfo->deflate_pkt) {
499 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
500 if (!vpninfo->deflate_pkt) {
501 vpn_progress(vpninfo, PRG_ERR,
502 _("Allocation of deflate buffer failed\n"));
503 inflateEnd(&vpninfo->inflate_strm);
504 deflateEnd(&vpninfo->deflate_strm);
505 vpninfo->deflate = 0;
507 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
508 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
509 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
514 return start_cstp_connection(vpninfo);
517 int cstp_reconnect(struct openconnect_info *vpninfo)
523 openconnect_close_https(vpninfo);
525 /* Requeue the original packet that was deflated */
526 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
527 vpninfo->current_ssl_pkt = NULL;
528 queue_packet(&vpninfo->outgoing_queue, vpninfo->pending_deflated_pkt);
529 vpninfo->pending_deflated_pkt = NULL;
531 if (vpninfo->deflate) {
532 inflateEnd(&vpninfo->inflate_strm);
533 deflateEnd(&vpninfo->deflate_strm);
535 timeout = vpninfo->reconnect_timeout;
536 interval = vpninfo->reconnect_interval;
538 while ((ret = make_cstp_connection(vpninfo))) {
541 vpn_progress(vpninfo, PRG_INFO,
542 _("sleep %ds, remaining timeout %ds\n"),
548 interval += vpninfo->reconnect_interval;
549 if (interval > RECONNECT_INTERVAL_MAX)
550 interval = RECONNECT_INTERVAL_MAX;
552 script_config_tun(vpninfo, "reconnect");
556 static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
557 unsigned char *buf, int len)
559 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
567 vpninfo->inflate_strm.next_in = buf;
568 vpninfo->inflate_strm.avail_in = len - 4;
570 vpninfo->inflate_strm.next_out = new->data;
571 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
572 vpninfo->inflate_strm.total_out = 0;
574 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
575 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
580 new->len = vpninfo->inflate_strm.total_out;
582 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
583 new->data, new->len);
585 pkt_sum = buf[len - 1] | (buf[len - 2] << 8) |
586 (buf[len - 3] << 16) | (buf[len - 4] << 24);
588 if (vpninfo->inflate_adler32 != pkt_sum) {
589 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
592 vpn_progress(vpninfo, PRG_TRACE,
593 _("Received compressed data packet of %ld bytes\n"),
594 (long)vpninfo->inflate_strm.total_out);
596 queue_packet(&vpninfo->incoming_queue, new);
600 #if defined (OPENCONNECT_OPENSSL)
601 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
605 len = SSL_read(vpninfo->https_ssl, buf, maxlen);
609 ret = SSL_get_error(vpninfo->https_ssl, len);
610 if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
611 vpn_progress(vpninfo, PRG_ERR,
612 _("SSL read error %d (server probably closed connection); reconnecting.\n"),
619 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
623 ret = SSL_write(vpninfo->https_ssl, buf, buflen);
627 ret = SSL_get_error(vpninfo->https_ssl, ret);
629 case SSL_ERROR_WANT_WRITE:
630 /* Waiting for the socket to become writable -- it's
631 probably stalled, and/or the buffers are full */
632 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
633 case SSL_ERROR_WANT_READ:
637 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
638 openconnect_report_ssl_errors(vpninfo);
642 #elif defined (OPENCONNECT_GNUTLS)
643 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
647 ret = gnutls_record_recv(vpninfo->https_sess, buf, maxlen);
651 if (ret != GNUTLS_E_AGAIN) {
652 vpn_progress(vpninfo, PRG_ERR,
653 _("SSL read error: %s; reconnecting.\n"),
654 gnutls_strerror(ret));
660 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
664 ret = gnutls_record_send(vpninfo->https_sess, buf, buflen);
668 if (ret == GNUTLS_E_AGAIN) {
669 if (gnutls_record_get_direction(vpninfo->https_sess)) {
670 /* Waiting for the socket to become writable -- it's
671 probably stalled, and/or the buffers are full */
672 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
676 vpn_progress(vpninfo, PRG_ERR, _("SSL send failed: %s\n"),
677 gnutls_strerror(ret));
682 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
684 unsigned char buf[16384];
688 /* FIXME: The poll() handling here is fairly simplistic. Actually,
689 if the SSL connection stalls it could return a WANT_WRITE error
690 on _either_ of the SSL_read() or SSL_write() calls. In that case,
691 we should probably remove POLLIN from the events we're looking for,
692 and add POLLOUT. As it is, though, it'll just chew CPU time in that
693 fairly unlikely situation, until the write backlog clears. */
694 while ( (len = cstp_read(vpninfo, buf, sizeof(buf))) > 0) {
697 if (buf[0] != 'S' || buf[1] != 'T' ||
698 buf[2] != 'F' || buf[3] != 1 || buf[7])
701 payload_len = (buf[4] << 8) + buf[5];
702 if (len != 8 + payload_len) {
703 vpn_progress(vpninfo, PRG_ERR,
704 _("Unexpected packet length. SSL_read returned %d but packet is\n"),
706 vpn_progress(vpninfo, PRG_ERR,
707 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
708 buf[0], buf[1], buf[2], buf[3],
709 buf[4], buf[5], buf[6], buf[7]);
712 vpninfo->ssl_times.last_rx = time(NULL);
715 vpn_progress(vpninfo, PRG_TRACE,
716 _("Got CSTP DPD request\n"));
717 vpninfo->owe_ssl_dpd_response = 1;
720 case AC_PKT_DPD_RESP:
721 vpn_progress(vpninfo, PRG_TRACE,
722 _("Got CSTP DPD response\n"));
725 case AC_PKT_KEEPALIVE:
726 vpn_progress(vpninfo, PRG_TRACE,
727 _("Got CSTP Keepalive\n"));
731 vpn_progress(vpninfo, PRG_TRACE,
732 _("Received uncompressed data packet of %d bytes\n"),
734 queue_new_packet(&vpninfo->incoming_queue, buf + 8,
739 case AC_PKT_DISCONN: {
741 for (i = 0; i < payload_len; i++) {
742 if (!isprint(buf[payload_len + 8 + i]))
743 buf[payload_len + 8 + i] = '.';
745 buf[payload_len + 8] = 0;
746 vpn_progress(vpninfo, PRG_ERR,
747 _("Received server disconnect: %02x '%s'\n"),
749 vpninfo->quit_reason = "Server request";
752 case AC_PKT_COMPRESSED:
753 if (!vpninfo->deflate) {
754 vpn_progress(vpninfo, PRG_ERR,
755 _("Compressed packet received in !deflate mode\n"));
758 inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
762 case AC_PKT_TERM_SERVER:
763 vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
764 vpninfo->quit_reason = "Server request";
769 vpn_progress(vpninfo, PRG_ERR,
770 _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
771 buf[0], buf[1], buf[2], buf[3],
772 buf[4], buf[5], buf[6], buf[7]);
773 vpninfo->quit_reason = "Unknown packet received";
780 /* If SSL_write() fails we are expected to try again. With exactly
781 the same data, at exactly the same location. So we keep the
782 packet we had before.... */
783 if (vpninfo->current_ssl_pkt) {
785 vpninfo->ssl_times.last_tx = time(NULL);
786 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
788 ret = cstp_write(vpninfo,
789 vpninfo->current_ssl_pkt->hdr,
790 vpninfo->current_ssl_pkt->len + 8);
794 else if (!ret && ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
797 if (ret != vpninfo->current_ssl_pkt->len + 8) {
798 vpn_progress(vpninfo, PRG_ERR,
799 _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
800 vpninfo->current_ssl_pkt->len + 8, ret);
801 vpninfo->quit_reason = "Internal error";
804 /* Don't free the 'special' packets */
805 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
806 free(vpninfo->pending_deflated_pkt);
807 else if (vpninfo->current_ssl_pkt != &dpd_pkt &&
808 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
809 vpninfo->current_ssl_pkt != &keepalive_pkt)
810 free(vpninfo->current_ssl_pkt);
812 vpninfo->current_ssl_pkt = NULL;
815 if (vpninfo->owe_ssl_dpd_response) {
816 vpninfo->owe_ssl_dpd_response = 0;
817 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
818 goto handle_outgoing;
821 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
823 /* Not that this will ever happen; we don't even process
824 the setting when we're asked for it. */
825 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
831 vpn_progress(vpninfo, PRG_ERR,
832 _("CSTP Dead Peer Detection detected dead peer!\n"));
834 if (cstp_reconnect(vpninfo)) {
835 vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
836 vpninfo->quit_reason = "CSTP reconnect failed";
839 /* I think we can leave DTLS to its own devices; when we reconnect
840 with the same master secret, we do seem to get the same sessid */
844 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
846 vpninfo->current_ssl_pkt = &dpd_pkt;
847 goto handle_outgoing;
850 /* No need to send an explicit keepalive
851 if we have real data to send */
852 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
855 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
857 vpninfo->current_ssl_pkt = &keepalive_pkt;
858 goto handle_outgoing;
864 /* Service outgoing packet queue, if no DTLS */
865 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
866 struct pkt *this = vpninfo->outgoing_queue;
867 vpninfo->outgoing_queue = this->next;
868 vpninfo->outgoing_qlen--;
870 if (vpninfo->deflate) {
871 unsigned char *adler;
874 vpninfo->deflate_strm.next_in = this->data;
875 vpninfo->deflate_strm.avail_in = this->len;
876 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
877 vpninfo->deflate_strm.avail_out = 2040;
878 vpninfo->deflate_strm.total_out = 0;
880 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
882 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
886 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
887 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
889 /* Add ongoing adler32 to tail of compressed packet */
890 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
891 this->data, this->len);
893 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
894 *(adler++) = vpninfo->deflate_adler32 >> 24;
895 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
896 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
897 *(adler) = vpninfo->deflate_adler32 & 0xff;
899 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
901 vpn_progress(vpninfo, PRG_TRACE,
902 _("Sending compressed data packet of %d bytes\n"),
905 vpninfo->pending_deflated_pkt = this;
906 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
909 memcpy(this->hdr, data_hdr, 8);
910 this->hdr[4] = this->len >> 8;
911 this->hdr[5] = this->len & 0xff;
913 vpn_progress(vpninfo, PRG_TRACE,
914 _("Sending uncompressed data packet of %d bytes\n"),
917 vpninfo->current_ssl_pkt = this;
919 goto handle_outgoing;
922 /* Work is not done if we just got rid of packets off the queue */
926 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
928 unsigned char *bye_pkt;
931 /* already lost connection? */
932 #if defined (OPENCONNECT_OPENSSL)
933 if (!vpninfo->https_ssl)
935 #elif defined (OPENCONNECT_GNUTLS)
936 if (!vpninfo->https_sess)
940 reason_len = strlen(reason);
941 bye_pkt = malloc(reason_len + 9);
945 memcpy(bye_pkt, data_hdr, 8);
946 memcpy(bye_pkt + 9, reason, reason_len);
948 bye_pkt[4] = (reason_len + 1) >> 8;
949 bye_pkt[5] = (reason_len + 1) & 0xff;
950 bye_pkt[6] = AC_PKT_DISCONN;
953 vpn_progress(vpninfo, PRG_INFO,
954 _("Send BYE packet: %s\n"), reason);
956 cstp_write(vpninfo, bye_pkt, reason_len + 9);