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