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
28 #include <openssl/ssl.h>
29 #include <openssl/err.h>
31 #include "openconnect.h"
34 * Data packets are encapsulated in the SSL stream as follows:
36 * 0000: Magic "STF\x1"
37 * 0004: Big-endian 16-bit length (not including 8-byte header)
38 * 0006: Byte packet type (see openconnect.h)
42 static char data_hdr[8] = {
45 AC_PKT_DATA, /* Type */
49 static struct pkt keepalive_pkt = {
50 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_KEEPALIVE, 0 },
53 static struct pkt dpd_pkt = {
54 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_OUT, 0 },
57 static struct pkt dpd_resp_pkt = {
58 .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 },
62 static int start_cstp_connection(struct openconnect_info *vpninfo)
67 struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
68 struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
69 struct vpn_option *old_cstp_opts = vpninfo->cstp_options;
70 struct vpn_option *old_dtls_opts = vpninfo->dtls_options;
71 const char *old_addr = vpninfo->vpn_addr;
72 const char *old_netmask = vpninfo->vpn_netmask;
74 /* Clear old options which will be overwritten */
75 vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
76 vpninfo->cstp_options = vpninfo->dtls_options = NULL;
78 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
81 openconnect_SSL_printf(vpninfo->https_ssl, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
82 openconnect_SSL_printf(vpninfo->https_ssl, "Host: %s\r\n", vpninfo->hostname);
83 openconnect_SSL_printf(vpninfo->https_ssl, "User-Agent: %s\r\n", vpninfo->useragent);
84 openconnect_SSL_printf(vpninfo->https_ssl, "Cookie: webvpn=%s\r\n", vpninfo->cookie);
85 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Version: 1\r\n");
86 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
88 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
89 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-MTU: %d\r\n", vpninfo->mtu);
90 /* To enable IPv6, send 'IPv6,IPv4'.
91 We don't know how most of that works yet though. */
92 openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Address-Type: IPv4\r\n");
93 openconnect_SSL_printf(vpninfo->https_ssl, "X-DTLS-Master-Secret: ");
94 for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
95 openconnect_SSL_printf(vpninfo->https_ssl, "%02X", vpninfo->dtls_secret[i]);
96 openconnect_SSL_printf(vpninfo->https_ssl, "\r\nX-DTLS-CipherSuite: AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA\r\n\r\n");
98 if (openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536) < 0) {
99 fprintf(stderr, "Error fetching HTTPS response\n");
102 SSL_free(vpninfo->https_ssl);
103 close(vpninfo->ssl_fd);
105 if (openconnect_open_https(vpninfo)) {
106 fprintf(stderr, "Failed to open HTTPS connection to %s\n",
115 if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
116 fprintf(stderr, "Got inappropriate HTTP CONNECT response: %s\n",
118 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
120 openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536);
125 printf("Got CONNECT response: %s\n", buf);
127 /* We may have advertised it, but we only do it if the server agrees */
128 vpninfo->deflate = 0;
130 while ((i=openconnect_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
131 struct vpn_option *new_option;
132 char *colon = strchr(buf, ':');
141 if (strncmp(buf, "X-DTLS-", 7) &&
142 strncmp(buf, "X-CSTP-", 7))
145 new_option = malloc(sizeof(*new_option));
147 fprintf(stderr, "No memory for options\n");
150 new_option->option = strdup(buf);
151 new_option->value = strdup(colon);
152 new_option->next = NULL;
154 if (!new_option->option || !new_option->value) {
155 fprintf(stderr, "No memory for options\n");
160 printf("%s: %s\n", buf, colon);
162 if (!strncmp(buf, "X-DTLS-", 7)) {
163 *next_dtls_option = new_option;
164 next_dtls_option = &new_option->next;
167 /* CSTP options... */
168 *next_cstp_option = new_option;
169 next_cstp_option = &new_option->next;
172 if (!strcmp(buf + 7, "Keepalive")) {
173 vpninfo->ssl_times.keepalive = atol(colon);
174 } else if (!strcmp(buf + 7, "DPD")) {
175 vpninfo->ssl_times.dpd = atol(colon);
176 } else if (!strcmp(buf + 7, "Content-Encoding")) {
177 if (!strcmp(colon, "deflate"))
178 vpninfo->deflate = 1;
181 "Unknown CSTP-Content-Encoding %s\n",
185 } else if (!strcmp(buf + 7, "MTU")) {
186 vpninfo->mtu = atol(colon);
187 } else if (!strcmp(buf + 7, "Address")) {
188 vpninfo->vpn_addr = new_option->value;
189 } else if (!strcmp(buf + 7, "Netmask")) {
190 vpninfo->vpn_netmask = new_option->value;
191 } else if (!strcmp(buf + 7, "DNS")) {
193 for (j = 0; j < 3; j++) {
194 if (!vpninfo->vpn_dns[j]) {
195 vpninfo->vpn_dns[j] = new_option->value;
199 } else if (!strcmp(buf + 7, "NBNS")) {
201 for (j = 0; j < 3; j++) {
202 if (!vpninfo->vpn_nbns[j]) {
203 vpninfo->vpn_nbns[j] = new_option->value;
207 } else if (!strcmp(buf + 7, "Default-Domain")) {
208 vpninfo->vpn_domain = new_option->value;
212 if (!vpninfo->vpn_addr) {
213 fprintf(stderr, "No IP address received. Aborting\n");
216 if (!vpninfo->vpn_netmask)
217 vpninfo->vpn_netmask = "255.255.255.255";
219 if (strcmp(old_addr, vpninfo->vpn_addr)) {
220 fprintf(stderr, "Reconnect gave different IP address (%s != %s)\n",
221 vpninfo->vpn_addr, old_addr);
226 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
227 fprintf(stderr, "Reconnect gave different netmask (%s != %s)\n",
228 vpninfo->vpn_netmask, old_netmask);
233 while (old_dtls_opts) {
234 struct vpn_option *tmp = old_dtls_opts;
235 old_dtls_opts = old_dtls_opts->next;
240 while (old_cstp_opts) {
241 struct vpn_option *tmp = old_cstp_opts;
242 old_cstp_opts = old_cstp_opts->next;
248 printf("CSTP connected. DPD %d, Keepalive %d\n",
249 vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
251 BIO_set_nbio(SSL_get_rbio(vpninfo->https_ssl),1);
252 BIO_set_nbio(SSL_get_wbio(vpninfo->https_ssl),1);
254 fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) | O_NONBLOCK);
255 vpninfo->ssl_pfd = vpn_add_pollfd(vpninfo, vpninfo->ssl_fd, POLLIN|POLLHUP|POLLERR);
257 vpninfo->ssl_times.last_rx = vpninfo->ssl_times.last_tx = time(NULL);
262 int make_cstp_connection(struct openconnect_info *vpninfo)
264 if (!vpninfo->https_ssl && openconnect_open_https(vpninfo))
267 if (vpninfo->deflate) {
268 vpninfo->deflate_adler32 = 1;
269 vpninfo->inflate_adler32 = 1;
271 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
272 deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
273 Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
274 fprintf(stderr, "Compression setup failed\n");
275 vpninfo->deflate = 0;
278 if (!vpninfo->deflate_pkt) {
279 vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
280 if (!vpninfo->deflate_pkt) {
281 fprintf(stderr, "Allocation of deflate buffer failed\n");
282 vpninfo->deflate = 0;
284 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
285 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
286 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
290 if (start_cstp_connection(vpninfo))
297 static int inflate_and_queue_packet(struct openconnect_info *vpninfo, int type, void *buf, int len)
299 struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
307 vpninfo->inflate_strm.next_in = buf;
308 vpninfo->inflate_strm.avail_in = len - 4;
310 vpninfo->inflate_strm.next_out = new->data;
311 vpninfo->inflate_strm.avail_out = vpninfo->mtu;
312 vpninfo->inflate_strm.total_out = 0;
314 if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
315 fprintf(stderr, "inflate failed\n");
320 new->len = vpninfo->inflate_strm.total_out;
322 vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
323 new->data, new->len);
325 if (vpninfo->inflate_adler32 != ntohl( *(uint32_t *)(buf + len - 4))) {
326 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
330 printf("Received compressed data packet of %ld bytes\n",
331 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 printf("Unexpected packet length. SSL_read returned %d but packet is\n",
361 printf("%02x %02x %02x %02x %02x %02x %02x %02x\n",
362 buf[0], buf[1], buf[2], buf[3],
363 buf[4], buf[5], buf[6], buf[7]);
366 vpninfo->ssl_times.last_rx = time(NULL);
370 printf("Got CSTP DPD request\n");
371 vpninfo->owe_ssl_dpd_response = 1;
374 case AC_PKT_DPD_RESP:
376 printf("Got CSTP DPD response\n");
379 case AC_PKT_KEEPALIVE:
381 printf("Got CSTP Keepalive\n");
386 printf("Received uncompressed data packet of %d bytes\n",
389 queue_new_packet(&vpninfo->incoming_queue, AF_INET, buf + 8,
394 case AC_PKT_COMPRESSED:
395 if (!vpninfo->deflate) {
396 fprintf(stderr, "Compressed packet received in !deflate mode\n");
399 inflate_and_queue_packet(vpninfo, AF_INET, buf + 8, payload_len);
403 case AC_PKT_TERM_SERVER:
404 fprintf(stderr, "received server terminate packet\n");
405 vpninfo->quit_reason = "Server request";
410 printf("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n",
411 buf[0], buf[1], buf[2], buf[3],
412 buf[4], buf[5], buf[6], buf[7]);
413 vpninfo->quit_reason = "Unknown packet received";
418 /* If SSL_write() fails we are expected to try again. With exactly
419 the same data, at exactly the same location. So we keep the
420 packet we had before.... */
421 if (vpninfo->current_ssl_pkt) {
423 vpninfo->ssl_times.last_tx = time(NULL);
424 vpninfo->pfds[vpninfo->ssl_pfd].events &= ~POLLOUT;
425 ret = SSL_write(vpninfo->https_ssl,
426 vpninfo->current_ssl_pkt->hdr,
427 vpninfo->current_ssl_pkt->len + 8);
429 ret = SSL_get_error(vpninfo->https_ssl, ret);
431 case SSL_ERROR_WANT_WRITE:
432 /* Waiting for the socket to become writable -- it's
433 probably stalled, and/or the buffers are full */
434 vpninfo->pfds[vpninfo->ssl_pfd].events |= POLLOUT;
435 case SSL_ERROR_WANT_READ:
436 if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
440 fprintf(stderr, "SSL_write failed: %d", ret);
441 ERR_print_errors_fp(stderr);
442 vpninfo->quit_reason = "SSL write error";
446 if (ret != vpninfo->current_ssl_pkt->len + 8) {
447 fprintf(stderr, "SSL wrote too few bytes! Asked for %d, sent %d\n",
448 vpninfo->current_ssl_pkt->len + 8, ret);
449 vpninfo->quit_reason = "Internal error";
452 /* Don't free the 'special' packets */
453 if (vpninfo->current_ssl_pkt != vpninfo->deflate_pkt &&
454 vpninfo->current_ssl_pkt != &dpd_pkt &&
455 vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
456 vpninfo->current_ssl_pkt != &keepalive_pkt)
457 free(vpninfo->current_ssl_pkt);
459 vpninfo->current_ssl_pkt = NULL;
462 if (vpninfo->owe_ssl_dpd_response) {
463 vpninfo->owe_ssl_dpd_response = 0;
464 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
465 goto handle_outgoing;
468 switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
470 /* Not that this will ever happen; we don't even process
471 the setting when we're asked for it. */
472 fprintf(stderr, "CSTP rekey due but we don't know how\n");
473 time(&vpninfo->ssl_times.last_rekey);
479 fprintf(stderr, "CSTP Dead Peer Detection detected dead peer!\n");
480 SSL_free(vpninfo->https_ssl);
481 vpninfo->https_ssl = NULL;
482 close(vpninfo->ssl_fd);
484 /* It's already deflated in the old stream. Extremely
485 non-trivial to reconstitute it; just throw it away */
486 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
487 vpninfo->current_ssl_pkt = NULL;
489 if (make_cstp_connection(vpninfo)) {
490 fprintf(stderr, "Reconnect failed\n");
491 vpninfo->quit_reason = "SSL DPD detected dead peer; reconnect failed";
494 /* I think we can leave DTLS to its own devices; when we reconnect
495 with the same master secret, we do seem to get the same sessid */
500 printf("Send CSTP DPD\n");
502 vpninfo->current_ssl_pkt = &dpd_pkt;
503 goto handle_outgoing;
506 /* No need to send an explicit keepalive
507 if we have real data to send */
508 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
512 printf("Send CSTP Keepalive\n");
514 vpninfo->current_ssl_pkt = &keepalive_pkt;
515 goto handle_outgoing;
521 /* Service outgoing packet queue, if no DTLS */
522 while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
523 struct pkt *this = vpninfo->outgoing_queue;
524 vpninfo->outgoing_queue = this->next;
526 if (vpninfo->deflate) {
527 unsigned char *adler;
530 vpninfo->deflate_strm.next_in = this->data;
531 vpninfo->deflate_strm.avail_in = this->len;
532 vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
533 vpninfo->deflate_strm.avail_out = 2040;
534 vpninfo->deflate_strm.total_out = 0;
536 ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
538 fprintf(stderr, "deflate failed %d\n", ret);
542 vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
543 vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
545 /* Add ongoing adler32 to tail of compressed packet */
546 vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
547 this->data, this->len);
549 adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
550 *(adler++) = vpninfo->deflate_adler32 >> 24;
551 *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
552 *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
553 *(adler) = vpninfo->deflate_adler32 & 0xff;
555 vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
558 printf("Sending compressed data packet of %d bytes\n",
561 vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
564 memcpy(this->hdr, data_hdr, 8);
565 this->hdr[4] = this->len >> 8;
566 this->hdr[5] = this->len & 0xff;
569 printf("Sending uncompressed data packet of %d bytes\n",
572 vpninfo->current_ssl_pkt = this;
574 goto handle_outgoing;
577 /* Work is not done if we just got rid of packets off the queue */
581 int cstp_bye(struct openconnect_info *vpninfo, char *reason)
583 unsigned char *bye_pkt;
584 int reason_len = strlen(reason);
585 bye_pkt = malloc(reason_len + 8);
589 memcpy(bye_pkt, data_hdr, 8);
590 memcpy(bye_pkt + 8, reason, strlen(reason));
592 bye_pkt[4] = reason_len >> 8;
593 bye_pkt[5] = reason_len & 0xff;
596 SSL_write(vpninfo->https_ssl, bye_pkt, reason_len + 8);
600 printf("Send BYE packet: %s\n", reason);