2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2008 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
31 #include <openssl/ssl.h>
32 #include <openssl/err.h>
34 #include "openconnect.h"
37 * Data packets are encapsulated in the SSL stream as follows:
39 * 0000: Magic "STF\x1"
40 * 0004: Big-endian 16-bit length (not including 8-byte header)
41 * 0006: Byte packet type (see openconnect.h)
45 static char data_hdr[8] = {
48 AC_PKT_DATA, /* Type */
52 static struct pkt keepalive_pkt = {
53 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_KEEPALIVE, 0 },
56 static struct pkt dpd_pkt = {
57 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_OUT, 0 },
60 static struct pkt dpd_resp_pkt = {
61 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 },
65 static int start_cstp_connection(struct openconnect_info *vpninfo)
70 struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
71 struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
72 struct vpn_option *old_cstp_opts = vpninfo->cstp_options;
73 struct vpn_option *old_dtls_opts = vpninfo->dtls_options;
74 const char *old_addr = vpninfo->vpn_addr;
75 const char *old_netmask = vpninfo->vpn_netmask;
76 struct split_include *inc;
78 /* Clear old options which will be overwritten */
79 vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
80 vpninfo->cstp_options = vpninfo->dtls_options = NULL;
82 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
84 for (inc = vpninfo->split_includes; inc; inc = inc->next) {
85 struct split_include *next = inc->next;
90 openconnect_SSL_printf(vpninfo->https_ssl, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
91 openconnect_SSL_printf(vpninfo->https_ssl, "Host: %s\r\n", vpninfo->hostname);
92 openconnect_SSL_printf(vpninfo->https_ssl, "User-Agent: %s\r\n", vpninfo->useragent);
93 openconnect_SSL_printf(vpninfo->https_ssl, "Cookie: webvpn=%s\r\n", vpninfo->cookie);
94 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Version: 1\r\n");
95 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
97 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
98 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-MTU: %d\r\n", vpninfo->mtu);
99 /* To enable IPv6, send 'IPv6,IPv4'.
100 We don't know how most of that works yet though. */
101 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Address-Type: IPv4\r\n");
102 openconnect_SSL_printf(vpninfo->https_ssl, "X-DTLS-Master-Secret: ");
103 for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
104 openconnect_SSL_printf(vpninfo->https_ssl, "%02X", vpninfo->dtls_secret[i]);
105 openconnect_SSL_printf(vpninfo->https_ssl, "\r\nX-DTLS-CipherSuite: AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA\r\n\r\n");
107 if (openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536) < 0) {
108 vpninfo->progress(vpninfo, PRG_ERR, "Error fetching HTTPS response\n");
111 openconnect_close_https(vpninfo);
113 if (openconnect_open_https(vpninfo)) {
114 vpninfo->progress(vpninfo, PRG_ERR,
115 "Failed to open HTTPS connection to %s\n",
124 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
125 if (!strncmp(buf, "HTTP/1.1 503 ", 13)) {
126 /* "Service Unavailable. Why? */
127 char *reason = "<unknown>";
128 while ((i = openconnect_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
129 if (!strncmp(buf, "X-Reason: ", 10)) {
134 vpninfo->progress(vpninfo, PRG_ERR, "VPN service unavailable; reason: %s\n",
138 vpninfo->progress(vpninfo, PRG_ERR,
139 "Got inappropriate HTTP CONNECT response: %s\n",
141 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
146 vpninfo->progress(vpninfo, PRG_INFO,
147 "Got CONNECT response: %s\n", buf);
149 /* We may have advertised it, but we only do it if the server agrees */
150 vpninfo->deflate = 0;
152 while ((i = openconnect_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
153 struct vpn_option *new_option;
154 char *colon = strchr(buf, ':');
163 if (strncmp(buf, "X-DTLS-", 7) &&
164 strncmp(buf, "X-CSTP-", 7))
167 new_option = malloc(sizeof(*new_option));
169 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
172 new_option->option = strdup(buf);
173 new_option->value = strdup(colon);
174 new_option->next = NULL;
176 if (!new_option->option || !new_option->value) {
177 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
181 vpninfo->progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
183 if (!strncmp(buf, "X-DTLS-", 7)) {
184 *next_dtls_option = new_option;
185 next_dtls_option = &new_option->next;
188 /* CSTP options... */
189 *next_cstp_option = new_option;
190 next_cstp_option = &new_option->next;
193 if (!strcmp(buf + 7, "Keepalive")) {
194 vpninfo->ssl_times.keepalive = atol(colon);
195 } else if (!strcmp(buf + 7, "DPD")) {
196 vpninfo->ssl_times.dpd = atol(colon);
197 } else if (!strcmp(buf + 7, "Content-Encoding")) {
198 if (!strcmp(colon, "deflate"))
199 vpninfo->deflate = 1;
201 vpninfo->progress(vpninfo, PRG_ERR,
202 "Unknown CSTP-Content-Encoding %s\n",
206 } else if (!strcmp(buf + 7, "MTU")) {
207 vpninfo->mtu = atol(colon);
208 } else if (!strcmp(buf + 7, "Address")) {
209 vpninfo->vpn_addr = new_option->value;
210 } else if (!strcmp(buf + 7, "Netmask")) {
211 vpninfo->vpn_netmask = new_option->value;
212 } else if (!strcmp(buf + 7, "DNS")) {
214 for (j = 0; j < 3; j++) {
215 if (!vpninfo->vpn_dns[j]) {
216 vpninfo->vpn_dns[j] = new_option->value;
220 } else if (!strcmp(buf + 7, "NBNS")) {
222 for (j = 0; j < 3; j++) {
223 if (!vpninfo->vpn_nbns[j]) {
224 vpninfo->vpn_nbns[j] = new_option->value;
228 } else if (!strcmp(buf + 7, "Default-Domain")) {
229 vpninfo->vpn_domain = new_option->value;
230 } else if (!strcmp(buf + 7, "Split-Include")) {
231 struct split_include *inc = malloc(sizeof(*inc));
234 inc->route = new_option->value;
235 inc->next = vpninfo->split_includes;
236 vpninfo->split_includes = inc;
240 if (!vpninfo->vpn_addr) {
241 vpninfo->progress(vpninfo, PRG_ERR, "No IP address received. Aborting\n");
244 if (!vpninfo->vpn_netmask)
245 vpninfo->vpn_netmask = "255.255.255.255";
247 if (strcmp(old_addr, vpninfo->vpn_addr)) {
248 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different IP address (%s != %s)\n",
249 vpninfo->vpn_addr, old_addr);
254 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
255 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different netmask (%s != %s)\n",
256 vpninfo->vpn_netmask, old_netmask);
261 free(vpninfo->dtls_cipher);
262 vpninfo->dtls_cipher = NULL;
264 while (old_dtls_opts) {
265 struct vpn_option *tmp = old_dtls_opts;
266 old_dtls_opts = old_dtls_opts->next;
271 while (old_cstp_opts) {
272 struct vpn_option *tmp = old_cstp_opts;
273 old_cstp_opts = old_cstp_opts->next;
278 vpninfo->progress(vpninfo, PRG_INFO, "CSTP connected. DPD %d, Keepalive %d\n",
279 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
281 BIO_set_nbio(SSL_get_rbio(vpninfo->https_ssl), 1);
282 BIO_set_nbio(SSL_get_wbio(vpninfo->https_ssl), 1);
284 fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) | O_NONBLOCK);
285 if (vpninfo->select_nfds <= vpninfo->ssl_fd)
286 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
288 FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
289 FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
291 vpninfo->ssl_times.last_rx = vpninfo->ssl_times.last_tx = time(NULL);
296 int make_cstp_connection(struct openconnect_info *vpninfo)
300 if (!vpninfo->https_ssl && (ret = openconnect_open_https(vpninfo)))
303 if (vpninfo->deflate) {
304 vpninfo->deflate_adler32 = 1;
305 vpninfo->inflate_adler32 = 1;
307 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
308 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
309 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
310 vpninfo->progress(vpninfo, PRG_ERR, "Compression setup failed\n");
311 vpninfo->deflate = 0;
314 if (!vpninfo->deflate_pkt) {
315 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
316 if (!vpninfo->deflate_pkt) {
317 vpninfo->progress(vpninfo, PRG_ERR, "Allocation of deflate buffer failed\n");
318 vpninfo->deflate = 0;
320 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
321 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
322 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
326 return start_cstp_connection(vpninfo);
329 static int cstp_reconnect(struct openconnect_info *vpninfo)
335 timeout = vpninfo->reconnect_timeout;
336 interval = vpninfo->reconnect_interval;
338 while ((ret = make_cstp_connection(vpninfo))) {
341 vpninfo->progress(vpninfo, PRG_INFO,
342 "sleep %ds, remaining timeout %ds\n",
348 interval += vpninfo->reconnect_interval;
349 if (interval > RECONNECT_INTERVAL_MAX)
350 interval = RECONNECT_INTERVAL_MAX;
355 static int inflate_and_queue_packet(struct openconnect_info *vpninfo, int type, void *buf, int len)
357 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
365 vpninfo->inflate_strm.next_in = buf;
366 vpninfo->inflate_strm.avail_in = len - 4;
368 vpninfo->inflate_strm.next_out = new->data;
369 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
370 vpninfo->inflate_strm.total_out = 0;
372 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
373 vpninfo->progress(vpninfo, PRG_ERR, "inflate failed\n");
378 new->len = vpninfo->inflate_strm.total_out;
380 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
381 new->data, new->len);
383 if (vpninfo->inflate_adler32 != ntohl( *(uint32_t *) (buf + len - 4) )) {
384 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
387 vpninfo->progress(vpninfo, PRG_TRACE,
388 "Received compressed data packet of %ld bytes\n",
389 vpninfo->inflate_strm.total_out);
391 queue_packet(&vpninfo->incoming_queue, new);
395 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
397 unsigned char buf[16384];
401 /* FIXME: The poll() handling here is fairly simplistic. Actually,
402 if the SSL connection stalls it could return a WANT_WRITE error
403 on _either_ of the SSL_read() or SSL_write() calls. In that case,
404 we should probably remove POLLIN from the events we're looking for,
405 and add POLLOUT. As it is, though, it'll just chew CPU time in that
406 fairly unlikely situation, until the write backlog clears. */
407 while ( (len = SSL_read(vpninfo->https_ssl, buf, sizeof(buf))) > 0) {
410 if (buf[0] != 'S' || buf[1] != 'T' ||
411 buf[2] != 'F' || buf[3] != 1 || buf[7])
414 payload_len = (buf[4] << 8) + buf[5];
415 if (len != 8 + payload_len) {
416 vpninfo->progress(vpninfo, PRG_ERR,
417 "Unexpected packet length. SSL_read returned %d but packet is\n",
419 vpninfo->progress(vpninfo, PRG_ERR,
420 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
421 buf[0], buf[1], buf[2], buf[3],
422 buf[4], buf[5], buf[6], buf[7]);
425 vpninfo->ssl_times.last_rx = time(NULL);
428 vpninfo->progress(vpninfo, PRG_TRACE,
429 "Got CSTP DPD request\n");
430 vpninfo->owe_ssl_dpd_response = 1;
433 case AC_PKT_DPD_RESP:
434 vpninfo->progress(vpninfo, PRG_TRACE,
435 "Got CSTP DPD response\n");
438 case AC_PKT_KEEPALIVE:
439 vpninfo->progress(vpninfo, PRG_TRACE,
440 "Got CSTP Keepalive\n");
444 vpninfo->progress(vpninfo, PRG_TRACE,
445 "Received uncompressed data packet of %d bytes\n",
447 queue_new_packet(&vpninfo->incoming_queue, AF_INET, buf + 8,
452 case AC_PKT_DISCONN: {
454 for (i = 0; i < payload_len; i++) {
455 if (!isprint(buf[payload_len + 8 + i]))
456 buf[payload_len + 8 + i] = '.';
458 buf[payload_len + 8] = 0;
459 vpninfo->progress(vpninfo, PRG_ERR,
460 "Received server disconnect: '%s'\n", buf + 8);
461 vpninfo->quit_reason = "Server request";
464 case AC_PKT_COMPRESSED:
465 if (!vpninfo->deflate) {
466 vpninfo->progress(vpninfo, PRG_ERR, "Compressed packet received in !deflate mode\n");
469 inflate_and_queue_packet(vpninfo, AF_INET, buf + 8, payload_len);
473 case AC_PKT_TERM_SERVER:
474 vpninfo->progress(vpninfo, PRG_ERR, "received server terminate packet\n");
475 vpninfo->quit_reason = "Server request";
480 vpninfo->progress(vpninfo, PRG_ERR,
481 "Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n",
482 buf[0], buf[1], buf[2], buf[3],
483 buf[4], buf[5], buf[6], buf[7]);
484 vpninfo->quit_reason = "Unknown packet received";
489 /* If SSL_write() fails we are expected to try again. With exactly
490 the same data, at exactly the same location. So we keep the
491 packet we had before.... */
492 if (vpninfo->current_ssl_pkt) {
494 vpninfo->ssl_times.last_tx = time(NULL);
495 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
496 ret = SSL_write(vpninfo->https_ssl,
497 vpninfo->current_ssl_pkt->hdr,
498 vpninfo->current_ssl_pkt->len + 8);
500 ret = SSL_get_error(vpninfo->https_ssl, ret);
502 case SSL_ERROR_WANT_WRITE:
503 /* Waiting for the socket to become writable -- it's
504 probably stalled, and/or the buffers are full */
505 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
507 case SSL_ERROR_WANT_READ:
508 if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
512 vpninfo->progress(vpninfo, PRG_ERR, "SSL_write failed: %d", ret);
513 ERR_print_errors_fp(stderr);
514 vpninfo->quit_reason = "SSL write error";
518 if (ret != vpninfo->current_ssl_pkt->len + 8) {
519 vpninfo->progress(vpninfo, PRG_ERR, "SSL wrote too few bytes! Asked for %d, sent %d\n",
520 vpninfo->current_ssl_pkt->len + 8, ret);
521 vpninfo->quit_reason = "Internal error";
524 /* Don't free the 'special' packets */
525 if (vpninfo->current_ssl_pkt != vpninfo->deflate_pkt &&
526 vpninfo->current_ssl_pkt != &dpd_pkt &&
527 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
528 vpninfo->current_ssl_pkt != &keepalive_pkt)
529 free(vpninfo->current_ssl_pkt);
531 vpninfo->current_ssl_pkt = NULL;
534 if (vpninfo->owe_ssl_dpd_response) {
535 vpninfo->owe_ssl_dpd_response = 0;
536 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
537 goto handle_outgoing;
540 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
542 /* Not that this will ever happen; we don't even process
543 the setting when we're asked for it. */
544 vpninfo->progress(vpninfo, PRG_ERR, "CSTP rekey due but we don't know how\n");
545 time(&vpninfo->ssl_times.last_rekey);
551 vpninfo->progress(vpninfo, PRG_ERR, "CSTP Dead Peer Detection detected dead peer!\n");
552 openconnect_close_https(vpninfo);
554 /* It's already deflated in the old stream. Extremely
555 non-trivial to reconstitute it; just throw it away */
556 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
557 vpninfo->current_ssl_pkt = NULL;
559 if (cstp_reconnect(vpninfo)) {
560 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect failed\n");
561 vpninfo->quit_reason = "SSL DPD detected dead peer; reconnect failed";
564 /* I think we can leave DTLS to its own devices; when we reconnect
565 with the same master secret, we do seem to get the same sessid */
569 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP DPD\n");
571 vpninfo->current_ssl_pkt = &dpd_pkt;
572 goto handle_outgoing;
575 /* No need to send an explicit keepalive
576 if we have real data to send */
577 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
580 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP Keepalive\n");
582 vpninfo->current_ssl_pkt = &keepalive_pkt;
583 goto handle_outgoing;
589 /* Service outgoing packet queue, if no DTLS */
590 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
591 struct pkt *this = vpninfo->outgoing_queue;
592 vpninfo->outgoing_queue = this->next;
593 vpninfo->outgoing_qlen--;
595 if (vpninfo->deflate) {
596 unsigned char *adler;
599 vpninfo->deflate_strm.next_in = this->data;
600 vpninfo->deflate_strm.avail_in = this->len;
601 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
602 vpninfo->deflate_strm.avail_out = 2040;
603 vpninfo->deflate_strm.total_out = 0;
605 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
607 vpninfo->progress(vpninfo, PRG_ERR, "deflate failed %d\n", ret);
611 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
612 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
614 /* Add ongoing adler32 to tail of compressed packet */
615 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
616 this->data, this->len);
618 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
619 *(adler++) = vpninfo->deflate_adler32 >> 24;
620 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
621 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
622 *(adler) = vpninfo->deflate_adler32 & 0xff;
624 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
626 vpninfo->progress(vpninfo, PRG_TRACE,
627 "Sending compressed data packet of %d bytes\n",
630 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
633 memcpy(this->hdr, data_hdr, 8);
634 this->hdr[4] = this->len >> 8;
635 this->hdr[5] = this->len & 0xff;
637 vpninfo->progress(vpninfo, PRG_TRACE,
638 "Sending uncompressed data packet of %d bytes\n",
641 vpninfo->current_ssl_pkt = this;
643 goto handle_outgoing;
646 /* Work is not done if we just got rid of packets off the queue */
650 int cstp_bye(struct openconnect_info *vpninfo, char *reason)
652 unsigned char *bye_pkt;
655 /* already lost connection? */
656 if (!vpninfo->https_ssl)
659 reason_len = strlen(reason);
660 bye_pkt = malloc(reason_len + 8);
664 memcpy(bye_pkt, data_hdr, 8);
665 memcpy(bye_pkt + 8, reason, reason_len);
667 bye_pkt[4] = reason_len >> 8;
668 bye_pkt[5] = reason_len & 0xff;
669 bye_pkt[6] = AC_PKT_DISCONN;
671 SSL_write(vpninfo->https_ssl, bye_pkt, reason_len + 8);
674 vpninfo->progress(vpninfo, PRG_INFO,
675 "Send BYE packet: %s\n", reason);