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 <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <netinet/tcp.h>
41 #include "openconnect-internal.h"
44 * Data packets are encapsulated in the SSL stream as follows:
46 * 0000: Magic "STF\x1"
47 * 0004: Big-endian 16-bit length (not including 8-byte header)
48 * 0006: Byte packet type (see openconnect-internal.h)
52 static char data_hdr[8] = {
55 AC_PKT_DATA, /* Type */
59 static struct pkt keepalive_pkt = {
60 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_KEEPALIVE, 0 },
63 static struct pkt dpd_pkt = {
64 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_OUT, 0 },
67 static struct pkt dpd_resp_pkt = {
68 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 },
71 static int __attribute__ ((format (printf, 3, 4)))
72 buf_append(char *buf, int len, const char *fmt, ...)
74 int start = strlen(buf);
82 ret = vsnprintf(buf + start, len - start, fmt, args);
91 /* Calculate MTU to request. Old servers simply use the X-CSTP-MTU: header,
92 * which represents the tunnel MTU, while new servers do calculations on the
93 * X-CSTP-Base-MTU: header which represents the cleartext MTU between client
96 * If possible, the legacy MTU value should be the TCP MSS less 5 bytes of
97 * TLS and 8 bytes of CSTP overhead. We can get the MSS from either the
98 * TCP_INFO or TCP_MAXSEG sockopts.
100 * The base MTU comes from the TCP_INFO sockopt under Linux, but I don't know
101 * how to work it out on other systems. So leave it blank and do things the
102 * legacy way there. Contributions welcome...
104 * If we don't even have TCP_MAXSEG, then default to sending a legacy MTU of
105 * 1406 which is what we always used to do.
107 static void calculate_mtu(struct openconnect_info *vpninfo, int *base_mtu, int *mtu)
110 *base_mtu = vpninfo->basemtu;
112 #if defined(__linux__) && defined(TCP_INFO)
113 if (!*mtu || !*base_mtu) {
115 socklen_t ti_size = sizeof(ti);
117 if (!getsockopt(vpninfo->ssl_fd, IPPROTO_TCP, TCP_INFO,
119 vpn_progress(vpninfo, PRG_TRACE,
120 _("TCP_INFO rcv mss %d, snd mss %d, adv mss %d, pmtu %d\n"),
121 ti.tcpi_rcv_mss, ti.tcpi_snd_mss, ti.tcpi_advmss, ti.tcpi_pmtu);
122 if (!*base_mtu) *base_mtu = ti.tcpi_pmtu;
124 if (ti.tcpi_rcv_mss < ti.tcpi_snd_mss)
125 *mtu = ti.tcpi_rcv_mss - 13;
127 *mtu = ti.tcpi_snd_mss - 13;
135 socklen_t mss_size = sizeof(mss);
136 if (!getsockopt(vpninfo->ssl_fd, IPPROTO_TCP, TCP_MAXSEG,
138 vpn_progress(vpninfo, PRG_TRACE, _("TCP_MAXSEG %d\n"), mss);
149 static int start_cstp_connection(struct openconnect_info *vpninfo)
153 int retried = 0, sessid_found = 0;
154 struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
155 struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
156 struct vpn_option *old_cstp_opts = vpninfo->cstp_options;
157 struct vpn_option *old_dtls_opts = vpninfo->dtls_options;
158 const char *old_addr = vpninfo->vpn_addr;
159 const char *old_netmask = vpninfo->vpn_netmask;
160 const char *old_addr6 = vpninfo->vpn_addr6;
161 const char *old_netmask6 = vpninfo->vpn_netmask6;
162 struct split_include *inc;
165 /* Clear old options which will be overwritten */
166 vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
167 vpninfo->vpn_addr6 = vpninfo->vpn_netmask6 = NULL;
168 vpninfo->cstp_options = vpninfo->dtls_options = NULL;
169 vpninfo->vpn_domain = vpninfo->vpn_proxy_pac = NULL;
170 vpninfo->banner = NULL;
173 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
175 for (inc = vpninfo->split_includes; inc; ) {
176 struct split_include *next = inc->next;
180 for (inc = vpninfo->split_excludes; inc; ) {
181 struct split_include *next = inc->next;
185 for (inc = vpninfo->split_dns; inc; ) {
186 struct split_include *next = inc->next;
190 vpninfo->split_dns = vpninfo->split_includes = vpninfo->split_excludes = NULL;
192 /* Create (new) random master key for DTLS connection, if needed */
193 if (vpninfo->dtls_times.last_rekey + vpninfo->dtls_times.rekey <
195 openconnect_random(vpninfo->dtls_secret, sizeof(vpninfo->dtls_secret))) {
196 fprintf(stderr, _("Failed to initialise DTLS secret\n"));
201 calculate_mtu(vpninfo, &base_mtu, &mtu);
204 buf_append(buf, sizeof(buf), "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
205 buf_append(buf, sizeof(buf), "Host: %s\r\n", vpninfo->hostname);
206 buf_append(buf, sizeof(buf), "User-Agent: %s\r\n", vpninfo->useragent);
207 buf_append(buf, sizeof(buf), "Cookie: webvpn=%s\r\n", vpninfo->cookie);
208 buf_append(buf, sizeof(buf), "X-CSTP-Version: 1\r\n");
209 buf_append(buf, sizeof(buf), "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
210 if (vpninfo->deflate && i < sizeof(buf))
211 buf_append(buf, sizeof(buf), "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
213 buf_append(buf, sizeof(buf), "X-CSTP-Base-MTU: %d\r\n", base_mtu);
214 buf_append(buf, sizeof(buf), "X-CSTP-MTU: %d\r\n", mtu);
215 buf_append(buf, sizeof(buf), "X-CSTP-Address-Type: %s\r\n",
216 vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4");
217 buf_append(buf, sizeof(buf), "X-DTLS-Master-Secret: ");
218 for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
219 buf_append(buf, sizeof(buf), "%02X", vpninfo->dtls_secret[i]);
220 buf_append(buf, sizeof(buf), "\r\nX-DTLS-CipherSuite: %s\r\n\r\n",
221 vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA");
223 openconnect_SSL_write(vpninfo, buf, strlen(buf));
225 if ((i = openconnect_SSL_gets(vpninfo, buf, 65536) < 0)) {
228 vpn_progress(vpninfo, PRG_ERR,
229 _("Error fetching HTTPS response\n"));
232 openconnect_close_https(vpninfo, 0);
234 if (openconnect_open_https(vpninfo)) {
235 vpn_progress(vpninfo, PRG_ERR,
236 _("Failed to open HTTPS connection to %s\n"),
245 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
246 if (!strncmp(buf, "HTTP/1.1 503 ", 13)) {
247 /* "Service Unavailable. Why? */
248 const char *reason = "<unknown>";
249 while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
250 if (!strncmp(buf, "X-Reason: ", 10)) {
255 vpn_progress(vpninfo, PRG_ERR,
256 _("VPN service unavailable; reason: %s\n"),
260 vpn_progress(vpninfo, PRG_ERR,
261 _("Got inappropriate HTTP CONNECT response: %s\n"),
263 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
268 vpn_progress(vpninfo, PRG_INFO, _("Got CONNECT response: %s\n"), buf);
270 /* We may have advertised it, but we only do it if the server agrees */
271 vpninfo->deflate = 0;
273 while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
274 struct vpn_option *new_option;
280 colon = strchr(buf, ':');
289 if (strncmp(buf, "X-DTLS-", 7) &&
290 strncmp(buf, "X-CSTP-", 7))
293 new_option = malloc(sizeof(*new_option));
295 vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
298 new_option->option = strdup(buf);
299 new_option->value = strdup(colon);
300 new_option->next = NULL;
302 if (!new_option->option || !new_option->value) {
303 vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
307 vpn_progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
309 if (!strncmp(buf, "X-DTLS-", 7)) {
310 *next_dtls_option = new_option;
311 next_dtls_option = &new_option->next;
313 if (!strcmp(buf + 7, "MTU")) {
314 int mtu = atol(colon);
315 if (mtu > vpninfo->mtu)
317 } else if (!strcmp(buf + 7, "Session-ID")) {
318 if (strlen(colon) != 64) {
319 vpn_progress(vpninfo, PRG_ERR,
320 _("X-DTLS-Session-ID not 64 characters; is: \"%s\"\n"),
322 vpninfo->dtls_attempt_period = 0;
325 for (i = 0; i < 64; i += 2)
326 vpninfo->dtls_session_id[i/2] = unhex(colon + i);
328 time(&vpninfo->dtls_times.last_rekey);
332 /* CSTP options... */
333 *next_cstp_option = new_option;
334 next_cstp_option = &new_option->next;
337 if (!strcmp(buf + 7, "Keepalive")) {
338 vpninfo->ssl_times.keepalive = atol(colon);
339 } else if (!strcmp(buf + 7, "DPD")) {
341 if (j && (!vpninfo->ssl_times.dpd || j < vpninfo->ssl_times.dpd))
342 vpninfo->ssl_times.dpd = j;
343 } else if (!strcmp(buf + 7, "Rekey-Time")) {
344 vpninfo->ssl_times.rekey = atol(colon);
345 } else if (!strcmp(buf + 7, "Content-Encoding")) {
346 if (!strcmp(colon, "deflate"))
347 vpninfo->deflate = 1;
349 vpn_progress(vpninfo, PRG_ERR,
350 _("Unknown CSTP-Content-Encoding %s\n"),
354 } else if (!strcmp(buf + 7, "MTU")) {
355 int mtu = atol(colon);
356 if (mtu > vpninfo->mtu)
358 } else if (!strcmp(buf + 7, "Address")) {
359 if (strchr(new_option->value, ':')) {
360 if (!vpninfo->disable_ipv6)
361 vpninfo->vpn_addr6 = new_option->value;
363 vpninfo->vpn_addr = new_option->value;
364 } else if (!strcmp(buf + 7, "Netmask")) {
365 if (strchr(new_option->value, ':')) {
366 if (!vpninfo->disable_ipv6)
367 vpninfo->vpn_netmask6 = new_option->value;
369 vpninfo->vpn_netmask = new_option->value;
370 } else if (!strcmp(buf + 7, "DNS")) {
372 for (j = 0; j < 3; j++) {
373 if (!vpninfo->vpn_dns[j]) {
374 vpninfo->vpn_dns[j] = new_option->value;
378 } else if (!strcmp(buf + 7, "NBNS")) {
380 for (j = 0; j < 3; j++) {
381 if (!vpninfo->vpn_nbns[j]) {
382 vpninfo->vpn_nbns[j] = new_option->value;
386 } else if (!strcmp(buf + 7, "Default-Domain")) {
387 vpninfo->vpn_domain = new_option->value;
388 } else if (!strcmp(buf + 7, "MSIE-Proxy-PAC-URL")) {
389 vpninfo->vpn_proxy_pac = new_option->value;
390 } else if (!strcmp(buf + 7, "Banner")) {
391 vpninfo->banner = new_option->value;
392 } else if (!strcmp(buf + 7, "Split-DNS")) {
393 struct split_include *dns = malloc(sizeof(*dns));
396 dns->route = new_option->value;
397 dns->next = vpninfo->split_dns;
398 vpninfo->split_dns = dns;
399 } else if (!strcmp(buf + 7, "Split-Include")) {
400 struct split_include *inc = malloc(sizeof(*inc));
403 inc->route = new_option->value;
404 inc->next = vpninfo->split_includes;
405 vpninfo->split_includes = inc;
406 } else if (!strcmp(buf + 7, "Split-Exclude")) {
407 struct split_include *exc = malloc(sizeof(*exc));
410 exc->route = new_option->value;
411 exc->next = vpninfo->split_excludes;
412 vpninfo->split_excludes = exc;
416 if (!vpninfo->vpn_addr && !vpninfo->vpn_addr6) {
417 vpn_progress(vpninfo, PRG_ERR,
418 _("No IP address received. Aborting\n"));
422 if (strcmp(old_addr, vpninfo->vpn_addr)) {
423 vpn_progress(vpninfo, PRG_ERR,
424 _("Reconnect gave different Legacy IP address (%s != %s)\n"),
425 vpninfo->vpn_addr, old_addr);
430 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
431 vpn_progress(vpninfo, PRG_ERR,
432 _("Reconnect gave different Legacy IP netmask (%s != %s)\n"),
433 vpninfo->vpn_netmask, old_netmask);
438 if (strcmp(old_addr6, vpninfo->vpn_addr6)) {
439 vpn_progress(vpninfo, PRG_ERR,
440 _("Reconnect gave different IPv6 address (%s != %s)\n"),
441 vpninfo->vpn_addr6, old_addr6);
446 if (strcmp(old_netmask6, vpninfo->vpn_netmask6)) {
447 vpn_progress(vpninfo, PRG_ERR,
448 _("Reconnect gave different IPv6 netmask (%s != %s)\n"),
449 vpninfo->vpn_netmask6, old_netmask6);
454 while (old_dtls_opts) {
455 struct vpn_option *tmp = old_dtls_opts;
456 old_dtls_opts = old_dtls_opts->next;
461 while (old_cstp_opts) {
462 struct vpn_option *tmp = old_cstp_opts;
463 old_cstp_opts = old_cstp_opts->next;
468 vpn_progress(vpninfo, PRG_INFO, _("CSTP connected. DPD %d, Keepalive %d\n"),
469 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
471 if (vpninfo->select_nfds <= vpninfo->ssl_fd)
472 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
474 FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
475 FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
478 vpninfo->dtls_attempt_period = 0;
480 vpninfo->ssl_times.last_rekey = vpninfo->ssl_times.last_rx =
481 vpninfo->ssl_times.last_tx = time(NULL);
486 int make_cstp_connection(struct openconnect_info *vpninfo)
490 ret = openconnect_open_https(vpninfo);
494 if (vpninfo->deflate) {
495 vpninfo->deflate_adler32 = 1;
496 vpninfo->inflate_adler32 = 1;
498 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
499 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
500 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
501 vpn_progress(vpninfo, PRG_ERR, _("Compression setup failed\n"));
502 vpninfo->deflate = 0;
505 if (!vpninfo->deflate_pkt) {
506 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
507 if (!vpninfo->deflate_pkt) {
508 vpn_progress(vpninfo, PRG_ERR,
509 _("Allocation of deflate buffer failed\n"));
510 inflateEnd(&vpninfo->inflate_strm);
511 deflateEnd(&vpninfo->deflate_strm);
512 vpninfo->deflate = 0;
514 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
515 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
516 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
521 return start_cstp_connection(vpninfo);
524 int cstp_reconnect(struct openconnect_info *vpninfo)
530 openconnect_close_https(vpninfo, 0);
532 /* Requeue the original packet that was deflated */
533 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
534 vpninfo->current_ssl_pkt = NULL;
535 queue_packet(&vpninfo->outgoing_queue, vpninfo->pending_deflated_pkt);
536 vpninfo->pending_deflated_pkt = NULL;
538 if (vpninfo->deflate) {
539 inflateEnd(&vpninfo->inflate_strm);
540 deflateEnd(&vpninfo->deflate_strm);
542 timeout = vpninfo->reconnect_timeout;
543 interval = vpninfo->reconnect_interval;
545 while ((ret = make_cstp_connection(vpninfo))) {
548 vpn_progress(vpninfo, PRG_INFO,
549 _("sleep %ds, remaining timeout %ds\n"),
555 interval += vpninfo->reconnect_interval;
556 if (interval > RECONNECT_INTERVAL_MAX)
557 interval = RECONNECT_INTERVAL_MAX;
559 script_config_tun(vpninfo, "reconnect");
563 static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
564 unsigned char *buf, int len)
566 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
574 vpninfo->inflate_strm.next_in = buf;
575 vpninfo->inflate_strm.avail_in = len - 4;
577 vpninfo->inflate_strm.next_out = new->data;
578 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
579 vpninfo->inflate_strm.total_out = 0;
581 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
582 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
587 new->len = vpninfo->inflate_strm.total_out;
589 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
590 new->data, new->len);
592 pkt_sum = buf[len - 1] | (buf[len - 2] << 8) |
593 (buf[len - 3] << 16) | (buf[len - 4] << 24);
595 if (vpninfo->inflate_adler32 != pkt_sum) {
596 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
599 vpn_progress(vpninfo, PRG_TRACE,
600 _("Received compressed data packet of %ld bytes\n"),
601 (long)vpninfo->inflate_strm.total_out);
603 queue_packet(&vpninfo->incoming_queue, new);
607 #if defined (OPENCONNECT_OPENSSL)
608 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
612 len = SSL_read(vpninfo->https_ssl, buf, maxlen);
616 ret = SSL_get_error(vpninfo->https_ssl, len);
617 if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
618 vpn_progress(vpninfo, PRG_ERR,
619 _("SSL read error %d (server probably closed connection); reconnecting.\n"),
626 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
630 ret = SSL_write(vpninfo->https_ssl, buf, buflen);
634 ret = SSL_get_error(vpninfo->https_ssl, ret);
636 case SSL_ERROR_WANT_WRITE:
637 /* Waiting for the socket to become writable -- it's
638 probably stalled, and/or the buffers are full */
639 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
640 case SSL_ERROR_WANT_READ:
644 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
645 openconnect_report_ssl_errors(vpninfo);
649 #elif defined (OPENCONNECT_GNUTLS)
650 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
654 ret = gnutls_record_recv(vpninfo->https_sess, buf, maxlen);
658 if (ret != GNUTLS_E_AGAIN) {
659 vpn_progress(vpninfo, PRG_ERR,
660 _("SSL read error: %s; reconnecting.\n"),
661 gnutls_strerror(ret));
667 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
671 ret = gnutls_record_send(vpninfo->https_sess, buf, buflen);
675 if (ret == GNUTLS_E_AGAIN) {
676 if (gnutls_record_get_direction(vpninfo->https_sess)) {
677 /* Waiting for the socket to become writable -- it's
678 probably stalled, and/or the buffers are full */
679 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
683 vpn_progress(vpninfo, PRG_ERR, _("SSL send failed: %s\n"),
684 gnutls_strerror(ret));
689 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
691 unsigned char buf[16384];
695 /* FIXME: The poll() handling here is fairly simplistic. Actually,
696 if the SSL connection stalls it could return a WANT_WRITE error
697 on _either_ of the SSL_read() or SSL_write() calls. In that case,
698 we should probably remove POLLIN from the events we're looking for,
699 and add POLLOUT. As it is, though, it'll just chew CPU time in that
700 fairly unlikely situation, until the write backlog clears. */
701 while ( (len = cstp_read(vpninfo, buf, sizeof(buf))) > 0) {
704 if (buf[0] != 'S' || buf[1] != 'T' ||
705 buf[2] != 'F' || buf[3] != 1 || buf[7])
708 payload_len = (buf[4] << 8) + buf[5];
709 if (len != 8 + payload_len) {
710 vpn_progress(vpninfo, PRG_ERR,
711 _("Unexpected packet length. SSL_read returned %d but packet is\n"),
713 vpn_progress(vpninfo, PRG_ERR,
714 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
715 buf[0], buf[1], buf[2], buf[3],
716 buf[4], buf[5], buf[6], buf[7]);
719 vpninfo->ssl_times.last_rx = time(NULL);
722 vpn_progress(vpninfo, PRG_TRACE,
723 _("Got CSTP DPD request\n"));
724 vpninfo->owe_ssl_dpd_response = 1;
727 case AC_PKT_DPD_RESP:
728 vpn_progress(vpninfo, PRG_TRACE,
729 _("Got CSTP DPD response\n"));
732 case AC_PKT_KEEPALIVE:
733 vpn_progress(vpninfo, PRG_TRACE,
734 _("Got CSTP Keepalive\n"));
738 vpn_progress(vpninfo, PRG_TRACE,
739 _("Received uncompressed data packet of %d bytes\n"),
741 queue_new_packet(&vpninfo->incoming_queue, buf + 8,
746 case AC_PKT_DISCONN: {
748 for (i = 0; i < payload_len; i++) {
749 if (!isprint(buf[payload_len + 8 + i]))
750 buf[payload_len + 8 + i] = '.';
752 buf[payload_len + 8] = 0;
753 vpn_progress(vpninfo, PRG_ERR,
754 _("Received server disconnect: %02x '%s'\n"),
756 vpninfo->quit_reason = "Server request";
759 case AC_PKT_COMPRESSED:
760 if (!vpninfo->deflate) {
761 vpn_progress(vpninfo, PRG_ERR,
762 _("Compressed packet received in !deflate mode\n"));
765 inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
769 case AC_PKT_TERM_SERVER:
770 vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
771 vpninfo->quit_reason = "Server request";
776 vpn_progress(vpninfo, PRG_ERR,
777 _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
778 buf[0], buf[1], buf[2], buf[3],
779 buf[4], buf[5], buf[6], buf[7]);
780 vpninfo->quit_reason = "Unknown packet received";
787 /* If SSL_write() fails we are expected to try again. With exactly
788 the same data, at exactly the same location. So we keep the
789 packet we had before.... */
790 if (vpninfo->current_ssl_pkt) {
792 vpninfo->ssl_times.last_tx = time(NULL);
793 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
795 ret = cstp_write(vpninfo,
796 vpninfo->current_ssl_pkt->hdr,
797 vpninfo->current_ssl_pkt->len + 8);
801 else if (!ret && ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
804 if (ret != vpninfo->current_ssl_pkt->len + 8) {
805 vpn_progress(vpninfo, PRG_ERR,
806 _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
807 vpninfo->current_ssl_pkt->len + 8, ret);
808 vpninfo->quit_reason = "Internal error";
811 /* Don't free the 'special' packets */
812 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
813 free(vpninfo->pending_deflated_pkt);
814 else if (vpninfo->current_ssl_pkt != &dpd_pkt &&
815 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
816 vpninfo->current_ssl_pkt != &keepalive_pkt)
817 free(vpninfo->current_ssl_pkt);
819 vpninfo->current_ssl_pkt = NULL;
822 if (vpninfo->owe_ssl_dpd_response) {
823 vpninfo->owe_ssl_dpd_response = 0;
824 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
825 goto handle_outgoing;
828 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
830 /* Not that this will ever happen; we don't even process
831 the setting when we're asked for it. */
832 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
838 vpn_progress(vpninfo, PRG_ERR,
839 _("CSTP Dead Peer Detection detected dead peer!\n"));
841 if (cstp_reconnect(vpninfo)) {
842 vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
843 vpninfo->quit_reason = "CSTP reconnect failed";
846 /* I think we can leave DTLS to its own devices; when we reconnect
847 with the same master secret, we do seem to get the same sessid */
851 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
853 vpninfo->current_ssl_pkt = &dpd_pkt;
854 goto handle_outgoing;
857 /* No need to send an explicit keepalive
858 if we have real data to send */
859 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
862 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
864 vpninfo->current_ssl_pkt = &keepalive_pkt;
865 goto handle_outgoing;
871 /* Service outgoing packet queue, if no DTLS */
872 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
873 struct pkt *this = vpninfo->outgoing_queue;
874 vpninfo->outgoing_queue = this->next;
875 vpninfo->outgoing_qlen--;
877 if (vpninfo->deflate) {
878 unsigned char *adler;
881 vpninfo->deflate_strm.next_in = this->data;
882 vpninfo->deflate_strm.avail_in = this->len;
883 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
884 vpninfo->deflate_strm.avail_out = 2040;
885 vpninfo->deflate_strm.total_out = 0;
887 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
889 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
893 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
894 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
896 /* Add ongoing adler32 to tail of compressed packet */
897 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
898 this->data, this->len);
900 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
901 *(adler++) = vpninfo->deflate_adler32 >> 24;
902 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
903 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
904 *(adler) = vpninfo->deflate_adler32 & 0xff;
906 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
908 vpn_progress(vpninfo, PRG_TRACE,
909 _("Sending compressed data packet of %d bytes\n"),
912 vpninfo->pending_deflated_pkt = this;
913 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
916 memcpy(this->hdr, data_hdr, 8);
917 this->hdr[4] = this->len >> 8;
918 this->hdr[5] = this->len & 0xff;
920 vpn_progress(vpninfo, PRG_TRACE,
921 _("Sending uncompressed data packet of %d bytes\n"),
924 vpninfo->current_ssl_pkt = this;
926 goto handle_outgoing;
929 /* Work is not done if we just got rid of packets off the queue */
933 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
935 unsigned char *bye_pkt;
938 /* already lost connection? */
939 #if defined (OPENCONNECT_OPENSSL)
940 if (!vpninfo->https_ssl)
942 #elif defined (OPENCONNECT_GNUTLS)
943 if (!vpninfo->https_sess)
947 reason_len = strlen(reason);
948 bye_pkt = malloc(reason_len + 9);
952 memcpy(bye_pkt, data_hdr, 8);
953 memcpy(bye_pkt + 9, reason, reason_len);
955 bye_pkt[4] = (reason_len + 1) >> 8;
956 bye_pkt[5] = (reason_len + 1) & 0xff;
957 bye_pkt[6] = AC_PKT_DISCONN;
960 vpn_progress(vpninfo, PRG_INFO,
961 _("Send BYE packet: %s\n"), reason);
963 cstp_write(vpninfo, bye_pkt, reason_len + 9);