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