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;
75 /* Clear old options which will be overwritten */
76 vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
77 vpninfo->cstp_options = vpninfo->dtls_options = NULL;
79 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
82 openconnect_SSL_printf(vpninfo->https_ssl, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
83 openconnect_SSL_printf(vpninfo->https_ssl, "Host: %s\r\n", vpninfo->hostname);
84 openconnect_SSL_printf(vpninfo->https_ssl, "User-Agent: %s\r\n", vpninfo->useragent);
85 openconnect_SSL_printf(vpninfo->https_ssl, "Cookie: webvpn=%s\r\n", vpninfo->cookie);
86 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Version: 1\r\n");
87 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
89 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
90 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-MTU: %d\r\n", vpninfo->mtu);
91 /* To enable IPv6, send 'IPv6,IPv4'.
92 We don't know how most of that works yet though. */
93 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Address-Type: IPv4\r\n");
94 openconnect_SSL_printf(vpninfo->https_ssl, "X-DTLS-Master-Secret: ");
95 for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
96 openconnect_SSL_printf(vpninfo->https_ssl, "%02X", vpninfo->dtls_secret[i]);
97 openconnect_SSL_printf(vpninfo->https_ssl, "\r\nX-DTLS-CipherSuite: AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA\r\n\r\n");
99 if (openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536) < 0) {
100 vpninfo->progress(vpninfo, PRG_ERR, "Error fetching HTTPS response\n");
103 SSL_free(vpninfo->https_ssl);
104 close(vpninfo->ssl_fd);
106 if (openconnect_open_https(vpninfo)) {
107 vpninfo->progress(vpninfo, PRG_ERR,
108 "Failed to open HTTPS connection to %s\n",
117 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
118 vpninfo->progress(vpninfo, PRG_ERR,
119 "Got inappropriate HTTP CONNECT response: %s\n",
121 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
123 openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536);
127 vpninfo->progress(vpninfo, PRG_INFO,
128 "Got CONNECT response: %s\n", buf);
130 /* We may have advertised it, but we only do it if the server agrees */
131 vpninfo->deflate = 0;
133 while ((i=openconnect_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
134 struct vpn_option *new_option;
135 char *colon = strchr(buf, ':');
144 if (strncmp(buf, "X-DTLS-", 7) &&
145 strncmp(buf, "X-CSTP-", 7))
148 new_option = malloc(sizeof(*new_option));
150 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
153 new_option->option = strdup(buf);
154 new_option->value = strdup(colon);
155 new_option->next = NULL;
157 if (!new_option->option || !new_option->value) {
158 vpninfo->progress(vpninfo, PRG_ERR, "No memory for options\n");
162 vpninfo->progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
164 if (!strncmp(buf, "X-DTLS-", 7)) {
165 *next_dtls_option = new_option;
166 next_dtls_option = &new_option->next;
169 /* CSTP options... */
170 *next_cstp_option = new_option;
171 next_cstp_option = &new_option->next;
174 if (!strcmp(buf + 7, "Keepalive")) {
175 vpninfo->ssl_times.keepalive = atol(colon);
176 } else if (!strcmp(buf + 7, "DPD")) {
177 vpninfo->ssl_times.dpd = atol(colon);
178 } else if (!strcmp(buf + 7, "Content-Encoding")) {
179 if (!strcmp(colon, "deflate"))
180 vpninfo->deflate = 1;
182 vpninfo->progress(vpninfo, PRG_ERR,
183 "Unknown CSTP-Content-Encoding %s\n",
187 } else if (!strcmp(buf + 7, "MTU")) {
188 vpninfo->mtu = atol(colon);
189 } else if (!strcmp(buf + 7, "Address")) {
190 vpninfo->vpn_addr = new_option->value;
191 } else if (!strcmp(buf + 7, "Netmask")) {
192 vpninfo->vpn_netmask = new_option->value;
193 } else if (!strcmp(buf + 7, "DNS")) {
195 for (j = 0; j < 3; j++) {
196 if (!vpninfo->vpn_dns[j]) {
197 vpninfo->vpn_dns[j] = new_option->value;
201 } else if (!strcmp(buf + 7, "NBNS")) {
203 for (j = 0; j < 3; j++) {
204 if (!vpninfo->vpn_nbns[j]) {
205 vpninfo->vpn_nbns[j] = new_option->value;
209 } else if (!strcmp(buf + 7, "Default-Domain")) {
210 vpninfo->vpn_domain = new_option->value;
214 if (!vpninfo->vpn_addr) {
215 vpninfo->progress(vpninfo, PRG_ERR, "No IP address received. Aborting\n");
218 if (!vpninfo->vpn_netmask)
219 vpninfo->vpn_netmask = "255.255.255.255";
221 if (strcmp(old_addr, vpninfo->vpn_addr)) {
222 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different IP address (%s != %s)\n",
223 vpninfo->vpn_addr, old_addr);
228 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
229 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect gave different netmask (%s != %s)\n",
230 vpninfo->vpn_netmask, old_netmask);
235 while (old_dtls_opts) {
236 struct vpn_option *tmp = old_dtls_opts;
237 old_dtls_opts = old_dtls_opts->next;
242 while (old_cstp_opts) {
243 struct vpn_option *tmp = old_cstp_opts;
244 old_cstp_opts = old_cstp_opts->next;
249 vpninfo->progress(vpninfo, PRG_INFO, "CSTP connected. DPD %d, Keepalive %d\n",
250 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
252 BIO_set_nbio(SSL_get_rbio(vpninfo->https_ssl),1);
253 BIO_set_nbio(SSL_get_wbio(vpninfo->https_ssl),1);
255 fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) | O_NONBLOCK);
256 vpninfo->ssl_pfd = vpn_add_pollfd(vpninfo, vpninfo->ssl_fd, POLLIN|POLLHUP|POLLERR);
258 vpninfo->ssl_times.last_rx = vpninfo->ssl_times.last_tx = time(NULL);
263 int make_cstp_connection(struct openconnect_info *vpninfo)
265 if (!vpninfo->https_ssl && openconnect_open_https(vpninfo))
268 if (vpninfo->deflate) {
269 vpninfo->deflate_adler32 = 1;
270 vpninfo->inflate_adler32 = 1;
272 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
273 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
274 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
275 vpninfo->progress(vpninfo, PRG_ERR, "Compression setup failed\n");
276 vpninfo->deflate = 0;
279 if (!vpninfo->deflate_pkt) {
280 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
281 if (!vpninfo->deflate_pkt) {
282 vpninfo->progress(vpninfo, PRG_ERR, "Allocation of deflate buffer failed\n");
283 vpninfo->deflate = 0;
285 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
286 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
287 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
291 if (start_cstp_connection(vpninfo))
298 static int inflate_and_queue_packet(struct openconnect_info *vpninfo, int type, void *buf, int len)
300 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
308 vpninfo->inflate_strm.next_in = buf;
309 vpninfo->inflate_strm.avail_in = len - 4;
311 vpninfo->inflate_strm.next_out = new->data;
312 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
313 vpninfo->inflate_strm.total_out = 0;
315 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
316 vpninfo->progress(vpninfo, PRG_ERR, "inflate failed\n");
321 new->len = vpninfo->inflate_strm.total_out;
323 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
324 new->data, new->len);
326 if (vpninfo->inflate_adler32 != ntohl( *(uint32_t *)(buf + len - 4))) {
327 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
330 vpninfo->progress(vpninfo, PRG_TRACE,
331 "Received compressed data packet of %ld bytes\n",
332 vpninfo->inflate_strm.total_out);
334 queue_packet(&vpninfo->incoming_queue, new);
338 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
340 unsigned char buf[16384];
344 /* FIXME: The poll() handling here is fairly simplistic. Actually,
345 if the SSL connection stalls it could return a WANT_WRITE error
346 on _either_ of the SSL_read() or SSL_write() calls. In that case,
347 we should probably remove POLLIN from the events we're looking for,
348 and add POLLOUT. As it is, though, it'll just chew CPU time in that
349 fairly unlikely situation, until the write backlog clears. */
350 while ( (len = SSL_read(vpninfo->https_ssl, buf, sizeof(buf))) > 0) {
353 if (buf[0] != 'S' || buf[1] != 'T' ||
354 buf[2] != 'F' || buf[3] != 1 || buf[7])
357 payload_len = (buf[4] << 8) + buf[5];
358 if (len != 8 + payload_len) {
359 vpninfo->progress(vpninfo, PRG_ERR,
360 "Unexpected packet length. SSL_read returned %d but packet is\n",
362 vpninfo->progress(vpninfo, PRG_ERR,
363 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
364 buf[0], buf[1], buf[2], buf[3],
365 buf[4], buf[5], buf[6], buf[7]);
368 vpninfo->ssl_times.last_rx = time(NULL);
371 vpninfo->progress(vpninfo, PRG_TRACE,
372 "Got CSTP DPD request\n");
373 vpninfo->owe_ssl_dpd_response = 1;
376 case AC_PKT_DPD_RESP:
377 vpninfo->progress(vpninfo, PRG_TRACE,
378 "Got CSTP DPD response\n");
381 case AC_PKT_KEEPALIVE:
382 vpninfo->progress(vpninfo, PRG_TRACE,
383 "Got CSTP Keepalive\n");
387 vpninfo->progress(vpninfo, PRG_TRACE,
388 "Received uncompressed data packet of %d bytes\n",
390 queue_new_packet(&vpninfo->incoming_queue, AF_INET, buf + 8,
395 case AC_PKT_DISCONN: {
397 for (i = 0; i < payload_len; i++) {
398 if (!isprint(buf[payload_len + 8 + i]))
399 buf[payload_len + 8 + i] = '.';
401 buf[payload_len + 8] = 0;
402 vpninfo->progress(vpninfo, PRG_ERR,
403 "Received server disconnect: '%s'\n", buf + 8);
404 vpninfo->quit_reason = "Server request";
407 case AC_PKT_COMPRESSED:
408 if (!vpninfo->deflate) {
409 vpninfo->progress(vpninfo, PRG_ERR, "Compressed packet received in !deflate mode\n");
412 inflate_and_queue_packet(vpninfo, AF_INET, buf + 8, payload_len);
416 case AC_PKT_TERM_SERVER:
417 vpninfo->progress(vpninfo, PRG_ERR, "received server terminate packet\n");
418 vpninfo->quit_reason = "Server request";
423 vpninfo->progress(vpninfo, PRG_ERR,
424 "Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n",
425 buf[0], buf[1], buf[2], buf[3],
426 buf[4], buf[5], buf[6], buf[7]);
427 vpninfo->quit_reason = "Unknown packet received";
432 /* If SSL_write() fails we are expected to try again. With exactly
433 the same data, at exactly the same location. So we keep the
434 packet we had before.... */
435 if (vpninfo->current_ssl_pkt) {
437 vpninfo->ssl_times.last_tx = time(NULL);
438 vpninfo->pfds[vpninfo->ssl_pfd].events &= ~POLLOUT;
439 ret = SSL_write(vpninfo->https_ssl,
440 vpninfo->current_ssl_pkt->hdr,
441 vpninfo->current_ssl_pkt->len + 8);
443 ret = SSL_get_error(vpninfo->https_ssl, ret);
445 case SSL_ERROR_WANT_WRITE:
446 /* Waiting for the socket to become writable -- it's
447 probably stalled, and/or the buffers are full */
448 vpninfo->pfds[vpninfo->ssl_pfd].events |= POLLOUT;
449 case SSL_ERROR_WANT_READ:
450 if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
454 vpninfo->progress(vpninfo, PRG_ERR, "SSL_write failed: %d", ret);
455 ERR_print_errors_fp(stderr);
456 vpninfo->quit_reason = "SSL write error";
460 if (ret != vpninfo->current_ssl_pkt->len + 8) {
461 vpninfo->progress(vpninfo, PRG_ERR, "SSL wrote too few bytes! Asked for %d, sent %d\n",
462 vpninfo->current_ssl_pkt->len + 8, ret);
463 vpninfo->quit_reason = "Internal error";
466 /* Don't free the 'special' packets */
467 if (vpninfo->current_ssl_pkt != vpninfo->deflate_pkt &&
468 vpninfo->current_ssl_pkt != &dpd_pkt &&
469 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
470 vpninfo->current_ssl_pkt != &keepalive_pkt)
471 free(vpninfo->current_ssl_pkt);
473 vpninfo->current_ssl_pkt = NULL;
476 if (vpninfo->owe_ssl_dpd_response) {
477 vpninfo->owe_ssl_dpd_response = 0;
478 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
479 goto handle_outgoing;
482 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
484 /* Not that this will ever happen; we don't even process
485 the setting when we're asked for it. */
486 vpninfo->progress(vpninfo, PRG_ERR, "CSTP rekey due but we don't know how\n");
487 time(&vpninfo->ssl_times.last_rekey);
493 vpninfo->progress(vpninfo, PRG_ERR, "CSTP Dead Peer Detection detected dead peer!\n");
494 SSL_free(vpninfo->https_ssl);
495 vpninfo->https_ssl = NULL;
496 close(vpninfo->ssl_fd);
498 /* It's already deflated in the old stream. Extremely
499 non-trivial to reconstitute it; just throw it away */
500 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
501 vpninfo->current_ssl_pkt = NULL;
503 if (make_cstp_connection(vpninfo)) {
504 vpninfo->progress(vpninfo, PRG_ERR, "Reconnect failed\n");
505 vpninfo->quit_reason = "SSL DPD detected dead peer; reconnect failed";
508 /* I think we can leave DTLS to its own devices; when we reconnect
509 with the same master secret, we do seem to get the same sessid */
513 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP DPD\n");
515 vpninfo->current_ssl_pkt = &dpd_pkt;
516 goto handle_outgoing;
519 /* No need to send an explicit keepalive
520 if we have real data to send */
521 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
524 vpninfo->progress(vpninfo, PRG_TRACE, "Send CSTP Keepalive\n");
526 vpninfo->current_ssl_pkt = &keepalive_pkt;
527 goto handle_outgoing;
533 /* Service outgoing packet queue, if no DTLS */
534 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
535 struct pkt *this = vpninfo->outgoing_queue;
536 vpninfo->outgoing_queue = this->next;
538 if (vpninfo->deflate) {
539 unsigned char *adler;
542 vpninfo->deflate_strm.next_in = this->data;
543 vpninfo->deflate_strm.avail_in = this->len;
544 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
545 vpninfo->deflate_strm.avail_out = 2040;
546 vpninfo->deflate_strm.total_out = 0;
548 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
550 vpninfo->progress(vpninfo, PRG_ERR, "deflate failed %d\n", ret);
554 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
555 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
557 /* Add ongoing adler32 to tail of compressed packet */
558 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
559 this->data, this->len);
561 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
562 *(adler++) = vpninfo->deflate_adler32 >> 24;
563 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
564 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
565 *(adler) = vpninfo->deflate_adler32 & 0xff;
567 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
569 vpninfo->progress(vpninfo, PRG_TRACE,
570 "Sending compressed data packet of %d bytes\n",
573 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
576 memcpy(this->hdr, data_hdr, 8);
577 this->hdr[4] = this->len >> 8;
578 this->hdr[5] = this->len & 0xff;
580 vpninfo->progress(vpninfo, PRG_TRACE,
581 "Sending uncompressed data packet of %d bytes\n",
584 vpninfo->current_ssl_pkt = this;
586 goto handle_outgoing;
589 /* Work is not done if we just got rid of packets off the queue */
593 int cstp_bye(struct openconnect_info *vpninfo, char *reason)
595 unsigned char *bye_pkt;
596 int reason_len = strlen(reason);
597 bye_pkt = malloc(reason_len + 8);
601 memcpy(bye_pkt, data_hdr, 8);
602 memcpy(bye_pkt + 8, reason, strlen(reason));
604 bye_pkt[4] = reason_len >> 8;
605 bye_pkt[5] = reason_len & 0xff;
606 bye_pkt[6] = AC_PKT_DISCONN;
608 SSL_write(vpninfo->https_ssl, bye_pkt, reason_len + 8);
611 vpninfo->progress(vpninfo, PRG_TRACE,
612 "Send BYE packet: %s\n", reason);