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