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