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