2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2008 Intel Corporation.
6 * Author: David Woodhouse <dwmw2@infradead.org>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * version 2.1, as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA
30 #include <openssl/ssl.h>
31 #include <openssl/err.h>
33 #include "openconnect.h"
36 * Data packets are encapsulated in the SSL stream as follows:
38 * 0000: Magic "STF\x1"
39 * 0004: Big-endian 16-bit length (not including 8-byte header)
40 * 0006: Byte packet type (see openconnect.h)
44 static char data_hdr[8] = {
47 AC_PKT_DATA, /* Type */
51 static struct pkt keepalive_pkt = {
52 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_KEEPALIVE, 0 },
55 static struct pkt dpd_pkt = {
56 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_OUT, 0 },
59 static struct pkt dpd_resp_pkt = {
60 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 },
64 static int start_cstp_connection(struct openconnect_info *vpninfo)
69 struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
70 struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
71 struct vpn_option *old_cstp_opts = vpninfo->cstp_options;
72 struct vpn_option *old_dtls_opts = vpninfo->dtls_options;
73 const char *old_addr = vpninfo->vpn_addr;
74 const char *old_netmask = vpninfo->vpn_netmask;
75 struct split_include *inc;
77 /* Clear old options which will be overwritten */
78 vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
79 vpninfo->cstp_options = vpninfo->dtls_options = NULL;
81 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
83 for (inc = vpninfo->split_includes; inc; inc = inc->next) {
84 struct split_include *next = inc->next;
89 openconnect_SSL_printf(vpninfo->https_ssl, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
90 openconnect_SSL_printf(vpninfo->https_ssl, "Host: %s\r\n", vpninfo->hostname);
91 openconnect_SSL_printf(vpninfo->https_ssl, "User-Agent: %s\r\n", vpninfo->useragent);
92 openconnect_SSL_printf(vpninfo->https_ssl, "Cookie: webvpn=%s\r\n", vpninfo->cookie);
93 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Version: 1\r\n");
94 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
96 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
97 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-MTU: %d\r\n", vpninfo->mtu);
98 /* To enable IPv6, send 'IPv6,IPv4'.
99 We don't know how most of that works yet though. */
100 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Address-Type: IPv4\r\n");
101 openconnect_SSL_printf(vpninfo->https_ssl, "X-DTLS-Master-Secret: ");
102 for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
103 openconnect_SSL_printf(vpninfo->https_ssl, "%02X", vpninfo->dtls_secret[i]);
104 openconnect_SSL_printf(vpninfo->https_ssl, "\r\nX-DTLS-CipherSuite: AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA\r\n\r\n");
106 if (openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536) < 0) {
107 vpninfo->progress(vpninfo, PRG_ERR, "Error fetching HTTPS response\n");
110 openconnect_close_https(vpninfo);
112 if (openconnect_open_https(vpninfo)) {
113 vpninfo->progress(vpninfo, PRG_ERR,
114 "Failed to open HTTPS connection to %s\n",
123 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
124 if (!strncmp(buf, "HTTP/1.1 503 ", 13)) {
125 /* "Service Unavailable. Why? */
126 char *reason = "<unknown>";
127 while ((i=openconnect_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
128 if (!strncmp(buf, "X-Reason: ", 10)) {
133 vpninfo->progress(vpninfo, PRG_ERR, "VPN service unavailable; reason: %s\n",
137 vpninfo->progress(vpninfo, PRG_ERR,
138 "Got inappropriate HTTP CONNECT response: %s\n",
140 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
145 vpninfo->progress(vpninfo, PRG_INFO,
146 "Got CONNECT response: %s\n", buf);
148 /* We may have advertised it, but we only do it if the server agrees */
149 vpninfo->deflate = 0;
151 while ((i=openconnect_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
152 struct vpn_option *new_option;
153 char *colon = strchr(buf, ':');
162 if (strncmp(buf, "X-DTLS-", 7) &&
163 strncmp(buf, "X-CSTP-", 7))
166 new_option = malloc(sizeof(*new_option));
168 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
171 new_option->option = strdup(buf);
172 new_option->value = strdup(colon);
173 new_option->next = NULL;
175 if (!new_option->option || !new_option->value) {
176 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
180 vpninfo->progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
182 if (!strncmp(buf, "X-DTLS-", 7)) {
183 *next_dtls_option = new_option;
184 next_dtls_option = &new_option->next;
187 /* CSTP options... */
188 *next_cstp_option = new_option;
189 next_cstp_option = &new_option->next;
192 if (!strcmp(buf + 7, "Keepalive")) {
193 vpninfo->ssl_times.keepalive = atol(colon);
194 } else if (!strcmp(buf + 7, "DPD")) {
195 vpninfo->ssl_times.dpd = atol(colon);
196 } else if (!strcmp(buf + 7, "Content-Encoding")) {
197 if (!strcmp(colon, "deflate"))
198 vpninfo->deflate = 1;
200 vpninfo->progress(vpninfo, PRG_ERR,
201 "Unknown CSTP-Content-Encoding %s\n",
205 } else if (!strcmp(buf + 7, "MTU")) {
206 vpninfo->mtu = atol(colon);
207 } else if (!strcmp(buf + 7, "Address")) {
208 vpninfo->vpn_addr = new_option->value;
209 } else if (!strcmp(buf + 7, "Netmask")) {
210 vpninfo->vpn_netmask = new_option->value;
211 } else if (!strcmp(buf + 7, "DNS")) {
213 for (j = 0; j < 3; j++) {
214 if (!vpninfo->vpn_dns[j]) {
215 vpninfo->vpn_dns[j] = new_option->value;
219 } else if (!strcmp(buf + 7, "NBNS")) {
221 for (j = 0; j < 3; j++) {
222 if (!vpninfo->vpn_nbns[j]) {
223 vpninfo->vpn_nbns[j] = new_option->value;
227 } else if (!strcmp(buf + 7, "Default-Domain")) {
228 vpninfo->vpn_domain = new_option->value;
229 } else if (!strcmp(buf + 7, "Split-Include")) {
230 struct split_include *inc = malloc(sizeof(*inc));
233 inc->route = new_option->value;
234 inc->next = vpninfo->split_includes;
235 vpninfo->split_includes = inc;
239 if (!vpninfo->vpn_addr) {
240 vpninfo->progress(vpninfo, PRG_ERR, "No IP address received. Aborting\n");
243 if (!vpninfo->vpn_netmask)
244 vpninfo->vpn_netmask = "255.255.255.255";
246 if (strcmp(old_addr, vpninfo->vpn_addr)) {
247 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different IP address (%s != %s)\n",
248 vpninfo->vpn_addr, old_addr);
253 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
254 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different netmask (%s != %s)\n",
255 vpninfo->vpn_netmask, old_netmask);
260 while (old_dtls_opts) {
261 struct vpn_option *tmp = old_dtls_opts;
262 old_dtls_opts = old_dtls_opts->next;
267 while (old_cstp_opts) {
268 struct vpn_option *tmp = old_cstp_opts;
269 old_cstp_opts = old_cstp_opts->next;
274 vpninfo->progress(vpninfo, PRG_INFO, "CSTP connected. DPD %d, Keepalive %d\n",
275 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
277 BIO_set_nbio(SSL_get_rbio(vpninfo->https_ssl),1);
278 BIO_set_nbio(SSL_get_wbio(vpninfo->https_ssl),1);
280 fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) | O_NONBLOCK);
281 if (vpninfo->select_nfds <= vpninfo->ssl_fd)
282 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
284 FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
285 FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
287 vpninfo->ssl_times.last_rx = vpninfo->ssl_times.last_tx = time(NULL);
292 int make_cstp_connection(struct openconnect_info *vpninfo)
294 if (!vpninfo->https_ssl && openconnect_open_https(vpninfo))
297 if (vpninfo->deflate) {
298 vpninfo->deflate_adler32 = 1;
299 vpninfo->inflate_adler32 = 1;
301 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
302 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
303 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
304 vpninfo->progress(vpninfo, PRG_ERR, "Compression setup failed\n");
305 vpninfo->deflate = 0;
308 if (!vpninfo->deflate_pkt) {
309 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
310 if (!vpninfo->deflate_pkt) {
311 vpninfo->progress(vpninfo, PRG_ERR, "Allocation of deflate buffer failed\n");
312 vpninfo->deflate = 0;
314 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
315 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
316 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
320 if (start_cstp_connection(vpninfo))
327 static int inflate_and_queue_packet(struct openconnect_info *vpninfo, int type, void *buf, int len)
329 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
337 vpninfo->inflate_strm.next_in = buf;
338 vpninfo->inflate_strm.avail_in = len - 4;
340 vpninfo->inflate_strm.next_out = new->data;
341 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
342 vpninfo->inflate_strm.total_out = 0;
344 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
345 vpninfo->progress(vpninfo, PRG_ERR, "inflate failed\n");
350 new->len = vpninfo->inflate_strm.total_out;
352 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
353 new->data, new->len);
355 if (vpninfo->inflate_adler32 != ntohl( *(uint32_t *)(buf + len - 4))) {
356 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
359 vpninfo->progress(vpninfo, PRG_TRACE,
360 "Received compressed data packet of %ld bytes\n",
361 vpninfo->inflate_strm.total_out);
363 queue_packet(&vpninfo->incoming_queue, new);
367 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
369 unsigned char buf[16384];
373 /* FIXME: The poll() handling here is fairly simplistic. Actually,
374 if the SSL connection stalls it could return a WANT_WRITE error
375 on _either_ of the SSL_read() or SSL_write() calls. In that case,
376 we should probably remove POLLIN from the events we're looking for,
377 and add POLLOUT. As it is, though, it'll just chew CPU time in that
378 fairly unlikely situation, until the write backlog clears. */
379 while ( (len = SSL_read(vpninfo->https_ssl, buf, sizeof(buf))) > 0) {
382 if (buf[0] != 'S' || buf[1] != 'T' ||
383 buf[2] != 'F' || buf[3] != 1 || buf[7])
386 payload_len = (buf[4] << 8) + buf[5];
387 if (len != 8 + payload_len) {
388 vpninfo->progress(vpninfo, PRG_ERR,
389 "Unexpected packet length. SSL_read returned %d but packet is\n",
391 vpninfo->progress(vpninfo, PRG_ERR,
392 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
393 buf[0], buf[1], buf[2], buf[3],
394 buf[4], buf[5], buf[6], buf[7]);
397 vpninfo->ssl_times.last_rx = time(NULL);
400 vpninfo->progress(vpninfo, PRG_TRACE,
401 "Got CSTP DPD request\n");
402 vpninfo->owe_ssl_dpd_response = 1;
405 case AC_PKT_DPD_RESP:
406 vpninfo->progress(vpninfo, PRG_TRACE,
407 "Got CSTP DPD response\n");
410 case AC_PKT_KEEPALIVE:
411 vpninfo->progress(vpninfo, PRG_TRACE,
412 "Got CSTP Keepalive\n");
416 vpninfo->progress(vpninfo, PRG_TRACE,
417 "Received uncompressed data packet of %d bytes\n",
419 queue_new_packet(&vpninfo->incoming_queue, AF_INET, buf + 8,
424 case AC_PKT_DISCONN: {
426 for (i = 0; i < payload_len; i++) {
427 if (!isprint(buf[payload_len + 8 + i]))
428 buf[payload_len + 8 + i] = '.';
430 buf[payload_len + 8] = 0;
431 vpninfo->progress(vpninfo, PRG_ERR,
432 "Received server disconnect: '%s'\n", buf + 8);
433 vpninfo->quit_reason = "Server request";
436 case AC_PKT_COMPRESSED:
437 if (!vpninfo->deflate) {
438 vpninfo->progress(vpninfo, PRG_ERR, "Compressed packet received in !deflate mode\n");
441 inflate_and_queue_packet(vpninfo, AF_INET, buf + 8, payload_len);
445 case AC_PKT_TERM_SERVER:
446 vpninfo->progress(vpninfo, PRG_ERR, "received server terminate packet\n");
447 vpninfo->quit_reason = "Server request";
452 vpninfo->progress(vpninfo, PRG_ERR,
453 "Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n",
454 buf[0], buf[1], buf[2], buf[3],
455 buf[4], buf[5], buf[6], buf[7]);
456 vpninfo->quit_reason = "Unknown packet received";
461 /* If SSL_write() fails we are expected to try again. With exactly
462 the same data, at exactly the same location. So we keep the
463 packet we had before.... */
464 if (vpninfo->current_ssl_pkt) {
466 vpninfo->ssl_times.last_tx = time(NULL);
467 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
468 ret = SSL_write(vpninfo->https_ssl,
469 vpninfo->current_ssl_pkt->hdr,
470 vpninfo->current_ssl_pkt->len + 8);
472 ret = SSL_get_error(vpninfo->https_ssl, ret);
474 case SSL_ERROR_WANT_WRITE:
475 /* Waiting for the socket to become writable -- it's
476 probably stalled, and/or the buffers are full */
477 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
479 case SSL_ERROR_WANT_READ:
480 if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
484 vpninfo->progress(vpninfo, PRG_ERR, "SSL_write failed: %d", ret);
485 ERR_print_errors_fp(stderr);
486 vpninfo->quit_reason = "SSL write error";
490 if (ret != vpninfo->current_ssl_pkt->len + 8) {
491 vpninfo->progress(vpninfo, PRG_ERR, "SSL wrote too few bytes! Asked for %d, sent %d\n",
492 vpninfo->current_ssl_pkt->len + 8, ret);
493 vpninfo->quit_reason = "Internal error";
496 /* Don't free the 'special' packets */
497 if (vpninfo->current_ssl_pkt != vpninfo->deflate_pkt &&
498 vpninfo->current_ssl_pkt != &dpd_pkt &&
499 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
500 vpninfo->current_ssl_pkt != &keepalive_pkt)
501 free(vpninfo->current_ssl_pkt);
503 vpninfo->current_ssl_pkt = NULL;
506 if (vpninfo->owe_ssl_dpd_response) {
507 vpninfo->owe_ssl_dpd_response = 0;
508 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
509 goto handle_outgoing;
512 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
514 /* Not that this will ever happen; we don't even process
515 the setting when we're asked for it. */
516 vpninfo->progress(vpninfo, PRG_ERR, "CSTP rekey due but we don't know how\n");
517 time(&vpninfo->ssl_times.last_rekey);
523 vpninfo->progress(vpninfo, PRG_ERR, "CSTP Dead Peer Detection detected dead peer!\n");
524 openconnect_close_https(vpninfo);
526 /* It's already deflated in the old stream. Extremely
527 non-trivial to reconstitute it; just throw it away */
528 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
529 vpninfo->current_ssl_pkt = NULL;
531 if (make_cstp_connection(vpninfo)) {
532 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect failed\n");
533 vpninfo->quit_reason = "SSL DPD detected dead peer; reconnect failed";
536 /* I think we can leave DTLS to its own devices; when we reconnect
537 with the same master secret, we do seem to get the same sessid */
541 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP DPD\n");
543 vpninfo->current_ssl_pkt = &dpd_pkt;
544 goto handle_outgoing;
547 /* No need to send an explicit keepalive
548 if we have real data to send */
549 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
552 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP Keepalive\n");
554 vpninfo->current_ssl_pkt = &keepalive_pkt;
555 goto handle_outgoing;
561 /* Service outgoing packet queue, if no DTLS */
562 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
563 struct pkt *this = vpninfo->outgoing_queue;
564 vpninfo->outgoing_queue = this->next;
565 vpninfo->outgoing_qlen--;
567 if (vpninfo->deflate) {
568 unsigned char *adler;
571 vpninfo->deflate_strm.next_in = this->data;
572 vpninfo->deflate_strm.avail_in = this->len;
573 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
574 vpninfo->deflate_strm.avail_out = 2040;
575 vpninfo->deflate_strm.total_out = 0;
577 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
579 vpninfo->progress(vpninfo, PRG_ERR, "deflate failed %d\n", ret);
583 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
584 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
586 /* Add ongoing adler32 to tail of compressed packet */
587 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
588 this->data, this->len);
590 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
591 *(adler++) = vpninfo->deflate_adler32 >> 24;
592 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
593 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
594 *(adler) = vpninfo->deflate_adler32 & 0xff;
596 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
598 vpninfo->progress(vpninfo, PRG_TRACE,
599 "Sending compressed data packet of %d bytes\n",
602 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
605 memcpy(this->hdr, data_hdr, 8);
606 this->hdr[4] = this->len >> 8;
607 this->hdr[5] = this->len & 0xff;
609 vpninfo->progress(vpninfo, PRG_TRACE,
610 "Sending uncompressed data packet of %d bytes\n",
613 vpninfo->current_ssl_pkt = this;
615 goto handle_outgoing;
618 /* Work is not done if we just got rid of packets off the queue */
622 int cstp_bye(struct openconnect_info *vpninfo, char *reason)
624 unsigned char *bye_pkt;
625 int reason_len = strlen(reason);
626 bye_pkt = malloc(reason_len + 8);
630 memcpy(bye_pkt, data_hdr, 8);
631 memcpy(bye_pkt + 8, reason, strlen(reason));
633 bye_pkt[4] = reason_len >> 8;
634 bye_pkt[5] = reason_len & 0xff;
635 bye_pkt[6] = AC_PKT_DISCONN;
637 SSL_write(vpninfo->https_ssl, bye_pkt, reason_len + 8);
640 vpninfo->progress(vpninfo, PRG_INFO,
641 "Send BYE packet: %s\n", reason);