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