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: %s\r\n\r\n",
106 vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA");
108 if (openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536) < 0) {
109 vpninfo->progress(vpninfo, PRG_ERR, "Error fetching HTTPS response\n");
112 openconnect_close_https(vpninfo);
114 if (openconnect_open_https(vpninfo)) {
115 vpninfo->progress(vpninfo, PRG_ERR,
116 "Failed to open HTTPS connection to %s\n",
125 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
126 if (!strncmp(buf, "HTTP/1.1 503 ", 13)) {
127 /* "Service Unavailable. Why? */
128 char *reason = "<unknown>";
129 while ((i = openconnect_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
130 if (!strncmp(buf, "X-Reason: ", 10)) {
135 vpninfo->progress(vpninfo, PRG_ERR, "VPN service unavailable; reason: %s\n",
139 vpninfo->progress(vpninfo, PRG_ERR,
140 "Got inappropriate HTTP CONNECT response: %s\n",
142 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
147 vpninfo->progress(vpninfo, PRG_INFO,
148 "Got CONNECT response: %s\n", buf);
150 /* We may have advertised it, but we only do it if the server agrees */
151 vpninfo->deflate = 0;
153 while ((i = openconnect_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
154 struct vpn_option *new_option;
155 char *colon = strchr(buf, ':');
164 if (strncmp(buf, "X-DTLS-", 7) &&
165 strncmp(buf, "X-CSTP-", 7))
168 new_option = malloc(sizeof(*new_option));
170 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
173 new_option->option = strdup(buf);
174 new_option->value = strdup(colon);
175 new_option->next = NULL;
177 if (!new_option->option || !new_option->value) {
178 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
182 vpninfo->progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
184 if (!strncmp(buf, "X-DTLS-", 7)) {
185 *next_dtls_option = new_option;
186 next_dtls_option = &new_option->next;
189 /* CSTP options... */
190 *next_cstp_option = new_option;
191 next_cstp_option = &new_option->next;
194 if (!strcmp(buf + 7, "Keepalive")) {
195 vpninfo->ssl_times.keepalive = atol(colon);
196 } else if (!strcmp(buf + 7, "DPD")) {
197 vpninfo->ssl_times.dpd = atol(colon);
198 } else if (!strcmp(buf + 7, "Content-Encoding")) {
199 if (!strcmp(colon, "deflate"))
200 vpninfo->deflate = 1;
202 vpninfo->progress(vpninfo, PRG_ERR,
203 "Unknown CSTP-Content-Encoding %s\n",
207 } else if (!strcmp(buf + 7, "MTU")) {
208 vpninfo->mtu = atol(colon);
209 } else if (!strcmp(buf + 7, "Address")) {
210 vpninfo->vpn_addr = new_option->value;
211 } else if (!strcmp(buf + 7, "Netmask")) {
212 vpninfo->vpn_netmask = new_option->value;
213 } else if (!strcmp(buf + 7, "DNS")) {
215 for (j = 0; j < 3; j++) {
216 if (!vpninfo->vpn_dns[j]) {
217 vpninfo->vpn_dns[j] = new_option->value;
221 } else if (!strcmp(buf + 7, "NBNS")) {
223 for (j = 0; j < 3; j++) {
224 if (!vpninfo->vpn_nbns[j]) {
225 vpninfo->vpn_nbns[j] = new_option->value;
229 } else if (!strcmp(buf + 7, "Default-Domain")) {
230 vpninfo->vpn_domain = new_option->value;
231 } else if (!strcmp(buf + 7, "Split-Include")) {
232 struct split_include *inc = malloc(sizeof(*inc));
235 inc->route = new_option->value;
236 inc->next = vpninfo->split_includes;
237 vpninfo->split_includes = inc;
241 if (!vpninfo->vpn_addr) {
242 vpninfo->progress(vpninfo, PRG_ERR, "No IP address received. Aborting\n");
245 if (!vpninfo->vpn_netmask)
246 vpninfo->vpn_netmask = "255.255.255.255";
248 if (strcmp(old_addr, vpninfo->vpn_addr)) {
249 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different IP address (%s != %s)\n",
250 vpninfo->vpn_addr, old_addr);
255 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
256 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different netmask (%s != %s)\n",
257 vpninfo->vpn_netmask, old_netmask);
262 free(vpninfo->dtls_cipher);
263 vpninfo->dtls_cipher = NULL;
265 while (old_dtls_opts) {
266 struct vpn_option *tmp = old_dtls_opts;
267 old_dtls_opts = old_dtls_opts->next;
272 while (old_cstp_opts) {
273 struct vpn_option *tmp = old_cstp_opts;
274 old_cstp_opts = old_cstp_opts->next;
279 vpninfo->progress(vpninfo, PRG_INFO, "CSTP connected. DPD %d, Keepalive %d\n",
280 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
282 BIO_set_nbio(SSL_get_rbio(vpninfo->https_ssl), 1);
283 BIO_set_nbio(SSL_get_wbio(vpninfo->https_ssl), 1);
285 fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) | O_NONBLOCK);
286 if (vpninfo->select_nfds <= vpninfo->ssl_fd)
287 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
289 FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
290 FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
292 vpninfo->ssl_times.last_rx = vpninfo->ssl_times.last_tx = time(NULL);
297 int make_cstp_connection(struct openconnect_info *vpninfo)
301 if (!vpninfo->https_ssl && (ret = openconnect_open_https(vpninfo)))
304 if (vpninfo->deflate) {
305 vpninfo->deflate_adler32 = 1;
306 vpninfo->inflate_adler32 = 1;
308 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
309 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
310 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
311 vpninfo->progress(vpninfo, PRG_ERR, "Compression setup failed\n");
312 vpninfo->deflate = 0;
315 if (!vpninfo->deflate_pkt) {
316 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
317 if (!vpninfo->deflate_pkt) {
318 vpninfo->progress(vpninfo, PRG_ERR, "Allocation of deflate buffer failed\n");
319 vpninfo->deflate = 0;
321 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
322 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
323 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
327 return start_cstp_connection(vpninfo);
330 static int cstp_reconnect(struct openconnect_info *vpninfo)
336 timeout = vpninfo->reconnect_timeout;
337 interval = vpninfo->reconnect_interval;
339 while ((ret = make_cstp_connection(vpninfo))) {
342 vpninfo->progress(vpninfo, PRG_INFO,
343 "sleep %ds, remaining timeout %ds\n",
349 interval += vpninfo->reconnect_interval;
350 if (interval > RECONNECT_INTERVAL_MAX)
351 interval = RECONNECT_INTERVAL_MAX;
356 static int inflate_and_queue_packet(struct openconnect_info *vpninfo, int type, void *buf, int len)
358 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
366 vpninfo->inflate_strm.next_in = buf;
367 vpninfo->inflate_strm.avail_in = len - 4;
369 vpninfo->inflate_strm.next_out = new->data;
370 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
371 vpninfo->inflate_strm.total_out = 0;
373 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
374 vpninfo->progress(vpninfo, PRG_ERR, "inflate failed\n");
379 new->len = vpninfo->inflate_strm.total_out;
381 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
382 new->data, new->len);
384 if (vpninfo->inflate_adler32 != ntohl( *(uint32_t *) (buf + len - 4) )) {
385 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
388 vpninfo->progress(vpninfo, PRG_TRACE,
389 "Received compressed data packet of %ld bytes\n",
390 vpninfo->inflate_strm.total_out);
392 queue_packet(&vpninfo->incoming_queue, new);
396 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
398 unsigned char buf[16384];
402 /* FIXME: The poll() handling here is fairly simplistic. Actually,
403 if the SSL connection stalls it could return a WANT_WRITE error
404 on _either_ of the SSL_read() or SSL_write() calls. In that case,
405 we should probably remove POLLIN from the events we're looking for,
406 and add POLLOUT. As it is, though, it'll just chew CPU time in that
407 fairly unlikely situation, until the write backlog clears. */
408 while ( (len = SSL_read(vpninfo->https_ssl, buf, sizeof(buf))) > 0) {
411 if (buf[0] != 'S' || buf[1] != 'T' ||
412 buf[2] != 'F' || buf[3] != 1 || buf[7])
415 payload_len = (buf[4] << 8) + buf[5];
416 if (len != 8 + payload_len) {
417 vpninfo->progress(vpninfo, PRG_ERR,
418 "Unexpected packet length. SSL_read returned %d but packet is\n",
420 vpninfo->progress(vpninfo, PRG_ERR,
421 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
422 buf[0], buf[1], buf[2], buf[3],
423 buf[4], buf[5], buf[6], buf[7]);
426 vpninfo->ssl_times.last_rx = time(NULL);
429 vpninfo->progress(vpninfo, PRG_TRACE,
430 "Got CSTP DPD request\n");
431 vpninfo->owe_ssl_dpd_response = 1;
434 case AC_PKT_DPD_RESP:
435 vpninfo->progress(vpninfo, PRG_TRACE,
436 "Got CSTP DPD response\n");
439 case AC_PKT_KEEPALIVE:
440 vpninfo->progress(vpninfo, PRG_TRACE,
441 "Got CSTP Keepalive\n");
445 vpninfo->progress(vpninfo, PRG_TRACE,
446 "Received uncompressed data packet of %d bytes\n",
448 queue_new_packet(&vpninfo->incoming_queue, AF_INET, buf + 8,
453 case AC_PKT_DISCONN: {
455 for (i = 0; i < payload_len; i++) {
456 if (!isprint(buf[payload_len + 8 + i]))
457 buf[payload_len + 8 + i] = '.';
459 buf[payload_len + 8] = 0;
460 vpninfo->progress(vpninfo, PRG_ERR,
461 "Received server disconnect: '%s'\n", buf + 8);
462 vpninfo->quit_reason = "Server request";
465 case AC_PKT_COMPRESSED:
466 if (!vpninfo->deflate) {
467 vpninfo->progress(vpninfo, PRG_ERR, "Compressed packet received in !deflate mode\n");
470 inflate_and_queue_packet(vpninfo, AF_INET, buf + 8, payload_len);
474 case AC_PKT_TERM_SERVER:
475 vpninfo->progress(vpninfo, PRG_ERR, "received server terminate packet\n");
476 vpninfo->quit_reason = "Server request";
481 vpninfo->progress(vpninfo, PRG_ERR,
482 "Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n",
483 buf[0], buf[1], buf[2], buf[3],
484 buf[4], buf[5], buf[6], buf[7]);
485 vpninfo->quit_reason = "Unknown packet received";
490 /* If SSL_write() fails we are expected to try again. With exactly
491 the same data, at exactly the same location. So we keep the
492 packet we had before.... */
493 if (vpninfo->current_ssl_pkt) {
495 vpninfo->ssl_times.last_tx = time(NULL);
496 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
497 ret = SSL_write(vpninfo->https_ssl,
498 vpninfo->current_ssl_pkt->hdr,
499 vpninfo->current_ssl_pkt->len + 8);
501 ret = SSL_get_error(vpninfo->https_ssl, ret);
503 case SSL_ERROR_WANT_WRITE:
504 /* Waiting for the socket to become writable -- it's
505 probably stalled, and/or the buffers are full */
506 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
508 case SSL_ERROR_WANT_READ:
509 if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
513 vpninfo->progress(vpninfo, PRG_ERR, "SSL_write failed: %d", ret);
514 ERR_print_errors_fp(stderr);
515 vpninfo->quit_reason = "SSL write error";
519 if (ret != vpninfo->current_ssl_pkt->len + 8) {
520 vpninfo->progress(vpninfo, PRG_ERR, "SSL wrote too few bytes! Asked for %d, sent %d\n",
521 vpninfo->current_ssl_pkt->len + 8, ret);
522 vpninfo->quit_reason = "Internal error";
525 /* Don't free the 'special' packets */
526 if (vpninfo->current_ssl_pkt != vpninfo->deflate_pkt &&
527 vpninfo->current_ssl_pkt != &dpd_pkt &&
528 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
529 vpninfo->current_ssl_pkt != &keepalive_pkt)
530 free(vpninfo->current_ssl_pkt);
532 vpninfo->current_ssl_pkt = NULL;
535 if (vpninfo->owe_ssl_dpd_response) {
536 vpninfo->owe_ssl_dpd_response = 0;
537 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
538 goto handle_outgoing;
541 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
543 /* Not that this will ever happen; we don't even process
544 the setting when we're asked for it. */
545 vpninfo->progress(vpninfo, PRG_ERR, "CSTP rekey due but we don't know how\n");
546 time(&vpninfo->ssl_times.last_rekey);
552 vpninfo->progress(vpninfo, PRG_ERR, "CSTP Dead Peer Detection detected dead peer!\n");
553 openconnect_close_https(vpninfo);
555 /* It's already deflated in the old stream. Extremely
556 non-trivial to reconstitute it; just throw it away */
557 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
558 vpninfo->current_ssl_pkt = NULL;
560 if (cstp_reconnect(vpninfo)) {
561 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect failed\n");
562 vpninfo->quit_reason = "SSL DPD detected dead peer; reconnect failed";
565 /* I think we can leave DTLS to its own devices; when we reconnect
566 with the same master secret, we do seem to get the same sessid */
570 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP DPD\n");
572 vpninfo->current_ssl_pkt = &dpd_pkt;
573 goto handle_outgoing;
576 /* No need to send an explicit keepalive
577 if we have real data to send */
578 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
581 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP Keepalive\n");
583 vpninfo->current_ssl_pkt = &keepalive_pkt;
584 goto handle_outgoing;
590 /* Service outgoing packet queue, if no DTLS */
591 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
592 struct pkt *this = vpninfo->outgoing_queue;
593 vpninfo->outgoing_queue = this->next;
594 vpninfo->outgoing_qlen--;
596 if (vpninfo->deflate) {
597 unsigned char *adler;
600 vpninfo->deflate_strm.next_in = this->data;
601 vpninfo->deflate_strm.avail_in = this->len;
602 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
603 vpninfo->deflate_strm.avail_out = 2040;
604 vpninfo->deflate_strm.total_out = 0;
606 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
608 vpninfo->progress(vpninfo, PRG_ERR, "deflate failed %d\n", ret);
612 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
613 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
615 /* Add ongoing adler32 to tail of compressed packet */
616 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
617 this->data, this->len);
619 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
620 *(adler++) = vpninfo->deflate_adler32 >> 24;
621 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
622 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
623 *(adler) = vpninfo->deflate_adler32 & 0xff;
625 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
627 vpninfo->progress(vpninfo, PRG_TRACE,
628 "Sending compressed data packet of %d bytes\n",
631 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
634 memcpy(this->hdr, data_hdr, 8);
635 this->hdr[4] = this->len >> 8;
636 this->hdr[5] = this->len & 0xff;
638 vpninfo->progress(vpninfo, PRG_TRACE,
639 "Sending uncompressed data packet of %d bytes\n",
642 vpninfo->current_ssl_pkt = this;
644 goto handle_outgoing;
647 /* Work is not done if we just got rid of packets off the queue */
651 int cstp_bye(struct openconnect_info *vpninfo, char *reason)
653 unsigned char *bye_pkt;
656 /* already lost connection? */
657 if (!vpninfo->https_ssl)
660 reason_len = strlen(reason);
661 bye_pkt = malloc(reason_len + 8);
665 memcpy(bye_pkt, data_hdr, 8);
666 memcpy(bye_pkt + 8, reason, reason_len);
668 bye_pkt[4] = reason_len >> 8;
669 bye_pkt[5] = reason_len & 0xff;
670 bye_pkt[6] = AC_PKT_DISCONN;
672 SSL_write(vpninfo->https_ssl, bye_pkt, reason_len + 8);
675 vpninfo->progress(vpninfo, PRG_INFO,
676 "Send BYE packet: %s\n", reason);