Don't unregister p11-kit PIN callback until vpninfo is finished with
[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 #include <netinet/tcp.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38
39 #include <openssl/ssl.h>
40 #include <openssl/err.h>
41
42 #include "openconnect-internal.h"
43
44 /*
45  * Data packets are encapsulated in the SSL stream as follows:
46  *
47  * 0000: Magic "STF\x1"
48  * 0004: Big-endian 16-bit length (not including 8-byte header)
49  * 0006: Byte packet type (see openconnect-internal.h)
50  * 0008: data payload
51  */
52
53 static char data_hdr[8] = {
54         'S', 'T', 'F', 1,
55         0, 0,           /* Length */
56         AC_PKT_DATA,    /* Type */
57         0               /* Unknown */
58 };
59
60 static struct pkt keepalive_pkt = {
61         .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_KEEPALIVE, 0 },
62 };
63
64 static struct pkt dpd_pkt = {
65         .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_OUT, 0 },
66 };
67
68 static struct pkt dpd_resp_pkt = {
69         .hdr = { 'S', 'T', 'F', 1, 0, 0, AC_PKT_DPD_RESP, 0 },
70 };
71
72 static int  __attribute__ ((format (printf, 3, 4)))
73     buf_append(char *buf, int len, const char *fmt, ...)
74 {
75         int start = strlen(buf);
76         int ret;
77         va_list args;
78
79         if (start >= len)
80                 return 0;
81
82         va_start(args, fmt);
83         ret = vsnprintf(buf + start, len - start, fmt, args);
84         va_end(args);
85
86         if (ret > len)
87                 ret = len;
88
89         return ret;
90 }
91
92 /* Calculate MTU to request. Old servers simply use the X-CSTP-MTU: header,
93  * which represents the tunnel MTU, while new servers do calculations on the
94  * X-CSTP-Base-MTU: header which represents the cleartext MTU between client
95  * and server.
96  *
97  * If possible, the legacy MTU value should be the TCP MSS less 5 bytes of
98  * TLS and 8 bytes of CSTP overhead. We can get the MSS from either the
99  * TCP_INFO or TCP_MAXSEG sockopts.
100  *
101  * The base MTU comes from the TCP_INFO sockopt under Linux, but I don't know
102  * how to work it out on other systems. So leave it blank and do things the
103  * legacy way there. Contributions welcome...
104  *
105  * If we don't even have TCP_MAXSEG, then default to sending a legacy MTU of
106  * 1406 which is what we always used to do.
107  */
108 static void calculate_mtu(struct openconnect_info *vpninfo, int *base_mtu, int *mtu)
109 {
110         *mtu = vpninfo->mtu;
111         *base_mtu = vpninfo->basemtu;
112
113 #ifdef TCP_INFO
114         if (!*mtu || !*base_mtu) {
115                 struct tcp_info ti;
116                 socklen_t ti_size = sizeof(ti);
117
118                 if (!getsockopt(vpninfo->ssl_fd, SOL_TCP, TCP_INFO,
119                                 &ti, &ti_size)) {
120                         vpn_progress(vpninfo, PRG_TRACE,
121                                      _("TCP_INFO rcv mss %d, snd mss %d, adv mss %d, pmtu %d\n"),
122                                      ti.tcpi_rcv_mss, ti.tcpi_snd_mss, ti.tcpi_advmss, ti.tcpi_pmtu);
123                         if (!*base_mtu) *base_mtu = ti.tcpi_pmtu;
124                         if (!*mtu) {
125                                 if (ti.tcpi_rcv_mss < ti.tcpi_snd_mss)
126                                         *mtu = ti.tcpi_rcv_mss - 13;
127                                 else
128                                         *mtu = ti.tcpi_snd_mss - 13;
129                         }
130                 }
131         }
132 #endif
133 #ifdef TCP_MAXSEG
134         if (!*mtu) {
135                 int mss;
136                 socklen_t mss_size = sizeof(mss);
137                 if (!getsockopt(vpninfo->ssl_fd, SOL_TCP, TCP_MAXSEG,
138                                 &mss, &mss_size)) {
139                         vpn_progress(vpninfo, PRG_TRACE, _("TCP_MAXSEG %d\n"), mss);
140                         *mtu = mss - 13;
141                 }
142         }
143 #endif
144         if (!*mtu) {
145                 /* Default */
146                 *mtu = 1406;
147         }
148 }
149
150 static int start_cstp_connection(struct openconnect_info *vpninfo)
151 {
152         char buf[65536];
153         int i;
154         int retried = 0, sessid_found = 0;
155         struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
156         struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
157         struct vpn_option *old_cstp_opts = vpninfo->cstp_options;
158         struct vpn_option *old_dtls_opts = vpninfo->dtls_options;
159         const char *old_addr = vpninfo->vpn_addr;
160         const char *old_netmask = vpninfo->vpn_netmask;
161         const char *old_addr6 = vpninfo->vpn_addr6;
162         const char *old_netmask6 = vpninfo->vpn_netmask6;
163         struct split_include *inc;
164         int base_mtu, mtu;
165
166         /* Clear old options which will be overwritten */
167         vpninfo->vpn_addr = vpninfo->vpn_netmask = NULL;
168         vpninfo->vpn_addr6 = vpninfo->vpn_netmask6 = NULL;
169         vpninfo->cstp_options = vpninfo->dtls_options = NULL;
170         vpninfo->vpn_domain = vpninfo->vpn_proxy_pac = NULL;
171         vpninfo->banner = NULL;
172
173         for (i=0; i<3; i++)
174                 vpninfo->vpn_dns[i] = vpninfo->vpn_nbns[i] = NULL;
175
176         for (inc = vpninfo->split_includes; inc; ) {
177                 struct split_include *next = inc->next;
178                 free(inc);
179                 inc = next;
180         }
181         for (inc = vpninfo->split_excludes; inc; ) {
182                 struct split_include *next = inc->next;
183                 free(inc);
184                 inc = next;
185         }
186         for (inc = vpninfo->split_dns; inc; ) {
187                 struct split_include *next = inc->next;
188                 free(inc);
189                 inc = next;
190         }
191         vpninfo->split_dns = vpninfo->split_includes = vpninfo->split_excludes = NULL;
192
193         /* Create (new) random master key for DTLS connection, if needed */
194         if (vpninfo->dtls_times.last_rekey + vpninfo->dtls_times.rekey <
195             time(NULL) + 300 &&
196             openconnect_random(vpninfo->dtls_secret, sizeof(vpninfo->dtls_secret))) {
197                 fprintf(stderr, _("Failed to initialise DTLS secret\n"));
198                 exit(1);
199         }
200
201  retry:
202         calculate_mtu(vpninfo, &base_mtu, &mtu);
203
204         buf[0] = 0;
205         buf_append(buf, sizeof(buf), "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
206         buf_append(buf, sizeof(buf), "Host: %s\r\n", vpninfo->hostname);
207         buf_append(buf, sizeof(buf), "User-Agent: %s\r\n", vpninfo->useragent);
208         buf_append(buf, sizeof(buf), "Cookie: webvpn=%s\r\n", vpninfo->cookie);
209         buf_append(buf, sizeof(buf), "X-CSTP-Version: 1\r\n");
210         buf_append(buf, sizeof(buf), "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
211         if (vpninfo->deflate && i < sizeof(buf))
212                 buf_append(buf, sizeof(buf), "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
213         if (base_mtu)
214                 buf_append(buf, sizeof(buf), "X-CSTP-Base-MTU: %d\r\n", base_mtu);
215         buf_append(buf, sizeof(buf), "X-CSTP-MTU: %d\r\n", mtu);
216         buf_append(buf, sizeof(buf), "X-CSTP-Address-Type: %s\r\n",
217                                vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4");
218         buf_append(buf, sizeof(buf), "X-DTLS-Master-Secret: ");
219         for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
220                 buf_append(buf, sizeof(buf), "%02X", vpninfo->dtls_secret[i]);
221         buf_append(buf, sizeof(buf), "\r\nX-DTLS-CipherSuite: %s\r\n\r\n",
222                                vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA");
223
224         openconnect_SSL_write(vpninfo, buf, strlen(buf));
225
226         if ((i = openconnect_SSL_gets(vpninfo, buf, 65536) < 0)) {
227                 if (i == -EINTR)
228                         return i;
229                 vpn_progress(vpninfo, PRG_ERR,
230                              _("Error fetching HTTPS response\n"));
231                 if (!retried) {
232                         retried = 1;
233                         openconnect_close_https(vpninfo, 0);
234
235                         if (openconnect_open_https(vpninfo)) {
236                                 vpn_progress(vpninfo, PRG_ERR,
237                                              _("Failed to open HTTPS connection to %s\n"),
238                                              vpninfo->hostname);
239                                 exit(1);
240                         }
241                         goto retry;
242                 }
243                 return -EINVAL;
244         }
245
246         if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
247                 if (!strncmp(buf, "HTTP/1.1 503 ", 13)) {
248                         /* "Service Unavailable. Why? */
249                         const char *reason = "<unknown>";
250                         while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
251                                 if (!strncmp(buf, "X-Reason: ", 10)) {
252                                         reason = buf + 10;
253                                         break;
254                                 }
255                         }
256                         vpn_progress(vpninfo, PRG_ERR,
257                                      _("VPN service unavailable; reason: %s\n"),
258                                      reason);
259                         return -EINVAL;
260                 }
261                 vpn_progress(vpninfo, PRG_ERR,
262                              _("Got inappropriate HTTP CONNECT response: %s\n"),
263                              buf);
264                 if (!strncmp(buf, "HTTP/1.1 401 ", 13))
265                         exit(2);
266                 return -EINVAL;
267         }
268
269         vpn_progress(vpninfo, PRG_INFO, _("Got CONNECT response: %s\n"), buf);
270
271         /* We may have advertised it, but we only do it if the server agrees */
272         vpninfo->deflate = 0;
273
274         while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) {
275                 struct vpn_option *new_option;
276                 char *colon;
277
278                 if (i < 0)
279                         return i;
280
281                 colon = strchr(buf, ':');
282                 if (!colon)
283                         continue;
284
285                 *colon = 0;
286                 colon++;
287                 if (*colon == ' ')
288                         colon++;
289
290                 if (strncmp(buf, "X-DTLS-", 7) &&
291                     strncmp(buf, "X-CSTP-", 7))
292                         continue;
293
294                 new_option = malloc(sizeof(*new_option));
295                 if (!new_option) {
296                         vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
297                         return -ENOMEM;
298                 }
299                 new_option->option = strdup(buf);
300                 new_option->value = strdup(colon);
301                 new_option->next = NULL;
302
303                 if (!new_option->option || !new_option->value) {
304                         vpn_progress(vpninfo, PRG_ERR, _("No memory for options\n"));
305                         return -ENOMEM;
306                 }
307
308                 vpn_progress(vpninfo, PRG_TRACE, "%s: %s\n", buf, colon);
309
310                 if (!strncmp(buf, "X-DTLS-", 7)) {
311                         *next_dtls_option = new_option;
312                         next_dtls_option = &new_option->next;
313
314                         if (!strcmp(buf + 7, "MTU")) {
315                                 int mtu = atol(colon);
316                                 if (mtu > vpninfo->mtu)
317                                         vpninfo->mtu = mtu;
318                         } else if (!strcmp(buf + 7, "Session-ID")) {
319                                 if (strlen(colon) != 64) {
320                                         vpn_progress(vpninfo, PRG_ERR,
321                                                      _("X-DTLS-Session-ID not 64 characters; is: \"%s\"\n"),
322                                                      colon);
323                                         vpninfo->dtls_attempt_period = 0;
324                                         return -EINVAL;
325                                 }
326                                 for (i = 0; i < 64; i += 2)
327                                         vpninfo->dtls_session_id[i/2] = unhex(colon + i);
328                                 sessid_found = 1;
329                                 time(&vpninfo->dtls_times.last_rekey);
330                         }
331                         continue;
332                 }
333                 /* CSTP options... */
334                 *next_cstp_option = new_option;
335                 next_cstp_option = &new_option->next;
336
337
338                 if (!strcmp(buf + 7, "Keepalive")) {
339                         vpninfo->ssl_times.keepalive = atol(colon);
340                 } else if (!strcmp(buf + 7, "DPD")) {
341                         int j = atol(colon);
342                         if (j && (!vpninfo->ssl_times.dpd || j < vpninfo->ssl_times.dpd))
343                                 vpninfo->ssl_times.dpd = j;
344                 } else if (!strcmp(buf + 7, "Rekey-Time")) {
345                         vpninfo->ssl_times.rekey = atol(colon);
346                 } else if (!strcmp(buf + 7, "Content-Encoding")) {
347                         if (!strcmp(colon, "deflate"))
348                                 vpninfo->deflate = 1;
349                         else {
350                                 vpn_progress(vpninfo, PRG_ERR,
351                                              _("Unknown CSTP-Content-Encoding %s\n"),
352                                              colon);
353                                 return -EINVAL;
354                         }
355                 } else if (!strcmp(buf + 7, "MTU")) {
356                         int mtu = atol(colon);
357                         if (mtu > vpninfo->mtu)
358                                 vpninfo->mtu = mtu;
359                 } else if (!strcmp(buf + 7, "Address")) {
360                         if (strchr(new_option->value, ':'))
361                                 vpninfo->vpn_addr6 = new_option->value;
362                         else
363                                 vpninfo->vpn_addr = new_option->value;
364                 } else if (!strcmp(buf + 7, "Netmask")) {
365                         if (strchr(new_option->value, ':'))
366                                 vpninfo->vpn_netmask6 = new_option->value;
367                         else
368                                 vpninfo->vpn_netmask = new_option->value;
369                 } else if (!strcmp(buf + 7, "DNS")) {
370                         int j;
371                         for (j = 0; j < 3; j++) {
372                                 if (!vpninfo->vpn_dns[j]) {
373                                         vpninfo->vpn_dns[j] = new_option->value;
374                                         break;
375                                 }
376                         }
377                 } else if (!strcmp(buf + 7, "NBNS")) {
378                         int j;
379                         for (j = 0; j < 3; j++) {
380                                 if (!vpninfo->vpn_nbns[j]) {
381                                         vpninfo->vpn_nbns[j] = new_option->value;
382                                         break;
383                                 }
384                         }
385                 } else if (!strcmp(buf + 7, "Default-Domain")) {
386                         vpninfo->vpn_domain = new_option->value;
387                 } else if (!strcmp(buf + 7, "MSIE-Proxy-PAC-URL")) {
388                         vpninfo->vpn_proxy_pac = new_option->value;
389                 } else if (!strcmp(buf + 7, "Banner")) {
390                         vpninfo->banner = new_option->value;
391                 } else if (!strcmp(buf + 7, "Split-DNS")) {
392                         struct split_include *dns = malloc(sizeof(*dns));
393                         if (!dns)
394                                 continue;
395                         dns->route = new_option->value;
396                         dns->next = vpninfo->split_dns;
397                         vpninfo->split_dns = dns;
398                 } else if (!strcmp(buf + 7, "Split-Include")) {
399                         struct split_include *inc = malloc(sizeof(*inc));
400                         if (!inc)
401                                 continue;
402                         inc->route = new_option->value;
403                         inc->next = vpninfo->split_includes;
404                         vpninfo->split_includes = inc;
405                 } else if (!strcmp(buf + 7, "Split-Exclude")) {
406                         struct split_include *exc = malloc(sizeof(*exc));
407                         if (!exc)
408                                 continue;
409                         exc->route = new_option->value;
410                         exc->next = vpninfo->split_excludes;
411                         vpninfo->split_excludes = exc;
412                 }
413         }
414
415         if (!vpninfo->vpn_addr && !vpninfo->vpn_addr6) {
416                 vpn_progress(vpninfo, PRG_ERR,
417                              _("No IP address received. Aborting\n"));
418                 return -EINVAL;
419         }
420         if (old_addr) {
421                 if (strcmp(old_addr, vpninfo->vpn_addr)) {
422                         vpn_progress(vpninfo, PRG_ERR,
423                                      _("Reconnect gave different Legacy IP address (%s != %s)\n"),
424                                      vpninfo->vpn_addr, old_addr);
425                         return -EINVAL;
426                 }
427         }
428         if (old_netmask) {
429                 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
430                         vpn_progress(vpninfo, PRG_ERR,
431                                      _("Reconnect gave different Legacy IP netmask (%s != %s)\n"),
432                                      vpninfo->vpn_netmask, old_netmask);
433                         return -EINVAL;
434                 }
435         }
436         if (old_addr6) {
437                 if (strcmp(old_addr6, vpninfo->vpn_addr6)) {
438                         vpn_progress(vpninfo, PRG_ERR,
439                                      _("Reconnect gave different IPv6 address (%s != %s)\n"),
440                                      vpninfo->vpn_addr6, old_addr6);
441                         return -EINVAL;
442                 }
443         }
444         if (old_netmask6) {
445                 if (strcmp(old_netmask6, vpninfo->vpn_netmask6)) {
446                         vpn_progress(vpninfo, PRG_ERR,
447                                      _("Reconnect gave different IPv6 netmask (%s != %s)\n"),
448                                      vpninfo->vpn_netmask6, old_netmask6);
449                         return -EINVAL;
450                 }
451         }
452
453         while (old_dtls_opts) {
454                 struct vpn_option *tmp = old_dtls_opts;
455                 old_dtls_opts = old_dtls_opts->next;
456                 free(tmp->value);
457                 free(tmp->option);
458                 free(tmp);
459         }
460         while (old_cstp_opts) {
461                 struct vpn_option *tmp = old_cstp_opts;
462                 old_cstp_opts = old_cstp_opts->next;
463                 free(tmp->value);
464                 free(tmp->option);
465                 free(tmp);
466         }
467         vpn_progress(vpninfo, PRG_INFO, _("CSTP connected. DPD %d, Keepalive %d\n"),
468                      vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
469
470         if (vpninfo->select_nfds <= vpninfo->ssl_fd)
471                 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
472
473         FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
474         FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
475
476         if (!sessid_found)
477                 vpninfo->dtls_attempt_period = 0;
478
479         vpninfo->ssl_times.last_rekey = vpninfo->ssl_times.last_rx =
480                 vpninfo->ssl_times.last_tx = time(NULL);
481         return 0;
482 }
483
484
485 int make_cstp_connection(struct openconnect_info *vpninfo)
486 {
487         int ret;
488
489         ret = openconnect_open_https(vpninfo);
490         if (ret)
491                 return ret;
492
493         if (vpninfo->deflate) {
494                 vpninfo->deflate_adler32 = 1;
495                 vpninfo->inflate_adler32 = 1;
496
497                 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
498                     deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
499                                  Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
500                         vpn_progress(vpninfo, PRG_ERR, _("Compression setup failed\n"));
501                         vpninfo->deflate = 0;
502                 }
503
504                 if (!vpninfo->deflate_pkt) {
505                         vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
506                         if (!vpninfo->deflate_pkt) {
507                                 vpn_progress(vpninfo, PRG_ERR,
508                                              _("Allocation of deflate buffer failed\n"));
509                                 inflateEnd(&vpninfo->inflate_strm);
510                                 deflateEnd(&vpninfo->deflate_strm);
511                                 vpninfo->deflate = 0;
512                         } else {
513                                 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
514                                 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
515                                 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
516                         }
517                 }
518         }
519
520         return start_cstp_connection(vpninfo);
521 }
522
523 int cstp_reconnect(struct openconnect_info *vpninfo)
524 {
525         int ret;
526         int timeout;
527         int interval;
528
529         openconnect_close_https(vpninfo, 0);
530
531         /* Requeue the original packet that was deflated */
532         if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
533                 vpninfo->current_ssl_pkt = NULL;
534                 queue_packet(&vpninfo->outgoing_queue, vpninfo->pending_deflated_pkt);
535                 vpninfo->pending_deflated_pkt = NULL;
536         }
537         if (vpninfo->deflate) {
538                 inflateEnd(&vpninfo->inflate_strm);
539                 deflateEnd(&vpninfo->deflate_strm);
540         }
541         timeout = vpninfo->reconnect_timeout;
542         interval = vpninfo->reconnect_interval;
543
544         while ((ret = make_cstp_connection(vpninfo))) {
545                 if (timeout <= 0)
546                         return ret;
547                 vpn_progress(vpninfo, PRG_INFO,
548                              _("sleep %ds, remaining timeout %ds\n"),
549                              interval, timeout);
550                 sleep(interval);
551                 if (killed)
552                         return 1;
553                 timeout -= interval;
554                 interval += vpninfo->reconnect_interval;
555                 if (interval > RECONNECT_INTERVAL_MAX)
556                         interval = RECONNECT_INTERVAL_MAX;
557         }
558         script_config_tun(vpninfo, "reconnect");
559         return 0;
560 }
561
562 static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
563                                     unsigned char *buf, int len)
564 {
565         struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
566         uint32_t pkt_sum;
567
568         if (!new)
569                 return -ENOMEM;
570
571         new->next = NULL;
572
573         vpninfo->inflate_strm.next_in = buf;
574         vpninfo->inflate_strm.avail_in = len - 4;
575
576         vpninfo->inflate_strm.next_out = new->data;
577         vpninfo->inflate_strm.avail_out = vpninfo->mtu;
578         vpninfo->inflate_strm.total_out = 0;
579
580         if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
581                 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
582                 free(new);
583                 return -EINVAL;
584         }
585
586         new->len = vpninfo->inflate_strm.total_out;
587
588         vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
589                                            new->data, new->len);
590
591         pkt_sum = buf[len - 1] | (buf[len - 2] << 8) |
592                 (buf[len - 3] << 16) | (buf[len - 4] << 24);
593
594         if (vpninfo->inflate_adler32 != pkt_sum) {
595                 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
596         }
597
598         vpn_progress(vpninfo, PRG_TRACE,
599                      _("Received compressed data packet of %ld bytes\n"),
600                      (long)vpninfo->inflate_strm.total_out);
601
602         queue_packet(&vpninfo->incoming_queue, new);
603         return 0;
604 }
605
606 #if defined (OPENCONNECT_OPENSSL)
607 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
608 {
609         int len, ret;
610
611         len = SSL_read(vpninfo->https_ssl, buf, maxlen);
612         if (len > 0)
613                 return len;
614
615         ret = SSL_get_error(vpninfo->https_ssl, len);
616         if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
617                 vpn_progress(vpninfo, PRG_ERR,
618                              _("SSL read error %d (server probably closed connection); reconnecting.\n"),
619                              ret);
620                 return -EIO;
621         }
622         return 0;
623 }
624
625 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
626 {
627         int ret;
628
629         ret = SSL_write(vpninfo->https_ssl, buf, buflen);
630         if (ret > 0)
631                 return ret;
632
633         ret = SSL_get_error(vpninfo->https_ssl, ret);
634         switch (ret) {
635         case SSL_ERROR_WANT_WRITE:
636                 /* Waiting for the socket to become writable -- it's
637                    probably stalled, and/or the buffers are full */
638                 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
639         case SSL_ERROR_WANT_READ:
640                 return 0;
641
642         default:
643                 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
644                 openconnect_report_ssl_errors(vpninfo);
645                 return -1;
646         }
647 }
648 #elif defined (OPENCONNECT_GNUTLS)
649 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
650 {
651         int ret;
652
653         ret = gnutls_record_recv(vpninfo->https_sess, buf, maxlen);
654         if (ret > 0)
655                 return ret;
656
657         if (ret != GNUTLS_E_AGAIN) {
658                 vpn_progress(vpninfo, PRG_ERR,
659                              _("SSL read error: %s; reconnecting.\n"),
660                              gnutls_strerror(ret));
661                 return -EIO;
662         }
663         return 0;
664 }
665
666 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
667 {
668         int ret;
669
670         ret = gnutls_record_send(vpninfo->https_sess, buf, buflen);
671         if (ret > 0)
672                 return ret;
673
674         if (ret == GNUTLS_E_AGAIN) {
675                 if (gnutls_record_get_direction(vpninfo->https_sess)) {
676                         /* Waiting for the socket to become writable -- it's
677                            probably stalled, and/or the buffers are full */
678                         FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
679                 }
680                 return 0;
681         }
682         vpn_progress(vpninfo, PRG_ERR, _("SSL send failed: %s\n"),
683                      gnutls_strerror(ret));
684         return -1;
685 }
686 #endif
687
688 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
689 {
690         unsigned char buf[16384];
691         int len, ret;
692         int work_done = 0;
693
694         /* FIXME: The poll() handling here is fairly simplistic. Actually,
695            if the SSL connection stalls it could return a WANT_WRITE error
696            on _either_ of the SSL_read() or SSL_write() calls. In that case,
697            we should probably remove POLLIN from the events we're looking for,
698            and add POLLOUT. As it is, though, it'll just chew CPU time in that
699            fairly unlikely situation, until the write backlog clears. */
700         while ( (len = cstp_read(vpninfo, buf, sizeof(buf))) > 0) {
701                 int payload_len;
702
703                 if (buf[0] != 'S' || buf[1] != 'T' ||
704                     buf[2] != 'F' || buf[3] != 1 || buf[7])
705                         goto unknown_pkt;
706
707                 payload_len = (buf[4] << 8) + buf[5];
708                 if (len != 8 + payload_len) {
709                         vpn_progress(vpninfo, PRG_ERR,
710                                      _("Unexpected packet length. SSL_read returned %d but packet is\n"),
711                                      len);
712                         vpn_progress(vpninfo, PRG_ERR,
713                                      "%02x %02x %02x %02x %02x %02x %02x %02x\n",
714                                      buf[0], buf[1], buf[2], buf[3],
715                                      buf[4], buf[5], buf[6], buf[7]);
716                         continue;
717                 }
718                 vpninfo->ssl_times.last_rx = time(NULL);
719                 switch(buf[6]) {
720                 case AC_PKT_DPD_OUT:
721                         vpn_progress(vpninfo, PRG_TRACE,
722                                      _("Got CSTP DPD request\n"));
723                         vpninfo->owe_ssl_dpd_response = 1;
724                         continue;
725
726                 case AC_PKT_DPD_RESP:
727                         vpn_progress(vpninfo, PRG_TRACE,
728                                      _("Got CSTP DPD response\n"));
729                         continue;
730
731                 case AC_PKT_KEEPALIVE:
732                         vpn_progress(vpninfo, PRG_TRACE,
733                                      _("Got CSTP Keepalive\n"));
734                         continue;
735
736                 case AC_PKT_DATA:
737                         vpn_progress(vpninfo, PRG_TRACE,
738                                      _("Received uncompressed data packet of %d bytes\n"),
739                                      payload_len);
740                         queue_new_packet(&vpninfo->incoming_queue, buf + 8,
741                                          payload_len);
742                         work_done = 1;
743                         continue;
744
745                 case AC_PKT_DISCONN: {
746                         int i;
747                         for (i = 0; i < payload_len; i++) {
748                                 if (!isprint(buf[payload_len + 8 + i]))
749                                         buf[payload_len + 8 + i] = '.';
750                         }
751                         buf[payload_len + 8] = 0;
752                         vpn_progress(vpninfo, PRG_ERR,
753                                      _("Received server disconnect: %02x '%s'\n"),
754                                      buf[8], buf + 9);
755                         vpninfo->quit_reason = "Server request";
756                         return 1;
757                 }
758                 case AC_PKT_COMPRESSED:
759                         if (!vpninfo->deflate) {
760                                 vpn_progress(vpninfo, PRG_ERR,
761                                              _("Compressed packet received in !deflate mode\n"));
762                                 goto unknown_pkt;
763                         }
764                         inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
765                         work_done = 1;
766                         continue;
767
768                 case AC_PKT_TERM_SERVER:
769                         vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
770                         vpninfo->quit_reason = "Server request";
771                         return 1;
772                 }
773
774         unknown_pkt:
775                 vpn_progress(vpninfo, PRG_ERR,
776                              _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
777                              buf[0], buf[1], buf[2], buf[3],
778                              buf[4], buf[5], buf[6], buf[7]);
779                 vpninfo->quit_reason = "Unknown packet received";
780                 return 1;
781         }
782         if (len < 0)
783                 goto do_reconnect;
784
785
786         /* If SSL_write() fails we are expected to try again. With exactly
787            the same data, at exactly the same location. So we keep the
788            packet we had before.... */
789         if (vpninfo->current_ssl_pkt) {
790         handle_outgoing:
791                 vpninfo->ssl_times.last_tx = time(NULL);
792                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
793
794                 ret = cstp_write(vpninfo,
795                                  vpninfo->current_ssl_pkt->hdr,
796                                  vpninfo->current_ssl_pkt->len + 8);
797                 
798                 if (ret < 0)
799                         goto do_reconnect;
800                 else if (!ret && ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
801                         goto peer_dead;
802
803                 if (ret != vpninfo->current_ssl_pkt->len + 8) {
804                         vpn_progress(vpninfo, PRG_ERR,
805                                      _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
806                                      vpninfo->current_ssl_pkt->len + 8, ret);
807                         vpninfo->quit_reason = "Internal error";
808                         return 1;
809                 }
810                 /* Don't free the 'special' packets */
811                 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
812                         free(vpninfo->pending_deflated_pkt);
813                 else if (vpninfo->current_ssl_pkt != &dpd_pkt &&
814                          vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
815                          vpninfo->current_ssl_pkt != &keepalive_pkt)
816                         free(vpninfo->current_ssl_pkt);
817
818                 vpninfo->current_ssl_pkt = NULL;
819         }
820
821         if (vpninfo->owe_ssl_dpd_response) {
822                 vpninfo->owe_ssl_dpd_response = 0;
823                 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
824                 goto handle_outgoing;
825         }
826
827         switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
828         case KA_REKEY:
829                 /* Not that this will ever happen; we don't even process
830                    the setting when we're asked for it. */
831                 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
832                 goto do_reconnect;
833                 break;
834
835         case KA_DPD_DEAD:
836         peer_dead:
837                 vpn_progress(vpninfo, PRG_ERR,
838                              _("CSTP Dead Peer Detection detected dead peer!\n"));
839         do_reconnect:
840                 if (cstp_reconnect(vpninfo)) {
841                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
842                         vpninfo->quit_reason = "CSTP reconnect failed";
843                         return 1;
844                 }
845                 /* I think we can leave DTLS to its own devices; when we reconnect
846                    with the same master secret, we do seem to get the same sessid */
847                 return 1;
848
849         case KA_DPD:
850                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
851
852                 vpninfo->current_ssl_pkt = &dpd_pkt;
853                 goto handle_outgoing;
854
855         case KA_KEEPALIVE:
856                 /* No need to send an explicit keepalive
857                    if we have real data to send */
858                 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
859                         break;
860
861                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
862
863                 vpninfo->current_ssl_pkt = &keepalive_pkt;
864                 goto handle_outgoing;
865
866         case KA_NONE:
867                 ;
868         }
869
870         /* Service outgoing packet queue, if no DTLS */
871         while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
872                 struct pkt *this = vpninfo->outgoing_queue;
873                 vpninfo->outgoing_queue = this->next;
874                 vpninfo->outgoing_qlen--;
875
876                 if (vpninfo->deflate) {
877                         unsigned char *adler;
878                         int ret;
879
880                         vpninfo->deflate_strm.next_in = this->data;
881                         vpninfo->deflate_strm.avail_in = this->len;
882                         vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
883                         vpninfo->deflate_strm.avail_out = 2040;
884                         vpninfo->deflate_strm.total_out = 0;
885
886                         ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
887                         if (ret) {
888                                 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
889                                 goto uncompr;
890                         }
891
892                         vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
893                         vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
894
895                         /* Add ongoing adler32 to tail of compressed packet */
896                         vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
897                                                            this->data, this->len);
898
899                         adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
900                         *(adler++) =  vpninfo->deflate_adler32 >> 24;
901                         *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
902                         *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
903                         *(adler)   =  vpninfo->deflate_adler32 & 0xff;
904
905                         vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
906
907                         vpn_progress(vpninfo, PRG_TRACE,
908                                      _("Sending compressed data packet of %d bytes\n"),
909                                      this->len);
910
911                         vpninfo->pending_deflated_pkt = this;
912                         vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
913                 } else {
914                 uncompr:
915                         memcpy(this->hdr, data_hdr, 8);
916                         this->hdr[4] = this->len >> 8;
917                         this->hdr[5] = this->len & 0xff;
918
919                         vpn_progress(vpninfo, PRG_TRACE,
920                                      _("Sending uncompressed data packet of %d bytes\n"),
921                                      this->len);
922
923                         vpninfo->current_ssl_pkt = this;
924                 }
925                 goto handle_outgoing;
926         }
927
928         /* Work is not done if we just got rid of packets off the queue */
929         return work_done;
930 }
931
932 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
933 {
934         unsigned char *bye_pkt;
935         int reason_len;
936
937         /* already lost connection? */
938 #if defined (OPENCONNECT_OPENSSL)
939         if (!vpninfo->https_ssl)
940                 return 0;
941 #elif defined (OPENCONNECT_GNUTLS)
942         if (!vpninfo->https_sess)
943                 return 0;
944 #endif
945
946         reason_len = strlen(reason);
947         bye_pkt = malloc(reason_len + 9);
948         if (!bye_pkt)
949                 return -ENOMEM;
950
951         memcpy(bye_pkt, data_hdr, 8);
952         memcpy(bye_pkt + 9, reason, reason_len);
953
954         bye_pkt[4] = (reason_len + 1) >> 8;
955         bye_pkt[5] = (reason_len + 1) & 0xff;
956         bye_pkt[6] = AC_PKT_DISCONN;
957         bye_pkt[8] = 0xb0;
958
959         vpn_progress(vpninfo, PRG_INFO,
960                      _("Send BYE packet: %s\n"), reason);
961
962         cstp_write(vpninfo, bye_pkt, reason_len + 9);
963         free(bye_pkt);
964
965         return 0;
966 }