2 * Open AnyConnect (SSL + DTLS) client
4 * © 2008 David Woodhouse <dwmw2@infradead.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to:
19 * Free Software Foundation, Inc.
20 * 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA
29 #include <openssl/ssl.h>
30 #include <openssl/err.h>
32 #include "openconnect.h"
35 * Data packets are encapsulated in the SSL stream as follows:
37 * 0000: Magic "STF\x1"
38 * 0004: Big-endian 16-bit length (not including 8-byte header)
39 * 0006: Byte packet type (see openconnect.h)
43 static char data_hdr[8] = {
46 AC_PKT_DATA, /* Type */
50 static struct pkt keepalive_pkt = {
51 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_KEEPALIVE, 0 },
54 static struct pkt dpd_pkt = {
55 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_OUT, 0 },
58 static struct pkt dpd_resp_pkt = {
59 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 },
63 static int start_cstp_connection(struct openconnect_info *vpninfo)
68 struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
69 struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
70 struct vpn_option *old_cstp_opts = vpninfo->cstp_options;
71 struct vpn_option *old_dtls_opts = vpninfo->dtls_options;
72 const char *old_addr = vpninfo->vpn_addr;
73 const char *old_netmask = vpninfo->vpn_netmask;
74 struct split_include *inc;
76 /* Clear old options which will be overwritten */
77 vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
78 vpninfo->cstp_options = vpninfo->dtls_options = NULL;
80 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
82 for (inc = vpninfo->split_includes; inc; inc = inc->next) {
83 struct split_include *next = inc->next;
88 openconnect_SSL_printf(vpninfo->https_ssl, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
89 openconnect_SSL_printf(vpninfo->https_ssl, "Host: %s\r\n", vpninfo->hostname);
90 openconnect_SSL_printf(vpninfo->https_ssl, "User-Agent: %s\r\n", vpninfo->useragent);
91 openconnect_SSL_printf(vpninfo->https_ssl, "Cookie: webvpn=%s\r\n", vpninfo->cookie);
92 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Version: 1\r\n");
93 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
95 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
96 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-MTU: %d\r\n", vpninfo->mtu);
97 /* To enable IPv6, send 'IPv6,IPv4'.
98 We don't know how most of that works yet though. */
99 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Address-Type: IPv4\r\n");
100 openconnect_SSL_printf(vpninfo->https_ssl, "X-DTLS-Master-Secret: ");
101 for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
102 openconnect_SSL_printf(vpninfo->https_ssl, "%02X", vpninfo->dtls_secret[i]);
103 openconnect_SSL_printf(vpninfo->https_ssl, "\r\nX-DTLS-CipherSuite: AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA\r\n\r\n");
105 if (openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536) < 0) {
106 vpninfo->progress(vpninfo, PRG_ERR, "Error fetching HTTPS response\n");
109 openconnect_close_https(vpninfo);
111 if (openconnect_open_https(vpninfo)) {
112 vpninfo->progress(vpninfo, PRG_ERR,
113 "Failed to open HTTPS connection to %s\n",
122 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
123 vpninfo->progress(vpninfo, PRG_ERR,
124 "Got inappropriate HTTP CONNECT response: %s\n",
126 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
128 openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536);
132 vpninfo->progress(vpninfo, PRG_INFO,
133 "Got CONNECT response: %s\n", buf);
135 /* We may have advertised it, but we only do it if the server agrees */
136 vpninfo->deflate = 0;
138 while ((i=openconnect_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
139 struct vpn_option *new_option;
140 char *colon = strchr(buf, ':');
149 if (strncmp(buf, "X-DTLS-", 7) &&
150 strncmp(buf, "X-CSTP-", 7))
153 new_option = malloc(sizeof(*new_option));
155 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
158 new_option->option = strdup(buf);
159 new_option->value = strdup(colon);
160 new_option->next = NULL;
162 if (!new_option->option || !new_option->value) {
163 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
167 vpninfo->progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
169 if (!strncmp(buf, "X-DTLS-", 7)) {
170 *next_dtls_option = new_option;
171 next_dtls_option = &new_option->next;
174 /* CSTP options... */
175 *next_cstp_option = new_option;
176 next_cstp_option = &new_option->next;
179 if (!strcmp(buf + 7, "Keepalive")) {
180 vpninfo->ssl_times.keepalive = atol(colon);
181 } else if (!strcmp(buf + 7, "DPD")) {
182 vpninfo->ssl_times.dpd = atol(colon);
183 } else if (!strcmp(buf + 7, "Content-Encoding")) {
184 if (!strcmp(colon, "deflate"))
185 vpninfo->deflate = 1;
187 vpninfo->progress(vpninfo, PRG_ERR,
188 "Unknown CSTP-Content-Encoding %s\n",
192 } else if (!strcmp(buf + 7, "MTU")) {
193 vpninfo->mtu = atol(colon);
194 } else if (!strcmp(buf + 7, "Address")) {
195 vpninfo->vpn_addr = new_option->value;
196 } else if (!strcmp(buf + 7, "Netmask")) {
197 vpninfo->vpn_netmask = new_option->value;
198 } else if (!strcmp(buf + 7, "DNS")) {
200 for (j = 0; j < 3; j++) {
201 if (!vpninfo->vpn_dns[j]) {
202 vpninfo->vpn_dns[j] = new_option->value;
206 } else if (!strcmp(buf + 7, "NBNS")) {
208 for (j = 0; j < 3; j++) {
209 if (!vpninfo->vpn_nbns[j]) {
210 vpninfo->vpn_nbns[j] = new_option->value;
214 } else if (!strcmp(buf + 7, "Default-Domain")) {
215 vpninfo->vpn_domain = new_option->value;
216 } else if (!strcmp(buf + 7, "Split-Include")) {
217 struct split_include *inc = malloc(sizeof(*inc));
220 inc->route = new_option->value;
221 inc->next = vpninfo->split_includes;
222 vpninfo->split_includes = inc;
226 if (!vpninfo->vpn_addr) {
227 vpninfo->progress(vpninfo, PRG_ERR, "No IP address received. Aborting\n");
230 if (!vpninfo->vpn_netmask)
231 vpninfo->vpn_netmask = "255.255.255.255";
233 if (strcmp(old_addr, vpninfo->vpn_addr)) {
234 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different IP address (%s != %s)\n",
235 vpninfo->vpn_addr, old_addr);
240 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
241 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different netmask (%s != %s)\n",
242 vpninfo->vpn_netmask, old_netmask);
247 while (old_dtls_opts) {
248 struct vpn_option *tmp = old_dtls_opts;
249 old_dtls_opts = old_dtls_opts->next;
254 while (old_cstp_opts) {
255 struct vpn_option *tmp = old_cstp_opts;
256 old_cstp_opts = old_cstp_opts->next;
261 vpninfo->progress(vpninfo, PRG_INFO, "CSTP connected. DPD %d, Keepalive %d\n",
262 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
264 BIO_set_nbio(SSL_get_rbio(vpninfo->https_ssl),1);
265 BIO_set_nbio(SSL_get_wbio(vpninfo->https_ssl),1);
267 fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) | O_NONBLOCK);
268 if (vpninfo->select_nfds <= vpninfo->ssl_fd)
269 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
271 FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
272 FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
274 vpninfo->ssl_times.last_rx = vpninfo->ssl_times.last_tx = time(NULL);
279 int make_cstp_connection(struct openconnect_info *vpninfo)
281 if (!vpninfo->https_ssl && openconnect_open_https(vpninfo))
284 if (vpninfo->deflate) {
285 vpninfo->deflate_adler32 = 1;
286 vpninfo->inflate_adler32 = 1;
288 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
289 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
290 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
291 vpninfo->progress(vpninfo, PRG_ERR, "Compression setup failed\n");
292 vpninfo->deflate = 0;
295 if (!vpninfo->deflate_pkt) {
296 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
297 if (!vpninfo->deflate_pkt) {
298 vpninfo->progress(vpninfo, PRG_ERR, "Allocation of deflate buffer failed\n");
299 vpninfo->deflate = 0;
301 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
302 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
303 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
307 if (start_cstp_connection(vpninfo))
314 static int inflate_and_queue_packet(struct openconnect_info *vpninfo, int type, void *buf, int len)
316 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
324 vpninfo->inflate_strm.next_in = buf;
325 vpninfo->inflate_strm.avail_in = len - 4;
327 vpninfo->inflate_strm.next_out = new->data;
328 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
329 vpninfo->inflate_strm.total_out = 0;
331 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
332 vpninfo->progress(vpninfo, PRG_ERR, "inflate failed\n");
337 new->len = vpninfo->inflate_strm.total_out;
339 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
340 new->data, new->len);
342 if (vpninfo->inflate_adler32 != ntohl( *(uint32_t *)(buf + len - 4))) {
343 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
346 vpninfo->progress(vpninfo, PRG_TRACE,
347 "Received compressed data packet of %ld bytes\n",
348 vpninfo->inflate_strm.total_out);
350 queue_packet(&vpninfo->incoming_queue, new);
354 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
356 unsigned char buf[16384];
360 /* FIXME: The poll() handling here is fairly simplistic. Actually,
361 if the SSL connection stalls it could return a WANT_WRITE error
362 on _either_ of the SSL_read() or SSL_write() calls. In that case,
363 we should probably remove POLLIN from the events we're looking for,
364 and add POLLOUT. As it is, though, it'll just chew CPU time in that
365 fairly unlikely situation, until the write backlog clears. */
366 while ( (len = SSL_read(vpninfo->https_ssl, buf, sizeof(buf))) > 0) {
369 if (buf[0] != 'S' || buf[1] != 'T' ||
370 buf[2] != 'F' || buf[3] != 1 || buf[7])
373 payload_len = (buf[4] << 8) + buf[5];
374 if (len != 8 + payload_len) {
375 vpninfo->progress(vpninfo, PRG_ERR,
376 "Unexpected packet length. SSL_read returned %d but packet is\n",
378 vpninfo->progress(vpninfo, PRG_ERR,
379 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
380 buf[0], buf[1], buf[2], buf[3],
381 buf[4], buf[5], buf[6], buf[7]);
384 vpninfo->ssl_times.last_rx = time(NULL);
387 vpninfo->progress(vpninfo, PRG_TRACE,
388 "Got CSTP DPD request\n");
389 vpninfo->owe_ssl_dpd_response = 1;
392 case AC_PKT_DPD_RESP:
393 vpninfo->progress(vpninfo, PRG_TRACE,
394 "Got CSTP DPD response\n");
397 case AC_PKT_KEEPALIVE:
398 vpninfo->progress(vpninfo, PRG_TRACE,
399 "Got CSTP Keepalive\n");
403 vpninfo->progress(vpninfo, PRG_TRACE,
404 "Received uncompressed data packet of %d bytes\n",
406 queue_new_packet(&vpninfo->incoming_queue, AF_INET, buf + 8,
411 case AC_PKT_DISCONN: {
413 for (i = 0; i < payload_len; i++) {
414 if (!isprint(buf[payload_len + 8 + i]))
415 buf[payload_len + 8 + i] = '.';
417 buf[payload_len + 8] = 0;
418 vpninfo->progress(vpninfo, PRG_ERR,
419 "Received server disconnect: '%s'\n", buf + 8);
420 vpninfo->quit_reason = "Server request";
423 case AC_PKT_COMPRESSED:
424 if (!vpninfo->deflate) {
425 vpninfo->progress(vpninfo, PRG_ERR, "Compressed packet received in !deflate mode\n");
428 inflate_and_queue_packet(vpninfo, AF_INET, buf + 8, payload_len);
432 case AC_PKT_TERM_SERVER:
433 vpninfo->progress(vpninfo, PRG_ERR, "received server terminate packet\n");
434 vpninfo->quit_reason = "Server request";
439 vpninfo->progress(vpninfo, PRG_ERR,
440 "Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n",
441 buf[0], buf[1], buf[2], buf[3],
442 buf[4], buf[5], buf[6], buf[7]);
443 vpninfo->quit_reason = "Unknown packet received";
448 /* If SSL_write() fails we are expected to try again. With exactly
449 the same data, at exactly the same location. So we keep the
450 packet we had before.... */
451 if (vpninfo->current_ssl_pkt) {
453 vpninfo->ssl_times.last_tx = time(NULL);
454 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
455 ret = SSL_write(vpninfo->https_ssl,
456 vpninfo->current_ssl_pkt->hdr,
457 vpninfo->current_ssl_pkt->len + 8);
459 ret = SSL_get_error(vpninfo->https_ssl, ret);
461 case SSL_ERROR_WANT_WRITE:
462 /* Waiting for the socket to become writable -- it's
463 probably stalled, and/or the buffers are full */
464 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
466 case SSL_ERROR_WANT_READ:
467 if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
471 vpninfo->progress(vpninfo, PRG_ERR, "SSL_write failed: %d", ret);
472 ERR_print_errors_fp(stderr);
473 vpninfo->quit_reason = "SSL write error";
477 if (ret != vpninfo->current_ssl_pkt->len + 8) {
478 vpninfo->progress(vpninfo, PRG_ERR, "SSL wrote too few bytes! Asked for %d, sent %d\n",
479 vpninfo->current_ssl_pkt->len + 8, ret);
480 vpninfo->quit_reason = "Internal error";
483 /* Don't free the 'special' packets */
484 if (vpninfo->current_ssl_pkt != vpninfo->deflate_pkt &&
485 vpninfo->current_ssl_pkt != &dpd_pkt &&
486 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
487 vpninfo->current_ssl_pkt != &keepalive_pkt)
488 free(vpninfo->current_ssl_pkt);
490 vpninfo->current_ssl_pkt = NULL;
493 if (vpninfo->owe_ssl_dpd_response) {
494 vpninfo->owe_ssl_dpd_response = 0;
495 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
496 goto handle_outgoing;
499 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
501 /* Not that this will ever happen; we don't even process
502 the setting when we're asked for it. */
503 vpninfo->progress(vpninfo, PRG_ERR, "CSTP rekey due but we don't know how\n");
504 time(&vpninfo->ssl_times.last_rekey);
510 vpninfo->progress(vpninfo, PRG_ERR, "CSTP Dead Peer Detection detected dead peer!\n");
511 openconnect_close_https(vpninfo);
513 /* It's already deflated in the old stream. Extremely
514 non-trivial to reconstitute it; just throw it away */
515 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
516 vpninfo->current_ssl_pkt = NULL;
518 if (make_cstp_connection(vpninfo)) {
519 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect failed\n");
520 vpninfo->quit_reason = "SSL DPD detected dead peer; reconnect failed";
523 /* I think we can leave DTLS to its own devices; when we reconnect
524 with the same master secret, we do seem to get the same sessid */
528 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP DPD\n");
530 vpninfo->current_ssl_pkt = &dpd_pkt;
531 goto handle_outgoing;
534 /* No need to send an explicit keepalive
535 if we have real data to send */
536 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
539 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP Keepalive\n");
541 vpninfo->current_ssl_pkt = &keepalive_pkt;
542 goto handle_outgoing;
548 /* Service outgoing packet queue, if no DTLS */
549 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
550 struct pkt *this = vpninfo->outgoing_queue;
551 vpninfo->outgoing_queue = this->next;
553 if (vpninfo->deflate) {
554 unsigned char *adler;
557 vpninfo->deflate_strm.next_in = this->data;
558 vpninfo->deflate_strm.avail_in = this->len;
559 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
560 vpninfo->deflate_strm.avail_out = 2040;
561 vpninfo->deflate_strm.total_out = 0;
563 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
565 vpninfo->progress(vpninfo, PRG_ERR, "deflate failed %d\n", ret);
569 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
570 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
572 /* Add ongoing adler32 to tail of compressed packet */
573 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
574 this->data, this->len);
576 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
577 *(adler++) = vpninfo->deflate_adler32 >> 24;
578 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
579 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
580 *(adler) = vpninfo->deflate_adler32 & 0xff;
582 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
584 vpninfo->progress(vpninfo, PRG_TRACE,
585 "Sending compressed data packet of %d bytes\n",
588 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
591 memcpy(this->hdr, data_hdr, 8);
592 this->hdr[4] = this->len >> 8;
593 this->hdr[5] = this->len & 0xff;
595 vpninfo->progress(vpninfo, PRG_TRACE,
596 "Sending uncompressed data packet of %d bytes\n",
599 vpninfo->current_ssl_pkt = this;
601 goto handle_outgoing;
604 /* Work is not done if we just got rid of packets off the queue */
608 int cstp_bye(struct openconnect_info *vpninfo, char *reason)
610 unsigned char *bye_pkt;
611 int reason_len = strlen(reason);
612 bye_pkt = malloc(reason_len + 8);
616 memcpy(bye_pkt, data_hdr, 8);
617 memcpy(bye_pkt + 8, reason, strlen(reason));
619 bye_pkt[4] = reason_len >> 8;
620 bye_pkt[5] = reason_len & 0xff;
621 bye_pkt[6] = AC_PKT_DISCONN;
623 SSL_write(vpninfo->https_ssl, bye_pkt, reason_len + 8);
626 vpninfo->progress(vpninfo, PRG_INFO,
627 "Send BYE packet: %s\n", reason);