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