Don't unregister p11-kit PIN callback until vpninfo is finished with
[platform/upstream/openconnect.git] / gnutls.c
1 /*
2  * OpenConnect (SSL + DTLS) VPN client
3  *
4  * Copyright © 2008-2012 Intel Corporation.
5  *
6  * Author: David Woodhouse <dwmw2@infradead.org>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1, as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to:
19  *
20  *   Free Software Foundation, Inc.
21  *   51 Franklin Street, Fifth Floor,
22  *   Boston, MA 02110-1301 USA
23  */
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/socket.h>
28 #include <netdb.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <stdio.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <errno.h>
37 #include <stdarg.h>
38 #include <stdlib.h>
39
40 #include <gnutls/gnutls.h>
41 #include <gnutls/x509.h>
42 #include <gnutls/crypto.h>
43 #include <gnutls/pkcs12.h>
44
45 #ifdef HAVE_P11KIT
46 #include <p11-kit/p11-kit.h>
47 #include <p11-kit/pin.h>
48
49 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
50                                const char *pin_description,
51                                P11KitPinFlags flags,
52                                void *_vpninfo);
53 #endif
54
55 #include "openconnect-internal.h"
56
57 /* Helper functions for reading/writing lines over SSL.
58    We could use cURL for the HTTP stuff, but it's overkill */
59
60 int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t len)
61 {
62         size_t orig_len = len;
63
64         while (len) {
65                 int done = gnutls_record_send(vpninfo->https_sess, buf, len);
66                 if (done > 0)
67                         len -= done;
68                 else if (done != GNUTLS_E_AGAIN) {
69                         vpn_progress(vpninfo, PRG_ERR, _("Failed to write to SSL socket: %s"),
70                                      gnutls_strerror(done));
71                         return -EIO;
72                 } else {
73                         fd_set wr_set, rd_set;
74                         int maxfd = vpninfo->ssl_fd;
75
76                         FD_ZERO(&wr_set);
77                         FD_ZERO(&rd_set);
78                         
79                         if (gnutls_record_get_direction(vpninfo->https_sess))
80                                 FD_SET(vpninfo->ssl_fd, &wr_set);
81                         else
82                                 FD_SET(vpninfo->ssl_fd, &rd_set);
83
84                         if (vpninfo->cancel_fd != -1) {
85                                 FD_SET(vpninfo->cancel_fd, &rd_set);
86                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
87                                         maxfd = vpninfo->cancel_fd;
88                         }
89                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
90                         if (vpninfo->cancel_fd != -1 &&
91                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
92                                 vpn_progress(vpninfo, PRG_ERR, _("SSL write cancelled\n"));
93                                 return -EINTR;
94                         }
95                 }
96         }
97         return orig_len;
98 }
99
100 int openconnect_SSL_read(struct openconnect_info *vpninfo, char *buf, size_t len)
101 {
102         int done;
103
104         while ((done = gnutls_record_recv(vpninfo->https_sess, buf, len)) < 0) {
105                 fd_set wr_set, rd_set;
106                 int maxfd = vpninfo->ssl_fd;
107
108                 if (done != GNUTLS_E_AGAIN) {
109                         vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s"),
110                                      gnutls_strerror(done));
111                         return -EIO;
112                 } else {
113                         FD_ZERO(&wr_set);
114                         FD_ZERO(&rd_set);
115                         
116                         if (gnutls_record_get_direction(vpninfo->https_sess))
117                                 FD_SET(vpninfo->ssl_fd, &wr_set);
118                         else
119                                 FD_SET(vpninfo->ssl_fd, &rd_set);
120
121                         if (vpninfo->cancel_fd != -1) {
122                                 FD_SET(vpninfo->cancel_fd, &rd_set);
123                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
124                                         maxfd = vpninfo->cancel_fd;
125                         }
126                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
127                         if (vpninfo->cancel_fd != -1 &&
128                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
129                                 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
130                                 return -EINTR;
131                         }
132                 }
133         }
134         return done;
135 }
136
137 int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
138 {
139         int i = 0;
140         int ret;
141
142         if (len < 2)
143                 return -EINVAL;
144
145         while (1) {
146                 ret = gnutls_record_recv(vpninfo->https_sess, buf + i, 1);
147                 if (ret == 1) {
148                         if (buf[i] == '\n') {
149                                 buf[i] = 0;
150                                 if (i && buf[i-1] == '\r') {
151                                         buf[i-1] = 0;
152                                         i--;
153                                 }
154                                 return i;
155                         }
156                         i++;
157
158                         if (i >= len - 1) {
159                                 buf[i] = 0;
160                                 return i;
161                         }
162                 } else if (ret != GNUTLS_E_AGAIN) {
163                         vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s\n"),
164                                      gnutls_strerror(ret));
165                         ret = -EIO;
166                         break;
167                 } else {
168                         fd_set rd_set, wr_set;
169                         int maxfd = vpninfo->ssl_fd;
170                         
171                         FD_ZERO(&rd_set);
172                         FD_ZERO(&wr_set);
173                         
174                         if (gnutls_record_get_direction(vpninfo->https_sess))
175                                 FD_SET(vpninfo->ssl_fd, &wr_set);
176                         else
177                                 FD_SET(vpninfo->ssl_fd, &rd_set);
178
179                         if (vpninfo->cancel_fd != -1) {
180                                 FD_SET(vpninfo->cancel_fd, &rd_set);
181                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
182                                         maxfd = vpninfo->cancel_fd;
183                         }
184                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
185                         if (vpninfo->cancel_fd != -1 &&
186                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
187                                 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
188                                 ret = -EINTR;
189                                 break;
190                         }
191                 }
192         }
193         buf[i] = 0;
194         return i ?: ret;
195 }
196
197 static int check_certificate_expiry(struct openconnect_info *vpninfo, gnutls_x509_crt_t cert)
198 {
199         const char *reason = NULL;
200         time_t expires = gnutls_x509_crt_get_expiration_time(cert);
201         time_t now = time(NULL);
202
203         if (expires == -1) {
204                 vpn_progress(vpninfo, PRG_ERR,
205                              _("Could not extract expiration time of certificate\n"));
206                 return -EINVAL;
207         }
208
209         if (expires < now)
210                 reason = _("Client certificate has expired at");
211         else if (expires < now + vpninfo->cert_expire_warning)
212                 reason = _("Client certificate expires soon at");
213
214         if (reason) {
215                 struct tm tm;
216                 char buf[80];
217
218                 gmtime_r(&expires, &tm);
219                 strftime(buf, 80, "%a, %d %b %Y %T %Z", &tm);
220
221                 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, buf);
222         }
223         return 0;
224 }
225
226 /* For systems that don't support O_CLOEXEC, just don't bother.
227    It's not open for long anyway. */
228 #ifndef O_CLOEXEC
229 #define O_CLOEXEC
230 #endif
231
232 static int load_datum(struct openconnect_info *vpninfo,
233                       gnutls_datum_t *datum, const char *fname)
234 {
235         struct stat st;
236         int fd, err;
237
238         fd = open(fname, O_RDONLY|O_CLOEXEC);
239         if (fd == -1) {
240                 err = errno;
241                 vpn_progress(vpninfo, PRG_ERR,
242                              _("Failed to open certificate file %s: %s\n"),
243                              vpninfo->cert, strerror(err));
244                 return -ENOENT;
245         }
246         if (fstat(fd, &st)) {
247                 err = errno;
248                 vpn_progress(vpninfo, PRG_ERR,
249                              _("Failed to stat certificate file %s: %s\n"),
250                              vpninfo->cert, strerror(err));
251                 close(fd);
252                 return -EIO;
253         }
254         datum->size = st.st_size;
255         datum->data = gnutls_malloc(st.st_size + 1);
256         if (!datum->data) {
257                 vpn_progress(vpninfo, PRG_ERR,
258                              _("Failed to allocate certificate buffer\n"));
259                 close(fd);
260                 return -ENOMEM;
261         }
262         errno = EAGAIN;
263         if (read(fd, datum->data, datum->size) != datum->size) {
264                 err = errno;
265                 vpn_progress(vpninfo, PRG_ERR,
266                              _("Failed to read certificate into memory: %s\n"),
267                              strerror(err));
268                 close(fd);
269                 gnutls_free(datum->data);
270                 return -EIO;
271         }
272         datum->data[st.st_size] = 0;
273         close(fd);
274         return 0;
275 }
276
277 #ifndef HAVE_GNUTLS_PKCS12_SIMPLE_PARSE
278 /* If we're using a version of GnuTLS from before this was 
279    exported, pull in our local copy. */
280 #include "gnutls_pkcs12.c"
281 #endif
282
283 /* A non-zero, non-error return to make load_certificate() continue and
284    interpreting the file as other types */
285 #define NOT_PKCS12      1
286
287 static int load_pkcs12_certificate(struct openconnect_info *vpninfo,
288                                    gnutls_datum_t *datum,
289                                    gnutls_x509_privkey_t *key,
290                                    gnutls_x509_crt_t **chain,
291                                    unsigned int *chain_len,
292                                    gnutls_x509_crt_t **extra_certs,
293                                    unsigned int *extra_certs_len,
294                                    gnutls_x509_crl_t *crl)
295 {
296         gnutls_pkcs12_t p12;
297         char *pass;
298         int err;
299
300         err = gnutls_pkcs12_init(&p12);
301         if (err) {
302                 vpn_progress(vpninfo, PRG_ERR,
303                              _("Failed to setup PKCS#12 data structure: %s\n"),
304                              gnutls_strerror(err));
305                 return -EIO;
306         }
307
308         err = gnutls_pkcs12_import(p12, datum, GNUTLS_X509_FMT_DER, 0);
309         if (err) {
310                 gnutls_pkcs12_deinit(p12);
311                 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN)
312                         return NOT_PKCS12;
313                 vpn_progress(vpninfo, PRG_ERR,
314                              _("Failed to import PKCS#12 file: %s\n"),
315                              gnutls_strerror(err));
316                 return -EINVAL;
317         }
318
319         pass = vpninfo->cert_password;
320         while ((err = gnutls_pkcs12_verify_mac(p12, pass)) == GNUTLS_E_MAC_VERIFY_FAILED) {
321                 if (pass)
322                         vpn_progress(vpninfo, PRG_ERR,
323                                      _("Failed to decrypt PKCS#12 certificate file\n"));
324                 free(pass);
325                 vpninfo->cert_password = NULL;
326                 err = request_passphrase(vpninfo, &pass,
327                                          _("Enter PKCS#12 pass phrase:"));
328                 if (err) {
329                         gnutls_pkcs12_deinit(p12);
330                         return -EINVAL;
331                 }
332         }
333         /* If it wasn't GNUTLS_E_MAC_VERIFY_FAILED, then the problem wasn't just a
334            bad password. Give up. */
335         if (err) {
336                 int level = PRG_ERR;
337                 int ret = -EINVAL;
338
339                 gnutls_pkcs12_deinit(p12);
340
341                 /* If the first attempt, and we didn't know for sure it was PKCS#12
342                    anyway, bail out and try loading it as something different. */
343                 if (pass == vpninfo->cert_password &&
344                     vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
345                         /* Make it non-fatal... */
346                         level = PRG_TRACE;
347                         ret = NOT_PKCS12;
348                 }
349
350                 vpn_progress(vpninfo, level,
351                              _("Failed to process PKCS#12 file: %s\n"),
352                                gnutls_strerror(err));
353                 return ret;
354         }
355
356         err = gnutls_pkcs12_simple_parse(p12, pass, key, chain, chain_len,
357                                          extra_certs, extra_certs_len, crl, 0);
358         gnutls_pkcs12_deinit(p12);
359         if (err) {
360                 vpn_progress(vpninfo, PRG_ERR,
361                              _("Failed to load PKCS#12 certificate: %s\n"),
362                              gnutls_strerror(err));
363                 return -EINVAL;
364         }
365         return 0;
366 }
367
368 /* Older versions of GnuTLS didn't actually bother to check this, so we'll
369    do it for them. */
370 static int check_issuer_sanity(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer)
371 {
372 #if GNUTLS_VERSION_NUMBER > 0x300014
373         return 0;
374 #else
375         unsigned char id1[512], id2[512];
376         size_t id1_size = 512, id2_size = 512;
377         int err;
378
379         err = gnutls_x509_crt_get_authority_key_id(cert, id1, &id1_size, NULL);
380         if (err)
381                 return 0;
382
383         err = gnutls_x509_crt_get_subject_key_id(issuer, id2, &id2_size, NULL);
384         if (err)
385                 return 0;
386         if (id1_size == id2_size && !memcmp(id1, id2, id1_size))
387                 return 0;
388
389         /* EEP! */
390         return -EIO;
391 #endif
392 }
393
394 static int count_x509_certificates(gnutls_datum_t *datum)
395 {
396         int count = 0;
397         char *p = (char *)datum->data;
398
399         while (p) {
400                 p = strstr(p, "-----BEGIN ");
401                 if (!p)
402                         break;
403                 p += 11;
404                 if (!strncmp(p, "CERTIFICATE", 11) ||
405                     !strncmp(p, "X509 CERTIFICATE", 16))
406                     count++;
407         }
408         return count;
409 }
410
411 static int load_certificate(struct openconnect_info *vpninfo)
412 {
413         gnutls_datum_t fdata;
414         gnutls_x509_privkey_t key = NULL;
415         gnutls_x509_crl_t crl = NULL;
416         gnutls_x509_crt_t last_cert, cert = NULL;
417         gnutls_x509_crt_t *extra_certs = NULL, *supporting_certs = NULL;
418         unsigned int nr_supporting_certs = 0, nr_extra_certs = 0;
419         unsigned int certs_to_free = 0; /* How many of supporting_certs */
420         int err; /* GnuTLS error */
421         int ret = 0; /* our error (zero or -errno) */
422         int i;
423         unsigned char key_id[20];
424         size_t key_id_size = sizeof(key_id);
425
426         if (vpninfo->cert_type == CERT_TYPE_TPM) {
427                 vpn_progress(vpninfo, PRG_ERR,
428                              _("TPM support not available with GnuTLS\n"));
429                 return -EINVAL;
430         }
431
432         if (!strncmp(vpninfo->cert, "pkcs11:", 7)) {
433                 char *cert_url = (char *)vpninfo->cert;
434                 char *key_url = (char *)vpninfo->sslkey;
435 #ifdef HAVE_P11KIT
436                 char pin_source[40];
437                 P11KitUri *uri;
438
439                 sprintf(pin_source, "openconnect:%p", vpninfo);
440
441                 uri = p11_kit_uri_new();
442                 if (p11_kit_uri_parse(vpninfo->cert, P11_KIT_URI_FOR_OBJECT, uri) != P11_KIT_URI_OK) {
443                         vpn_progress(vpninfo, PRG_ERR, _("Failed to parse PKCS#11 URL '%s'\n"),
444                                      vpninfo->cert);
445                         p11_kit_uri_free(uri);
446                         return -EINVAL;
447                 }
448                 if (!p11_kit_uri_get_pin_source(uri)) {
449                         p11_kit_uri_set_pin_source(uri, pin_source);
450                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &cert_url);
451                 }
452
453                 if (p11_kit_uri_parse(vpninfo->sslkey, P11_KIT_URI_FOR_OBJECT, uri) != P11_KIT_URI_OK) {
454                         vpn_progress(vpninfo, PRG_ERR, _("Failed to parse PKCS#11 URL '%s'\n"),
455                                      vpninfo->sslkey);
456                         p11_kit_uri_free(uri);
457                         free(cert_url);
458                         return -EINVAL;
459                 }
460                 if (!p11_kit_uri_get_pin_source(uri)) {
461                         p11_kit_uri_set_pin_source(uri, pin_source);
462                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &key_url);
463                 }
464                 p11_kit_uri_free(uri);
465                 p11_kit_pin_register_callback(pin_source, pin_callback, vpninfo, NULL);
466 #endif
467                 vpn_progress(vpninfo, PRG_TRACE,
468                              _("Using PKCS#11 certificate %s\n"), vpninfo->cert);
469
470                 err = gnutls_certificate_set_x509_key_file(vpninfo->https_cred,
471                                                            cert_url, key_url,
472                                                            GNUTLS_X509_FMT_PEM);
473                 if (cert_url != vpninfo->cert)
474                         free(cert_url);
475                 if (key_url != vpninfo->sslkey)
476                         free(key_url);
477
478                 if (err) {
479                         vpn_progress(vpninfo, PRG_ERR,
480                                      _("Error loading PKCS#11 certificate: %s\n"),
481                                      gnutls_strerror(err));
482                         return -EIO;
483                 }
484                 return 0;
485         }
486
487         vpn_progress(vpninfo, PRG_TRACE,
488                      _("Using certificate file %s\n"), vpninfo->cert);
489
490         ret = load_datum(vpninfo, &fdata, vpninfo->cert);
491         if (ret)
492                 return ret;
493
494         if (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
495             vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
496                 ret = load_pkcs12_certificate(vpninfo, &fdata, &key,
497                                               &supporting_certs, &nr_supporting_certs,
498                                               &extra_certs, &nr_extra_certs,
499                                               &crl);
500                 if (ret < 0)
501                         goto out;
502                 else if (!ret) {
503                         if (nr_supporting_certs) {
504                                 cert = supporting_certs[0];
505                                 goto got_cert;
506                         }
507                         vpn_progress(vpninfo, PRG_ERR,
508                                      _("PKCS#11 file contained no certificate\n"));
509                         ret = -EINVAL;
510                         goto out;
511                 }
512
513                 /* It returned NOT_PKCS12.
514                    Fall through to try PEM formats. */
515         }
516
517         /* We need to know how many there are in *advance*; it won't just allocate
518            the array for us :( */
519         nr_extra_certs = count_x509_certificates(&fdata);
520         if (!nr_extra_certs)
521                 nr_extra_certs = 1; /* wtf? Oh well, we'll fail later... */
522
523         extra_certs = calloc(nr_extra_certs, sizeof(cert));
524         if (!extra_certs) {
525                 nr_extra_certs = 0;
526                 ret = -ENOMEM;
527                 goto out;
528         }
529         err = gnutls_x509_crt_list_import(extra_certs, &nr_extra_certs, &fdata,
530                                           GNUTLS_X509_FMT_PEM, 0);
531         if (err <= 0) {
532                 const char *reason;
533                 if (!err || err == GNUTLS_E_NO_CERTIFICATE_FOUND)
534                         reason = _("No certificate found in file");
535                 else
536                         reason = gnutls_strerror(err);
537
538                 vpn_progress(vpninfo, PRG_ERR,
539                              _("Loading certificate failed: %s\n"),
540                              reason);
541                 ret = -EINVAL;
542                 goto out;
543         }
544         nr_extra_certs = err;
545         err = 0;
546
547         if (vpninfo->sslkey != vpninfo->cert) {
548                 gnutls_free(fdata.data);
549
550                 vpn_progress(vpninfo, PRG_TRACE,
551                              _("Using private key file %s\n"), vpninfo->cert);
552
553                 ret = load_datum(vpninfo, &fdata, vpninfo->sslkey);
554                 if (ret)
555                         goto out;
556         }
557
558         gnutls_x509_privkey_init(&key);
559         /* Try PKCS#1 (and PKCS#8 without password) first. GnuTLS doesn't
560            support OpenSSL's old PKCS#1-based encrypted format. We should
561            probably check for it and give a more coherent failure mode. */
562         err = gnutls_x509_privkey_import(key, &fdata, GNUTLS_X509_FMT_PEM);
563         if (err) {
564                 /* If that fails, try PKCS#8 */
565                 char *pass = vpninfo->cert_password;
566
567                 /* Yay, just for fun this is *different* to PKCS#12. Where we could
568                    try an empty password there, in this case the empty-password case
569                    has already been *tried* by gnutls_x509_privkey_import(). If we
570                    just call gnutls_x509_privkey_import_pkcs8() with a NULL password,
571                    it'll SEGV. You have to set the GNUTLS_PKCS_PLAIN flag if you want
572                    to try without a password. Passing NULL evidently isn't enough of
573                    a hint. And in GnuTLS 3.1 where that crash has been fixed, passing
574                    NULL will cause it to return GNUTLS_E_ENCRYPTED_STRUCTURE (a new
575                    error code) rather than GNUTLS_E_DECRYPTION_FAILED. So just pass ""
576                    instead of NULL, and don't worry about either case. */
577                 while ((err = gnutls_x509_privkey_import_pkcs8(key, &fdata,
578                                                                GNUTLS_X509_FMT_PEM,
579                                                                pass?pass:"", 0))) {
580                         if (err != GNUTLS_E_DECRYPTION_FAILED) {
581                                 vpn_progress(vpninfo, PRG_ERR,
582                                              _("Failed to load private key as PKCS#8: %s\n"),
583                                              gnutls_strerror(err));
584                                 ret = -EINVAL;
585                                 goto out;
586                         }
587                         if (pass) {
588                                 vpn_progress(vpninfo, PRG_ERR,
589                                              _("Failed to decrypt PKCS#8 certificate file\n"));
590                                 free (pass);
591                         }
592                         err = request_passphrase(vpninfo, &pass,
593                                                  _("Enter PEM pass phrase:"));
594                         if (err) {
595                                 ret = -EINVAL;
596                                 goto out;
597                         }
598                 }
599         }
600         err = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size);
601         if (err) {
602                 vpn_progress(vpninfo, PRG_ERR,
603                              _("Failed to get key ID: %s\n"),
604                              gnutls_strerror(err));
605                 goto out;
606         }
607         for (i = 0; i < nr_extra_certs; i++) {
608                 unsigned char cert_id[20];
609                 size_t cert_id_size = sizeof(cert_id);
610
611                 err = gnutls_x509_crt_get_key_id(extra_certs[i], 0, cert_id, &cert_id_size);
612                 if (err)
613                         continue;
614
615                 if (cert_id_size == key_id_size && !memcmp(cert_id, key_id, key_id_size)) {
616                         cert = extra_certs[i];
617
618                         /* Move the rest of the array down */
619                         for (; i < nr_extra_certs - 1; i++)
620                                 extra_certs[i] = extra_certs[i+1];
621
622                         nr_extra_certs--;
623                         goto got_cert;
624                 }
625         }
626         /* We shouldn't reach this. It means that we didn't find *any* matching cert */
627         vpn_progress(vpninfo, PRG_ERR,
628                      _("No SSL certificate found to match private key\n"));
629         ret = -EINVAL;
630         goto out;
631
632  got_cert:
633         check_certificate_expiry(vpninfo, cert);
634
635         if (crl) {
636                 err = gnutls_certificate_set_x509_crl(vpninfo->https_cred, &crl, 1);
637                 if (err) {
638                         vpn_progress(vpninfo, PRG_ERR,
639                                      _("Setting certificate recovation list failed: %s\n"),
640                                      gnutls_strerror(err));
641                         goto out;
642                 }
643         }
644
645         /* OpenSSL has problems with certificate chains — if there are
646            multiple certs with the same name, it doesn't necessarily
647            choose the _right_ one. (RT#1942)
648            Pick the right ones for ourselves and add them manually. */
649
650         if (nr_supporting_certs) {
651                 /* We already got a bunch of certs from PKCS#12 file. 
652                    Remember how many need to be freed when we're done,
653                    since we'll expand the supporting_certs array with
654                    more from the cafile if we can. */
655                 last_cert = supporting_certs[nr_supporting_certs-1];
656                 certs_to_free = nr_supporting_certs;
657         } else {
658                 last_cert = cert;
659                 certs_to_free = nr_supporting_certs = 1;
660         }
661         while (1) {
662                 gnutls_x509_crt_t issuer;
663
664                 for (i = 0; i < nr_extra_certs; i++) {
665                         if (gnutls_x509_crt_check_issuer(last_cert, extra_certs[i]) &&
666                             !check_issuer_sanity(last_cert, extra_certs[i]))
667                                 break;
668                 }
669
670                 if (i < nr_extra_certs) {
671                         issuer = extra_certs[i];
672                 } else {
673                         err = gnutls_certificate_get_issuer(vpninfo->https_cred,
674                                                             last_cert, &issuer, 0);
675                         if (err)
676                                 break;
677                 }
678
679                 /* The check_issuer_sanity() function works fine as a workaround where
680                    it was used above, but when gnutls_certificate_get_issuer() returns
681                    a bogus cert, there's nothing we can do to fix it up. We don't get
682                    to iterate over all the available certs like we can over our own
683                    list. */
684                 if (check_issuer_sanity(last_cert, issuer)) {
685                         /* Hm, is there a bug reference for this? Or just the git commit
686                            reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
687                         vpn_progress(vpninfo, PRG_ERR,
688                                      _("WARNING: GnuTLS returned incorrect issuer certs; authentication may fail!\n"));
689                         break;
690                 }
691
692                 if (issuer == last_cert) {
693                         /* Don't actually include the root CA. If they don't already trust it,
694                            then handing it to them isn't going to help. But don't omit the
695                            original certificate if it's self-signed. */
696                         if (nr_supporting_certs > 1)
697                                 nr_supporting_certs--;
698                         break;
699                 }
700
701                 /* OK, we found a new cert to add to our chain. */
702                 supporting_certs = gnutls_realloc(supporting_certs,
703                                                   sizeof(cert) * ++nr_supporting_certs);
704                 if (!supporting_certs) {
705                         vpn_progress(vpninfo, PRG_ERR,
706                                      _("Failed to allocate memory for supporting certificates\n"));
707                         /* The world is probably about to end, but try without them anyway */
708                         certs_to_free = 0;
709                         ret = -ENOMEM;
710                         goto out;
711                 }
712
713                 /* First time we actually allocated an array? Copy the first cert into it */
714                 if (nr_supporting_certs == 2)
715                         supporting_certs[0] = cert;
716
717                 /* Append the new one */
718                 supporting_certs[nr_supporting_certs-1] = issuer;
719                 last_cert = issuer;
720
721         }
722         for (i = 1; i < nr_supporting_certs; i++) {
723                 char name[80];
724                 size_t namelen;
725
726                 sprintf(name, "<unknown>");
727                 namelen = sizeof(name);
728                 if (gnutls_x509_crt_get_dn_by_oid(supporting_certs[i],
729                                                   GNUTLS_OID_X520_COMMON_NAME,
730                                                   0, 0, name, &namelen) &&
731                     gnutls_x509_crt_get_dn(supporting_certs[i], name, &namelen))
732                         sprintf(name, "<unknown>");
733
734                 vpn_progress(vpninfo, PRG_DEBUG,
735                              _("Adding supporting CA '%s'\n"), name);
736         }
737
738         err = gnutls_certificate_set_x509_key(vpninfo->https_cred,
739                                               supporting_certs ? supporting_certs : &cert,
740                                               supporting_certs ? 1 : nr_supporting_certs,
741                                               key);
742         if (err) {
743                 vpn_progress(vpninfo, PRG_ERR,
744                              _("Setting certificate failed: %s\n"),
745                              gnutls_strerror(err));
746                 ret = -EIO;
747         }
748  out:
749         if (crl)
750                 gnutls_x509_crl_deinit(crl);
751         if (key)
752                 gnutls_x509_privkey_deinit(key);
753         if (cert)
754                 gnutls_x509_crt_deinit(cert);
755         /* From 1 because cert is the first one (and might exist
756            even if supporting_certs is NULL) */
757         for (i = 1; i < certs_to_free; i++) {
758                 if (supporting_certs[i])
759                         gnutls_x509_crt_deinit(supporting_certs[i]);
760         }
761         for (i = 0; i < nr_extra_certs; i++) {
762                 if (extra_certs[i])
763                         gnutls_x509_crt_deinit(extra_certs[i]);
764         }
765         gnutls_free(extra_certs);
766         gnutls_free(supporting_certs);
767         gnutls_free(fdata.data);
768         return ret;
769 }
770
771 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
772                                 gnutls_x509_crt_t cert,
773                                 gnutls_digest_algorithm_t algo,
774                                 char *buf)
775 {
776         unsigned char md[256];
777         size_t md_size = sizeof(md);
778         unsigned int i;
779
780         if (gnutls_x509_crt_get_fingerprint(cert, algo, md, &md_size))
781                 return -EIO;
782
783         for (i=0; i < md_size; i++)
784                 sprintf(&buf[i*2], "%02X", md[i]);
785
786         return 0;
787 }
788
789 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
790                              OPENCONNECT_X509 *cert, char *buf)
791 {
792         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_MD5, buf);
793 }
794
795 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
796                               OPENCONNECT_X509 *cert, char *buf)
797 {
798         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_SHA1, buf);
799 }
800
801 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
802                                    OPENCONNECT_X509 *cert)
803 {
804         gnutls_datum_t buf;
805         char *ret;
806
807         if (gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &buf))
808                 return NULL;
809         
810         /* Just in case gnutls_free() isn't free(), we can't steal it. */
811         ret = strdup((char *)buf.data);
812         gnutls_free(buf.data);
813         
814         return ret;
815 }
816
817 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
818                              OPENCONNECT_X509 *cert, unsigned char **buf)
819 {
820         size_t l = 0;
821         unsigned char *ret = NULL;
822
823         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l) != 
824             GNUTLS_E_SHORT_MEMORY_BUFFER)
825                 return -EIO;
826
827         ret = malloc(l);
828         if (!ret)
829                 return -ENOMEM;
830
831         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l)) {
832                 free(ret);
833                 return -EIO;
834         }
835         *buf = ret;
836         return l;
837 }
838
839 static int verify_peer(gnutls_session_t session)
840 {
841         struct openconnect_info *vpninfo = gnutls_session_get_ptr(session);
842         const gnutls_datum_t *cert_list;
843         gnutls_x509_crt_t cert;
844         unsigned int status, cert_list_size;
845         const char *reason = NULL;
846         int err;
847
848         if (vpninfo->peer_cert) {
849                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
850                 vpninfo->peer_cert = NULL;
851         }
852
853         cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
854         if (!cert_list) {
855                 vpn_progress(vpninfo, PRG_ERR, _("Server presented no certificate\n"));
856                 return GNUTLS_E_CERTIFICATE_ERROR;
857         }
858
859         if (vpninfo->servercert) {
860                 unsigned char sha1bin[SHA1_SIZE];
861                 char fingerprint[(SHA1_SIZE * 2) + 1];
862                 int i;
863                 
864                 err = openconnect_sha1(sha1bin, cert_list[0].data, cert_list[0].size);
865                 if (err) {
866                         vpn_progress(vpninfo, PRG_ERR,
867                                      _("Could not calculate SHA1 of server's certificate\n"));
868                         return GNUTLS_E_CERTIFICATE_ERROR;
869                 }
870                 for (i=0; i < SHA1_SIZE; i++)
871                         sprintf(&fingerprint[i*2], "%02X", sha1bin[i]);
872
873                 if (strcasecmp(vpninfo->servercert, fingerprint)) {
874                         vpn_progress(vpninfo, PRG_ERR,
875                                      _("Server SSL certificate didn't match: %s\n"), fingerprint);
876                         return GNUTLS_E_CERTIFICATE_ERROR;
877                 }
878                 return 0;
879         }
880
881         err = gnutls_certificate_verify_peers2 (session, &status);
882         if (err) {
883                 vpn_progress(vpninfo, PRG_ERR, _("Error checking server cert status\n"));
884                 return GNUTLS_E_CERTIFICATE_ERROR;
885         }
886
887         if (status & GNUTLS_CERT_REVOKED)
888                 reason = _("certificate revoked");
889         else if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
890                 reason = _("signer not found");
891         else if (status & GNUTLS_CERT_SIGNER_NOT_CA)
892                 reason = _("signer not a CA certificate");
893         else if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
894                 reason = _("insecure algorithm");
895         else if (status & GNUTLS_CERT_NOT_ACTIVATED)
896                 reason = _("certificate not yet activated");
897         else if (status & GNUTLS_CERT_EXPIRED)
898                 reason = _("certificate expired");
899         else if (status & GNUTLS_CERT_INVALID)
900                 /* If this is set and no other reason, it apparently means
901                    that signature verification failed. Not entirely sure
902                    why we don't just set a bit for that too. */
903                 reason = _("signature verification failed");
904
905         err = gnutls_x509_crt_init(&cert);
906         if (err) {
907                 vpn_progress(vpninfo, PRG_ERR, _("Error initialising X509 cert structure\n"));
908                 return GNUTLS_E_CERTIFICATE_ERROR;
909         }
910
911         err = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
912         if (err) {
913                 vpn_progress(vpninfo, PRG_ERR, _("Error importing server's cert\n"));
914                 gnutls_x509_crt_deinit(cert);
915                 return GNUTLS_E_CERTIFICATE_ERROR;
916         }
917
918         if (!reason && !gnutls_x509_crt_check_hostname(cert, vpninfo->hostname))
919                 reason = _("certificate does not match hostname");
920
921         if (reason) {
922                 vpn_progress(vpninfo, PRG_INFO, "Server certificate verify failed: %s\n",
923                              reason);
924                 if (vpninfo->validate_peer_cert)
925                         err = vpninfo->validate_peer_cert(vpninfo->cbdata,
926                                                           cert,
927                                                           reason) ? GNUTLS_E_CERTIFICATE_ERROR : 0;
928                 else
929                         err = GNUTLS_E_CERTIFICATE_ERROR;
930         }
931
932         vpninfo->peer_cert = cert;
933
934         return err;
935 }
936
937
938 int openconnect_open_https(struct openconnect_info *vpninfo)
939 {
940         int ssl_sock = -1;
941         int err;
942
943         if (vpninfo->https_sess)
944                 return 0;
945
946         ssl_sock = connect_https_socket(vpninfo);
947         if (ssl_sock < 0)
948                 return ssl_sock;
949
950         if (!vpninfo->https_cred) {
951                 gnutls_certificate_allocate_credentials(&vpninfo->https_cred);
952                 gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
953                                                        "/etc/pki/tls/certs/ca-bundle.crt",
954                                                        GNUTLS_X509_FMT_PEM);
955                 gnutls_certificate_set_verify_function (vpninfo->https_cred,
956                                                         verify_peer);
957                 /* FIXME: Ensure TLSv1.0, no options */
958
959                 if (vpninfo->cafile) {
960                         err = gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
961                                                                      vpninfo->cafile,
962                                                                      GNUTLS_X509_FMT_PEM);
963                         if (err < 0) {
964                                 vpn_progress(vpninfo, PRG_ERR,
965                                              _("Failed to open CA file '%s': %s\n"),
966                                              vpninfo->cafile, gnutls_strerror(err));
967                                 close(ssl_sock);
968                                 return -EINVAL;
969                         }
970                 }
971
972                 if (vpninfo->cert) {
973                         err = load_certificate(vpninfo);
974                         if (err) {
975                                 vpn_progress(vpninfo, PRG_ERR,
976                                              _("Loading certificate failed. Aborting.\n"));
977                                 return err;
978                         }
979                 }
980
981                 /* We just want to do:
982                    SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY); 
983                    ... but it doesn't work with OpenSSL < 0.9.8k because of 
984                    problems with inheritance (fixed in v1.1.4.6 of
985                    crypto/x509/x509_vpm.c) so we have to play silly buggers
986                    instead. This trick doesn't work _either_ in < 0.9.7 but
987                    I don't know of _any_ workaround which will, and can't
988                    be bothered to find out either. */
989
990
991         }
992         gnutls_init (&vpninfo->https_sess, GNUTLS_CLIENT);
993         gnutls_session_set_ptr (vpninfo->https_sess, (void *) vpninfo);
994         err = gnutls_priority_set_direct (vpninfo->https_sess, "NONE:+VERS-TLS1.0:+SHA1:+AES-128-CBC:+RSA:+COMP-NULL:%COMPAT:%DISABLE_SAFE_RENEGOTIATION", NULL);
995         if (err) {
996                 vpn_progress(vpninfo, PRG_ERR,
997                              _("Failed to set TLS priority string: %s\n"),
998                              gnutls_strerror(err));
999                 return -EIO;
1000         }
1001
1002         gnutls_record_disable_padding (vpninfo->https_sess);
1003         gnutls_credentials_set (vpninfo->https_sess, GNUTLS_CRD_CERTIFICATE, vpninfo->https_cred);
1004         gnutls_transport_set_ptr(vpninfo->https_sess, /* really? */(gnutls_transport_ptr_t)(long) ssl_sock);
1005
1006         vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1007                      vpninfo->hostname);
1008
1009         while ((err = gnutls_handshake (vpninfo->https_sess))) {
1010                 if (err == GNUTLS_E_AGAIN) {
1011                         fd_set rd_set, wr_set;
1012                         int maxfd = ssl_sock;
1013                         
1014                         FD_ZERO(&rd_set);
1015                         FD_ZERO(&wr_set);
1016                         
1017                         if (gnutls_record_get_direction(vpninfo->https_sess))
1018                                 FD_SET(ssl_sock, &wr_set);
1019                         else
1020                                 FD_SET(ssl_sock, &rd_set);
1021
1022                         if (vpninfo->cancel_fd != -1) {
1023                                 FD_SET(vpninfo->cancel_fd, &rd_set);
1024                                 if (vpninfo->cancel_fd > ssl_sock)
1025                                         maxfd = vpninfo->cancel_fd;
1026                         }
1027                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1028                         if (vpninfo->cancel_fd != -1 &&
1029                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1030                                 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1031                                 gnutls_deinit(vpninfo->https_sess);
1032                                 vpninfo->https_sess = NULL;
1033                                 close(ssl_sock);
1034                                 return -EINTR;
1035                         }
1036                 } else if (err == GNUTLS_E_INTERRUPTED || gnutls_error_is_fatal(err)) {
1037                         vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure: %s\n"),
1038                                                          gnutls_strerror(err));
1039                         gnutls_deinit(vpninfo->https_sess);
1040                         vpninfo->https_sess = NULL;
1041                         close(ssl_sock);
1042                         return -EIO;
1043                 } else {
1044                         /* non-fatal error or warning. Ignore it and continue */
1045                         vpn_progress(vpninfo, PRG_TRACE,
1046                                      _("GnuTLS non-fatal return during handshake: %s\n"),
1047                                      gnutls_strerror(err));
1048                 }
1049         }
1050
1051         vpninfo->ssl_fd = ssl_sock;
1052
1053         vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1054                      vpninfo->hostname);
1055
1056         return 0;
1057 }
1058
1059 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1060 {
1061         if (vpninfo->peer_cert) {
1062                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1063                 vpninfo->peer_cert = NULL;
1064         }
1065         if (vpninfo->https_sess) {
1066                 gnutls_deinit(vpninfo->https_sess);
1067                 vpninfo->https_sess = NULL;
1068         }
1069         if (vpninfo->ssl_fd != -1) {
1070                 close(vpninfo->ssl_fd);
1071                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1072                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1073                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1074                 vpninfo->ssl_fd = -1;
1075         }
1076         if (final && vpninfo->https_cred) {
1077                 gnutls_certificate_free_credentials(vpninfo->https_cred);
1078                 vpninfo->https_cred = NULL;
1079 #ifdef HAVE_P11KIT
1080                 if (!strncmp(vpninfo->cert, "pkcs11:", 7)) {
1081                         char pin_source[40];
1082
1083                         sprintf(pin_source, "openconnect:%p", vpninfo);
1084                         p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
1085                 }
1086 #endif
1087         }
1088 }
1089
1090 void openconnect_init_ssl(void)
1091 {
1092         gnutls_global_init();
1093 }
1094
1095 int openconnect_sha1(unsigned char *result, void *data, int datalen)
1096 {
1097         gnutls_datum_t d;
1098         size_t shalen = SHA1_SIZE;
1099
1100         d.data = data;
1101         d.size = datalen;
1102         if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, result, &shalen))
1103                 return -1;
1104
1105         return 0;
1106 }
1107
1108 int openconnect_random(void *bytes, int len)
1109 {
1110         if (gnutls_rnd(GNUTLS_RND_RANDOM, bytes, len))
1111                 return -EIO;
1112         return 0;
1113 }
1114
1115 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1116                                char *buf)
1117 {
1118         const gnutls_datum_t *d;
1119         size_t md5len = 16;
1120
1121         buf[0] = 0;
1122
1123         d = gnutls_certificate_get_ours(vpninfo->https_sess);
1124         if (!d)
1125                 return -EIO;
1126
1127         if (gnutls_fingerprint(GNUTLS_DIG_MD5, d, buf, &md5len))
1128                 return -EIO;
1129
1130         return 0;
1131 }
1132
1133 #ifdef HAVE_P11KIT
1134 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
1135                         const char *pin_description,
1136                         P11KitPinFlags flags,
1137                         void *_vpninfo)
1138 {
1139         struct openconnect_info *vpninfo = _vpninfo;
1140         struct oc_auth_form f;
1141         struct oc_form_opt o;
1142         char message[1024];
1143         P11KitPin *pin;
1144         int ret;
1145
1146         if (!vpninfo || !vpninfo->process_auth_form)
1147                 return NULL;
1148
1149         memset(&f, 0, sizeof(f));
1150         f.auth_id = (char *)"pkcs11_pin";
1151         f.opts = &o;
1152
1153         message[sizeof(message)-1] = 0;
1154         snprintf(message, sizeof(message) - 1, _("PIN required for %s"), pin_description);
1155         f.message = message;
1156         
1157         /* 
1158          * p11-kit flags are *odd*.
1159          * RETRY is 0xa, FINAL_TRY is 0x14 and MANY_TRIES is 0x28.
1160          * So don't treat it like a sane bitmask.
1161          */
1162         if ((flags & P11_KIT_PIN_FLAGS_RETRY) == P11_KIT_PIN_FLAGS_RETRY)
1163                 f.error = _("Wrong PIN");
1164
1165         if ((flags & P11_KIT_PIN_FLAGS_FINAL_TRY) == P11_KIT_PIN_FLAGS_FINAL_TRY)
1166                 f.banner = _("This is the final try before locking!");
1167         else if ((flags & P11_KIT_PIN_FLAGS_MANY_TRIES) == P11_KIT_PIN_FLAGS_MANY_TRIES)
1168                 f.banner = _("Only a few tries left before locking!");
1169
1170         o.next = NULL;
1171         o.type = OC_FORM_OPT_PASSWORD;
1172         o.name = (char *)"pkcs11_pin";
1173         o.label = _("Enter PIN:");
1174         o.value = NULL;
1175
1176         ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
1177         if (ret || !o.value)
1178                 return NULL;
1179
1180         pin = p11_kit_pin_new_for_string(o.value);
1181         free(o.value);
1182
1183         return pin;
1184 }
1185 #endif