Add $CISCO_SPLIT_DNS environment variable for vpnc-script
[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);
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, "Session-ID")) {
315                                 if (strlen(colon) != 64) {
316                                         vpn_progress(vpninfo, PRG_ERR,
317                                                      _("X-DTLS-Session-ID not 64 characters; is: \"%s\"\n"),
318                                                      colon);
319                                         vpninfo->dtls_attempt_period = 0;
320                                         return -EINVAL;
321                                 }
322                                 for (i = 0; i < 64; i += 2)
323                                         vpninfo->dtls_session_id[i/2] = unhex(colon + i);
324                                 sessid_found = 1;
325                                 time(&vpninfo->dtls_times.last_rekey);
326                         }
327                         continue;
328                 }
329                 /* CSTP options... */
330                 *next_cstp_option = new_option;
331                 next_cstp_option = &new_option->next;
332
333
334                 if (!strcmp(buf + 7, "Keepalive")) {
335                         vpninfo->ssl_times.keepalive = atol(colon);
336                 } else if (!strcmp(buf + 7, "DPD")) {
337                         int j = atol(colon);
338                         if (j && (!vpninfo->ssl_times.dpd || j < vpninfo->ssl_times.dpd))
339                                 vpninfo->ssl_times.dpd = j;
340                 } else if (!strcmp(buf + 7, "Rekey-Time")) {
341                         vpninfo->ssl_times.rekey = atol(colon);
342                 } else if (!strcmp(buf + 7, "Content-Encoding")) {
343                         if (!strcmp(colon, "deflate"))
344                                 vpninfo->deflate = 1;
345                         else {
346                                 vpn_progress(vpninfo, PRG_ERR,
347                                              _("Unknown CSTP-Content-Encoding %s\n"),
348                                              colon);
349                                 return -EINVAL;
350                         }
351                 } else if (!strcmp(buf + 7, "MTU")) {
352                         vpninfo->mtu = atol(colon);
353                 } else if (!strcmp(buf + 7, "Address")) {
354                         if (strchr(new_option->value, ':'))
355                                 vpninfo->vpn_addr6 = new_option->value;
356                         else
357                                 vpninfo->vpn_addr = new_option->value;
358                 } else if (!strcmp(buf + 7, "Netmask")) {
359                         if (strchr(new_option->value, ':'))
360                                 vpninfo->vpn_netmask6 = new_option->value;
361                         else
362                                 vpninfo->vpn_netmask = new_option->value;
363                 } else if (!strcmp(buf + 7, "DNS")) {
364                         int j;
365                         for (j = 0; j < 3; j++) {
366                                 if (!vpninfo->vpn_dns[j]) {
367                                         vpninfo->vpn_dns[j] = new_option->value;
368                                         break;
369                                 }
370                         }
371                 } else if (!strcmp(buf + 7, "NBNS")) {
372                         int j;
373                         for (j = 0; j < 3; j++) {
374                                 if (!vpninfo->vpn_nbns[j]) {
375                                         vpninfo->vpn_nbns[j] = new_option->value;
376                                         break;
377                                 }
378                         }
379                 } else if (!strcmp(buf + 7, "Default-Domain")) {
380                         vpninfo->vpn_domain = new_option->value;
381                 } else if (!strcmp(buf + 7, "MSIE-Proxy-PAC-URL")) {
382                         vpninfo->vpn_proxy_pac = new_option->value;
383                 } else if (!strcmp(buf + 7, "Banner")) {
384                         vpninfo->banner = new_option->value;
385                 } else if (!strcmp(buf + 7, "Split-DNS")) {
386                         struct split_include *dns = malloc(sizeof(*dns));
387                         if (!dns)
388                                 continue;
389                         dns->route = new_option->value;
390                         dns->next = vpninfo->split_dns;
391                         vpninfo->split_dns = dns;
392                 } else if (!strcmp(buf + 7, "Split-Include")) {
393                         struct split_include *inc = malloc(sizeof(*inc));
394                         if (!inc)
395                                 continue;
396                         inc->route = new_option->value;
397                         inc->next = vpninfo->split_includes;
398                         vpninfo->split_includes = inc;
399                 } else if (!strcmp(buf + 7, "Split-Exclude")) {
400                         struct split_include *exc = malloc(sizeof(*exc));
401                         if (!exc)
402                                 continue;
403                         exc->route = new_option->value;
404                         exc->next = vpninfo->split_excludes;
405                         vpninfo->split_excludes = exc;
406                 }
407         }
408
409         if (!vpninfo->vpn_addr && !vpninfo->vpn_addr6) {
410                 vpn_progress(vpninfo, PRG_ERR,
411                              _("No IP address received. Aborting\n"));
412                 return -EINVAL;
413         }
414         if (old_addr) {
415                 if (strcmp(old_addr, vpninfo->vpn_addr)) {
416                         vpn_progress(vpninfo, PRG_ERR,
417                                      _("Reconnect gave different Legacy IP address (%s != %s)\n"),
418                                      vpninfo->vpn_addr, old_addr);
419                         return -EINVAL;
420                 }
421         }
422         if (old_netmask) {
423                 if (strcmp(old_netmask, vpninfo->vpn_netmask)) {
424                         vpn_progress(vpninfo, PRG_ERR,
425                                      _("Reconnect gave different Legacy IP netmask (%s != %s)\n"),
426                                      vpninfo->vpn_netmask, old_netmask);
427                         return -EINVAL;
428                 }
429         }
430         if (old_addr6) {
431                 if (strcmp(old_addr6, vpninfo->vpn_addr6)) {
432                         vpn_progress(vpninfo, PRG_ERR,
433                                      _("Reconnect gave different IPv6 address (%s != %s)\n"),
434                                      vpninfo->vpn_addr6, old_addr6);
435                         return -EINVAL;
436                 }
437         }
438         if (old_netmask6) {
439                 if (strcmp(old_netmask6, vpninfo->vpn_netmask6)) {
440                         vpn_progress(vpninfo, PRG_ERR,
441                                      _("Reconnect gave different IPv6 netmask (%s != %s)\n"),
442                                      vpninfo->vpn_netmask6, old_netmask6);
443                         return -EINVAL;
444                 }
445         }
446
447         while (old_dtls_opts) {
448                 struct vpn_option *tmp = old_dtls_opts;
449                 old_dtls_opts = old_dtls_opts->next;
450                 free(tmp->value);
451                 free(tmp->option);
452                 free(tmp);
453         }
454         while (old_cstp_opts) {
455                 struct vpn_option *tmp = old_cstp_opts;
456                 old_cstp_opts = old_cstp_opts->next;
457                 free(tmp->value);
458                 free(tmp->option);
459                 free(tmp);
460         }
461         vpn_progress(vpninfo, PRG_INFO, _("CSTP connected. DPD %d, Keepalive %d\n"),
462                      vpninfo->ssl_times.dpd, vpninfo->ssl_times.keepalive);
463
464         if (vpninfo->select_nfds <= vpninfo->ssl_fd)
465                 vpninfo->select_nfds = vpninfo->ssl_fd + 1;
466
467         FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
468         FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
469
470         if (!sessid_found)
471                 vpninfo->dtls_attempt_period = 0;
472
473         vpninfo->ssl_times.last_rekey = vpninfo->ssl_times.last_rx =
474                 vpninfo->ssl_times.last_tx = time(NULL);
475         return 0;
476 }
477
478
479 int make_cstp_connection(struct openconnect_info *vpninfo)
480 {
481         int ret;
482
483         ret = openconnect_open_https(vpninfo);
484         if (ret)
485                 return ret;
486
487         if (vpninfo->deflate) {
488                 vpninfo->deflate_adler32 = 1;
489                 vpninfo->inflate_adler32 = 1;
490
491                 if (inflateInit2(&vpninfo->inflate_strm, -12) ||
492                     deflateInit2(&vpninfo->deflate_strm, Z_DEFAULT_COMPRESSION,
493                                  Z_DEFLATED, -12, 9, Z_DEFAULT_STRATEGY)) {
494                         vpn_progress(vpninfo, PRG_ERR, _("Compression setup failed\n"));
495                         vpninfo->deflate = 0;
496                 }
497
498                 if (!vpninfo->deflate_pkt) {
499                         vpninfo->deflate_pkt = malloc(sizeof(struct pkt) + 2048);
500                         if (!vpninfo->deflate_pkt) {
501                                 vpn_progress(vpninfo, PRG_ERR,
502                                              _("Allocation of deflate buffer failed\n"));
503                                 inflateEnd(&vpninfo->inflate_strm);
504                                 deflateEnd(&vpninfo->deflate_strm);
505                                 vpninfo->deflate = 0;
506                         } else {
507                                 memset(vpninfo->deflate_pkt, 0, sizeof(struct pkt));
508                                 memcpy(vpninfo->deflate_pkt->hdr, data_hdr, 8);
509                                 vpninfo->deflate_pkt->hdr[6] = AC_PKT_COMPRESSED;
510                         }
511                 }
512         }
513
514         return start_cstp_connection(vpninfo);
515 }
516
517 int cstp_reconnect(struct openconnect_info *vpninfo)
518 {
519         int ret;
520         int timeout;
521         int interval;
522
523         openconnect_close_https(vpninfo);
524
525         /* Requeue the original packet that was deflated */
526         if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
527                 vpninfo->current_ssl_pkt = NULL;
528                 queue_packet(&vpninfo->outgoing_queue, vpninfo->pending_deflated_pkt);
529                 vpninfo->pending_deflated_pkt = NULL;
530         }
531         if (vpninfo->deflate) {
532                 inflateEnd(&vpninfo->inflate_strm);
533                 deflateEnd(&vpninfo->deflate_strm);
534         }
535         timeout = vpninfo->reconnect_timeout;
536         interval = vpninfo->reconnect_interval;
537
538         while ((ret = make_cstp_connection(vpninfo))) {
539                 if (timeout <= 0)
540                         return ret;
541                 vpn_progress(vpninfo, PRG_INFO,
542                              _("sleep %ds, remaining timeout %ds\n"),
543                              interval, timeout);
544                 sleep(interval);
545                 if (killed)
546                         return 1;
547                 timeout -= interval;
548                 interval += vpninfo->reconnect_interval;
549                 if (interval > RECONNECT_INTERVAL_MAX)
550                         interval = RECONNECT_INTERVAL_MAX;
551         }
552         script_config_tun(vpninfo, "reconnect");
553         return 0;
554 }
555
556 static int inflate_and_queue_packet(struct openconnect_info *vpninfo,
557                                     unsigned char *buf, int len)
558 {
559         struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
560         uint32_t pkt_sum;
561
562         if (!new)
563                 return -ENOMEM;
564
565         new->next = NULL;
566
567         vpninfo->inflate_strm.next_in = buf;
568         vpninfo->inflate_strm.avail_in = len - 4;
569
570         vpninfo->inflate_strm.next_out = new->data;
571         vpninfo->inflate_strm.avail_out = vpninfo->mtu;
572         vpninfo->inflate_strm.total_out = 0;
573
574         if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
575                 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
576                 free(new);
577                 return -EINVAL;
578         }
579
580         new->len = vpninfo->inflate_strm.total_out;
581
582         vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
583                                            new->data, new->len);
584
585         pkt_sum = buf[len - 1] | (buf[len - 2] << 8) |
586                 (buf[len - 3] << 16) | (buf[len - 4] << 24);
587
588         if (vpninfo->inflate_adler32 != pkt_sum) {
589                 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
590         }
591
592         vpn_progress(vpninfo, PRG_TRACE,
593                      _("Received compressed data packet of %ld bytes\n"),
594                      (long)vpninfo->inflate_strm.total_out);
595
596         queue_packet(&vpninfo->incoming_queue, new);
597         return 0;
598 }
599
600 #if defined (OPENCONNECT_OPENSSL)
601 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
602 {
603         int len, ret;
604
605         len = SSL_read(vpninfo->https_ssl, buf, maxlen);
606         if (len > 0)
607                 return len;
608
609         ret = SSL_get_error(vpninfo->https_ssl, len);
610         if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
611                 vpn_progress(vpninfo, PRG_ERR,
612                              _("SSL read error %d (server probably closed connection); reconnecting.\n"),
613                              ret);
614                 return -EIO;
615         }
616         return 0;
617 }
618
619 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
620 {
621         int ret;
622
623         ret = SSL_write(vpninfo->https_ssl, buf, buflen);
624         if (ret > 0)
625                 return ret;
626
627         ret = SSL_get_error(vpninfo->https_ssl, ret);
628         switch (ret) {
629         case SSL_ERROR_WANT_WRITE:
630                 /* Waiting for the socket to become writable -- it's
631                    probably stalled, and/or the buffers are full */
632                 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
633         case SSL_ERROR_WANT_READ:
634                 return 0;
635
636         default:
637                 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
638                 openconnect_report_ssl_errors(vpninfo);
639                 return -1;
640         }
641 }
642 #elif defined (OPENCONNECT_GNUTLS)
643 static int cstp_read(struct openconnect_info *vpninfo, void *buf, int maxlen)
644 {
645         int ret;
646
647         ret = gnutls_record_recv(vpninfo->https_sess, buf, maxlen);
648         if (ret > 0)
649                 return ret;
650
651         if (ret != GNUTLS_E_AGAIN) {
652                 vpn_progress(vpninfo, PRG_ERR,
653                              _("SSL read error: %s; reconnecting.\n"),
654                              gnutls_strerror(ret));
655                 return -EIO;
656         }
657         return 0;
658 }
659
660 static int cstp_write(struct openconnect_info *vpninfo, void *buf, int buflen)
661 {
662         int ret;
663
664         ret = gnutls_record_send(vpninfo->https_sess, buf, buflen);
665         if (ret > 0)
666                 return ret;
667
668         if (ret == GNUTLS_E_AGAIN) {
669                 if (gnutls_record_get_direction(vpninfo->https_sess)) {
670                         /* Waiting for the socket to become writable -- it's
671                            probably stalled, and/or the buffers are full */
672                         FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
673                 }
674                 return 0;
675         }
676         vpn_progress(vpninfo, PRG_ERR, _("SSL send failed: %s\n"),
677                      gnutls_strerror(ret));
678         return -1;
679 }
680 #endif
681
682 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
683 {
684         unsigned char buf[16384];
685         int len, ret;
686         int work_done = 0;
687
688         /* FIXME: The poll() handling here is fairly simplistic. Actually,
689            if the SSL connection stalls it could return a WANT_WRITE error
690            on _either_ of the SSL_read() or SSL_write() calls. In that case,
691            we should probably remove POLLIN from the events we're looking for,
692            and add POLLOUT. As it is, though, it'll just chew CPU time in that
693            fairly unlikely situation, until the write backlog clears. */
694         while ( (len = cstp_read(vpninfo, buf, sizeof(buf))) > 0) {
695                 int payload_len;
696
697                 if (buf[0] != 'S' || buf[1] != 'T' ||
698                     buf[2] != 'F' || buf[3] != 1 || buf[7])
699                         goto unknown_pkt;
700
701                 payload_len = (buf[4] << 8) + buf[5];
702                 if (len != 8 + payload_len) {
703                         vpn_progress(vpninfo, PRG_ERR,
704                                      _("Unexpected packet length. SSL_read returned %d but packet is\n"),
705                                      len);
706                         vpn_progress(vpninfo, PRG_ERR,
707                                      "%02x %02x %02x %02x %02x %02x %02x %02x\n",
708                                      buf[0], buf[1], buf[2], buf[3],
709                                      buf[4], buf[5], buf[6], buf[7]);
710                         continue;
711                 }
712                 vpninfo->ssl_times.last_rx = time(NULL);
713                 switch(buf[6]) {
714                 case AC_PKT_DPD_OUT:
715                         vpn_progress(vpninfo, PRG_TRACE,
716                                      _("Got CSTP DPD request\n"));
717                         vpninfo->owe_ssl_dpd_response = 1;
718                         continue;
719
720                 case AC_PKT_DPD_RESP:
721                         vpn_progress(vpninfo, PRG_TRACE,
722                                      _("Got CSTP DPD response\n"));
723                         continue;
724
725                 case AC_PKT_KEEPALIVE:
726                         vpn_progress(vpninfo, PRG_TRACE,
727                                      _("Got CSTP Keepalive\n"));
728                         continue;
729
730                 case AC_PKT_DATA:
731                         vpn_progress(vpninfo, PRG_TRACE,
732                                      _("Received uncompressed data packet of %d bytes\n"),
733                                      payload_len);
734                         queue_new_packet(&vpninfo->incoming_queue, buf + 8,
735                                          payload_len);
736                         work_done = 1;
737                         continue;
738
739                 case AC_PKT_DISCONN: {
740                         int i;
741                         for (i = 0; i < payload_len; i++) {
742                                 if (!isprint(buf[payload_len + 8 + i]))
743                                         buf[payload_len + 8 + i] = '.';
744                         }
745                         buf[payload_len + 8] = 0;
746                         vpn_progress(vpninfo, PRG_ERR,
747                                      _("Received server disconnect: %02x '%s'\n"),
748                                      buf[8], buf + 9);
749                         vpninfo->quit_reason = "Server request";
750                         return 1;
751                 }
752                 case AC_PKT_COMPRESSED:
753                         if (!vpninfo->deflate) {
754                                 vpn_progress(vpninfo, PRG_ERR,
755                                              _("Compressed packet received in !deflate mode\n"));
756                                 goto unknown_pkt;
757                         }
758                         inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
759                         work_done = 1;
760                         continue;
761
762                 case AC_PKT_TERM_SERVER:
763                         vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
764                         vpninfo->quit_reason = "Server request";
765                         return 1;
766                 }
767
768         unknown_pkt:
769                 vpn_progress(vpninfo, PRG_ERR,
770                              _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
771                              buf[0], buf[1], buf[2], buf[3],
772                              buf[4], buf[5], buf[6], buf[7]);
773                 vpninfo->quit_reason = "Unknown packet received";
774                 return 1;
775         }
776         if (len < 0)
777                 goto do_reconnect;
778
779
780         /* If SSL_write() fails we are expected to try again. With exactly
781            the same data, at exactly the same location. So we keep the
782            packet we had before.... */
783         if (vpninfo->current_ssl_pkt) {
784         handle_outgoing:
785                 vpninfo->ssl_times.last_tx = time(NULL);
786                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
787
788                 ret = cstp_write(vpninfo,
789                                  vpninfo->current_ssl_pkt->hdr,
790                                  vpninfo->current_ssl_pkt->len + 8);
791                 
792                 if (ret < 0)
793                         goto do_reconnect;
794                 else if (!ret && ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
795                         goto peer_dead;
796
797                 if (ret != vpninfo->current_ssl_pkt->len + 8) {
798                         vpn_progress(vpninfo, PRG_ERR,
799                                      _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
800                                      vpninfo->current_ssl_pkt->len + 8, ret);
801                         vpninfo->quit_reason = "Internal error";
802                         return 1;
803                 }
804                 /* Don't free the 'special' packets */
805                 if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt)
806                         free(vpninfo->pending_deflated_pkt);
807                 else if (vpninfo->current_ssl_pkt != &dpd_pkt &&
808                          vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
809                          vpninfo->current_ssl_pkt != &keepalive_pkt)
810                         free(vpninfo->current_ssl_pkt);
811
812                 vpninfo->current_ssl_pkt = NULL;
813         }
814
815         if (vpninfo->owe_ssl_dpd_response) {
816                 vpninfo->owe_ssl_dpd_response = 0;
817                 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
818                 goto handle_outgoing;
819         }
820
821         switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
822         case KA_REKEY:
823                 /* Not that this will ever happen; we don't even process
824                    the setting when we're asked for it. */
825                 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
826                 goto do_reconnect;
827                 break;
828
829         case KA_DPD_DEAD:
830         peer_dead:
831                 vpn_progress(vpninfo, PRG_ERR,
832                              _("CSTP Dead Peer Detection detected dead peer!\n"));
833         do_reconnect:
834                 if (cstp_reconnect(vpninfo)) {
835                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
836                         vpninfo->quit_reason = "CSTP reconnect failed";
837                         return 1;
838                 }
839                 /* I think we can leave DTLS to its own devices; when we reconnect
840                    with the same master secret, we do seem to get the same sessid */
841                 return 1;
842
843         case KA_DPD:
844                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
845
846                 vpninfo->current_ssl_pkt = &dpd_pkt;
847                 goto handle_outgoing;
848
849         case KA_KEEPALIVE:
850                 /* No need to send an explicit keepalive
851                    if we have real data to send */
852                 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
853                         break;
854
855                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
856
857                 vpninfo->current_ssl_pkt = &keepalive_pkt;
858                 goto handle_outgoing;
859
860         case KA_NONE:
861                 ;
862         }
863
864         /* Service outgoing packet queue, if no DTLS */
865         while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
866                 struct pkt *this = vpninfo->outgoing_queue;
867                 vpninfo->outgoing_queue = this->next;
868                 vpninfo->outgoing_qlen--;
869
870                 if (vpninfo->deflate) {
871                         unsigned char *adler;
872                         int ret;
873
874                         vpninfo->deflate_strm.next_in = this->data;
875                         vpninfo->deflate_strm.avail_in = this->len;
876                         vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
877                         vpninfo->deflate_strm.avail_out = 2040;
878                         vpninfo->deflate_strm.total_out = 0;
879
880                         ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
881                         if (ret) {
882                                 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
883                                 goto uncompr;
884                         }
885
886                         vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
887                         vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
888
889                         /* Add ongoing adler32 to tail of compressed packet */
890                         vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
891                                                            this->data, this->len);
892
893                         adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
894                         *(adler++) =  vpninfo->deflate_adler32 >> 24;
895                         *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
896                         *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
897                         *(adler)   =  vpninfo->deflate_adler32 & 0xff;
898
899                         vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
900
901                         vpn_progress(vpninfo, PRG_TRACE,
902                                      _("Sending compressed data packet of %d bytes\n"),
903                                      this->len);
904
905                         vpninfo->pending_deflated_pkt = this;
906                         vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
907                 } else {
908                 uncompr:
909                         memcpy(this->hdr, data_hdr, 8);
910                         this->hdr[4] = this->len >> 8;
911                         this->hdr[5] = this->len & 0xff;
912
913                         vpn_progress(vpninfo, PRG_TRACE,
914                                      _("Sending uncompressed data packet of %d bytes\n"),
915                                      this->len);
916
917                         vpninfo->current_ssl_pkt = this;
918                 }
919                 goto handle_outgoing;
920         }
921
922         /* Work is not done if we just got rid of packets off the queue */
923         return work_done;
924 }
925
926 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
927 {
928         unsigned char *bye_pkt;
929         int reason_len;
930
931         /* already lost connection? */
932 #if defined (OPENCONNECT_OPENSSL)
933         if (!vpninfo->https_ssl)
934                 return 0;
935 #elif defined (OPENCONNECT_GNUTLS)
936         if (!vpninfo->https_sess)
937                 return 0;
938 #endif
939
940         reason_len = strlen(reason);
941         bye_pkt = malloc(reason_len + 9);
942         if (!bye_pkt)
943                 return -ENOMEM;
944
945         memcpy(bye_pkt, data_hdr, 8);
946         memcpy(bye_pkt + 9, reason, reason_len);
947
948         bye_pkt[4] = (reason_len + 1) >> 8;
949         bye_pkt[5] = (reason_len + 1) & 0xff;
950         bye_pkt[6] = AC_PKT_DISCONN;
951         bye_pkt[8] = 0xb0;
952
953         vpn_progress(vpninfo, PRG_INFO,
954                      _("Send BYE packet: %s\n"), reason);
955
956         cstp_write(vpninfo, bye_pkt, reason_len + 9);
957         free(bye_pkt);
958
959         return 0;
960 }