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