Move setting of vpninfo->my_p11key to somewhere tidier
[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_P11KIT) || defined (HAVE_TROUSERS)
433 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
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
470 static int assign_privkey_gtls2(struct openconnect_info *vpninfo,
471                                 gnutls_privkey_t pkey,
472                                 gnutls_x509_crt_t *certs,
473                                 unsigned int nr_certs,
474                                 gnutls_x509_crt_t *extra_certs,
475                                 unsigned int nr_extra_certs)
476 {
477         int i;
478
479         vpninfo->my_certs = gnutls_calloc(nr_certs, sizeof(*certs));
480         if (!vpninfo->my_certs)
481                 return GNUTLS_E_MEMORY_ERROR;
482
483         memcpy(vpninfo->my_certs, certs, nr_certs * sizeof(*certs));
484         vpninfo->nr_my_certs = nr_certs;
485
486         /* We are *keeping* the certs, unlike in GnuTLS 3 where we can
487            free them after calling gnutls_certificate_set_key(). So
488            first wipe the 'certs' array (which is either '&cert' or
489            'supporting_certs' in load_certificate())... */
490         memset(certs, 0, nr_certs * sizeof(*certs));
491
492         /* ... and then also zero out the entries in the extra_certs
493            array that correspond to certs that were added into the
494            supporting_certs array (but above the certs_to_free index).
495
496            The first one is 'cert', which was already stolen by the
497            load_certificate() function and put into our certs[0]..
498            So start at 1. */
499         for (i = 1; i < nr_certs; i++) {
500                 int j;
501                 for (j = 0; j < nr_extra_certs; j++) {
502                         if (vpninfo->my_certs[i] == extra_certs[j]) {
503                                 extra_certs[j] = NULL;
504                                 break;
505                         }
506                 }
507         }
508
509         gnutls_certificate_set_retrieve_function(vpninfo->https_cred,
510                                                  gtls_cert_cb);
511         vpninfo->my_pkey = pkey;
512
513         return 0;
514 }
515 #else /* !SET_KEY */
516 static int assign_privkey_gtls3(struct openconnect_info *vpninfo,
517                                 gnutls_privkey_t pkey,
518                                 gnutls_x509_crt_t *certs,
519                                 unsigned int nr_certs)
520 {
521         /* Ug. If we got a gnutls_privkey_t from PKCS#11 rather than the
522            gnutls_x509_privkey_t that we get from PEM or PKCS#12 files, then
523            we can't use gnutls_certificate_set_x509_key(). Instead we have
524            to convert our chain of X509 certificates to gnutls_pcert_st and
525            then use gnutls_certificate_set_key() with that instead. */
526         gnutls_pcert_st *pcerts = calloc(nr_certs, sizeof(*pcerts));
527         int i, err;
528
529         if (!pcerts)
530                 return GNUTLS_E_MEMORY_ERROR;
531
532         for (i=0 ; i < nr_certs; i++) {
533                 err = gnutls_pcert_import_x509(pcerts + i, certs[i], 0);
534                 if (err) {
535                         vpn_progress(vpninfo, PRG_ERR,
536                                      _("Importing X509 certificate failed: %s\n"),
537                                      gnutls_strerror(err));
538                         goto free_pcerts;
539                 }
540         }
541
542         err = gnutls_certificate_set_key(vpninfo->https_cred, NULL, 0,
543                                          pcerts, nr_certs, pkey);
544         if (err) {
545                 vpn_progress(vpninfo, PRG_ERR,
546                              _("Setting PKCS#11 certificate failed: %s\n"),
547                              gnutls_strerror(err));
548         free_pcerts:
549                 for (i=0 ; i < nr_certs; i++)
550                         gnutls_pcert_deinit(pcerts + i);
551                 free (pcerts);
552         }
553         return err;
554 }
555 #endif /* !SET_KEY */
556 #endif /* (P11KIT || TROUSERS) */
557
558 static int load_certificate(struct openconnect_info *vpninfo)
559 {
560         gnutls_datum_t fdata;
561         gnutls_x509_privkey_t key = NULL;
562 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
563         gnutls_privkey_t pkey = NULL;
564         gnutls_datum_t pkey_sig = {NULL, 0};
565         void *dummy_hash_data = &load_certificate;
566 #endif
567 #ifdef HAVE_P11KIT
568         char *cert_url = (char *)vpninfo->cert;
569         char *key_url = (char *)vpninfo->sslkey;
570         gnutls_pkcs11_privkey_t p11key = NULL;
571 #endif
572         gnutls_x509_crl_t crl = NULL;
573         gnutls_x509_crt_t last_cert, cert = NULL;
574         gnutls_x509_crt_t *extra_certs = NULL, *supporting_certs = NULL;
575         unsigned int nr_supporting_certs = 0, nr_extra_certs = 0;
576         unsigned int certs_to_free = 0; /* How many of supporting_certs */
577         int err; /* GnuTLS error */
578         int ret;
579         int i;
580         int cert_is_p11 = 0, key_is_p11 = 0;
581         unsigned char key_id[20];
582         size_t key_id_size = sizeof(key_id);
583         char name[80];
584
585         fdata.data = NULL;
586
587         key_is_p11 = !strncmp(vpninfo->sslkey, "pkcs11:", 7);
588         cert_is_p11 = !strncmp(vpninfo->cert, "pkcs11:", 7);
589
590         /* Install PIN handler if either certificate or key are coming from PKCS#11 */
591         if (key_is_p11 || cert_is_p11) {
592 #ifdef HAVE_P11KIT
593                 CK_OBJECT_CLASS class;
594                 CK_ATTRIBUTE attr;
595                 char pin_source[40];
596                 P11KitUri *uri;
597
598                 sprintf(pin_source, "openconnect:%p", vpninfo);
599                 p11_kit_pin_register_callback(pin_source, pin_callback, vpninfo, NULL);
600
601                 uri = p11_kit_uri_new();
602
603                 attr.type = CKA_CLASS;
604                 attr.pValue = &class;
605                 attr.ulValueLen = sizeof(class);
606
607                 /* Add appropriate pin-source and object-type attributes to
608                    both certificate and key URLs, unless they already exist. */
609                 if (cert_is_p11 &&
610                     !p11_kit_uri_parse(cert_url, P11_KIT_URI_FOR_OBJECT, uri)) {
611                         if (!p11_kit_uri_get_pin_source(uri))
612                                 p11_kit_uri_set_pin_source(uri, pin_source);
613                         if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
614                                 class = CKO_CERTIFICATE;
615                                 p11_kit_uri_set_attribute(uri, &attr);
616                         }
617                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &cert_url);
618                 }
619
620                 if (key_is_p11 &&
621                     !p11_kit_uri_parse(key_url, P11_KIT_URI_FOR_OBJECT, uri)) {
622                         if (!p11_kit_uri_get_pin_source(uri))
623                                 p11_kit_uri_set_pin_source(uri, pin_source);
624                         if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
625                                 class = CKO_PRIVATE_KEY;
626                                 p11_kit_uri_set_attribute(uri, &attr);
627                         }
628                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &key_url);
629                 }
630
631                 p11_kit_uri_free(uri);
632 #else
633                 vpn_progress(vpninfo, PRG_ERR,
634                              _("This binary built without PKCS#11 support\n"));
635                 return -EINVAL;
636 #endif
637         }
638
639         /* Load certificate(s) first... */
640 #ifdef HAVE_P11KIT
641         if (cert_is_p11) {
642                 vpn_progress(vpninfo, PRG_TRACE,
643                              _("Using PKCS#11 certificate %s\n"), cert_url);
644
645                 err = gnutls_x509_crt_init(&cert);
646                 if (err) {
647                         ret = -ENOMEM;
648                         goto out;
649                 }
650                 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url, 0);
651                 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
652                         err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url,
653                                                                 GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
654                 if (err) {
655                         vpn_progress(vpninfo, PRG_ERR,
656                                      _("Error loading certificate from PKCS#11: %s\n"),
657                                      gnutls_strerror(err));
658                         ret = -EIO;
659                         goto out;
660                 }
661                 goto got_certs;
662         }
663 #endif /* HAVE_P11KIT */
664
665         vpn_progress(vpninfo, PRG_TRACE,
666                      _("Using certificate file %s\n"), vpninfo->cert);
667
668         ret = load_datum(vpninfo, &fdata, vpninfo->cert);
669         if (ret)
670                 return ret;
671
672         if (!key_is_p11 && (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
673                             vpninfo->cert_type == CERT_TYPE_UNKNOWN)) {
674                 /* PKCS#12 should actually contain certificates *and* private key */
675                 ret = load_pkcs12_certificate(vpninfo, &fdata, &key,
676                                               &supporting_certs, &nr_supporting_certs,
677                                               &extra_certs, &nr_extra_certs,
678                                               &crl);
679                 if (ret < 0)
680                         goto out;
681                 else if (!ret) {
682                         if (nr_supporting_certs) {
683                                 cert = supporting_certs[0];
684                                 goto got_key;
685                         }
686                         vpn_progress(vpninfo, PRG_ERR,
687                                      _("PKCS#11 file contained no certificate\n"));
688                         ret = -EINVAL;
689                         goto out;
690                 }
691
692                 /* It returned NOT_PKCS12.
693                    Fall through to try PEM formats. */
694         }
695
696         /* We need to know how many there are in *advance*; it won't just allocate
697            the array for us :( */
698         nr_extra_certs = count_x509_certificates(&fdata);
699         if (!nr_extra_certs)
700                 nr_extra_certs = 1; /* wtf? Oh well, we'll fail later... */
701
702         extra_certs = calloc(nr_extra_certs, sizeof(cert));
703         if (!extra_certs) {
704                 nr_extra_certs = 0;
705                 ret = -ENOMEM;
706                 goto out;
707         }
708         err = gnutls_x509_crt_list_import(extra_certs, &nr_extra_certs, &fdata,
709                                           GNUTLS_X509_FMT_PEM, 0);
710         if (err <= 0) {
711                 const char *reason;
712                 if (!err || err == GNUTLS_E_NO_CERTIFICATE_FOUND)
713                         reason = _("No certificate found in file");
714                 else
715                         reason = gnutls_strerror(err);
716
717                 vpn_progress(vpninfo, PRG_ERR,
718                              _("Loading certificate failed: %s\n"),
719                              reason);
720                 ret = -EINVAL;
721                 goto out;
722         }
723         nr_extra_certs = err;
724         err = 0;
725
726         goto got_certs;
727  got_certs:
728         /* Now we have the certificate(s) and we're looking for the private key... */
729 #if defined (HAVE_P11KIT)
730         if (key_is_p11) {
731                 vpn_progress(vpninfo, PRG_TRACE,
732                              _("Using PKCS#11 key %s\n"), key_url);
733
734                 err = gnutls_pkcs11_privkey_init(&p11key);
735                 if (err) {
736                         vpn_progress(vpninfo, PRG_ERR,
737                                      _("Error initialising PKCS#11 key structure: %s\n"),
738                                      gnutls_strerror(err));
739                         ret = -EIO;
740                         goto out;
741                 }
742
743                 err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0);
744                 if (err) {
745                         vpn_progress(vpninfo, PRG_ERR,
746                                      _("Error importing PKCS#11 URL %s: %s\n"),
747                                      key_url, gnutls_strerror(err));
748                         gnutls_pkcs11_privkey_deinit(p11key);
749                         ret = -EIO;
750                         goto out;
751                 }
752
753                 err = gnutls_privkey_init(&pkey);
754                 if (err) {
755                         vpn_progress(vpninfo, PRG_ERR,
756                                      _("Error initialising private key structure: %s\n"),
757                                      gnutls_strerror(err));
758                         gnutls_pkcs11_privkey_deinit(p11key);
759                         ret = -EIO;
760                         goto out;
761                 }
762
763                 err = gnutls_privkey_import_pkcs11(pkey, p11key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
764                 if (err) {
765                         vpn_progress(vpninfo, PRG_ERR,
766                                      _("Error importing PKCS#11 key into private key structure: %s\n"),
767                                      gnutls_strerror(err));
768                         gnutls_pkcs11_privkey_deinit(p11key);
769                         ret = -EIO;
770                         goto out;
771                 }
772 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
773                 /* This can be set now and doesn't need to be separately freed.
774                    It goes with the pkey. This is a PITA; it would be better
775                    if there was a way to get the p11key *back* from a privkey
776                    that we *know* is based on one. In fact, since this is only
777                    for GnuTLS 2.12 and we *know* the gnutls_privkey_st won't
778                    ever change there, so we *could* do something evil... but
779                    we won't :) */
780                 vpninfo->my_p11key = p11key;
781 #endif /* !SET_KEY */
782                 goto match_cert;
783         }
784 #endif /* HAVE_P11KIT */
785
786         /* We're loading the private key from a file. Load the file into memory
787            unless it's the same as the certificate and we already loaded that. */
788         if (!fdata.data || vpninfo->sslkey != vpninfo->cert) {
789                 gnutls_free(fdata.data);
790                 fdata.data = NULL;
791
792                 vpn_progress(vpninfo, PRG_TRACE,
793                              _("Using private key file %s\n"), vpninfo->sslkey);
794
795                 ret = load_datum(vpninfo, &fdata, vpninfo->sslkey);
796                 if (ret)
797                         goto out;
798         }
799
800         if (vpninfo->cert_type == CERT_TYPE_TPM ||
801             (vpninfo->cert_type == CERT_TYPE_UNKNOWN &&
802              strstr((char *)fdata.data, "-----BEGIN TSS KEY BLOB-----"))) {
803 #ifndef HAVE_TROUSERS
804                 vpn_progress(vpninfo, PRG_ERR,
805                              _("This version of OpenConnect was built without TPM support\n"));
806                 return -EINVAL;
807 #else
808                 ret = load_tpm_key(vpninfo, &fdata, &pkey, &pkey_sig);
809                 if (ret)
810                         goto out;
811
812                 goto match_cert;
813 #endif
814         }
815
816         gnutls_x509_privkey_init(&key);
817         /* Try PKCS#1 (and PKCS#8 without password) first. GnuTLS doesn't
818            support OpenSSL's old PKCS#1-based encrypted format. We should
819            probably check for it and give a more coherent failure mode. */
820         err = gnutls_x509_privkey_import(key, &fdata, GNUTLS_X509_FMT_PEM);
821         if (err) {
822                 /* If that fails, try PKCS#8 */
823                 char *pass = vpninfo->cert_password;
824
825                 /* Yay, just for fun this is *different* to PKCS#12. Where we could
826                    try an empty password there, in this case the empty-password case
827                    has already been *tried* by gnutls_x509_privkey_import(). If we
828                    just call gnutls_x509_privkey_import_pkcs8() with a NULL password,
829                    it'll SEGV. You have to set the GNUTLS_PKCS_PLAIN flag if you want
830                    to try without a password. Passing NULL evidently isn't enough of
831                    a hint. And in GnuTLS 3.1 where that crash has been fixed, passing
832                    NULL will cause it to return GNUTLS_E_ENCRYPTED_STRUCTURE (a new
833                    error code) rather than GNUTLS_E_DECRYPTION_FAILED. So just pass ""
834                    instead of NULL, and don't worry about either case. */
835                 while ((err = gnutls_x509_privkey_import_pkcs8(key, &fdata,
836                                                                GNUTLS_X509_FMT_PEM,
837                                                                pass?pass:"", 0))) {
838                         if (err != GNUTLS_E_DECRYPTION_FAILED) {
839                                 vpn_progress(vpninfo, PRG_ERR,
840                                              _("Failed to load private key as PKCS#8: %s\n"),
841                                              gnutls_strerror(err));
842                                 ret = -EINVAL;
843                                 goto out;
844                         }
845                         vpninfo->cert_password = NULL;
846                         if (pass) {
847                                 vpn_progress(vpninfo, PRG_ERR,
848                                              _("Failed to decrypt PKCS#8 certificate file\n"));
849                                 free(pass);
850                         }
851                         err = request_passphrase(vpninfo, "openconnect_pem",
852                                                  &pass, _("Enter PEM pass phrase:"));
853                         if (err) {
854                                 ret = -EINVAL;
855                                 goto out;
856                         }
857                 }
858                 free(pass);
859                 vpninfo->cert_password = NULL;
860         }
861
862         /* Now attempt to make sure we use the *correct* certificate, to match the key */
863         err = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size);
864         if (err) {
865                 vpn_progress(vpninfo, PRG_ERR,
866                              _("Failed to get key ID: %s\n"),
867                              gnutls_strerror(err));
868                 ret = -EINVAL;
869                 goto out;
870         }
871         for (i = 0; i < (extra_certs?nr_extra_certs:1); i++) {
872                 unsigned char cert_id[20];
873                 size_t cert_id_size = sizeof(cert_id);
874
875                 err = gnutls_x509_crt_get_key_id(extra_certs?extra_certs[i]:cert, 0, cert_id, &cert_id_size);
876                 if (err)
877                         continue;
878
879                 if (cert_id_size == key_id_size && !memcmp(cert_id, key_id, key_id_size)) {
880                         if (extra_certs) {
881                                 cert = extra_certs[i];
882
883                                 /* Move the rest of the array down */
884                                 for (; i < nr_extra_certs - 1; i++)
885                                         extra_certs[i] = extra_certs[i+1];
886
887                                 nr_extra_certs--;
888                         }
889                         goto got_key;
890                 }
891         }
892         /* There's no pkey (there's an x509 key), so we'll fall straight through the
893          * bit at match_cert: below, and go directly to the bit where it prints the
894          * 'no match found' error and exits. */
895
896 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
897  match_cert:
898         /* If we have a privkey from PKCS#11 or TPM, we can't do the simple comparison
899            of key ID that we do for software keys to find which certificate is a
900            match. So sign some dummy data and then check the signature against each
901            of the available certificates until we find the right one. */
902         if (pkey) {
903                 /* The TPM code may have already signed it, to test authorisation. We
904                    only sign here for PKCS#11 keys, in which case fdata might be
905                    empty too so point it at dummy data. */
906                 if (!pkey_sig.data) {
907                         if (!fdata.data) {
908                                 fdata.data = dummy_hash_data;
909                                 fdata.size = 20;
910                         }
911
912                         err = sign_dummy_data(vpninfo, pkey, &fdata, &pkey_sig);
913                         if (err) {
914                                 vpn_progress(vpninfo, PRG_ERR,
915                                              _("Error signing test data with private key: %s\n"),
916                                              gnutls_strerror(err));
917                                 ret = -EINVAL;
918                                 goto out;
919                         }
920                 }
921
922                 for (i=0; i < (extra_certs?nr_extra_certs:1); i++) {
923                         gnutls_pubkey_t pubkey;
924
925                         gnutls_pubkey_init(&pubkey);
926                         err = gnutls_pubkey_import_x509(pubkey, extra_certs?extra_certs[i]:cert, 0);
927                         if (err) {
928                                 vpn_progress(vpninfo, PRG_ERR,
929                                              _("Error validating signature against certificate: %s\n"),
930                                              gnutls_strerror(err));
931                                 /* We'll probably fail shortly if we don't find it. */
932                                 gnutls_pubkey_deinit(pubkey);
933                                 continue;
934                         }
935                         err = gnutls_pubkey_verify_data(pubkey, 0, &fdata, &pkey_sig);
936                         gnutls_pubkey_deinit(pubkey);
937
938                         if (err >= 0) {
939                                 if (extra_certs) {
940                                         cert = extra_certs[i];
941
942                                         /* Move the rest of the array down */
943                                         for (; i < nr_extra_certs - 1; i++)
944                                                 extra_certs[i] = extra_certs[i+1];
945
946                                         nr_extra_certs--;
947                                 }
948                                 gnutls_free(pkey_sig.data);
949                                 goto got_key;
950                         }
951                 }
952                 gnutls_free(pkey_sig.data);
953         }
954 #endif /* P11KIT || TROUSERS */
955
956         /* We shouldn't reach this. It means that we didn't find *any* matching cert */
957         vpn_progress(vpninfo, PRG_ERR,
958                      _("No SSL certificate found to match private key\n"));
959         ret = -EINVAL;
960         goto out;
961
962         /********************************************************************/
963  got_key:
964         /* Now we have both cert(s) and key, and we should be ready to go. */
965         check_certificate_expiry(vpninfo, cert);
966         get_cert_name(cert, name, sizeof(name));
967         vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"),
968                      name);
969
970         if (crl) {
971                 err = gnutls_certificate_set_x509_crl(vpninfo->https_cred, &crl, 1);
972                 if (err) {
973                         vpn_progress(vpninfo, PRG_ERR,
974                                      _("Setting certificate recovation list failed: %s\n"),
975                                      gnutls_strerror(err));
976                         ret = -EINVAL;
977                         goto out;
978                 }
979         }
980
981         /* OpenSSL has problems with certificate chains — if there are
982            multiple certs with the same name, it doesn't necessarily
983            choose the _right_ one. (RT#1942)
984            Pick the right ones for ourselves and add them manually. */
985
986         if (nr_supporting_certs) {
987                 /* We already got a bunch of certs from PKCS#12 file. 
988                    Remember how many need to be freed when we're done,
989                    since we'll expand the supporting_certs array with
990                    more from the cafile if we can. */
991                 last_cert = supporting_certs[nr_supporting_certs-1];
992                 certs_to_free = nr_supporting_certs;
993         } else {
994                 last_cert = cert;
995                 certs_to_free = nr_supporting_certs = 1;
996         }
997         while (1) {
998                 gnutls_x509_crt_t issuer;
999
1000                 for (i = 0; i < nr_extra_certs; i++) {
1001                         if (gnutls_x509_crt_check_issuer(last_cert, extra_certs[i]) &&
1002                             !check_issuer_sanity(last_cert, extra_certs[i]))
1003                                 break;
1004                 }
1005
1006                 if (i < nr_extra_certs) {
1007                         issuer = extra_certs[i];
1008                 } else {
1009                         err = gnutls_certificate_get_issuer(vpninfo->https_cred,
1010                                                             last_cert, &issuer, 0);
1011                         if (err)
1012                                 break;
1013                 }
1014
1015                 /* The check_issuer_sanity() function works fine as a workaround where
1016                    it was used above, but when gnutls_certificate_get_issuer() returns
1017                    a bogus cert, there's nothing we can do to fix it up. We don't get
1018                    to iterate over all the available certs like we can over our own
1019                    list. */
1020                 if (check_issuer_sanity(last_cert, issuer)) {
1021                         /* Hm, is there a bug reference for this? Or just the git commit
1022                            reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
1023                         vpn_progress(vpninfo, PRG_ERR,
1024                                      _("WARNING: GnuTLS returned incorrect issuer certs; authentication may fail!\n"));
1025                         break;
1026                 }
1027
1028                 if (issuer == last_cert) {
1029                         /* Don't actually include the root CA. If they don't already trust it,
1030                            then handing it to them isn't going to help. But don't omit the
1031                            original certificate if it's self-signed. */
1032                         if (nr_supporting_certs > 1)
1033                                 nr_supporting_certs--;
1034                         break;
1035                 }
1036
1037                 /* OK, we found a new cert to add to our chain. */
1038                 supporting_certs = gnutls_realloc(supporting_certs,
1039                                                   sizeof(cert) * ++nr_supporting_certs);
1040                 if (!supporting_certs) {
1041                         vpn_progress(vpninfo, PRG_ERR,
1042                                      _("Failed to allocate memory for supporting certificates\n"));
1043                         /* The world is probably about to end, but try without them anyway */
1044                         certs_to_free = 0;
1045                         ret = -ENOMEM;
1046                         goto out;
1047                 }
1048
1049                 /* First time we actually allocated an array? Copy the first cert into it */
1050                 if (nr_supporting_certs == 2)
1051                         supporting_certs[0] = cert;
1052
1053                 /* Append the new one */
1054                 supporting_certs[nr_supporting_certs-1] = issuer;
1055                 last_cert = issuer;
1056
1057         }
1058         for (i = 1; i < nr_supporting_certs; i++) {
1059                 get_cert_name(supporting_certs[i], name, sizeof(name));
1060
1061                 vpn_progress(vpninfo, PRG_DEBUG,
1062                              _("Adding supporting CA '%s'\n"), name);
1063         }
1064
1065 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1066         if (pkey) {
1067 #if defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY)
1068                 err = assign_privkey_gtls3(vpninfo, pkey, supporting_certs?:&cert, nr_supporting_certs);
1069                 if (err) {
1070                         ret = -EIO;
1071                         goto out;
1072                 }
1073 #else /* !HAVE_GNUTLS_CERTIFICATE_SET_KEY so fake it using sign_callback */
1074                 err = assign_privkey_gtls2(vpninfo, pkey, supporting_certs?:&cert, nr_supporting_certs,
1075                                            extra_certs, nr_extra_certs);
1076                 if (err) {
1077                         ret = -EIO;
1078                         goto out;
1079                 }
1080 #endif
1081                 pkey = NULL; /* we gave it away, along with pcerts */
1082         } else
1083 #endif /* P11KIT || TROUSERS */
1084                 err = gnutls_certificate_set_x509_key(vpninfo->https_cred,
1085                                                       supporting_certs ? supporting_certs : &cert,
1086                                                       supporting_certs ? nr_supporting_certs : 1,
1087                                                       key);
1088
1089         if (err) {
1090                 vpn_progress(vpninfo, PRG_ERR,
1091                              _("Setting certificate failed: %s\n"),
1092                              gnutls_strerror(err));
1093                 ret = -EIO;
1094         } else
1095                 ret = 0;
1096  out:
1097         if (crl)
1098                 gnutls_x509_crl_deinit(crl);
1099         if (key)
1100                 gnutls_x509_privkey_deinit(key);
1101         if (supporting_certs) {
1102                 for (i = 0; i < certs_to_free; i++) {
1103                         if (supporting_certs[i])
1104                                 gnutls_x509_crt_deinit(supporting_certs[i]);
1105                 }
1106                 gnutls_free(supporting_certs);
1107         } else if (cert) {
1108                 /* Not if supporting_certs. It's supporting_certs[0] then and
1109                    was already freed. */
1110                 gnutls_x509_crt_deinit(cert);
1111         }
1112         for (i = 0; i < nr_extra_certs; i++) {
1113                 if (extra_certs[i])
1114                         gnutls_x509_crt_deinit(extra_certs[i]);
1115         }
1116         gnutls_free(extra_certs);
1117 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1118         if (pkey && pkey != OPENCONNECT_TPM_PKEY)
1119                 gnutls_privkey_deinit(pkey);
1120         if (fdata.data != dummy_hash_data)
1121 #endif /* It's conditional if we support arbitrary privkeys: */
1122                 gnutls_free(fdata.data);
1123 #ifdef HAVE_P11KIT
1124         if (cert_url != vpninfo->cert)
1125                 free(cert_url);
1126         if (key_url != vpninfo->sslkey)
1127                 free(key_url);
1128 #endif
1129         return ret;
1130 }
1131
1132 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
1133                                 gnutls_x509_crt_t cert,
1134                                 gnutls_digest_algorithm_t algo,
1135                                 char *buf)
1136 {
1137         unsigned char md[256];
1138         size_t md_size = sizeof(md);
1139         unsigned int i;
1140
1141         if (gnutls_x509_crt_get_fingerprint(cert, algo, md, &md_size))
1142                 return -EIO;
1143
1144         for (i=0; i < md_size; i++)
1145                 sprintf(&buf[i*2], "%02X", md[i]);
1146
1147         return 0;
1148 }
1149
1150 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
1151                              OPENCONNECT_X509 *cert, char *buf)
1152 {
1153         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_MD5, buf);
1154 }
1155
1156 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
1157                               OPENCONNECT_X509 *cert, char *buf)
1158 {
1159         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_SHA1, buf);
1160 }
1161
1162 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1163                                    OPENCONNECT_X509 *cert)
1164 {
1165         gnutls_datum_t buf;
1166         char *ret;
1167
1168         if (gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &buf))
1169                 return NULL;
1170         
1171         /* Just in case gnutls_free() isn't free(), we can't steal it. */
1172         ret = strdup((char *)buf.data);
1173         gnutls_free(buf.data);
1174         
1175         return ret;
1176 }
1177
1178 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
1179                              OPENCONNECT_X509 *cert, unsigned char **buf)
1180 {
1181         size_t l = 0;
1182         unsigned char *ret = NULL;
1183
1184         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l) != 
1185             GNUTLS_E_SHORT_MEMORY_BUFFER)
1186                 return -EIO;
1187
1188         ret = malloc(l);
1189         if (!ret)
1190                 return -ENOMEM;
1191
1192         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l)) {
1193                 free(ret);
1194                 return -EIO;
1195         }
1196         *buf = ret;
1197         return l;
1198 }
1199
1200 static int verify_peer(gnutls_session_t session)
1201 {
1202         struct openconnect_info *vpninfo = gnutls_session_get_ptr(session);
1203         const gnutls_datum_t *cert_list;
1204         gnutls_x509_crt_t cert;
1205         unsigned int status, cert_list_size;
1206         const char *reason = NULL;
1207         int err;
1208
1209         if (vpninfo->peer_cert) {
1210                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1211                 vpninfo->peer_cert = NULL;
1212         }
1213
1214         cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
1215         if (!cert_list) {
1216                 vpn_progress(vpninfo, PRG_ERR, _("Server presented no certificate\n"));
1217                 return GNUTLS_E_CERTIFICATE_ERROR;
1218         }
1219
1220         if (vpninfo->servercert) {
1221                 unsigned char sha1bin[SHA1_SIZE];
1222                 char fingerprint[(SHA1_SIZE * 2) + 1];
1223                 int i;
1224                 
1225                 err = openconnect_sha1(sha1bin, cert_list[0].data, cert_list[0].size);
1226                 if (err) {
1227                         vpn_progress(vpninfo, PRG_ERR,
1228                                      _("Could not calculate SHA1 of server's certificate\n"));
1229                         return GNUTLS_E_CERTIFICATE_ERROR;
1230                 }
1231                 for (i=0; i < SHA1_SIZE; i++)
1232                         sprintf(&fingerprint[i*2], "%02X", sha1bin[i]);
1233
1234                 if (strcasecmp(vpninfo->servercert, fingerprint)) {
1235                         vpn_progress(vpninfo, PRG_ERR,
1236                                      _("Server SSL certificate didn't match: %s\n"), fingerprint);
1237                         return GNUTLS_E_CERTIFICATE_ERROR;
1238                 }
1239                 return 0;
1240         }
1241
1242         err = gnutls_certificate_verify_peers2 (session, &status);
1243         if (err) {
1244                 vpn_progress(vpninfo, PRG_ERR, _("Error checking server cert status\n"));
1245                 return GNUTLS_E_CERTIFICATE_ERROR;
1246         }
1247
1248         if (status & GNUTLS_CERT_REVOKED)
1249                 reason = _("certificate revoked");
1250         else if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1251                 reason = _("signer not found");
1252         else if (status & GNUTLS_CERT_SIGNER_NOT_CA)
1253                 reason = _("signer not a CA certificate");
1254         else if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1255                 reason = _("insecure algorithm");
1256         else if (status & GNUTLS_CERT_NOT_ACTIVATED)
1257                 reason = _("certificate not yet activated");
1258         else if (status & GNUTLS_CERT_EXPIRED)
1259                 reason = _("certificate expired");
1260         else if (status & GNUTLS_CERT_INVALID)
1261                 /* If this is set and no other reason, it apparently means
1262                    that signature verification failed. Not entirely sure
1263                    why we don't just set a bit for that too. */
1264                 reason = _("signature verification failed");
1265
1266         err = gnutls_x509_crt_init(&cert);
1267         if (err) {
1268                 vpn_progress(vpninfo, PRG_ERR, _("Error initialising X509 cert structure\n"));
1269                 return GNUTLS_E_CERTIFICATE_ERROR;
1270         }
1271
1272         err = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
1273         if (err) {
1274                 vpn_progress(vpninfo, PRG_ERR, _("Error importing server's cert\n"));
1275                 gnutls_x509_crt_deinit(cert);
1276                 return GNUTLS_E_CERTIFICATE_ERROR;
1277         }
1278
1279         if (!reason && !gnutls_x509_crt_check_hostname(cert, vpninfo->hostname))
1280                 reason = _("certificate does not match hostname");
1281
1282         if (reason) {
1283                 vpn_progress(vpninfo, PRG_INFO, "Server certificate verify failed: %s\n",
1284                              reason);
1285                 if (vpninfo->validate_peer_cert)
1286                         err = vpninfo->validate_peer_cert(vpninfo->cbdata,
1287                                                           cert,
1288                                                           reason) ? GNUTLS_E_CERTIFICATE_ERROR : 0;
1289                 else
1290                         err = GNUTLS_E_CERTIFICATE_ERROR;
1291         }
1292
1293         vpninfo->peer_cert = cert;
1294
1295         return err;
1296 }
1297
1298
1299 int openconnect_open_https(struct openconnect_info *vpninfo)
1300 {
1301         int ssl_sock = -1;
1302         int err;
1303
1304         if (vpninfo->https_sess)
1305                 return 0;
1306
1307         ssl_sock = connect_https_socket(vpninfo);
1308         if (ssl_sock < 0)
1309                 return ssl_sock;
1310
1311         if (!vpninfo->https_cred) {
1312                 gnutls_certificate_allocate_credentials(&vpninfo->https_cred);
1313 #ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST
1314                 gnutls_certificate_set_x509_system_trust(vpninfo->https_cred);
1315 #else
1316                 gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1317                                                        "/etc/pki/tls/certs/ca-bundle.crt",
1318                                                        GNUTLS_X509_FMT_PEM);
1319 #endif
1320                 gnutls_certificate_set_verify_function (vpninfo->https_cred,
1321                                                         verify_peer);
1322
1323                 if (vpninfo->cafile) {
1324                         err = gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1325                                                                      vpninfo->cafile,
1326                                                                      GNUTLS_X509_FMT_PEM);
1327                         if (err < 0) {
1328                                 vpn_progress(vpninfo, PRG_ERR,
1329                                              _("Failed to open CA file '%s': %s\n"),
1330                                              vpninfo->cafile, gnutls_strerror(err));
1331                                 close(ssl_sock);
1332                                 return -EINVAL;
1333                         }
1334                 }
1335
1336                 if (vpninfo->cert) {
1337                         err = load_certificate(vpninfo);
1338                         if (err) {
1339                                 vpn_progress(vpninfo, PRG_ERR,
1340                                              _("Loading certificate failed. Aborting.\n"));
1341                                 return err;
1342                         }
1343                 }
1344         }
1345         gnutls_init (&vpninfo->https_sess, GNUTLS_CLIENT);
1346         gnutls_session_set_ptr (vpninfo->https_sess, (void *) vpninfo);
1347 #if defined(HAVE_TROUSERS) && !defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY)
1348         if (vpninfo->my_pkey == OPENCONNECT_TPM_PKEY)
1349                 gnutls_sign_callback_set(vpninfo->https_sess, gtls2_tpm_sign_cb, vpninfo);
1350 #endif
1351         err = gnutls_priority_set_direct (vpninfo->https_sess, "NONE:+VERS-TLS1.0:+SHA1:+AES-128-CBC:+RSA:+COMP-NULL:%COMPAT:%DISABLE_SAFE_RENEGOTIATION", NULL);
1352         if (err) {
1353                 vpn_progress(vpninfo, PRG_ERR,
1354                              _("Failed to set TLS priority string: %s\n"),
1355                              gnutls_strerror(err));
1356                 return -EIO;
1357         }
1358
1359         gnutls_record_disable_padding (vpninfo->https_sess);
1360         gnutls_credentials_set (vpninfo->https_sess, GNUTLS_CRD_CERTIFICATE, vpninfo->https_cred);
1361         gnutls_transport_set_ptr(vpninfo->https_sess, /* really? */(gnutls_transport_ptr_t)(long) ssl_sock);
1362
1363         vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1364                      vpninfo->hostname);
1365
1366         while ((err = gnutls_handshake (vpninfo->https_sess))) {
1367                 if (err == GNUTLS_E_AGAIN) {
1368                         fd_set rd_set, wr_set;
1369                         int maxfd = ssl_sock;
1370                         
1371                         FD_ZERO(&rd_set);
1372                         FD_ZERO(&wr_set);
1373                         
1374                         if (gnutls_record_get_direction(vpninfo->https_sess))
1375                                 FD_SET(ssl_sock, &wr_set);
1376                         else
1377                                 FD_SET(ssl_sock, &rd_set);
1378
1379                         if (vpninfo->cancel_fd != -1) {
1380                                 FD_SET(vpninfo->cancel_fd, &rd_set);
1381                                 if (vpninfo->cancel_fd > ssl_sock)
1382                                         maxfd = vpninfo->cancel_fd;
1383                         }
1384                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1385                         if (vpninfo->cancel_fd != -1 &&
1386                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1387                                 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1388                                 gnutls_deinit(vpninfo->https_sess);
1389                                 vpninfo->https_sess = NULL;
1390                                 close(ssl_sock);
1391                                 return -EINTR;
1392                         }
1393                 } else if (err == GNUTLS_E_INTERRUPTED || gnutls_error_is_fatal(err)) {
1394                         vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure: %s\n"),
1395                                                          gnutls_strerror(err));
1396                         gnutls_deinit(vpninfo->https_sess);
1397                         vpninfo->https_sess = NULL;
1398                         close(ssl_sock);
1399                         return -EIO;
1400                 } else {
1401                         /* non-fatal error or warning. Ignore it and continue */
1402                         vpn_progress(vpninfo, PRG_TRACE,
1403                                      _("GnuTLS non-fatal return during handshake: %s\n"),
1404                                      gnutls_strerror(err));
1405                 }
1406         }
1407
1408         vpninfo->ssl_fd = ssl_sock;
1409
1410         vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1411                      vpninfo->hostname);
1412
1413         return 0;
1414 }
1415
1416 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1417 {
1418         if (vpninfo->peer_cert) {
1419                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1420                 vpninfo->peer_cert = NULL;
1421         }
1422         if (vpninfo->https_sess) {
1423                 gnutls_deinit(vpninfo->https_sess);
1424                 vpninfo->https_sess = NULL;
1425         }
1426         if (vpninfo->ssl_fd != -1) {
1427                 close(vpninfo->ssl_fd);
1428                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1429                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1430                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1431                 vpninfo->ssl_fd = -1;
1432         }
1433         if (final && vpninfo->https_cred) {
1434                 gnutls_certificate_free_credentials(vpninfo->https_cred);
1435                 vpninfo->https_cred = NULL;
1436 #ifdef HAVE_P11KIT
1437                 if (!strncmp(vpninfo->cert, "pkcs11:", 7) ||
1438                     !strncmp(vpninfo->sslkey, "pkcs11:", 7)) {
1439                         char pin_source[40];
1440
1441                         sprintf(pin_source, "openconnect:%p", vpninfo);
1442                         p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
1443
1444                         while (vpninfo->pin_cache) {
1445                                 struct pin_cache *cache = vpninfo->pin_cache;
1446
1447                                 free(cache->token);
1448                                 memset(cache->pin, 0x5a, strlen(cache->pin));
1449                                 free(cache->pin);
1450                                 vpninfo->pin_cache = cache->next;
1451                                 free(cache);
1452                         }
1453                 }
1454 #endif
1455 #ifdef HAVE_TROUSERS
1456                 if (vpninfo->tpm_key_policy) {
1457                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key_policy);
1458                         vpninfo->tpm_key = 0;
1459                 }
1460                 if (vpninfo->tpm_key) {
1461                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key);
1462                         vpninfo->tpm_key = 0;
1463                 }
1464                 if (vpninfo->srk_policy) {
1465                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
1466                         vpninfo->srk_policy = 0;
1467                 }
1468                 if (vpninfo->srk) {
1469                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
1470                         vpninfo->srk = 0;
1471                 }
1472                 if (vpninfo->tpm_context) {
1473                         Tspi_Context_Close(vpninfo->tpm_context);
1474                         vpninfo->tpm_context = 0;
1475                 }
1476 #endif
1477 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
1478                 if (vpninfo->my_pkey && vpninfo->my_pkey != OPENCONNECT_TPM_PKEY) {
1479                         gnutls_privkey_deinit(vpninfo->my_pkey);
1480                         vpninfo->my_pkey = NULL;
1481                         /* my_p11key went with it */
1482                 }
1483                 if (vpninfo->my_certs) {
1484                         int i;
1485                         for (i = 0; i < vpninfo->nr_my_certs; i++)
1486                                 gnutls_x509_crt_deinit(vpninfo->my_certs[i]);
1487                         free(vpninfo->my_certs);
1488                         vpninfo->my_certs = NULL;
1489                 }
1490 #endif
1491         }
1492 }
1493
1494 void openconnect_init_ssl(void)
1495 {
1496         gnutls_global_init();
1497 }
1498
1499 int openconnect_sha1(unsigned char *result, void *data, int datalen)
1500 {
1501         gnutls_datum_t d;
1502         size_t shalen = SHA1_SIZE;
1503
1504         d.data = data;
1505         d.size = datalen;
1506         if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, result, &shalen))
1507                 return -1;
1508
1509         return 0;
1510 }
1511
1512 int openconnect_random(void *bytes, int len)
1513 {
1514         if (gnutls_rnd(GNUTLS_RND_RANDOM, bytes, len))
1515                 return -EIO;
1516         return 0;
1517 }
1518
1519 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1520                                char *buf)
1521 {
1522         const gnutls_datum_t *d;
1523         size_t md5len = 16;
1524
1525         buf[0] = 0;
1526
1527         d = gnutls_certificate_get_ours(vpninfo->https_sess);
1528         if (!d)
1529                 return -EIO;
1530
1531         if (gnutls_fingerprint(GNUTLS_DIG_MD5, d, buf, &md5len))
1532                 return -EIO;
1533
1534         return 0;
1535 }
1536
1537 #ifdef HAVE_P11KIT
1538 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
1539                         const char *pin_description,
1540                         P11KitPinFlags flags,
1541                         void *_vpninfo)
1542 {
1543         struct openconnect_info *vpninfo = _vpninfo;
1544         struct pin_cache **cache = &vpninfo->pin_cache;
1545         struct oc_auth_form f;
1546         struct oc_form_opt o;
1547         char message[1024];
1548         char *uri;
1549         P11KitPin *pin;
1550         int ret;
1551
1552         if (!vpninfo || !vpninfo->process_auth_form)
1553                 return NULL;
1554
1555         if (p11_kit_uri_format(pin_uri, P11_KIT_URI_FOR_TOKEN, &uri))
1556                 return NULL;
1557         
1558         while (*cache) {
1559                 if (!strcmp(uri, (*cache)->token)) {
1560                         free(uri);
1561                         uri = NULL;
1562                         if ((*cache)->pin) {
1563                                 if ((flags & P11_KIT_PIN_FLAGS_RETRY) != P11_KIT_PIN_FLAGS_RETRY)
1564                                         return p11_kit_pin_new_for_string((*cache)->pin);
1565                                 memset((*cache)->pin, 0x5a, strlen((*cache)->pin));
1566                                 free((*cache)->pin);
1567                                 (*cache)->pin = NULL;
1568                         }
1569                         break;
1570                 }
1571         }
1572         if (!*cache) {
1573                 *cache = calloc(1, sizeof(struct pin_cache));
1574                 if (!*cache) {
1575                         free(uri);
1576                         return NULL;
1577                 }
1578                 (*cache)->token = uri;
1579         }
1580
1581         memset(&f, 0, sizeof(f));
1582         f.auth_id = (char *)"pkcs11_pin";
1583         f.opts = &o;
1584
1585         message[sizeof(message)-1] = 0;
1586         snprintf(message, sizeof(message) - 1, _("PIN required for %s"), pin_description);
1587         f.message = message;
1588         
1589         /* 
1590          * In p11-kit <= 0.12, these flags are *odd*.
1591          * RETRY is 0xa, FINAL_TRY is 0x14 and MANY_TRIES is 0x28.
1592          * So don't treat it like a sane bitmask. Fixed in
1593          * http://cgit.freedesktop.org/p11-glue/p11-kit/commit/?id=59774b11
1594          */
1595         if ((flags & P11_KIT_PIN_FLAGS_RETRY) == P11_KIT_PIN_FLAGS_RETRY)
1596                 f.error = (char *)_("Wrong PIN");
1597
1598         if ((flags & P11_KIT_PIN_FLAGS_FINAL_TRY) == P11_KIT_PIN_FLAGS_FINAL_TRY)
1599                 f.banner = (char *)_("This is the final try before locking!");
1600         else if ((flags & P11_KIT_PIN_FLAGS_MANY_TRIES) == P11_KIT_PIN_FLAGS_MANY_TRIES)
1601                 f.banner = (char *)_("Only a few tries left before locking!");
1602
1603         o.next = NULL;
1604         o.type = OC_FORM_OPT_PASSWORD;
1605         o.name = (char *)"pkcs11_pin";
1606         o.label = (char *)_("Enter PIN:");
1607         o.value = NULL;
1608
1609         ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
1610         if (ret || !o.value)
1611                 return NULL;
1612
1613         pin = p11_kit_pin_new_for_string(o.value);
1614         (*cache)->pin = o.value;
1615
1616         return pin;
1617 }
1618 #endif