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