Make more strings translatable
[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 #include <netdb.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <time.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <arpa/inet.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, void *buf, int len)
443 {
444         struct pkt *new = malloc(sizeof(struct pkt) + vpninfo->mtu);
445
446         if (!new)
447                 return -ENOMEM;
448
449         new->next = NULL;
450
451         vpninfo->inflate_strm.next_in = buf;
452         vpninfo->inflate_strm.avail_in = len - 4;
453
454         vpninfo->inflate_strm.next_out = new->data;
455         vpninfo->inflate_strm.avail_out = vpninfo->mtu;
456         vpninfo->inflate_strm.total_out = 0;
457
458         if (inflate(&vpninfo->inflate_strm, Z_SYNC_FLUSH)) {
459                 vpn_progress(vpninfo, PRG_ERR, _("inflate failed\n"));
460                 free(new);
461                 return -EINVAL;
462         }
463
464         new->len = vpninfo->inflate_strm.total_out;
465
466         vpninfo->inflate_adler32 = adler32(vpninfo->inflate_adler32,
467                                            new->data, new->len);
468
469         if (vpninfo->inflate_adler32 != ntohl( *(uint32_t *) (buf + len - 4) )) {
470                 vpninfo->quit_reason = "Compression (inflate) adler32 failure";
471         }
472
473         vpn_progress(vpninfo, PRG_TRACE,
474                      _("Received compressed data packet of %ld bytes\n"),
475                      vpninfo->inflate_strm.total_out);
476
477         queue_packet(&vpninfo->incoming_queue, new);
478         return 0;
479 }
480
481 int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
482 {
483         unsigned char buf[16384];
484         int len, ret;
485         int work_done = 0;
486
487         /* FIXME: The poll() handling here is fairly simplistic. Actually,
488            if the SSL connection stalls it could return a WANT_WRITE error
489            on _either_ of the SSL_read() or SSL_write() calls. In that case,
490            we should probably remove POLLIN from the events we're looking for,
491            and add POLLOUT. As it is, though, it'll just chew CPU time in that
492            fairly unlikely situation, until the write backlog clears. */
493         while ( (len = SSL_read(vpninfo->https_ssl, buf, sizeof(buf))) > 0) {
494                 int payload_len;
495
496                 if (buf[0] != 'S' || buf[1] != 'T' ||
497                     buf[2] != 'F' || buf[3] != 1 || buf[7])
498                         goto unknown_pkt;
499
500                 payload_len = (buf[4] << 8) + buf[5];
501                 if (len != 8 + payload_len) {
502                         vpn_progress(vpninfo, PRG_ERR,
503                                      _("Unexpected packet length. SSL_read returned %d but packet is\n"),
504                                      len);
505                         vpn_progress(vpninfo, PRG_ERR,
506                                      "%02x %02x %02x %02x %02x %02x %02x %02x\n",
507                                      buf[0], buf[1], buf[2], buf[3],
508                                      buf[4], buf[5], buf[6], buf[7]);
509                         continue;
510                 }
511                 vpninfo->ssl_times.last_rx = time(NULL);
512                 switch(buf[6]) {
513                 case AC_PKT_DPD_OUT:
514                         vpn_progress(vpninfo, PRG_TRACE,
515                                      _("Got CSTP DPD request\n"));
516                         vpninfo->owe_ssl_dpd_response = 1;
517                         continue;
518
519                 case AC_PKT_DPD_RESP:
520                         vpn_progress(vpninfo, PRG_TRACE,
521                                      _("Got CSTP DPD response\n"));
522                         continue;
523
524                 case AC_PKT_KEEPALIVE:
525                         vpn_progress(vpninfo, PRG_TRACE,
526                                      _("Got CSTP Keepalive\n"));
527                         continue;
528
529                 case AC_PKT_DATA:
530                         vpn_progress(vpninfo, PRG_TRACE,
531                                      _("Received uncompressed data packet of %d bytes\n"),
532                                      payload_len);
533                         queue_new_packet(&vpninfo->incoming_queue, buf + 8,
534                                          payload_len);
535                         work_done = 1;
536                         continue;
537
538                 case AC_PKT_DISCONN: {
539                         int i;
540                         for (i = 0; i < payload_len; i++) {
541                                 if (!isprint(buf[payload_len + 8 + i]))
542                                         buf[payload_len + 8 + i] = '.';
543                         }
544                         buf[payload_len + 8] = 0;
545                         vpn_progress(vpninfo, PRG_ERR,
546                                      _("Received server disconnect: %02x '%s'\n"),
547                                      buf[8], buf + 9);
548                         vpninfo->quit_reason = "Server request";
549                         return 1;
550                 }
551                 case AC_PKT_COMPRESSED:
552                         if (!vpninfo->deflate) {
553                                 vpn_progress(vpninfo, PRG_ERR,
554                                              _("Compressed packet received in !deflate mode\n"));
555                                 goto unknown_pkt;
556                         }
557                         inflate_and_queue_packet(vpninfo, buf + 8, payload_len);
558                         work_done = 1;
559                         continue;
560
561                 case AC_PKT_TERM_SERVER:
562                         vpn_progress(vpninfo, PRG_ERR, _("received server terminate packet\n"));
563                         vpninfo->quit_reason = "Server request";
564                         return 1;
565                 }
566
567         unknown_pkt:
568                 vpn_progress(vpninfo, PRG_ERR,
569                              _("Unknown packet %02x %02x %02x %02x %02x %02x %02x %02x\n"),
570                              buf[0], buf[1], buf[2], buf[3],
571                              buf[4], buf[5], buf[6], buf[7]);
572                 vpninfo->quit_reason = "Unknown packet received";
573                 return 1;
574         }
575
576         ret = SSL_get_error(vpninfo->https_ssl, len);
577         if (ret == SSL_ERROR_SYSCALL || ret == SSL_ERROR_ZERO_RETURN) {
578                 vpn_progress(vpninfo, PRG_ERR,
579                              _("SSL read error %d (server probably closed connection); reconnecting.\n"),
580                              ret);
581                         goto do_reconnect;
582         }
583
584
585         /* If SSL_write() fails we are expected to try again. With exactly
586            the same data, at exactly the same location. So we keep the
587            packet we had before.... */
588         if (vpninfo->current_ssl_pkt) {
589         handle_outgoing:
590                 vpninfo->ssl_times.last_tx = time(NULL);
591                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
592                 ret = SSL_write(vpninfo->https_ssl,
593                                 vpninfo->current_ssl_pkt->hdr,
594                                 vpninfo->current_ssl_pkt->len + 8);
595                 if (ret <= 0) {
596                         ret = SSL_get_error(vpninfo->https_ssl, ret);
597                         switch (ret) {
598                         case SSL_ERROR_WANT_WRITE:
599                                 /* Waiting for the socket to become writable -- it's
600                                    probably stalled, and/or the buffers are full */
601                                 FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
602
603                         case SSL_ERROR_WANT_READ:
604                                 if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
605                                         goto peer_dead;
606                                 return work_done;
607                         default:
608                                 vpn_progress(vpninfo, PRG_ERR, _("SSL_write failed: %d\n"), ret);
609                                 report_ssl_errors(vpninfo);
610                                 goto do_reconnect;
611                         }
612                 }
613                 if (ret != vpninfo->current_ssl_pkt->len + 8) {
614                         vpn_progress(vpninfo, PRG_ERR,
615                                      _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
616                                      vpninfo->current_ssl_pkt->len + 8, ret);
617                         vpninfo->quit_reason = "Internal error";
618                         return 1;
619                 }
620                 /* Don't free the 'special' packets */
621                 if (vpninfo->current_ssl_pkt != vpninfo->deflate_pkt &&
622                     vpninfo->current_ssl_pkt != &dpd_pkt &&
623                     vpninfo->current_ssl_pkt != &dpd_resp_pkt &&
624                     vpninfo->current_ssl_pkt != &keepalive_pkt)
625                         free(vpninfo->current_ssl_pkt);
626
627                 vpninfo->current_ssl_pkt = NULL;
628         }
629
630         if (vpninfo->owe_ssl_dpd_response) {
631                 vpninfo->owe_ssl_dpd_response = 0;
632                 vpninfo->current_ssl_pkt = &dpd_resp_pkt;
633                 goto handle_outgoing;
634         }
635
636         switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
637         case KA_REKEY:
638                 /* Not that this will ever happen; we don't even process
639                    the setting when we're asked for it. */
640                 vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
641                 goto do_reconnect;
642                 break;
643
644         case KA_DPD_DEAD:
645         peer_dead:
646                 vpn_progress(vpninfo, PRG_ERR,
647                              _("CSTP Dead Peer Detection detected dead peer!\n"));
648         do_reconnect:
649                 if (cstp_reconnect(vpninfo)) {
650                         vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
651                         vpninfo->quit_reason = "CSTP reconnect failed";
652                         return 1;
653                 }
654                 /* I think we can leave DTLS to its own devices; when we reconnect
655                    with the same master secret, we do seem to get the same sessid */
656                 return 1;
657
658         case KA_DPD:
659                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP DPD\n"));
660
661                 vpninfo->current_ssl_pkt = &dpd_pkt;
662                 goto handle_outgoing;
663
664         case KA_KEEPALIVE:
665                 /* No need to send an explicit keepalive
666                    if we have real data to send */
667                 if (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue)
668                         break;
669
670                 vpn_progress(vpninfo, PRG_TRACE, _("Send CSTP Keepalive\n"));
671
672                 vpninfo->current_ssl_pkt = &keepalive_pkt;
673                 goto handle_outgoing;
674
675         case KA_NONE:
676                 ;
677         }
678
679         /* Service outgoing packet queue, if no DTLS */
680         while (vpninfo->dtls_fd == -1 && vpninfo->outgoing_queue) {
681                 struct pkt *this = vpninfo->outgoing_queue;
682                 vpninfo->outgoing_queue = this->next;
683                 vpninfo->outgoing_qlen--;
684
685                 if (vpninfo->deflate) {
686                         unsigned char *adler;
687                         int ret;
688
689                         vpninfo->deflate_strm.next_in = this->data;
690                         vpninfo->deflate_strm.avail_in = this->len;
691                         vpninfo->deflate_strm.next_out = (void *)vpninfo->deflate_pkt->data;
692                         vpninfo->deflate_strm.avail_out = 2040;
693                         vpninfo->deflate_strm.total_out = 0;
694
695                         ret = deflate(&vpninfo->deflate_strm, Z_SYNC_FLUSH);
696                         if (ret) {
697                                 vpn_progress(vpninfo, PRG_ERR, _("deflate failed %d\n"), ret);
698                                 goto uncompr;
699                         }
700
701                         vpninfo->deflate_pkt->hdr[4] = (vpninfo->deflate_strm.total_out + 4) >> 8;
702                         vpninfo->deflate_pkt->hdr[5] = (vpninfo->deflate_strm.total_out + 4) & 0xff;
703
704                         /* Add ongoing adler32 to tail of compressed packet */
705                         vpninfo->deflate_adler32 = adler32(vpninfo->deflate_adler32,
706                                                            this->data, this->len);
707
708                         adler = &vpninfo->deflate_pkt->data[vpninfo->deflate_strm.total_out];
709                         *(adler++) =  vpninfo->deflate_adler32 >> 24;
710                         *(adler++) = (vpninfo->deflate_adler32 >> 16) & 0xff;
711                         *(adler++) = (vpninfo->deflate_adler32 >> 8) & 0xff;
712                         *(adler)   =  vpninfo->deflate_adler32 & 0xff;
713
714                         vpninfo->deflate_pkt->len = vpninfo->deflate_strm.total_out + 4;
715
716                         vpn_progress(vpninfo, PRG_TRACE,
717                                      _("Sending compressed data packet of %d bytes\n"),
718                                      this->len);
719
720                         vpninfo->current_ssl_pkt = vpninfo->deflate_pkt;
721                 } else {
722                 uncompr:
723                         memcpy(this->hdr, data_hdr, 8);
724                         this->hdr[4] = this->len >> 8;
725                         this->hdr[5] = this->len & 0xff;
726
727                         vpn_progress(vpninfo, PRG_TRACE,
728                                      _("Sending uncompressed data packet of %d bytes\n"),
729                                      this->len);
730
731                         vpninfo->current_ssl_pkt = this;
732                 }
733                 goto handle_outgoing;
734         }
735
736         /* Work is not done if we just got rid of packets off the queue */
737         return work_done;
738 }
739
740 int cstp_bye(struct openconnect_info *vpninfo, const char *reason)
741 {
742         unsigned char *bye_pkt;
743         int reason_len;
744
745         /* already lost connection? */
746         if (!vpninfo->https_ssl)
747                 return 0;
748
749         reason_len = strlen(reason);
750         bye_pkt = malloc(reason_len + 9);
751         if (!bye_pkt)
752                 return -ENOMEM;
753
754         memcpy(bye_pkt, data_hdr, 8);
755         memcpy(bye_pkt + 9, reason, reason_len);
756
757         bye_pkt[4] = (reason_len + 1) >> 8;
758         bye_pkt[5] = (reason_len + 1) & 0xff;
759         bye_pkt[6] = AC_PKT_DISCONN;
760         bye_pkt[8] = 0xb0;
761
762         SSL_write(vpninfo->https_ssl, bye_pkt, reason_len + 9);
763         free(bye_pkt);
764
765         vpn_progress(vpninfo, PRG_INFO,
766                      _("Send BYE packet: %s\n"), reason);
767
768         return 0;
769 }