Move TPM code out into gnutls_tpm.c
[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 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
41 /* Shut up about gnutls_sign_callback_set() being deprecated. We only use it
42    in the GnuTLS 2.12 case, and there just isn't another way of doing it. */
43 #define GNUTLS_INTERNAL_BUILD 1
44 #endif
45
46 #include <gnutls/gnutls.h>
47 #include <gnutls/x509.h>
48 #include <gnutls/crypto.h>
49 #include <gnutls/pkcs12.h>
50 #include <gnutls/abstract.h>
51
52 #ifdef HAVE_TROUSERS
53 #include <trousers/tss.h>
54 #include <trousers/trousers.h>
55 #endif
56 #ifdef HAVE_P11KIT
57 #include <p11-kit/p11-kit.h>
58 #include <p11-kit/pkcs11.h>
59 #include <p11-kit/pin.h>
60
61 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
62                                const char *pin_description,
63                                P11KitPinFlags flags,
64                                void *_vpninfo);
65 #endif
66
67 #include "gnutls.h"
68 #include "openconnect-internal.h"
69
70 /* Helper functions for reading/writing lines over SSL.
71    We could use cURL for the HTTP stuff, but it's overkill */
72
73 int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t len)
74 {
75         size_t orig_len = len;
76
77         while (len) {
78                 int done = gnutls_record_send(vpninfo->https_sess, buf, len);
79                 if (done > 0)
80                         len -= done;
81                 else if (done != GNUTLS_E_AGAIN) {
82                         vpn_progress(vpninfo, PRG_ERR, _("Failed to write to SSL socket: %s"),
83                                      gnutls_strerror(done));
84                         return -EIO;
85                 } else {
86                         fd_set wr_set, rd_set;
87                         int maxfd = vpninfo->ssl_fd;
88
89                         FD_ZERO(&wr_set);
90                         FD_ZERO(&rd_set);
91                         
92                         if (gnutls_record_get_direction(vpninfo->https_sess))
93                                 FD_SET(vpninfo->ssl_fd, &wr_set);
94                         else
95                                 FD_SET(vpninfo->ssl_fd, &rd_set);
96
97                         if (vpninfo->cancel_fd != -1) {
98                                 FD_SET(vpninfo->cancel_fd, &rd_set);
99                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
100                                         maxfd = vpninfo->cancel_fd;
101                         }
102                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
103                         if (vpninfo->cancel_fd != -1 &&
104                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
105                                 vpn_progress(vpninfo, PRG_ERR, _("SSL write cancelled\n"));
106                                 return -EINTR;
107                         }
108                 }
109         }
110         return orig_len;
111 }
112
113 int openconnect_SSL_read(struct openconnect_info *vpninfo, char *buf, size_t len)
114 {
115         int done;
116
117         while ((done = gnutls_record_recv(vpninfo->https_sess, buf, len)) < 0) {
118                 fd_set wr_set, rd_set;
119                 int maxfd = vpninfo->ssl_fd;
120
121                 if (done != GNUTLS_E_AGAIN) {
122                         vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s"),
123                                      gnutls_strerror(done));
124                         return -EIO;
125                 } else {
126                         FD_ZERO(&wr_set);
127                         FD_ZERO(&rd_set);
128                         
129                         if (gnutls_record_get_direction(vpninfo->https_sess))
130                                 FD_SET(vpninfo->ssl_fd, &wr_set);
131                         else
132                                 FD_SET(vpninfo->ssl_fd, &rd_set);
133
134                         if (vpninfo->cancel_fd != -1) {
135                                 FD_SET(vpninfo->cancel_fd, &rd_set);
136                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
137                                         maxfd = vpninfo->cancel_fd;
138                         }
139                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
140                         if (vpninfo->cancel_fd != -1 &&
141                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
142                                 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
143                                 return -EINTR;
144                         }
145                 }
146         }
147         return done;
148 }
149
150 int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
151 {
152         int i = 0;
153         int ret;
154
155         if (len < 2)
156                 return -EINVAL;
157
158         while (1) {
159                 ret = gnutls_record_recv(vpninfo->https_sess, buf + i, 1);
160                 if (ret == 1) {
161                         if (buf[i] == '\n') {
162                                 buf[i] = 0;
163                                 if (i && buf[i-1] == '\r') {
164                                         buf[i-1] = 0;
165                                         i--;
166                                 }
167                                 return i;
168                         }
169                         i++;
170
171                         if (i >= len - 1) {
172                                 buf[i] = 0;
173                                 return i;
174                         }
175                 } else if (ret != GNUTLS_E_AGAIN) {
176                         vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s\n"),
177                                      gnutls_strerror(ret));
178                         ret = -EIO;
179                         break;
180                 } else {
181                         fd_set rd_set, wr_set;
182                         int maxfd = vpninfo->ssl_fd;
183                         
184                         FD_ZERO(&rd_set);
185                         FD_ZERO(&wr_set);
186                         
187                         if (gnutls_record_get_direction(vpninfo->https_sess))
188                                 FD_SET(vpninfo->ssl_fd, &wr_set);
189                         else
190                                 FD_SET(vpninfo->ssl_fd, &rd_set);
191
192                         if (vpninfo->cancel_fd != -1) {
193                                 FD_SET(vpninfo->cancel_fd, &rd_set);
194                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
195                                         maxfd = vpninfo->cancel_fd;
196                         }
197                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
198                         if (vpninfo->cancel_fd != -1 &&
199                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
200                                 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
201                                 ret = -EINTR;
202                                 break;
203                         }
204                 }
205         }
206         buf[i] = 0;
207         return i ?: ret;
208 }
209
210 static int check_certificate_expiry(struct openconnect_info *vpninfo, gnutls_x509_crt_t cert)
211 {
212         const char *reason = NULL;
213         time_t expires = gnutls_x509_crt_get_expiration_time(cert);
214         time_t now = time(NULL);
215
216         if (expires == -1) {
217                 vpn_progress(vpninfo, PRG_ERR,
218                              _("Could not extract expiration time of certificate\n"));
219                 return -EINVAL;
220         }
221
222         if (expires < now)
223                 reason = _("Client certificate has expired at");
224         else if (expires < now + vpninfo->cert_expire_warning)
225                 reason = _("Client certificate expires soon at");
226
227         if (reason) {
228                 struct tm tm;
229                 char buf[80];
230
231                 gmtime_r(&expires, &tm);
232                 strftime(buf, 80, "%a, %d %b %Y %T %Z", &tm);
233
234                 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, buf);
235         }
236         return 0;
237 }
238
239 /* For systems that don't support O_CLOEXEC, just don't bother.
240    It's not open for long anyway. */
241 #ifndef O_CLOEXEC
242 #define O_CLOEXEC
243 #endif
244
245 static int load_datum(struct openconnect_info *vpninfo,
246                       gnutls_datum_t *datum, const char *fname)
247 {
248         struct stat st;
249         int fd, err;
250
251         fd = open(fname, O_RDONLY|O_CLOEXEC);
252         if (fd == -1) {
253                 err = errno;
254                 vpn_progress(vpninfo, PRG_ERR,
255                              _("Failed to open key/certificate file %s: %s\n"),
256                              fname, strerror(err));
257                 return -ENOENT;
258         }
259         if (fstat(fd, &st)) {
260                 err = errno;
261                 vpn_progress(vpninfo, PRG_ERR,
262                              _("Failed to stat key/certificate file %s: %s\n"),
263                              fname, strerror(err));
264                 close(fd);
265                 return -EIO;
266         }
267         datum->size = st.st_size;
268         datum->data = gnutls_malloc(st.st_size + 1);
269         if (!datum->data) {
270                 vpn_progress(vpninfo, PRG_ERR,
271                              _("Failed to allocate certificate buffer\n"));
272                 close(fd);
273                 return -ENOMEM;
274         }
275         errno = EAGAIN;
276         if (read(fd, datum->data, datum->size) != datum->size) {
277                 err = errno;
278                 vpn_progress(vpninfo, PRG_ERR,
279                              _("Failed to read certificate into memory: %s\n"),
280                              strerror(err));
281                 close(fd);
282                 gnutls_free(datum->data);
283                 return -EIO;
284         }
285         datum->data[st.st_size] = 0;
286         close(fd);
287         return 0;
288 }
289
290 /* A non-zero, non-error return to make load_certificate() continue and
291    interpreting the file as other types */
292 #define NOT_PKCS12      1
293
294 static int load_pkcs12_certificate(struct openconnect_info *vpninfo,
295                                    gnutls_datum_t *datum,
296                                    gnutls_x509_privkey_t *key,
297                                    gnutls_x509_crt_t **chain,
298                                    unsigned int *chain_len,
299                                    gnutls_x509_crt_t **extra_certs,
300                                    unsigned int *extra_certs_len,
301                                    gnutls_x509_crl_t *crl)
302 {
303         gnutls_pkcs12_t p12;
304         char *pass;
305         int err;
306
307         err = gnutls_pkcs12_init(&p12);
308         if (err) {
309                 vpn_progress(vpninfo, PRG_ERR,
310                              _("Failed to setup PKCS#12 data structure: %s\n"),
311                              gnutls_strerror(err));
312                 return -EIO;
313         }
314
315         err = gnutls_pkcs12_import(p12, datum, GNUTLS_X509_FMT_DER, 0);
316         if (err) {
317                 gnutls_pkcs12_deinit(p12);
318                 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN)
319                         return NOT_PKCS12;
320                 vpn_progress(vpninfo, PRG_ERR,
321                              _("Failed to import PKCS#12 file: %s\n"),
322                              gnutls_strerror(err));
323                 return -EINVAL;
324         }
325
326         pass = vpninfo->cert_password;
327         while ((err = gnutls_pkcs12_verify_mac(p12, pass)) == GNUTLS_E_MAC_VERIFY_FAILED) {
328                 if (pass)
329                         vpn_progress(vpninfo, PRG_ERR,
330                                      _("Failed to decrypt PKCS#12 certificate file\n"));
331                 free(pass);
332                 vpninfo->cert_password = NULL;
333                 err = request_passphrase(vpninfo, "openconnect_pkcs12", &pass,
334                                          _("Enter PKCS#12 pass phrase:"));
335                 if (err) {
336                         gnutls_pkcs12_deinit(p12);
337                         return -EINVAL;
338                 }
339         }
340         /* If it wasn't GNUTLS_E_MAC_VERIFY_FAILED, then the problem wasn't just a
341            bad password. Give up. */
342         if (err) {
343                 int level = PRG_ERR;
344                 int ret = -EINVAL;
345
346                 gnutls_pkcs12_deinit(p12);
347
348                 /* If the first attempt, and we didn't know for sure it was PKCS#12
349                    anyway, bail out and try loading it as something different. */
350                 if (pass == vpninfo->cert_password &&
351                     vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
352                         /* Make it non-fatal... */
353                         level = PRG_TRACE;
354                         ret = NOT_PKCS12;
355                 }
356
357                 vpn_progress(vpninfo, level,
358                              _("Failed to process PKCS#12 file: %s\n"),
359                                gnutls_strerror(err));
360                 return ret;
361         }
362         err = gnutls_pkcs12_simple_parse(p12, pass, key, chain, chain_len,
363                                          extra_certs, extra_certs_len, crl, 0);
364         free(pass);
365         vpninfo->cert_password = NULL;
366
367         gnutls_pkcs12_deinit(p12);
368         if (err) {
369                 vpn_progress(vpninfo, PRG_ERR,
370                              _("Failed to load PKCS#12 certificate: %s\n"),
371                              gnutls_strerror(err));
372                 return -EINVAL;
373         }
374         return 0;
375 }
376
377 /* Older versions of GnuTLS didn't actually bother to check this, so we'll
378    do it for them. */
379 static int check_issuer_sanity(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer)
380 {
381 #if GNUTLS_VERSION_NUMBER > 0x300014
382         return 0;
383 #else
384         unsigned char id1[512], id2[512];
385         size_t id1_size = 512, id2_size = 512;
386         int err;
387
388         err = gnutls_x509_crt_get_authority_key_id(cert, id1, &id1_size, NULL);
389         if (err)
390                 return 0;
391
392         err = gnutls_x509_crt_get_subject_key_id(issuer, id2, &id2_size, NULL);
393         if (err)
394                 return 0;
395         if (id1_size == id2_size && !memcmp(id1, id2, id1_size))
396                 return 0;
397
398         /* EEP! */
399         return -EIO;
400 #endif
401 }
402
403 static int count_x509_certificates(gnutls_datum_t *datum)
404 {
405         int count = 0;
406         char *p = (char *)datum->data;
407
408         while (p) {
409                 p = strstr(p, "-----BEGIN ");
410                 if (!p)
411                         break;
412                 p += 11;
413                 if (!strncmp(p, "CERTIFICATE", 11) ||
414                     !strncmp(p, "X509 CERTIFICATE", 16))
415                     count++;
416         }
417         return count;
418 }
419
420 static int get_cert_name(gnutls_x509_crt_t cert, char *name, size_t namelen)
421 {
422         if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME,
423                                           0, 0, name, &namelen) &&
424             gnutls_x509_crt_get_dn(cert, name, &namelen)) {
425                 name[namelen-1] = 0;
426                 snprintf(name, namelen-1, "<unknown>");
427                 return -EINVAL;
428         }
429         return 0;
430 }
431
432 #if !defined (HAVE_GNUTLS_CERTIFICATE_SET_KEY) && \
433         (defined (HAVE_P11KIT) || defined (HAVE_TROUSERS))
434 /* For GnuTLS 2.12 even if we *have* a privkey (as we do for PKCS#11), we
435    can't register it. So we have to use the cert_callback function. This
436    just hands out the certificate chain we prepared in load_certificate().
437    If we have a pkey then return that too; otherwise leave the key NULL —
438    we'll also have registered a sign_callback for the session, which will
439    handle that. */
440 static int gtls_cert_cb(gnutls_session_t sess, const gnutls_datum_t *req_ca_dn,
441                         int nreqs, const gnutls_pk_algorithm_t *pk_algos,
442                         int pk_algos_length, gnutls_retr2_st *st) {
443
444         struct openconnect_info *vpninfo = gnutls_session_get_ptr(sess);
445         int algo = GNUTLS_PK_RSA; /* TPM */
446         int i;
447
448 #ifdef HAVE_P11KIT
449         if (vpninfo->my_p11key) {
450                 st->key_type = GNUTLS_PRIVKEY_PKCS11;
451                 st->key.pkcs11 = vpninfo->my_p11key;
452                 algo = gnutls_pkcs11_privkey_get_pk_algorithm(vpninfo->my_p11key, NULL);
453         };
454 #endif
455         for (i = 0; i < pk_algos_length; i++) {
456                 if (algo == pk_algos[i])
457                         break;
458         }
459         if (i == pk_algos_length)
460                 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
461
462         st->cert_type = GNUTLS_CRT_X509;
463         st->cert.x509 = vpninfo->my_certs;
464         st->ncerts = vpninfo->nr_my_certs;
465         st->deinit_all = 0;
466
467         return 0;
468 }
469 #endif /* !SET_KEY && (P11KIT || TROUSERS) */
470
471 static int load_certificate(struct openconnect_info *vpninfo)
472 {
473         gnutls_datum_t fdata;
474         gnutls_x509_privkey_t key = NULL;
475 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
476         gnutls_privkey_t pkey = NULL;
477         gnutls_datum_t pkey_sig = {NULL, 0};
478         void *dummy_hash_data = &load_certificate;
479 #endif
480 #ifdef HAVE_P11KIT
481         char *cert_url = (char *)vpninfo->cert;
482         char *key_url = (char *)vpninfo->sslkey;
483         gnutls_pkcs11_privkey_t p11key = NULL;
484 #endif
485         gnutls_x509_crl_t crl = NULL;
486         gnutls_x509_crt_t last_cert, cert = NULL;
487         gnutls_x509_crt_t *extra_certs = NULL, *supporting_certs = NULL;
488         unsigned int nr_supporting_certs = 0, nr_extra_certs = 0;
489         unsigned int certs_to_free = 0; /* How many of supporting_certs */
490         int err; /* GnuTLS error */
491         int ret;
492         int i;
493         int cert_is_p11 = 0, key_is_p11 = 0;
494         unsigned char key_id[20];
495         size_t key_id_size = sizeof(key_id);
496         char name[80];
497
498         fdata.data = NULL;
499
500         key_is_p11 = !strncmp(vpninfo->sslkey, "pkcs11:", 7);
501         cert_is_p11 = !strncmp(vpninfo->cert, "pkcs11:", 7);
502
503         /* Install PIN handler if either certificate or key are coming from PKCS#11 */
504         if (key_is_p11 || cert_is_p11) {
505 #ifdef HAVE_P11KIT
506                 CK_OBJECT_CLASS class;
507                 CK_ATTRIBUTE attr;
508                 char pin_source[40];
509                 P11KitUri *uri;
510
511                 sprintf(pin_source, "openconnect:%p", vpninfo);
512                 p11_kit_pin_register_callback(pin_source, pin_callback, vpninfo, NULL);
513
514                 uri = p11_kit_uri_new();
515
516                 attr.type = CKA_CLASS;
517                 attr.pValue = &class;
518                 attr.ulValueLen = sizeof(class);
519
520                 /* Add appropriate pin-source and object-type attributes to
521                    both certificate and key URLs, unless they already exist. */
522                 if (cert_is_p11 &&
523                     !p11_kit_uri_parse(cert_url, P11_KIT_URI_FOR_OBJECT, uri)) {
524                         if (!p11_kit_uri_get_pin_source(uri))
525                                 p11_kit_uri_set_pin_source(uri, pin_source);
526                         if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
527                                 class = CKO_CERTIFICATE;
528                                 p11_kit_uri_set_attribute(uri, &attr);
529                         }
530                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &cert_url);
531                 }
532
533                 if (key_is_p11 &&
534                     !p11_kit_uri_parse(key_url, P11_KIT_URI_FOR_OBJECT, uri)) {
535                         if (!p11_kit_uri_get_pin_source(uri))
536                                 p11_kit_uri_set_pin_source(uri, pin_source);
537                         if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
538                                 class = CKO_PRIVATE_KEY;
539                                 p11_kit_uri_set_attribute(uri, &attr);
540                         }
541                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &key_url);
542                 }
543
544                 p11_kit_uri_free(uri);
545 #else
546                 vpn_progress(vpninfo, PRG_ERR,
547                              _("This binary built without PKCS#11 support\n"));
548                 return -EINVAL;
549 #endif
550         }
551
552         /* Load certificate(s) first... */
553 #ifdef HAVE_P11KIT
554         if (cert_is_p11) {
555                 vpn_progress(vpninfo, PRG_TRACE,
556                              _("Using PKCS#11 certificate %s\n"), cert_url);
557
558                 err = gnutls_x509_crt_init(&cert);
559                 if (err) {
560                         ret = -ENOMEM;
561                         goto out;
562                 }
563                 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url, 0);
564                 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
565                         err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url,
566                                                                 GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
567                 if (err) {
568                         vpn_progress(vpninfo, PRG_ERR,
569                                      _("Error loading certificate from PKCS#11: %s\n"),
570                                      gnutls_strerror(err));
571                         ret = -EIO;
572                         goto out;
573                 }
574                 goto got_certs;
575         }
576 #endif /* HAVE_P11KIT */
577
578         vpn_progress(vpninfo, PRG_TRACE,
579                      _("Using certificate file %s\n"), vpninfo->cert);
580
581         ret = load_datum(vpninfo, &fdata, vpninfo->cert);
582         if (ret)
583                 return ret;
584
585         if (!key_is_p11 && (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
586                             vpninfo->cert_type == CERT_TYPE_UNKNOWN)) {
587                 /* PKCS#12 should actually contain certificates *and* private key */
588                 ret = load_pkcs12_certificate(vpninfo, &fdata, &key,
589                                               &supporting_certs, &nr_supporting_certs,
590                                               &extra_certs, &nr_extra_certs,
591                                               &crl);
592                 if (ret < 0)
593                         goto out;
594                 else if (!ret) {
595                         if (nr_supporting_certs) {
596                                 cert = supporting_certs[0];
597                                 goto got_key;
598                         }
599                         vpn_progress(vpninfo, PRG_ERR,
600                                      _("PKCS#11 file contained no certificate\n"));
601                         ret = -EINVAL;
602                         goto out;
603                 }
604
605                 /* It returned NOT_PKCS12.
606                    Fall through to try PEM formats. */
607         }
608
609         /* We need to know how many there are in *advance*; it won't just allocate
610            the array for us :( */
611         nr_extra_certs = count_x509_certificates(&fdata);
612         if (!nr_extra_certs)
613                 nr_extra_certs = 1; /* wtf? Oh well, we'll fail later... */
614
615         extra_certs = calloc(nr_extra_certs, sizeof(cert));
616         if (!extra_certs) {
617                 nr_extra_certs = 0;
618                 ret = -ENOMEM;
619                 goto out;
620         }
621         err = gnutls_x509_crt_list_import(extra_certs, &nr_extra_certs, &fdata,
622                                           GNUTLS_X509_FMT_PEM, 0);
623         if (err <= 0) {
624                 const char *reason;
625                 if (!err || err == GNUTLS_E_NO_CERTIFICATE_FOUND)
626                         reason = _("No certificate found in file");
627                 else
628                         reason = gnutls_strerror(err);
629
630                 vpn_progress(vpninfo, PRG_ERR,
631                              _("Loading certificate failed: %s\n"),
632                              reason);
633                 ret = -EINVAL;
634                 goto out;
635         }
636         nr_extra_certs = err;
637         err = 0;
638
639         goto got_certs;
640  got_certs:
641         /* Now we have the certificate(s) and we're looking for the private key... */
642 #if defined (HAVE_P11KIT)
643         if (key_is_p11) {
644                 vpn_progress(vpninfo, PRG_TRACE,
645                              _("Using PKCS#11 key %s\n"), key_url);
646
647                 err = gnutls_pkcs11_privkey_init(&p11key);
648                 if (err) {
649                         vpn_progress(vpninfo, PRG_ERR,
650                                      _("Error initialising PKCS#11 key structure: %s\n"),
651                                      gnutls_strerror(err));
652                         ret = -EIO;
653                         goto out;
654                 }
655
656                 err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0);
657                 if (err) {
658                         vpn_progress(vpninfo, PRG_ERR,
659                                      _("Error importing PKCS#11 URL %s: %s\n"),
660                                      key_url, gnutls_strerror(err));
661                         gnutls_pkcs11_privkey_deinit(p11key);
662                         ret = -EIO;
663                         goto out;
664                 }
665
666                 err = gnutls_privkey_init(&pkey);
667                 if (err) {
668                         vpn_progress(vpninfo, PRG_ERR,
669                                      _("Error initialising private key structure: %s\n"),
670                                      gnutls_strerror(err));
671                         gnutls_pkcs11_privkey_deinit(p11key);
672                         ret = -EIO;
673                         goto out;
674                 }
675
676                 err = gnutls_privkey_import_pkcs11(pkey, p11key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
677                 if (err) {
678                         vpn_progress(vpninfo, PRG_ERR,
679                                      _("Error importing PKCS#11 key into private key structure: %s\n"),
680                                      gnutls_strerror(err));
681                         gnutls_pkcs11_privkey_deinit(p11key);
682                         ret = -EIO;
683                         goto out;
684                 }
685
686                 goto match_cert;
687         }
688 #endif
689
690         /* We're loading the private key from a file. Load the file into memory
691            unless it's the same as the certificate and we already loaded that. */
692         if (!fdata.data || vpninfo->sslkey != vpninfo->cert) {
693                 gnutls_free(fdata.data);
694                 fdata.data = NULL;
695
696                 vpn_progress(vpninfo, PRG_TRACE,
697                              _("Using private key file %s\n"), vpninfo->sslkey);
698
699                 ret = load_datum(vpninfo, &fdata, vpninfo->sslkey);
700                 if (ret)
701                         goto out;
702         }
703
704         if (vpninfo->cert_type == CERT_TYPE_TPM ||
705             (vpninfo->cert_type == CERT_TYPE_UNKNOWN &&
706              strstr((char *)fdata.data, "-----BEGIN TSS KEY BLOB-----"))) {
707 #ifndef HAVE_TROUSERS
708                 vpn_progress(vpninfo, PRG_ERR,
709                              _("This version of OpenConnect was built without TPM support\n"));
710                 return -EINVAL;
711 #else
712                 ret = load_tpm_key(vpninfo, &fdata, &pkey, &pkey_sig);
713                 if (ret)
714                         goto out;
715
716                 goto match_cert;
717 #endif
718         }
719
720         gnutls_x509_privkey_init(&key);
721         /* Try PKCS#1 (and PKCS#8 without password) first. GnuTLS doesn't
722            support OpenSSL's old PKCS#1-based encrypted format. We should
723            probably check for it and give a more coherent failure mode. */
724         err = gnutls_x509_privkey_import(key, &fdata, GNUTLS_X509_FMT_PEM);
725         if (err) {
726                 /* If that fails, try PKCS#8 */
727                 char *pass = vpninfo->cert_password;
728
729                 /* Yay, just for fun this is *different* to PKCS#12. Where we could
730                    try an empty password there, in this case the empty-password case
731                    has already been *tried* by gnutls_x509_privkey_import(). If we
732                    just call gnutls_x509_privkey_import_pkcs8() with a NULL password,
733                    it'll SEGV. You have to set the GNUTLS_PKCS_PLAIN flag if you want
734                    to try without a password. Passing NULL evidently isn't enough of
735                    a hint. And in GnuTLS 3.1 where that crash has been fixed, passing
736                    NULL will cause it to return GNUTLS_E_ENCRYPTED_STRUCTURE (a new
737                    error code) rather than GNUTLS_E_DECRYPTION_FAILED. So just pass ""
738                    instead of NULL, and don't worry about either case. */
739                 while ((err = gnutls_x509_privkey_import_pkcs8(key, &fdata,
740                                                                GNUTLS_X509_FMT_PEM,
741                                                                pass?pass:"", 0))) {
742                         if (err != GNUTLS_E_DECRYPTION_FAILED) {
743                                 vpn_progress(vpninfo, PRG_ERR,
744                                              _("Failed to load private key as PKCS#8: %s\n"),
745                                              gnutls_strerror(err));
746                                 ret = -EINVAL;
747                                 goto out;
748                         }
749                         vpninfo->cert_password = NULL;
750                         if (pass) {
751                                 vpn_progress(vpninfo, PRG_ERR,
752                                              _("Failed to decrypt PKCS#8 certificate file\n"));
753                                 free(pass);
754                         }
755                         err = request_passphrase(vpninfo, "openconnect_pem",
756                                                  &pass, _("Enter PEM pass phrase:"));
757                         if (err) {
758                                 ret = -EINVAL;
759                                 goto out;
760                         }
761                 }
762                 free(pass);
763                 vpninfo->cert_password = NULL;
764         }
765
766         /* Now attempt to make sure we use the *correct* certificate, to match the key */
767         err = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size);
768         if (err) {
769                 vpn_progress(vpninfo, PRG_ERR,
770                              _("Failed to get key ID: %s\n"),
771                              gnutls_strerror(err));
772                 ret = -EINVAL;
773                 goto out;
774         }
775         for (i = 0; i < (extra_certs?nr_extra_certs:1); i++) {
776                 unsigned char cert_id[20];
777                 size_t cert_id_size = sizeof(cert_id);
778
779                 err = gnutls_x509_crt_get_key_id(extra_certs?extra_certs[i]:cert, 0, cert_id, &cert_id_size);
780                 if (err)
781                         continue;
782
783                 if (cert_id_size == key_id_size && !memcmp(cert_id, key_id, key_id_size)) {
784                         if (extra_certs) {
785                                 cert = extra_certs[i];
786
787                                 /* Move the rest of the array down */
788                                 for (; i < nr_extra_certs - 1; i++)
789                                         extra_certs[i] = extra_certs[i+1];
790
791                                 nr_extra_certs--;
792                         }
793                         goto got_key;
794                 }
795         }
796         /* There's no pkey (there's an x509 key), so we'll fall straight through the
797          * bit at match_cert: below, and go directly to the bit where it prints the
798          * 'no match found' error and exits. */
799
800 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
801  match_cert:
802         /* If we have a privkey from PKCS#11 or TPM, we can't do the simple comparison
803            of key ID that we do for software keys to find which certificate is a
804            match. So sign some dummy data and then check the signature against each
805            of the available certificates until we find the right one. */
806         if (pkey) {
807                 /* The TPM code may have already signed it, to test authorisation. We
808                    only sign here for PKCS#11 keys, in which case fdata might be
809                    empty too so point it at dummy data. */
810                 if (!pkey_sig.data) {
811                         if (!fdata.data) {
812                                 fdata.data = dummy_hash_data;
813                                 fdata.size = 20;
814                         }
815
816                         err = sign_dummy_data(vpninfo, pkey, &fdata, &pkey_sig);
817                         if (err) {
818                                 vpn_progress(vpninfo, PRG_ERR,
819                                              _("Error signing test data with private key: %s\n"),
820                                              gnutls_strerror(err));
821                                 ret = -EINVAL;
822                                 goto out;
823                         }
824                 }
825
826                 for (i=0; i < (extra_certs?nr_extra_certs:1); i++) {
827                         gnutls_pubkey_t pubkey;
828
829                         gnutls_pubkey_init(&pubkey);
830                         err = gnutls_pubkey_import_x509(pubkey, extra_certs?extra_certs[i]:cert, 0);
831                         if (err) {
832                                 vpn_progress(vpninfo, PRG_ERR,
833                                              _("Error validating signature against certificate: %s\n"),
834                                              gnutls_strerror(err));
835                                 /* We'll probably fail shortly if we don't find it. */
836                                 gnutls_pubkey_deinit(pubkey);
837                                 continue;
838                         }
839                         err = gnutls_pubkey_verify_data(pubkey, 0, &fdata, &pkey_sig);
840                         gnutls_pubkey_deinit(pubkey);
841
842                         if (err >= 0) {
843                                 if (extra_certs) {
844                                         cert = extra_certs[i];
845
846                                         /* Move the rest of the array down */
847                                         for (; i < nr_extra_certs - 1; i++)
848                                                 extra_certs[i] = extra_certs[i+1];
849
850                                         nr_extra_certs--;
851                                 }
852                                 gnutls_free(pkey_sig.data);
853                                 goto got_key;
854                         }
855                 }
856                 gnutls_free(pkey_sig.data);
857         }
858 #endif /* P11KIT || TROUSERS */
859
860         /* We shouldn't reach this. It means that we didn't find *any* matching cert */
861         vpn_progress(vpninfo, PRG_ERR,
862                      _("No SSL certificate found to match private key\n"));
863         ret = -EINVAL;
864         goto out;
865
866         /********************************************************************/
867  got_key:
868         /* Now we have both cert(s) and key, and we should be ready to go. */
869         check_certificate_expiry(vpninfo, cert);
870         get_cert_name(cert, name, sizeof(name));
871         vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"),
872                      name);
873
874         if (crl) {
875                 err = gnutls_certificate_set_x509_crl(vpninfo->https_cred, &crl, 1);
876                 if (err) {
877                         vpn_progress(vpninfo, PRG_ERR,
878                                      _("Setting certificate recovation list failed: %s\n"),
879                                      gnutls_strerror(err));
880                         ret = -EINVAL;
881                         goto out;
882                 }
883         }
884
885         /* OpenSSL has problems with certificate chains — if there are
886            multiple certs with the same name, it doesn't necessarily
887            choose the _right_ one. (RT#1942)
888            Pick the right ones for ourselves and add them manually. */
889
890         if (nr_supporting_certs) {
891                 /* We already got a bunch of certs from PKCS#12 file. 
892                    Remember how many need to be freed when we're done,
893                    since we'll expand the supporting_certs array with
894                    more from the cafile if we can. */
895                 last_cert = supporting_certs[nr_supporting_certs-1];
896                 certs_to_free = nr_supporting_certs;
897         } else {
898                 last_cert = cert;
899                 certs_to_free = nr_supporting_certs = 1;
900         }
901         while (1) {
902                 gnutls_x509_crt_t issuer;
903
904                 for (i = 0; i < nr_extra_certs; i++) {
905                         if (gnutls_x509_crt_check_issuer(last_cert, extra_certs[i]) &&
906                             !check_issuer_sanity(last_cert, extra_certs[i]))
907                                 break;
908                 }
909
910                 if (i < nr_extra_certs) {
911                         issuer = extra_certs[i];
912                 } else {
913                         err = gnutls_certificate_get_issuer(vpninfo->https_cred,
914                                                             last_cert, &issuer, 0);
915                         if (err)
916                                 break;
917                 }
918
919                 /* The check_issuer_sanity() function works fine as a workaround where
920                    it was used above, but when gnutls_certificate_get_issuer() returns
921                    a bogus cert, there's nothing we can do to fix it up. We don't get
922                    to iterate over all the available certs like we can over our own
923                    list. */
924                 if (check_issuer_sanity(last_cert, issuer)) {
925                         /* Hm, is there a bug reference for this? Or just the git commit
926                            reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
927                         vpn_progress(vpninfo, PRG_ERR,
928                                      _("WARNING: GnuTLS returned incorrect issuer certs; authentication may fail!\n"));
929                         break;
930                 }
931
932                 if (issuer == last_cert) {
933                         /* Don't actually include the root CA. If they don't already trust it,
934                            then handing it to them isn't going to help. But don't omit the
935                            original certificate if it's self-signed. */
936                         if (nr_supporting_certs > 1)
937                                 nr_supporting_certs--;
938                         break;
939                 }
940
941                 /* OK, we found a new cert to add to our chain. */
942                 supporting_certs = gnutls_realloc(supporting_certs,
943                                                   sizeof(cert) * ++nr_supporting_certs);
944                 if (!supporting_certs) {
945                         vpn_progress(vpninfo, PRG_ERR,
946                                      _("Failed to allocate memory for supporting certificates\n"));
947                         /* The world is probably about to end, but try without them anyway */
948                         certs_to_free = 0;
949                         ret = -ENOMEM;
950                         goto out;
951                 }
952
953                 /* First time we actually allocated an array? Copy the first cert into it */
954                 if (nr_supporting_certs == 2)
955                         supporting_certs[0] = cert;
956
957                 /* Append the new one */
958                 supporting_certs[nr_supporting_certs-1] = issuer;
959                 last_cert = issuer;
960
961         }
962         for (i = 1; i < nr_supporting_certs; i++) {
963                 get_cert_name(supporting_certs[i], name, sizeof(name));
964
965                 vpn_progress(vpninfo, PRG_DEBUG,
966                              _("Adding supporting CA '%s'\n"), name);
967         }
968
969 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
970         if (pkey) {
971 #if defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY)
972                 /* Ug. If we got a gnutls_privkey_t from PKCS#11 rather than the
973                    gnutls_x509_privkey_t that we get from PEM or PKCS#12 files, then
974                    we can't use gnutls_certificate_set_x509_key(). Instead we have
975                    to convert our chain of X509 certificates to gnutls_pcert_st and
976                    then use gnutls_certificate_set_key() with that instead. */
977                 gnutls_pcert_st *pcerts = calloc(nr_supporting_certs, sizeof(*pcerts));
978
979                 if (!pcerts) {
980                         ret = -ENOMEM;
981                         goto out;
982                 }
983
984                 for (i=0 ; i < nr_supporting_certs; i++) {
985                         err = gnutls_pcert_import_x509(pcerts + i, supporting_certs?supporting_certs[i]:cert, 0);
986                         if (err) {
987                                 vpn_progress(vpninfo, PRG_ERR,
988                                              _("Importing X509 certificate failed: %s\n"),
989                                              gnutls_strerror(err));
990                                 goto free_pcerts;
991                         }
992                 }
993
994                 err = gnutls_certificate_set_key(vpninfo->https_cred, NULL, 0, pcerts, nr_supporting_certs, pkey);
995                 if (err) {
996                         vpn_progress(vpninfo, PRG_ERR,
997                                      _("Setting PKCS#11 certificate failed: %s\n"),
998                                      gnutls_strerror(err));
999                 free_pcerts:
1000                         for (i=0 ; i < nr_supporting_certs; i++)
1001                                 gnutls_pcert_deinit(pcerts + i);
1002                         free (pcerts);
1003                         ret = -EIO;
1004                         goto out;
1005                 }
1006 #else /* !HAVE_GNUTLS_CERTIFICATE_SET_KEY so fake it using sign_callback */
1007                 vpninfo->my_pkey = pkey;
1008 #ifdef HAVE_P11KIT
1009                 vpninfo->my_p11key = p11key;
1010 #endif
1011
1012                 if (supporting_certs) {
1013                         vpninfo->my_certs = supporting_certs;
1014                         vpninfo->nr_my_certs = nr_supporting_certs;
1015                         /* We are *keeping* the certs in supporting_certs, unlike in
1016                            GnuTLS 3 where we can free them after calling g_c_set_key().
1017                            So steal the ones we need out of the extra_certs array.
1018                            The first one is 'cert', which was already stolen. So
1019                            start at 1. */
1020                         for (i = 1; i < nr_supporting_certs; i++) {
1021                                 int j;
1022                                 for (j = 0; j < nr_extra_certs; j++) {
1023                                         if (supporting_certs[i] == extra_certs[j]) {
1024                                                 extra_certs[j] = NULL;
1025                                                 break;
1026                                         }
1027                                 }
1028                         }
1029                         supporting_certs = NULL;
1030                 } else {
1031                         vpninfo->my_certs = gnutls_calloc(1, sizeof(cert));
1032                         if (!vpninfo->my_certs) {
1033                                 ret = -ENOMEM;
1034                                 goto out;
1035                         }
1036                         vpninfo->my_certs[0] = cert;
1037                         vpninfo->nr_my_certs = 1;
1038                 }
1039                 cert = NULL;
1040                 gnutls_certificate_set_retrieve_function(vpninfo->https_cred,
1041                                                          gtls_cert_cb);
1042                 err = 0;
1043                 vpninfo->my_pkey = pkey;
1044 #endif
1045                 pkey = NULL; /* we gave it away, along with pcerts */
1046         } else
1047 #endif /* P11KIT || TROUSERS */
1048                 err = gnutls_certificate_set_x509_key(vpninfo->https_cred,
1049                                                       supporting_certs ? supporting_certs : &cert,
1050                                                       supporting_certs ? nr_supporting_certs : 1,
1051                                                       key);
1052
1053         if (err) {
1054                 vpn_progress(vpninfo, PRG_ERR,
1055                              _("Setting certificate failed: %s\n"),
1056                              gnutls_strerror(err));
1057                 ret = -EIO;
1058         } else
1059                 ret = 0;
1060  out:
1061         if (crl)
1062                 gnutls_x509_crl_deinit(crl);
1063         if (key)
1064                 gnutls_x509_privkey_deinit(key);
1065         if (cert)
1066                 gnutls_x509_crt_deinit(cert);
1067         /* From 1 because cert is the first one (and might exist
1068            even if supporting_certs is NULL) */
1069         for (i = 1; i < certs_to_free; i++) {
1070                 if (supporting_certs[i])
1071                         gnutls_x509_crt_deinit(supporting_certs[i]);
1072         }
1073         for (i = 0; i < nr_extra_certs; i++) {
1074                 if (extra_certs[i])
1075                         gnutls_x509_crt_deinit(extra_certs[i]);
1076         }
1077         gnutls_free(extra_certs);
1078         gnutls_free(supporting_certs);
1079 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1080         if (pkey && pkey != OPENCONNECT_TPM_PKEY)
1081                 gnutls_privkey_deinit(pkey);
1082         if (fdata.data != dummy_hash_data)
1083 #endif /* It's conditional if we support arbitrary privkeys: */
1084                 gnutls_free(fdata.data);
1085 #ifdef HAVE_P11KIT
1086         if (cert_url != vpninfo->cert)
1087                 free(cert_url);
1088         if (key_url != vpninfo->sslkey)
1089                 free(key_url);
1090 #endif
1091         return ret;
1092 }
1093
1094 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
1095                                 gnutls_x509_crt_t cert,
1096                                 gnutls_digest_algorithm_t algo,
1097                                 char *buf)
1098 {
1099         unsigned char md[256];
1100         size_t md_size = sizeof(md);
1101         unsigned int i;
1102
1103         if (gnutls_x509_crt_get_fingerprint(cert, algo, md, &md_size))
1104                 return -EIO;
1105
1106         for (i=0; i < md_size; i++)
1107                 sprintf(&buf[i*2], "%02X", md[i]);
1108
1109         return 0;
1110 }
1111
1112 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
1113                              OPENCONNECT_X509 *cert, char *buf)
1114 {
1115         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_MD5, buf);
1116 }
1117
1118 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
1119                               OPENCONNECT_X509 *cert, char *buf)
1120 {
1121         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_SHA1, buf);
1122 }
1123
1124 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1125                                    OPENCONNECT_X509 *cert)
1126 {
1127         gnutls_datum_t buf;
1128         char *ret;
1129
1130         if (gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &buf))
1131                 return NULL;
1132         
1133         /* Just in case gnutls_free() isn't free(), we can't steal it. */
1134         ret = strdup((char *)buf.data);
1135         gnutls_free(buf.data);
1136         
1137         return ret;
1138 }
1139
1140 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
1141                              OPENCONNECT_X509 *cert, unsigned char **buf)
1142 {
1143         size_t l = 0;
1144         unsigned char *ret = NULL;
1145
1146         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l) != 
1147             GNUTLS_E_SHORT_MEMORY_BUFFER)
1148                 return -EIO;
1149
1150         ret = malloc(l);
1151         if (!ret)
1152                 return -ENOMEM;
1153
1154         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l)) {
1155                 free(ret);
1156                 return -EIO;
1157         }
1158         *buf = ret;
1159         return l;
1160 }
1161
1162 static int verify_peer(gnutls_session_t session)
1163 {
1164         struct openconnect_info *vpninfo = gnutls_session_get_ptr(session);
1165         const gnutls_datum_t *cert_list;
1166         gnutls_x509_crt_t cert;
1167         unsigned int status, cert_list_size;
1168         const char *reason = NULL;
1169         int err;
1170
1171         if (vpninfo->peer_cert) {
1172                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1173                 vpninfo->peer_cert = NULL;
1174         }
1175
1176         cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
1177         if (!cert_list) {
1178                 vpn_progress(vpninfo, PRG_ERR, _("Server presented no certificate\n"));
1179                 return GNUTLS_E_CERTIFICATE_ERROR;
1180         }
1181
1182         if (vpninfo->servercert) {
1183                 unsigned char sha1bin[SHA1_SIZE];
1184                 char fingerprint[(SHA1_SIZE * 2) + 1];
1185                 int i;
1186                 
1187                 err = openconnect_sha1(sha1bin, cert_list[0].data, cert_list[0].size);
1188                 if (err) {
1189                         vpn_progress(vpninfo, PRG_ERR,
1190                                      _("Could not calculate SHA1 of server's certificate\n"));
1191                         return GNUTLS_E_CERTIFICATE_ERROR;
1192                 }
1193                 for (i=0; i < SHA1_SIZE; i++)
1194                         sprintf(&fingerprint[i*2], "%02X", sha1bin[i]);
1195
1196                 if (strcasecmp(vpninfo->servercert, fingerprint)) {
1197                         vpn_progress(vpninfo, PRG_ERR,
1198                                      _("Server SSL certificate didn't match: %s\n"), fingerprint);
1199                         return GNUTLS_E_CERTIFICATE_ERROR;
1200                 }
1201                 return 0;
1202         }
1203
1204         err = gnutls_certificate_verify_peers2 (session, &status);
1205         if (err) {
1206                 vpn_progress(vpninfo, PRG_ERR, _("Error checking server cert status\n"));
1207                 return GNUTLS_E_CERTIFICATE_ERROR;
1208         }
1209
1210         if (status & GNUTLS_CERT_REVOKED)
1211                 reason = _("certificate revoked");
1212         else if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1213                 reason = _("signer not found");
1214         else if (status & GNUTLS_CERT_SIGNER_NOT_CA)
1215                 reason = _("signer not a CA certificate");
1216         else if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1217                 reason = _("insecure algorithm");
1218         else if (status & GNUTLS_CERT_NOT_ACTIVATED)
1219                 reason = _("certificate not yet activated");
1220         else if (status & GNUTLS_CERT_EXPIRED)
1221                 reason = _("certificate expired");
1222         else if (status & GNUTLS_CERT_INVALID)
1223                 /* If this is set and no other reason, it apparently means
1224                    that signature verification failed. Not entirely sure
1225                    why we don't just set a bit for that too. */
1226                 reason = _("signature verification failed");
1227
1228         err = gnutls_x509_crt_init(&cert);
1229         if (err) {
1230                 vpn_progress(vpninfo, PRG_ERR, _("Error initialising X509 cert structure\n"));
1231                 return GNUTLS_E_CERTIFICATE_ERROR;
1232         }
1233
1234         err = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
1235         if (err) {
1236                 vpn_progress(vpninfo, PRG_ERR, _("Error importing server's cert\n"));
1237                 gnutls_x509_crt_deinit(cert);
1238                 return GNUTLS_E_CERTIFICATE_ERROR;
1239         }
1240
1241         if (!reason && !gnutls_x509_crt_check_hostname(cert, vpninfo->hostname))
1242                 reason = _("certificate does not match hostname");
1243
1244         if (reason) {
1245                 vpn_progress(vpninfo, PRG_INFO, "Server certificate verify failed: %s\n",
1246                              reason);
1247                 if (vpninfo->validate_peer_cert)
1248                         err = vpninfo->validate_peer_cert(vpninfo->cbdata,
1249                                                           cert,
1250                                                           reason) ? GNUTLS_E_CERTIFICATE_ERROR : 0;
1251                 else
1252                         err = GNUTLS_E_CERTIFICATE_ERROR;
1253         }
1254
1255         vpninfo->peer_cert = cert;
1256
1257         return err;
1258 }
1259
1260
1261 int openconnect_open_https(struct openconnect_info *vpninfo)
1262 {
1263         int ssl_sock = -1;
1264         int err;
1265
1266         if (vpninfo->https_sess)
1267                 return 0;
1268
1269         ssl_sock = connect_https_socket(vpninfo);
1270         if (ssl_sock < 0)
1271                 return ssl_sock;
1272
1273         if (!vpninfo->https_cred) {
1274                 gnutls_certificate_allocate_credentials(&vpninfo->https_cred);
1275 #ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST
1276                 gnutls_certificate_set_x509_system_trust(vpninfo->https_cred);
1277 #else
1278                 gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1279                                                        "/etc/pki/tls/certs/ca-bundle.crt",
1280                                                        GNUTLS_X509_FMT_PEM);
1281 #endif
1282                 gnutls_certificate_set_verify_function (vpninfo->https_cred,
1283                                                         verify_peer);
1284
1285                 if (vpninfo->cafile) {
1286                         err = gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1287                                                                      vpninfo->cafile,
1288                                                                      GNUTLS_X509_FMT_PEM);
1289                         if (err < 0) {
1290                                 vpn_progress(vpninfo, PRG_ERR,
1291                                              _("Failed to open CA file '%s': %s\n"),
1292                                              vpninfo->cafile, gnutls_strerror(err));
1293                                 close(ssl_sock);
1294                                 return -EINVAL;
1295                         }
1296                 }
1297
1298                 if (vpninfo->cert) {
1299                         err = load_certificate(vpninfo);
1300                         if (err) {
1301                                 vpn_progress(vpninfo, PRG_ERR,
1302                                              _("Loading certificate failed. Aborting.\n"));
1303                                 return err;
1304                         }
1305                 }
1306         }
1307         gnutls_init (&vpninfo->https_sess, GNUTLS_CLIENT);
1308         gnutls_session_set_ptr (vpninfo->https_sess, (void *) vpninfo);
1309 #if defined(HAVE_TROUSERS) && !defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY)
1310         if (vpninfo->my_pkey == OPENCONNECT_TPM_PKEY)
1311                 gnutls_sign_callback_set(vpninfo->https_sess, gtls2_tpm_sign_cb, vpninfo);
1312 #endif
1313         err = gnutls_priority_set_direct (vpninfo->https_sess, "NONE:+VERS-TLS1.0:+SHA1:+AES-128-CBC:+RSA:+COMP-NULL:%COMPAT:%DISABLE_SAFE_RENEGOTIATION", NULL);
1314         if (err) {
1315                 vpn_progress(vpninfo, PRG_ERR,
1316                              _("Failed to set TLS priority string: %s\n"),
1317                              gnutls_strerror(err));
1318                 return -EIO;
1319         }
1320
1321         gnutls_record_disable_padding (vpninfo->https_sess);
1322         gnutls_credentials_set (vpninfo->https_sess, GNUTLS_CRD_CERTIFICATE, vpninfo->https_cred);
1323         gnutls_transport_set_ptr(vpninfo->https_sess, /* really? */(gnutls_transport_ptr_t)(long) ssl_sock);
1324
1325         vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1326                      vpninfo->hostname);
1327
1328         while ((err = gnutls_handshake (vpninfo->https_sess))) {
1329                 if (err == GNUTLS_E_AGAIN) {
1330                         fd_set rd_set, wr_set;
1331                         int maxfd = ssl_sock;
1332                         
1333                         FD_ZERO(&rd_set);
1334                         FD_ZERO(&wr_set);
1335                         
1336                         if (gnutls_record_get_direction(vpninfo->https_sess))
1337                                 FD_SET(ssl_sock, &wr_set);
1338                         else
1339                                 FD_SET(ssl_sock, &rd_set);
1340
1341                         if (vpninfo->cancel_fd != -1) {
1342                                 FD_SET(vpninfo->cancel_fd, &rd_set);
1343                                 if (vpninfo->cancel_fd > ssl_sock)
1344                                         maxfd = vpninfo->cancel_fd;
1345                         }
1346                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1347                         if (vpninfo->cancel_fd != -1 &&
1348                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1349                                 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1350                                 gnutls_deinit(vpninfo->https_sess);
1351                                 vpninfo->https_sess = NULL;
1352                                 close(ssl_sock);
1353                                 return -EINTR;
1354                         }
1355                 } else if (err == GNUTLS_E_INTERRUPTED || gnutls_error_is_fatal(err)) {
1356                         vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure: %s\n"),
1357                                                          gnutls_strerror(err));
1358                         gnutls_deinit(vpninfo->https_sess);
1359                         vpninfo->https_sess = NULL;
1360                         close(ssl_sock);
1361                         return -EIO;
1362                 } else {
1363                         /* non-fatal error or warning. Ignore it and continue */
1364                         vpn_progress(vpninfo, PRG_TRACE,
1365                                      _("GnuTLS non-fatal return during handshake: %s\n"),
1366                                      gnutls_strerror(err));
1367                 }
1368         }
1369
1370         vpninfo->ssl_fd = ssl_sock;
1371
1372         vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1373                      vpninfo->hostname);
1374
1375         return 0;
1376 }
1377
1378 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1379 {
1380         if (vpninfo->peer_cert) {
1381                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1382                 vpninfo->peer_cert = NULL;
1383         }
1384         if (vpninfo->https_sess) {
1385                 gnutls_deinit(vpninfo->https_sess);
1386                 vpninfo->https_sess = NULL;
1387         }
1388         if (vpninfo->ssl_fd != -1) {
1389                 close(vpninfo->ssl_fd);
1390                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1391                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1392                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1393                 vpninfo->ssl_fd = -1;
1394         }
1395         if (final && vpninfo->https_cred) {
1396                 gnutls_certificate_free_credentials(vpninfo->https_cred);
1397                 vpninfo->https_cred = NULL;
1398 #ifdef HAVE_P11KIT
1399                 if (!strncmp(vpninfo->cert, "pkcs11:", 7) ||
1400                     !strncmp(vpninfo->sslkey, "pkcs11:", 7)) {
1401                         char pin_source[40];
1402
1403                         sprintf(pin_source, "openconnect:%p", vpninfo);
1404                         p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
1405
1406                         while (vpninfo->pin_cache) {
1407                                 struct pin_cache *cache = vpninfo->pin_cache;
1408
1409                                 free(cache->token);
1410                                 memset(cache->pin, 0x5a, strlen(cache->pin));
1411                                 free(cache->pin);
1412                                 vpninfo->pin_cache = cache->next;
1413                                 free(cache);
1414                         }
1415                 }
1416 #endif
1417 #ifdef HAVE_TROUSERS
1418                 if (vpninfo->tpm_key_policy) {
1419                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key_policy);
1420                         vpninfo->tpm_key = 0;
1421                 }
1422                 if (vpninfo->tpm_key) {
1423                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key);
1424                         vpninfo->tpm_key = 0;
1425                 }
1426                 if (vpninfo->srk_policy) {
1427                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
1428                         vpninfo->srk_policy = 0;
1429                 }
1430                 if (vpninfo->srk) {
1431                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
1432                         vpninfo->srk = 0;
1433                 }
1434                 if (vpninfo->tpm_context) {
1435                         Tspi_Context_Close(vpninfo->tpm_context);
1436                         vpninfo->tpm_context = 0;
1437                 }
1438 #endif
1439 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
1440                 if (vpninfo->my_pkey && vpninfo->my_pkey != OPENCONNECT_TPM_PKEY) {
1441                         gnutls_privkey_deinit(vpninfo->my_pkey);
1442                         vpninfo->my_pkey = NULL;
1443                         /* my_p11key went with it */
1444                 }
1445                 if (vpninfo->my_certs) {
1446                         int i;
1447                         for (i = 0; i < vpninfo->nr_my_certs; i++)
1448                                 gnutls_x509_crt_deinit(vpninfo->my_certs[i]);
1449                         free(vpninfo->my_certs);
1450                         vpninfo->my_certs = NULL;
1451                 }
1452 #endif
1453         }
1454 }
1455
1456 void openconnect_init_ssl(void)
1457 {
1458         gnutls_global_init();
1459 }
1460
1461 int openconnect_sha1(unsigned char *result, void *data, int datalen)
1462 {
1463         gnutls_datum_t d;
1464         size_t shalen = SHA1_SIZE;
1465
1466         d.data = data;
1467         d.size = datalen;
1468         if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, result, &shalen))
1469                 return -1;
1470
1471         return 0;
1472 }
1473
1474 int openconnect_random(void *bytes, int len)
1475 {
1476         if (gnutls_rnd(GNUTLS_RND_RANDOM, bytes, len))
1477                 return -EIO;
1478         return 0;
1479 }
1480
1481 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1482                                char *buf)
1483 {
1484         const gnutls_datum_t *d;
1485         size_t md5len = 16;
1486
1487         buf[0] = 0;
1488
1489         d = gnutls_certificate_get_ours(vpninfo->https_sess);
1490         if (!d)
1491                 return -EIO;
1492
1493         if (gnutls_fingerprint(GNUTLS_DIG_MD5, d, buf, &md5len))
1494                 return -EIO;
1495
1496         return 0;
1497 }
1498
1499 #ifdef HAVE_P11KIT
1500 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
1501                         const char *pin_description,
1502                         P11KitPinFlags flags,
1503                         void *_vpninfo)
1504 {
1505         struct openconnect_info *vpninfo = _vpninfo;
1506         struct pin_cache **cache = &vpninfo->pin_cache;
1507         struct oc_auth_form f;
1508         struct oc_form_opt o;
1509         char message[1024];
1510         char *uri;
1511         P11KitPin *pin;
1512         int ret;
1513
1514         if (!vpninfo || !vpninfo->process_auth_form)
1515                 return NULL;
1516
1517         if (p11_kit_uri_format(pin_uri, P11_KIT_URI_FOR_TOKEN, &uri))
1518                 return NULL;
1519         
1520         while (*cache) {
1521                 if (!strcmp(uri, (*cache)->token)) {
1522                         free(uri);
1523                         uri = NULL;
1524                         if ((*cache)->pin) {
1525                                 if ((flags & P11_KIT_PIN_FLAGS_RETRY) != P11_KIT_PIN_FLAGS_RETRY)
1526                                         return p11_kit_pin_new_for_string((*cache)->pin);
1527                                 memset((*cache)->pin, 0x5a, strlen((*cache)->pin));
1528                                 free((*cache)->pin);
1529                                 (*cache)->pin = NULL;
1530                         }
1531                         break;
1532                 }
1533         }
1534         if (!*cache) {
1535                 *cache = calloc(1, sizeof(struct pin_cache));
1536                 if (!*cache) {
1537                         free(uri);
1538                         return NULL;
1539                 }
1540                 (*cache)->token = uri;
1541         }
1542
1543         memset(&f, 0, sizeof(f));
1544         f.auth_id = (char *)"pkcs11_pin";
1545         f.opts = &o;
1546
1547         message[sizeof(message)-1] = 0;
1548         snprintf(message, sizeof(message) - 1, _("PIN required for %s"), pin_description);
1549         f.message = message;
1550         
1551         /* 
1552          * In p11-kit <= 0.12, these flags are *odd*.
1553          * RETRY is 0xa, FINAL_TRY is 0x14 and MANY_TRIES is 0x28.
1554          * So don't treat it like a sane bitmask. Fixed in
1555          * http://cgit.freedesktop.org/p11-glue/p11-kit/commit/?id=59774b11
1556          */
1557         if ((flags & P11_KIT_PIN_FLAGS_RETRY) == P11_KIT_PIN_FLAGS_RETRY)
1558                 f.error = (char *)_("Wrong PIN");
1559
1560         if ((flags & P11_KIT_PIN_FLAGS_FINAL_TRY) == P11_KIT_PIN_FLAGS_FINAL_TRY)
1561                 f.banner = (char *)_("This is the final try before locking!");
1562         else if ((flags & P11_KIT_PIN_FLAGS_MANY_TRIES) == P11_KIT_PIN_FLAGS_MANY_TRIES)
1563                 f.banner = (char *)_("Only a few tries left before locking!");
1564
1565         o.next = NULL;
1566         o.type = OC_FORM_OPT_PASSWORD;
1567         o.name = (char *)"pkcs11_pin";
1568         o.label = (char *)_("Enter PIN:");
1569         o.value = NULL;
1570
1571         ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
1572         if (ret || !o.value)
1573                 return NULL;
1574
1575         pin = p11_kit_pin_new_for_string(o.value);
1576         (*cache)->pin = o.value;
1577
1578         return pin;
1579 }
1580 #endif