Add cancellable openconnect_SSL_write(), use it from openconnect_SSL_printf()
[platform/upstream/openconnect.git] / cstp.c
1 /*
2  * OpenConnect (SSL + DTLS) VPN client
3  *
4  * Copyright © 2008-2010 Intel Corporation.
5  * Copyright © 2008 Nick Andrew <nick@nick-andrew.net>
6  *
7  * Author: David Woodhouse <dwmw2@infradead.org>
8  *
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.
12  *
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.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to:
20  *
21  *   Free Software Foundation, Inc.
22  *   51 Franklin Street, Fifth Floor,
23  *   Boston, MA 02110-1301 USA
24  */
25
26 #include <netdb.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <time.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <openssl/ssl.h>
34 #include <openssl/err.h>
35 #include <openssl/rand.h>
36
37 #include "openconnect-internal.h"
38
39 /*
40  * Data packets are encapsulated in the SSL stream as follows:
41  *
42  * 0000: Magic "STF\x1"
43  * 0004: Big-endian 16-bit length (not including 8-byte header)
44  * 0006: Byte packet type (see openconnect-internal.h)
45  * 0008: data payload
46  */
47
48 static char data_hdr[8] = {
49         'S', 'T', 'F', 1,
50         0, 0,           /* Length */
51         AC_PKT_DATA,    /* Type */
52         0               /* Unknown */
53 };
54
55 static struct pkt keepalive_pkt = {
56         .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_KEEPALIVE, 0 },
57 };
58
59 static struct pkt dpd_pkt = {
60         .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_OUT, 0 },
61 };
62
63 static struct pkt dpd_resp_pkt = {
64         .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 },
65 };
66
67
68 static int start_cstp_connection(struct openconnect_info *vpninfo)
69 {
70         char buf[65536];
71         int i;
72         int retried = 0, sessid_found = 0;
73         struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
74         struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
75         struct vpn_option *old_cstp_opts = vpninfo->cstp_options;
76         struct vpn_option *old_dtls_opts = vpninfo->dtls_options;
77         const char *old_addr = vpninfo->vpn_addr;
78         const char *old_netmask = vpninfo->vpn_netmask;
79         const char *old_addr6 = vpninfo->vpn_addr6;
80         const char *old_netmask6 = vpninfo->vpn_netmask6;
81         struct split_include *inc;
82
83         /* Clear old options which will be overwritten */
84         vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
85         vpninfo->vpn_addr6 = vpninfo->vpn_netmask6 = NULL;
86         vpninfo->cstp_options = vpninfo->dtls_options = NULL;
87         vpninfo->vpn_domain = vpninfo->vpn_proxy_pac = NULL;
88         vpninfo->banner = NULL;
89
90         for (i=0; i<3; i++)
91                 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
92
93         for (inc = vpninfo->split_includes; inc; ) {
94                 struct split_include *next = inc->next;
95                 free(inc);
96                 inc = next;
97         }
98         for (inc = vpninfo->split_excludes; inc; ) {
99                 struct split_include *next = inc->next;
100                 free(inc);
101                 inc = next;
102         }
103         vpninfo->split_includes = vpninfo->split_excludes = NULL;
104
105         /* Create (new) random master key for DTLS connection, if needed */
106         if (vpninfo->dtls_times.last_rekey + vpninfo->dtls_times.rekey <
107             time(NULL) + 300 &&
108             RAND_bytes(vpninfo->dtls_secret, sizeof(vpninfo->dtls_secret)) != 1) {
109                 fprintf(stderr, _("Failed to initialise DTLS secret\n"));
110                 exit(1);
111         }
112
113  retry:
114         openconnect_SSL_printf(vpninfo, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
115         openconnect_SSL_printf(vpninfo, "Host: %s\r\n", vpninfo->hostname);
116         openconnect_SSL_printf(vpninfo, "User-Agent: %s\r\n", vpninfo->useragent);
117         openconnect_SSL_printf(vpninfo, "Cookie: webvpn=%s\r\n", vpninfo->cookie);
118         openconnect_SSL_printf(vpninfo, "X-CSTP-Version: 1\r\n");
119         openconnect_SSL_printf(vpninfo, "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
120         if (vpninfo->deflate)
121                 openconnect_SSL_printf(vpninfo, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
122         openconnect_SSL_printf(vpninfo, "X-CSTP-MTU: %d\r\n", vpninfo->mtu);
123         openconnect_SSL_printf(vpninfo, "X-CSTP-Address-Type: %s\r\n",
124                                vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4");
125         openconnect_SSL_printf(vpninfo, "X-DTLS-Master-Secret: ");
126         for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
127                 openconnect_SSL_printf(vpninfo, "%02X", vpninfo->dtls_secret[i]);
128         openconnect_SSL_printf(vpninfo, "\r\nX-DTLS-CipherSuite: %s\r\n\r\n",
129                                vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA");
130
131         fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) & ~O_NONBLOCK);
132         if (openconnect_SSL_gets(vpninfo, buf, 65536) < 0) {
133                 vpn_progress(vpninfo, PRG_ERR,
134                              _("Error fetching HTTPS response\n"));
135                 if (!retried) {
136                         retried = 1;
137                         openconnect_close_https(vpninfo);
138
139                         if (openconnect_open_https(vpninfo)) {
140                                 vpn_progress(vpninfo, PRG_ERR,
141                                              _("Failed to open HTTPS connection to %s\n"),
142                                              vpninfo->hostname);
143                                 exit(1);
144                         }
145                         goto retry;
146                 }
147                 return -EINVAL;
148         }
149
150         if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
151                 if (!strncmp(buf, "HTTP/1.1 503 ", 13)) {
152                         /* "Service Unavailable. Why? */
153                         const char *reason = "<unknown>";
154                         while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
155                                 if (!strncmp(buf, "X-Reason: ", 10)) {
156                                         reason = buf + 10;
157                                         break;
158                                 }
159                         }
160                         vpn_progress(vpninfo, PRG_ERR,
161                                      _("VPN service unavailable; reason: %s\n"),
162                                      reason);
163                         return -EINVAL;
164                 }
165                 vpn_progress(vpninfo, PRG_ERR,
166                              _("Got inappropriate HTTP CONNECT response: %s\n"),
167                              buf);
168                 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
169                         exit(2);
170                 return -EINVAL;
171         }
172
173         vpn_progress(vpninfo, PRG_INFO, _("Got CONNECT response: %s\n"), buf);
174
175         /* We may have advertised it, but we only do it if the server agrees */
176         vpninfo->deflate = 0;
177
178         while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
179                 struct vpn_option *new_option;
180                 char *colon = strchr(buf, ':');
181                 if (!colon)
182                         continue;
183
184                 *colon = 0;
185                 colon++;
186                 if (*colon == ' ')
187                         colon++;
188
189                 if (strncmp(buf, "X-DTLS-", 7) &&
190                     strncmp(buf, "X-CSTP-", 7))
191                         continue;
192
193                 new_option = malloc(sizeof(*new_option));
194                 if (!new_option) {
195                         vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
196                         return -ENOMEM;
197                 }
198                 new_option->option = strdup(buf);
199                 new_option->value = strdup(colon);
200                 new_option->next = NULL;
201
202                 if (!new_option->option || !new_option->value) {
203                         vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
204                         return -ENOMEM;
205                 }
206
207                 vpn_progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
208
209                 if (!strncmp(buf, "X-DTLS-", 7)) {
210                         *next_dtls_option = new_option;
211                         next_dtls_option = &new_option->next;
212
213                         if (!strcmp(buf + 7, "Session-ID")) {
214                                 if (strlen(colon) != 64) {
215                                         vpn_progress(vpninfo, PRG_ERR,
216                                                      _("X-DTLS-Session-ID not 64 characters; is: \"%s\"\n"),
217                                                      colon);
218                                         vpninfo->dtls_attempt_period = 0;
219                                         return -EINVAL;
220                                 }
221                                 for (i = 0; i < 64; i += 2)
222                                         vpninfo->dtls_session_id[i/2] = unhex(colon + i);
223                                 sessid_found = 1;
224                                 time(&vpninfo->dtls_times.last_rekey);
225                         }
226                         continue;
227                 }
228                 /* CSTP options... */
229                 *next_cstp_option = new_option;
230                 next_cstp_option = &new_option->next;
231
232
233                 if (!strcmp(buf + 7, "Keepalive")) {
234                         vpninfo->ssl_times.keepalive = atol(colon);
235                 } else if (!strcmp(buf + 7, "DPD")) {
236                         int j = atol(colon);
237                         if (j && (!vpninfo->ssl_times.dpd || j < vpninfo->ssl_times.dpd))
238                                 vpninfo->ssl_times.dpd = j;
239                 } else if (!strcmp(buf + 7, "Rekey-Time")) {
240                         vpninfo->ssl_times.rekey = atol(colon);
241                 } else if (!strcmp(buf + 7, "Content-Encoding")) {
242                         if (!strcmp(colon, "deflate"))
243                                 vpninfo->deflate = 1;
244                         else {
245                                 vpn_progress(vpninfo, PRG_ERR,
246                                              _("Unknown CSTP-Content-Encoding %s\n"),
247                                              colon);
248                                 return -EINVAL;
249                         }
250                 } else if (!strcmp(buf + 7, "MTU")) {
251                         vpninfo->mtu = atol(colon);
252                 } else if (!strcmp(buf + 7, "Address")) {
253                         if (strchr(new_option->value, ':'))
254                                 vpninfo->vpn_addr6 = new_option->value;
255                         else
256                                 vpninfo->vpn_addr = new_option->value;
257                 } else if (!strcmp(buf + 7, "Netmask")) {
258                         if (strchr(new_option->value, ':'))
259                                 vpninfo->vpn_netmask6 = new_option->value;
260                         else
261                                 vpninfo->vpn_netmask = new_option->value;
262                 } else if (!strcmp(buf + 7, "DNS")) {
263                         int j;
264                         for (j = 0; j < 3; j++) {
265                                 if (!vpninfo->vpn_dns[j]) {
266                                         vpninfo->vpn_dns[j] = new_option->value;
267                                         break;
268                                 }
269                         }
270                 } else if (!strcmp(buf + 7, "NBNS")) {
271                         int j;
272                         for (j = 0; j < 3; j++) {
273                                 if (!vpninfo->vpn_nbns[j]) {
274                                         vpninfo->vpn_nbns[j] = new_option->value;
275                                         break;
276                                 }
277                         }
278                 } else if (!strcmp(buf + 7, "Default-Domain")) {
279                         vpninfo->vpn_domain = new_option->value;
280                 } else if (!strcmp(buf + 7, "MSIE-Proxy-PAC-URL")) {
281                         vpninfo->vpn_proxy_pac = new_option->value;
282                 } else if (!strcmp(buf + 7, "Banner")) {
283                         vpninfo->banner = new_option->value;
284                 } else if (!strcmp(buf + 7, "Split-Include")) {
285                         struct split_include *inc = malloc(sizeof(*inc));
286                         if (!inc)
287                                 continue;
288                         inc->route = new_option->value;
289                         inc->next = vpninfo->split_includes;
290                         vpninfo->split_includes = inc;
291                 } else if (!strcmp(buf + 7, "Split-Exclude")) {
292                         struct split_include *exc = malloc(sizeof(*exc));
293                         if (!exc)
294                                 continue;
295                         exc->route = new_option->value;
296                         exc->next = vpninfo->split_excludes;
297                         vpninfo->split_excludes = exc;
298                 }
299         }
300
301         if (!vpninfo->vpn_addr && !vpninfo->vpn_addr6) {
302                 vpn_progress(vpninfo, PRG_ERR,
303                              _("No IP address received. Aborting\n"));
304                 return -EINVAL;
305         }
306         if (old_addr) {
307                 if (strcmp(old_addr, vpninfo->vpn_addr)) {
308                         vpn_progress(vpninfo, PRG_ERR,
309                                      _("Reconnect gave different Legacy IP address (%s != %s)\n"),
310                                      vpninfo->vpn_addr, old_addr);
311                         return -EINVAL;
312                 }
313         }
314         if (old_netmask) {
315                 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
316                         vpn_progress(vpninfo, PRG_ERR,
317                                      _("Reconnect gave different Legacy IP netmask (%s != %s)\n"),
318                                      vpninfo->vpn_netmask, old_netmask);
319                         return -EINVAL;
320                 }
321         }
322         if (old_addr6) {
323                 if (strcmp(old_addr6, vpninfo->vpn_addr6)) {
324                         vpn_progress(vpninfo, PRG_ERR,
325                                      _("Reconnect gave different IPv6 address (%s != %s)\n"),
326                                      vpninfo->vpn_addr6, old_addr6);
327                         return -EINVAL;
328                 }
329         }
330         if (old_netmask6) {
331                 if (strcmp(old_netmask6, vpninfo->vpn_netmask6)) {
332                         vpn_progress(vpninfo, PRG_ERR,
333                                      _("Reconnect gave different IPv6 netmask (%s != %s)\n"),
334                                      vpninfo->vpn_netmask6, old_netmask6);
335                         return -EINVAL;
336                 }
337         }
338
339         while (old_dtls_opts) {
340                 struct vpn_option *tmp = old_dtls_opts;
341                 old_dtls_opts = old_dtls_opts->next;
342                 free(tmp->value);
343                 free(tmp->option);
344                 free(tmp);
345         }
346         while (old_cstp_opts) {
347                 struct vpn_option *tmp = old_cstp_opts;
348                 old_cstp_opts = old_cstp_opts->next;
349                 free(tmp->value);
350                 free(tmp->option);
351                 free(tmp);
352         }
353         vpn_progress(vpninfo, PRG_INFO, _("CSTP connected. DPD %d, Keepalive %d\n"),
354                      vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
355
356         BIO_set_nbio(SSL_get_rbio(vpninfo->https_ssl), 1);
357         BIO_set_nbio(SSL_get_wbio(vpninfo->https_ssl), 1);
358
359         fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) | O_NONBLOCK);
360         if (vpninfo->select_nfds <= vpninfo->ssl_fd)
361                 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
362
363         FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
364         FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
365
366         if (!sessid_found)
367                 vpninfo->dtls_attempt_period = 0;
368
369         vpninfo->ssl_times.last_rekey = vpninfo->ssl_times.last_rx =
370                 vpninfo->ssl_times.last_tx = time(NULL);
371         return 0;
372 }
373
374
375 int make_cstp_connection(struct openconnect_info *vpninfo)
376 {
377         int ret;
378
379         if (!vpninfo->https_ssl && (ret = openconnect_open_https(vpninfo)))
380                 return ret;
381
382         if (vpninfo->deflate) {
383                 vpninfo->deflate_adler32 = 1;
384                 vpninfo->inflate_adler32 = 1;
385
386                 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
387                     deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
388                                  Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
389                         vpn_progress(vpninfo, PRG_ERR, _("Compression setup failed\n"));
390                         vpninfo->deflate = 0;
391                 }
392
393                 if (!vpninfo->deflate_pkt) {
394                         vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
395                         if (!vpninfo->deflate_pkt) {
396                                 vpn_progress(vpninfo, PRG_ERR,
397                                              _("Allocation of deflate buffer failed\n"));
398                                 inflateEnd(&vpninfo->inflate_strm);
399                                 deflateEnd(&vpninfo->deflate_strm);
400                                 vpninfo->deflate = 0;
401                         } else {
402                                 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
403                                 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
404                                 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
405                         }
406                 }
407         }
408
409         return start_cstp_connection(vpninfo);
410 }
411
412 int cstp_reconnect(struct openconnect_info *vpninfo)
413 {
414         int ret;
415         int timeout;
416         int interval;
417
418         openconnect_close_https(vpninfo);
419
420         /* Requeue the original packet that was deflated */
421         if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
422                 vpninfo->current_ssl_pkt = NULL;
423                 queue_packet(&vpninfo->outgoing_queue, vpninfo->pending_deflated_pkt);
424                 vpninfo->pending_deflated_pkt = NULL;
425         }
426         if (vpninfo->deflate) {
427                 inflateEnd(&vpninfo->inflate_strm);
428                 deflateEnd(&vpninfo->deflate_strm);
429         }
430         timeout = vpninfo->reconnect_timeout;
431         interval = vpninfo->reconnect_interval;
432
433         while ((ret = make_cstp_connection(vpninfo))) {
434                 if (timeout <= 0)
435                         return ret;
436                 vpn_progress(vpninfo, PRG_INFO,
437                              _("sleep %ds, remaining timeout %ds\n"),
438                              interval, timeout);
439                 sleep(interval);
440                 if (killed)
441                         return 1;
442                 timeout -= interval;
443                 interval += vpninfo->reconnect_interval;
444                 if (interval > RECONNECT_INTERVAL_MAX)
445                         interval = RECONNECT_INTERVAL_MAX;
446         }
447         script_config_tun(vpninfo, "reconnect");
448         return 0;
449 }
450
451 static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
452                                     unsigned char *buf, int len)
453 {
454         struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
455         uint32_t pkt_sum;
456
457         if (!new)
458                 return -ENOMEM;
459
460         new->next = NULL;
461
462         vpninfo->inflate_strm.next_in = buf;
463         vpninfo->inflate_strm.avail_in = len - 4;
464
465         vpninfo->inflate_strm.next_out = new->data;
466         vpninfo->inflate_strm.avail_out = vpninfo->mtu;
467         vpninfo->inflate_strm.total_out = 0;
468
469         if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
470                 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
471                 free(new);
472                 return -EINVAL;
473         }
474
475         new->len = vpninfo->inflate_strm.total_out;
476
477         vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
478                                            new->data, new->len);
479
480         pkt_sum = buf[len - 1] | (buf[len - 2] << 8) |
481                 (buf[len - 3] << 16) | (buf[len - 4] << 24);
482
483         if (vpninfo->inflate_adler32 != pkt_sum) {
484                 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
485         }
486
487         vpn_progress(vpninfo, PRG_TRACE,
488                      _("Received compressed data packet of %ld bytes\n"),
489                      (long)vpninfo->inflate_strm.total_out);
490
491         queue_packet(&vpninfo->incoming_queue, new);
492         return 0;
493 }
494
495 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
496 {
497         unsigned char buf[16384];
498         int len, ret;
499         int work_done = 0;
500
501         /* FIXME: The poll() handling here is fairly simplistic. Actually,
502            if the SSL connection stalls it could return a WANT_WRITE error
503            on _either_ of the SSL_read() or SSL_write() calls. In that case,
504            we should probably remove POLLIN from the events we're looking for,
505            and add POLLOUT. As it is, though, it'll just chew CPU time in that
506            fairly unlikely situation, until the write backlog clears. */
507         while ( (len = SSL_read(vpninfo->https_ssl, buf, sizeof(buf))) > 0) {
508                 int payload_len;
509
510                 if (buf[0] != 'S' || buf[1] != 'T' ||
511                     buf[2] != 'F' || buf[3] != 1 || buf[7])
512                         goto unknown_pkt;
513
514                 payload_len = (buf[4] << 8) + buf[5];
515                 if (len != 8 + payload_len) {
516                         vpn_progress(vpninfo, PRG_ERR,
517                                      _("Unexpected packet length. SSL_read returned %d but packet is\n"),
518                                      len);
519                         vpn_progress(vpninfo, PRG_ERR,
520                                      "%02x %02x %02x %02x %02x %02x %02x %02x\n",
521                                      buf[0], buf[1], buf[2], buf[3],
522                                      buf[4], buf[5], buf[6], buf[7]);
523                         continue;
524                 }
525                 vpninfo->ssl_times.last_rx = time(NULL);
526                 switch(buf[6]) {
527                 case AC_PKT_DPD_OUT:
528                         vpn_progress(vpninfo, PRG_TRACE,
529                                      _("Got CSTP DPD request\n"));
530                         vpninfo->owe_ssl_dpd_response = 1;
531                         continue;
532
533                 case AC_PKT_DPD_RESP:
534                         vpn_progress(vpninfo, PRG_TRACE,
535                                      _("Got CSTP DPD response\n"));
536                         continue;
537
538                 case AC_PKT_KEEPALIVE:
539                         vpn_progress(vpninfo, PRG_TRACE,
540                                      _("Got CSTP Keepalive\n"));
541                         continue;
542
543                 case AC_PKT_DATA:
544                         vpn_progress(vpninfo, PRG_TRACE,
545                                      _("Received uncompressed data packet of %d bytes\n"),
546                                      payload_len);
547                         queue_new_packet(&vpninfo->incoming_queue, buf + 8,
548                                          payload_len);
549                         work_done = 1;
550                         continue;
551
552                 case AC_PKT_DISCONN: {
553                         int i;
554                         for (i = 0; i < payload_len; i++) {
555                                 if (!isprint(buf[payload_len + 8 + i]))
556                                         buf[payload_len + 8 + i] = '.';
557                         }
558                         buf[payload_len + 8] = 0;
559                         vpn_progress(vpninfo, PRG_ERR,
560                                      _("Received server disconnect: %02x '%s'\n"),
561                                      buf[8], buf + 9);
562                         vpninfo->quit_reason = "Server request";
563                         return 1;
564                 }
565                 case AC_PKT_COMPRESSED:
566                         if (!vpninfo->deflate) {
567                                 vpn_progress(vpninfo, PRG_ERR,
568                                              _("Compressed packet received in !deflate mode\n"));
569                                 goto unknown_pkt;
570                         }
571                         inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
572                         work_done = 1;
573                         continue;
574
575                 case AC_PKT_TERM_SERVER:
576                         vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
577                         vpninfo->quit_reason = "Server request";
578                         return 1;
579                 }
580
581         unknown_pkt:
582                 vpn_progress(vpninfo, PRG_ERR,
583                              _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
584                              buf[0], buf[1], buf[2], buf[3],
585                              buf[4], buf[5], buf[6], buf[7]);
586                 vpninfo->quit_reason = "Unknown packet received";
587                 return 1;
588         }
589
590         ret = SSL_get_error(vpninfo->https_ssl, len);
591         if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
592                 vpn_progress(vpninfo, PRG_ERR,
593                              _("SSL read error %d (server probably closed connection); reconnecting.\n"),
594                              ret);
595                         goto do_reconnect;
596         }
597
598
599         /* If SSL_write() fails we are expected to try again. With exactly
600            the same data, at exactly the same location. So we keep the
601            packet we had before.... */
602         if (vpninfo->current_ssl_pkt) {
603         handle_outgoing:
604                 vpninfo->ssl_times.last_tx = time(NULL);
605                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
606                 ret = SSL_write(vpninfo->https_ssl,
607                                 vpninfo->current_ssl_pkt->hdr,
608                                 vpninfo->current_ssl_pkt->len + 8);
609                 if (ret <= 0) {
610                         ret = SSL_get_error(vpninfo->https_ssl, ret);
611                         switch (ret) {
612                         case SSL_ERROR_WANT_WRITE:
613                                 /* Waiting for the socket to become writable -- it's
614                                    probably stalled, and/or the buffers are full */
615                                 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
616
617                         case SSL_ERROR_WANT_READ:
618                                 if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
619                                         goto peer_dead;
620                                 return work_done;
621                         default:
622                                 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
623                                 report_ssl_errors(vpninfo);
624                                 goto do_reconnect;
625                         }
626                 }
627                 if (ret != vpninfo->current_ssl_pkt->len + 8) {
628                         vpn_progress(vpninfo, PRG_ERR,
629                                      _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
630                                      vpninfo->current_ssl_pkt->len + 8, ret);
631                         vpninfo->quit_reason = "Internal error";
632                         return 1;
633                 }
634                 /* Don't free the 'special' packets */
635                 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
636                         free(vpninfo->pending_deflated_pkt);
637                 else if (vpninfo->current_ssl_pkt != &dpd_pkt &&
638                          vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
639                          vpninfo->current_ssl_pkt != &keepalive_pkt)
640                         free(vpninfo->current_ssl_pkt);
641
642                 vpninfo->current_ssl_pkt = NULL;
643         }
644
645         if (vpninfo->owe_ssl_dpd_response) {
646                 vpninfo->owe_ssl_dpd_response = 0;
647                 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
648                 goto handle_outgoing;
649         }
650
651         switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
652         case KA_REKEY:
653                 /* Not that this will ever happen; we don't even process
654                    the setting when we're asked for it. */
655                 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
656                 goto do_reconnect;
657                 break;
658
659         case KA_DPD_DEAD:
660         peer_dead:
661                 vpn_progress(vpninfo, PRG_ERR,
662                              _("CSTP Dead Peer Detection detected dead peer!\n"));
663         do_reconnect:
664                 if (cstp_reconnect(vpninfo)) {
665                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
666                         vpninfo->quit_reason = "CSTP reconnect failed";
667                         return 1;
668                 }
669                 /* I think we can leave DTLS to its own devices; when we reconnect
670                    with the same master secret, we do seem to get the same sessid */
671                 return 1;
672
673         case KA_DPD:
674                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
675
676                 vpninfo->current_ssl_pkt = &dpd_pkt;
677                 goto handle_outgoing;
678
679         case KA_KEEPALIVE:
680                 /* No need to send an explicit keepalive
681                    if we have real data to send */
682                 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
683                         break;
684
685                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
686
687                 vpninfo->current_ssl_pkt = &keepalive_pkt;
688                 goto handle_outgoing;
689
690         case KA_NONE:
691                 ;
692         }
693
694         /* Service outgoing packet queue, if no DTLS */
695         while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
696                 struct pkt *this = vpninfo->outgoing_queue;
697                 vpninfo->outgoing_queue = this->next;
698                 vpninfo->outgoing_qlen--;
699
700                 if (vpninfo->deflate) {
701                         unsigned char *adler;
702                         int ret;
703
704                         vpninfo->deflate_strm.next_in = this->data;
705                         vpninfo->deflate_strm.avail_in = this->len;
706                         vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
707                         vpninfo->deflate_strm.avail_out = 2040;
708                         vpninfo->deflate_strm.total_out = 0;
709
710                         ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
711                         if (ret) {
712                                 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
713                                 goto uncompr;
714                         }
715
716                         vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
717                         vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
718
719                         /* Add ongoing adler32 to tail of compressed packet */
720                         vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
721                                                            this->data, this->len);
722
723                         adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
724                         *(adler++) =  vpninfo->deflate_adler32 >> 24;
725                         *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
726                         *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
727                         *(adler)   =  vpninfo->deflate_adler32 & 0xff;
728
729                         vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
730
731                         vpn_progress(vpninfo, PRG_TRACE,
732                                      _("Sending compressed data packet of %d bytes\n"),
733                                      this->len);
734
735                         vpninfo->pending_deflated_pkt = this;
736                         vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
737                 } else {
738                 uncompr:
739                         memcpy(this->hdr, data_hdr, 8);
740                         this->hdr[4] = this->len >> 8;
741                         this->hdr[5] = this->len & 0xff;
742
743                         vpn_progress(vpninfo, PRG_TRACE,
744                                      _("Sending uncompressed data packet of %d bytes\n"),
745                                      this->len);
746
747                         vpninfo->current_ssl_pkt = this;
748                 }
749                 goto handle_outgoing;
750         }
751
752         /* Work is not done if we just got rid of packets off the queue */
753         return work_done;
754 }
755
756 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
757 {
758         unsigned char *bye_pkt;
759         int reason_len;
760
761         /* already lost connection? */
762         if (!vpninfo->https_ssl)
763                 return 0;
764
765         reason_len = strlen(reason);
766         bye_pkt = malloc(reason_len + 9);
767         if (!bye_pkt)
768                 return -ENOMEM;
769
770         memcpy(bye_pkt, data_hdr, 8);
771         memcpy(bye_pkt + 9, reason, reason_len);
772
773         bye_pkt[4] = (reason_len + 1) >> 8;
774         bye_pkt[5] = (reason_len + 1) & 0xff;
775         bye_pkt[6] = AC_PKT_DISCONN;
776         bye_pkt[8] = 0xb0;
777
778         SSL_write(vpninfo->https_ssl, bye_pkt, reason_len + 9);
779         free(bye_pkt);
780
781         vpn_progress(vpninfo, PRG_INFO,
782                      _("Send BYE packet: %s\n"), reason);
783
784         return 0;
785 }