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 vpninfo->vpn_addr6 = new_option->value;
362 vpninfo->vpn_addr = new_option->value;
363 } else if (!strcmp(buf + 7, "Netmask")) {
364 if (strchr(new_option->value, ':'))
365 vpninfo->vpn_netmask6 = new_option->value;
367 vpninfo->vpn_netmask = new_option->value;
368 } else if (!strcmp(buf + 7, "DNS")) {
370 for (j = 0; j < 3; j++) {
371 if (!vpninfo->vpn_dns[j]) {
372 vpninfo->vpn_dns[j] = new_option->value;
376 } else if (!strcmp(buf + 7, "NBNS")) {
378 for (j = 0; j < 3; j++) {
379 if (!vpninfo->vpn_nbns[j]) {
380 vpninfo->vpn_nbns[j] = new_option->value;
384 } else if (!strcmp(buf + 7, "Default-Domain")) {
385 vpninfo->vpn_domain = new_option->value;
386 } else if (!strcmp(buf + 7, "MSIE-Proxy-PAC-URL")) {
387 vpninfo->vpn_proxy_pac = new_option->value;
388 } else if (!strcmp(buf + 7, "Banner")) {
389 vpninfo->banner = new_option->value;
390 } else if (!strcmp(buf + 7, "Split-DNS")) {
391 struct split_include *dns = malloc(sizeof(*dns));
394 dns->route = new_option->value;
395 dns->next = vpninfo->split_dns;
396 vpninfo->split_dns = dns;
397 } else if (!strcmp(buf + 7, "Split-Include")) {
398 struct split_include *inc = malloc(sizeof(*inc));
401 inc->route = new_option->value;
402 inc->next = vpninfo->split_includes;
403 vpninfo->split_includes = inc;
404 } else if (!strcmp(buf + 7, "Split-Exclude")) {
405 struct split_include *exc = malloc(sizeof(*exc));
408 exc->route = new_option->value;
409 exc->next = vpninfo->split_excludes;
410 vpninfo->split_excludes = exc;
414 if (!vpninfo->vpn_addr && !vpninfo->vpn_addr6) {
415 vpn_progress(vpninfo, PRG_ERR,
416 _("No IP address received. Aborting\n"));
420 if (strcmp(old_addr, vpninfo->vpn_addr)) {
421 vpn_progress(vpninfo, PRG_ERR,
422 _("Reconnect gave different Legacy IP address (%s != %s)\n"),
423 vpninfo->vpn_addr, old_addr);
428 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
429 vpn_progress(vpninfo, PRG_ERR,
430 _("Reconnect gave different Legacy IP netmask (%s != %s)\n"),
431 vpninfo->vpn_netmask, old_netmask);
436 if (strcmp(old_addr6, vpninfo->vpn_addr6)) {
437 vpn_progress(vpninfo, PRG_ERR,
438 _("Reconnect gave different IPv6 address (%s != %s)\n"),
439 vpninfo->vpn_addr6, old_addr6);
444 if (strcmp(old_netmask6, vpninfo->vpn_netmask6)) {
445 vpn_progress(vpninfo, PRG_ERR,
446 _("Reconnect gave different IPv6 netmask (%s != %s)\n"),
447 vpninfo->vpn_netmask6, old_netmask6);
452 while (old_dtls_opts) {
453 struct vpn_option *tmp = old_dtls_opts;
454 old_dtls_opts = old_dtls_opts->next;
459 while (old_cstp_opts) {
460 struct vpn_option *tmp = old_cstp_opts;
461 old_cstp_opts = old_cstp_opts->next;
466 vpn_progress(vpninfo, PRG_INFO, _("CSTP connected. DPD %d, Keepalive %d\n"),
467 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
469 if (vpninfo->select_nfds <= vpninfo->ssl_fd)
470 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
472 FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
473 FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
476 vpninfo->dtls_attempt_period = 0;
478 vpninfo->ssl_times.last_rekey = vpninfo->ssl_times.last_rx =
479 vpninfo->ssl_times.last_tx = time(NULL);
484 int make_cstp_connection(struct openconnect_info *vpninfo)
488 ret = openconnect_open_https(vpninfo);
492 if (vpninfo->deflate) {
493 vpninfo->deflate_adler32 = 1;
494 vpninfo->inflate_adler32 = 1;
496 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
497 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
498 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
499 vpn_progress(vpninfo, PRG_ERR, _("Compression setup failed\n"));
500 vpninfo->deflate = 0;
503 if (!vpninfo->deflate_pkt) {
504 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
505 if (!vpninfo->deflate_pkt) {
506 vpn_progress(vpninfo, PRG_ERR,
507 _("Allocation of deflate buffer failed\n"));
508 inflateEnd(&vpninfo->inflate_strm);
509 deflateEnd(&vpninfo->deflate_strm);
510 vpninfo->deflate = 0;
512 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
513 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
514 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
519 return start_cstp_connection(vpninfo);
522 int cstp_reconnect(struct openconnect_info *vpninfo)
528 openconnect_close_https(vpninfo, 0);
530 /* Requeue the original packet that was deflated */
531 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
532 vpninfo->current_ssl_pkt = NULL;
533 queue_packet(&vpninfo->outgoing_queue, vpninfo->pending_deflated_pkt);
534 vpninfo->pending_deflated_pkt = NULL;
536 if (vpninfo->deflate) {
537 inflateEnd(&vpninfo->inflate_strm);
538 deflateEnd(&vpninfo->deflate_strm);
540 timeout = vpninfo->reconnect_timeout;
541 interval = vpninfo->reconnect_interval;
543 while ((ret = make_cstp_connection(vpninfo))) {
546 vpn_progress(vpninfo, PRG_INFO,
547 _("sleep %ds, remaining timeout %ds\n"),
553 interval += vpninfo->reconnect_interval;
554 if (interval > RECONNECT_INTERVAL_MAX)
555 interval = RECONNECT_INTERVAL_MAX;
557 script_config_tun(vpninfo, "reconnect");
561 static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
562 unsigned char *buf, int len)
564 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
572 vpninfo->inflate_strm.next_in = buf;
573 vpninfo->inflate_strm.avail_in = len - 4;
575 vpninfo->inflate_strm.next_out = new->data;
576 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
577 vpninfo->inflate_strm.total_out = 0;
579 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
580 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
585 new->len = vpninfo->inflate_strm.total_out;
587 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
588 new->data, new->len);
590 pkt_sum = buf[len - 1] | (buf[len - 2] << 8) |
591 (buf[len - 3] << 16) | (buf[len - 4] << 24);
593 if (vpninfo->inflate_adler32 != pkt_sum) {
594 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
597 vpn_progress(vpninfo, PRG_TRACE,
598 _("Received compressed data packet of %ld bytes\n"),
599 (long)vpninfo->inflate_strm.total_out);
601 queue_packet(&vpninfo->incoming_queue, new);
605 #if defined (OPENCONNECT_OPENSSL)
606 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
610 len = SSL_read(vpninfo->https_ssl, buf, maxlen);
614 ret = SSL_get_error(vpninfo->https_ssl, len);
615 if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
616 vpn_progress(vpninfo, PRG_ERR,
617 _("SSL read error %d (server probably closed connection); reconnecting.\n"),
624 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
628 ret = SSL_write(vpninfo->https_ssl, buf, buflen);
632 ret = SSL_get_error(vpninfo->https_ssl, ret);
634 case SSL_ERROR_WANT_WRITE:
635 /* Waiting for the socket to become writable -- it's
636 probably stalled, and/or the buffers are full */
637 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
638 case SSL_ERROR_WANT_READ:
642 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
643 openconnect_report_ssl_errors(vpninfo);
647 #elif defined (OPENCONNECT_GNUTLS)
648 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
652 ret = gnutls_record_recv(vpninfo->https_sess, buf, maxlen);
656 if (ret != GNUTLS_E_AGAIN) {
657 vpn_progress(vpninfo, PRG_ERR,
658 _("SSL read error: %s; reconnecting.\n"),
659 gnutls_strerror(ret));
665 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
669 ret = gnutls_record_send(vpninfo->https_sess, buf, buflen);
673 if (ret == GNUTLS_E_AGAIN) {
674 if (gnutls_record_get_direction(vpninfo->https_sess)) {
675 /* Waiting for the socket to become writable -- it's
676 probably stalled, and/or the buffers are full */
677 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
681 vpn_progress(vpninfo, PRG_ERR, _("SSL send failed: %s\n"),
682 gnutls_strerror(ret));
687 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
689 unsigned char buf[16384];
693 /* FIXME: The poll() handling here is fairly simplistic. Actually,
694 if the SSL connection stalls it could return a WANT_WRITE error
695 on _either_ of the SSL_read() or SSL_write() calls. In that case,
696 we should probably remove POLLIN from the events we're looking for,
697 and add POLLOUT. As it is, though, it'll just chew CPU time in that
698 fairly unlikely situation, until the write backlog clears. */
699 while ( (len = cstp_read(vpninfo, buf, sizeof(buf))) > 0) {
702 if (buf[0] != 'S' || buf[1] != 'T' ||
703 buf[2] != 'F' || buf[3] != 1 || buf[7])
706 payload_len = (buf[4] << 8) + buf[5];
707 if (len != 8 + payload_len) {
708 vpn_progress(vpninfo, PRG_ERR,
709 _("Unexpected packet length. SSL_read returned %d but packet is\n"),
711 vpn_progress(vpninfo, PRG_ERR,
712 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
713 buf[0], buf[1], buf[2], buf[3],
714 buf[4], buf[5], buf[6], buf[7]);
717 vpninfo->ssl_times.last_rx = time(NULL);
720 vpn_progress(vpninfo, PRG_TRACE,
721 _("Got CSTP DPD request\n"));
722 vpninfo->owe_ssl_dpd_response = 1;
725 case AC_PKT_DPD_RESP:
726 vpn_progress(vpninfo, PRG_TRACE,
727 _("Got CSTP DPD response\n"));
730 case AC_PKT_KEEPALIVE:
731 vpn_progress(vpninfo, PRG_TRACE,
732 _("Got CSTP Keepalive\n"));
736 vpn_progress(vpninfo, PRG_TRACE,
737 _("Received uncompressed data packet of %d bytes\n"),
739 queue_new_packet(&vpninfo->incoming_queue, buf + 8,
744 case AC_PKT_DISCONN: {
746 for (i = 0; i < payload_len; i++) {
747 if (!isprint(buf[payload_len + 8 + i]))
748 buf[payload_len + 8 + i] = '.';
750 buf[payload_len + 8] = 0;
751 vpn_progress(vpninfo, PRG_ERR,
752 _("Received server disconnect: %02x '%s'\n"),
754 vpninfo->quit_reason = "Server request";
757 case AC_PKT_COMPRESSED:
758 if (!vpninfo->deflate) {
759 vpn_progress(vpninfo, PRG_ERR,
760 _("Compressed packet received in !deflate mode\n"));
763 inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
767 case AC_PKT_TERM_SERVER:
768 vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
769 vpninfo->quit_reason = "Server request";
774 vpn_progress(vpninfo, PRG_ERR,
775 _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
776 buf[0], buf[1], buf[2], buf[3],
777 buf[4], buf[5], buf[6], buf[7]);
778 vpninfo->quit_reason = "Unknown packet received";
785 /* If SSL_write() fails we are expected to try again. With exactly
786 the same data, at exactly the same location. So we keep the
787 packet we had before.... */
788 if (vpninfo->current_ssl_pkt) {
790 vpninfo->ssl_times.last_tx = time(NULL);
791 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
793 ret = cstp_write(vpninfo,
794 vpninfo->current_ssl_pkt->hdr,
795 vpninfo->current_ssl_pkt->len + 8);
799 else if (!ret && ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
802 if (ret != vpninfo->current_ssl_pkt->len + 8) {
803 vpn_progress(vpninfo, PRG_ERR,
804 _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
805 vpninfo->current_ssl_pkt->len + 8, ret);
806 vpninfo->quit_reason = "Internal error";
809 /* Don't free the 'special' packets */
810 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
811 free(vpninfo->pending_deflated_pkt);
812 else if (vpninfo->current_ssl_pkt != &dpd_pkt &&
813 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
814 vpninfo->current_ssl_pkt != &keepalive_pkt)
815 free(vpninfo->current_ssl_pkt);
817 vpninfo->current_ssl_pkt = NULL;
820 if (vpninfo->owe_ssl_dpd_response) {
821 vpninfo->owe_ssl_dpd_response = 0;
822 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
823 goto handle_outgoing;
826 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
828 /* Not that this will ever happen; we don't even process
829 the setting when we're asked for it. */
830 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
836 vpn_progress(vpninfo, PRG_ERR,
837 _("CSTP Dead Peer Detection detected dead peer!\n"));
839 if (cstp_reconnect(vpninfo)) {
840 vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
841 vpninfo->quit_reason = "CSTP reconnect failed";
844 /* I think we can leave DTLS to its own devices; when we reconnect
845 with the same master secret, we do seem to get the same sessid */
849 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
851 vpninfo->current_ssl_pkt = &dpd_pkt;
852 goto handle_outgoing;
855 /* No need to send an explicit keepalive
856 if we have real data to send */
857 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
860 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
862 vpninfo->current_ssl_pkt = &keepalive_pkt;
863 goto handle_outgoing;
869 /* Service outgoing packet queue, if no DTLS */
870 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
871 struct pkt *this = vpninfo->outgoing_queue;
872 vpninfo->outgoing_queue = this->next;
873 vpninfo->outgoing_qlen--;
875 if (vpninfo->deflate) {
876 unsigned char *adler;
879 vpninfo->deflate_strm.next_in = this->data;
880 vpninfo->deflate_strm.avail_in = this->len;
881 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
882 vpninfo->deflate_strm.avail_out = 2040;
883 vpninfo->deflate_strm.total_out = 0;
885 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
887 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
891 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
892 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
894 /* Add ongoing adler32 to tail of compressed packet */
895 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
896 this->data, this->len);
898 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
899 *(adler++) = vpninfo->deflate_adler32 >> 24;
900 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
901 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
902 *(adler) = vpninfo->deflate_adler32 & 0xff;
904 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
906 vpn_progress(vpninfo, PRG_TRACE,
907 _("Sending compressed data packet of %d bytes\n"),
910 vpninfo->pending_deflated_pkt = this;
911 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
914 memcpy(this->hdr, data_hdr, 8);
915 this->hdr[4] = this->len >> 8;
916 this->hdr[5] = this->len & 0xff;
918 vpn_progress(vpninfo, PRG_TRACE,
919 _("Sending uncompressed data packet of %d bytes\n"),
922 vpninfo->current_ssl_pkt = this;
924 goto handle_outgoing;
927 /* Work is not done if we just got rid of packets off the queue */
931 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
933 unsigned char *bye_pkt;
936 /* already lost connection? */
937 #if defined (OPENCONNECT_OPENSSL)
938 if (!vpninfo->https_ssl)
940 #elif defined (OPENCONNECT_GNUTLS)
941 if (!vpninfo->https_sess)
945 reason_len = strlen(reason);
946 bye_pkt = malloc(reason_len + 9);
950 memcpy(bye_pkt, data_hdr, 8);
951 memcpy(bye_pkt + 9, reason, reason_len);
953 bye_pkt[4] = (reason_len + 1) >> 8;
954 bye_pkt[5] = (reason_len + 1) & 0xff;
955 bye_pkt[6] = AC_PKT_DISCONN;
958 vpn_progress(vpninfo, PRG_INFO,
959 _("Send BYE packet: %s\n"), reason);
961 cstp_write(vpninfo, bye_pkt, reason_len + 9);