Invoke vpnc-script with "pre-init" to load tun module if necessary
[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                                 inflateEnd(&vpninfo->inflate_strm);
398                                 deflateEnd(&vpninfo->deflate_strm);
399                                 vpninfo->deflate = 0;
400                         } else {
401                                 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
402                                 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
403                                 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
404                         }
405                 }
406         }
407
408         return start_cstp_connection(vpninfo);
409 }
410
411 int cstp_reconnect(struct openconnect_info *vpninfo)
412 {
413         int ret;
414         int timeout;
415         int interval;
416
417         openconnect_close_https(vpninfo);
418
419         /* Requeue the original packet that was deflated */
420         if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
421                 vpninfo->current_ssl_pkt = NULL;
422                 queue_packet(&vpninfo->outgoing_queue, vpninfo->pending_deflated_pkt);
423                 vpninfo->pending_deflated_pkt = NULL;
424         }
425         if (vpninfo->deflate) {
426                 inflateEnd(&vpninfo->inflate_strm);
427                 deflateEnd(&vpninfo->deflate_strm);
428         }
429         timeout = vpninfo->reconnect_timeout;
430         interval = vpninfo->reconnect_interval;
431
432         while ((ret = make_cstp_connection(vpninfo))) {
433                 if (timeout <= 0)
434                         return ret;
435                 vpn_progress(vpninfo, PRG_INFO,
436                              _("sleep %ds, remaining timeout %ds\n"),
437                              interval, timeout);
438                 sleep(interval);
439                 if (killed)
440                         return 1;
441                 timeout -= interval;
442                 interval += vpninfo->reconnect_interval;
443                 if (interval > RECONNECT_INTERVAL_MAX)
444                         interval = RECONNECT_INTERVAL_MAX;
445         }
446         script_config_tun(vpninfo, "reconnect");
447         return 0;
448 }
449
450 static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
451                                     unsigned char *buf, int len)
452 {
453         struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
454         uint32_t pkt_sum;
455
456         if (!new)
457                 return -ENOMEM;
458
459         new->next = NULL;
460
461         vpninfo->inflate_strm.next_in = buf;
462         vpninfo->inflate_strm.avail_in = len - 4;
463
464         vpninfo->inflate_strm.next_out = new->data;
465         vpninfo->inflate_strm.avail_out = vpninfo->mtu;
466         vpninfo->inflate_strm.total_out = 0;
467
468         if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
469                 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
470                 free(new);
471                 return -EINVAL;
472         }
473
474         new->len = vpninfo->inflate_strm.total_out;
475
476         vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
477                                            new->data, new->len);
478
479         pkt_sum = buf[len - 1] | (buf[len - 2] << 8) |
480                 (buf[len - 3] << 16) | (buf[len - 4] << 24);
481
482         if (vpninfo->inflate_adler32 != pkt_sum) {
483                 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
484         }
485
486         vpn_progress(vpninfo, PRG_TRACE,
487                      _("Received compressed data packet of %ld bytes\n"),
488                      (long)vpninfo->inflate_strm.total_out);
489
490         queue_packet(&vpninfo->incoming_queue, new);
491         return 0;
492 }
493
494 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
495 {
496         unsigned char buf[16384];
497         int len, ret;
498         int work_done = 0;
499
500         /* FIXME: The poll() handling here is fairly simplistic. Actually,
501            if the SSL connection stalls it could return a WANT_WRITE error
502            on _either_ of the SSL_read() or SSL_write() calls. In that case,
503            we should probably remove POLLIN from the events we're looking for,
504            and add POLLOUT. As it is, though, it'll just chew CPU time in that
505            fairly unlikely situation, until the write backlog clears. */
506         while ( (len = SSL_read(vpninfo->https_ssl, buf, sizeof(buf))) > 0) {
507                 int payload_len;
508
509                 if (buf[0] != 'S' || buf[1] != 'T' ||
510                     buf[2] != 'F' || buf[3] != 1 || buf[7])
511                         goto unknown_pkt;
512
513                 payload_len = (buf[4] << 8) + buf[5];
514                 if (len != 8 + payload_len) {
515                         vpn_progress(vpninfo, PRG_ERR,
516                                      _("Unexpected packet length. SSL_read returned %d but packet is\n"),
517                                      len);
518                         vpn_progress(vpninfo, PRG_ERR,
519                                      "%02x %02x %02x %02x %02x %02x %02x %02x\n",
520                                      buf[0], buf[1], buf[2], buf[3],
521                                      buf[4], buf[5], buf[6], buf[7]);
522                         continue;
523                 }
524                 vpninfo->ssl_times.last_rx = time(NULL);
525                 switch(buf[6]) {
526                 case AC_PKT_DPD_OUT:
527                         vpn_progress(vpninfo, PRG_TRACE,
528                                      _("Got CSTP DPD request\n"));
529                         vpninfo->owe_ssl_dpd_response = 1;
530                         continue;
531
532                 case AC_PKT_DPD_RESP:
533                         vpn_progress(vpninfo, PRG_TRACE,
534                                      _("Got CSTP DPD response\n"));
535                         continue;
536
537                 case AC_PKT_KEEPALIVE:
538                         vpn_progress(vpninfo, PRG_TRACE,
539                                      _("Got CSTP Keepalive\n"));
540                         continue;
541
542                 case AC_PKT_DATA:
543                         vpn_progress(vpninfo, PRG_TRACE,
544                                      _("Received uncompressed data packet of %d bytes\n"),
545                                      payload_len);
546                         queue_new_packet(&vpninfo->incoming_queue, buf + 8,
547                                          payload_len);
548                         work_done = 1;
549                         continue;
550
551                 case AC_PKT_DISCONN: {
552                         int i;
553                         for (i = 0; i < payload_len; i++) {
554                                 if (!isprint(buf[payload_len + 8 + i]))
555                                         buf[payload_len + 8 + i] = '.';
556                         }
557                         buf[payload_len + 8] = 0;
558                         vpn_progress(vpninfo, PRG_ERR,
559                                      _("Received server disconnect: %02x '%s'\n"),
560                                      buf[8], buf + 9);
561                         vpninfo->quit_reason = "Server request";
562                         return 1;
563                 }
564                 case AC_PKT_COMPRESSED:
565                         if (!vpninfo->deflate) {
566                                 vpn_progress(vpninfo, PRG_ERR,
567                                              _("Compressed packet received in !deflate mode\n"));
568                                 goto unknown_pkt;
569                         }
570                         inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
571                         work_done = 1;
572                         continue;
573
574                 case AC_PKT_TERM_SERVER:
575                         vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
576                         vpninfo->quit_reason = "Server request";
577                         return 1;
578                 }
579
580         unknown_pkt:
581                 vpn_progress(vpninfo, PRG_ERR,
582                              _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
583                              buf[0], buf[1], buf[2], buf[3],
584                              buf[4], buf[5], buf[6], buf[7]);
585                 vpninfo->quit_reason = "Unknown packet received";
586                 return 1;
587         }
588
589         ret = SSL_get_error(vpninfo->https_ssl, len);
590         if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
591                 vpn_progress(vpninfo, PRG_ERR,
592                              _("SSL read error %d (server probably closed connection); reconnecting.\n"),
593                              ret);
594                         goto do_reconnect;
595         }
596
597
598         /* If SSL_write() fails we are expected to try again. With exactly
599            the same data, at exactly the same location. So we keep the
600            packet we had before.... */
601         if (vpninfo->current_ssl_pkt) {
602         handle_outgoing:
603                 vpninfo->ssl_times.last_tx = time(NULL);
604                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
605                 ret = SSL_write(vpninfo->https_ssl,
606                                 vpninfo->current_ssl_pkt->hdr,
607                                 vpninfo->current_ssl_pkt->len + 8);
608                 if (ret <= 0) {
609                         ret = SSL_get_error(vpninfo->https_ssl, ret);
610                         switch (ret) {
611                         case SSL_ERROR_WANT_WRITE:
612                                 /* Waiting for the socket to become writable -- it's
613                                    probably stalled, and/or the buffers are full */
614                                 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
615
616                         case SSL_ERROR_WANT_READ:
617                                 if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
618                                         goto peer_dead;
619                                 return work_done;
620                         default:
621                                 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
622                                 report_ssl_errors(vpninfo);
623                                 goto do_reconnect;
624                         }
625                 }
626                 if (ret != vpninfo->current_ssl_pkt->len + 8) {
627                         vpn_progress(vpninfo, PRG_ERR,
628                                      _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
629                                      vpninfo->current_ssl_pkt->len + 8, ret);
630                         vpninfo->quit_reason = "Internal error";
631                         return 1;
632                 }
633                 /* Don't free the 'special' packets */
634                 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
635                         free(vpninfo->pending_deflated_pkt);
636                 else if (vpninfo->current_ssl_pkt != &dpd_pkt &&
637                          vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
638                          vpninfo->current_ssl_pkt != &keepalive_pkt)
639                         free(vpninfo->current_ssl_pkt);
640
641                 vpninfo->current_ssl_pkt = NULL;
642         }
643
644         if (vpninfo->owe_ssl_dpd_response) {
645                 vpninfo->owe_ssl_dpd_response = 0;
646                 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
647                 goto handle_outgoing;
648         }
649
650         switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
651         case KA_REKEY:
652                 /* Not that this will ever happen; we don't even process
653                    the setting when we're asked for it. */
654                 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
655                 goto do_reconnect;
656                 break;
657
658         case KA_DPD_DEAD:
659         peer_dead:
660                 vpn_progress(vpninfo, PRG_ERR,
661                              _("CSTP Dead Peer Detection detected dead peer!\n"));
662         do_reconnect:
663                 if (cstp_reconnect(vpninfo)) {
664                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
665                         vpninfo->quit_reason = "CSTP reconnect failed";
666                         return 1;
667                 }
668                 /* I think we can leave DTLS to its own devices; when we reconnect
669                    with the same master secret, we do seem to get the same sessid */
670                 return 1;
671
672         case KA_DPD:
673                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
674
675                 vpninfo->current_ssl_pkt = &dpd_pkt;
676                 goto handle_outgoing;
677
678         case KA_KEEPALIVE:
679                 /* No need to send an explicit keepalive
680                    if we have real data to send */
681                 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
682                         break;
683
684                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
685
686                 vpninfo->current_ssl_pkt = &keepalive_pkt;
687                 goto handle_outgoing;
688
689         case KA_NONE:
690                 ;
691         }
692
693         /* Service outgoing packet queue, if no DTLS */
694         while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
695                 struct pkt *this = vpninfo->outgoing_queue;
696                 vpninfo->outgoing_queue = this->next;
697                 vpninfo->outgoing_qlen--;
698
699                 if (vpninfo->deflate) {
700                         unsigned char *adler;
701                         int ret;
702
703                         vpninfo->deflate_strm.next_in = this->data;
704                         vpninfo->deflate_strm.avail_in = this->len;
705                         vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
706                         vpninfo->deflate_strm.avail_out = 2040;
707                         vpninfo->deflate_strm.total_out = 0;
708
709                         ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
710                         if (ret) {
711                                 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
712                                 goto uncompr;
713                         }
714
715                         vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
716                         vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
717
718                         /* Add ongoing adler32 to tail of compressed packet */
719                         vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
720                                                            this->data, this->len);
721
722                         adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
723                         *(adler++) =  vpninfo->deflate_adler32 >> 24;
724                         *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
725                         *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
726                         *(adler)   =  vpninfo->deflate_adler32 & 0xff;
727
728                         vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
729
730                         vpn_progress(vpninfo, PRG_TRACE,
731                                      _("Sending compressed data packet of %d bytes\n"),
732                                      this->len);
733
734                         vpninfo->pending_deflated_pkt = this;
735                         vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
736                 } else {
737                 uncompr:
738                         memcpy(this->hdr, data_hdr, 8);
739                         this->hdr[4] = this->len >> 8;
740                         this->hdr[5] = this->len & 0xff;
741
742                         vpn_progress(vpninfo, PRG_TRACE,
743                                      _("Sending uncompressed data packet of %d bytes\n"),
744                                      this->len);
745
746                         vpninfo->current_ssl_pkt = this;
747                 }
748                 goto handle_outgoing;
749         }
750
751         /* Work is not done if we just got rid of packets off the queue */
752         return work_done;
753 }
754
755 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
756 {
757         unsigned char *bye_pkt;
758         int reason_len;
759
760         /* already lost connection? */
761         if (!vpninfo->https_ssl)
762                 return 0;
763
764         reason_len = strlen(reason);
765         bye_pkt = malloc(reason_len + 9);
766         if (!bye_pkt)
767                 return -ENOMEM;
768
769         memcpy(bye_pkt, data_hdr, 8);
770         memcpy(bye_pkt + 9, reason, reason_len);
771
772         bye_pkt[4] = (reason_len + 1) >> 8;
773         bye_pkt[5] = (reason_len + 1) & 0xff;
774         bye_pkt[6] = AC_PKT_DISCONN;
775         bye_pkt[8] = 0xb0;
776
777         SSL_write(vpninfo->https_ssl, bye_pkt, reason_len + 9);
778         free(bye_pkt);
779
780         vpn_progress(vpninfo, PRG_INFO,
781                      _("Send BYE packet: %s\n"), reason);
782
783         return 0;
784 }