2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2008-2012 Intel Corporation.
6 * Author: David Woodhouse <dwmw2@infradead.org>
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.
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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA
25 #include <sys/types.h>
27 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
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
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>
53 #include <trousers/tss.h>
54 #include <trousers/trousers.h>
57 #include <p11-kit/p11-kit.h>
58 #include <p11-kit/pkcs11.h>
59 #include <p11-kit/pin.h>
61 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
62 const char *pin_description,
68 #include "openconnect-internal.h"
70 /* Helper functions for reading/writing lines over SSL.
71 We could use cURL for the HTTP stuff, but it's overkill */
73 int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t len)
75 size_t orig_len = len;
78 int done = gnutls_record_send(vpninfo->https_sess, buf, len);
81 else if (done != GNUTLS_E_AGAIN) {
82 vpn_progress(vpninfo, PRG_ERR, _("Failed to write to SSL socket: %s"),
83 gnutls_strerror(done));
86 fd_set wr_set, rd_set;
87 int maxfd = vpninfo->ssl_fd;
92 if (gnutls_record_get_direction(vpninfo->https_sess))
93 FD_SET(vpninfo->ssl_fd, &wr_set);
95 FD_SET(vpninfo->ssl_fd, &rd_set);
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;
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"));
113 int openconnect_SSL_read(struct openconnect_info *vpninfo, char *buf, size_t len)
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;
121 if (done != GNUTLS_E_AGAIN) {
122 vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s"),
123 gnutls_strerror(done));
129 if (gnutls_record_get_direction(vpninfo->https_sess))
130 FD_SET(vpninfo->ssl_fd, &wr_set);
132 FD_SET(vpninfo->ssl_fd, &rd_set);
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;
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"));
150 int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
159 ret = gnutls_record_recv(vpninfo->https_sess, buf + i, 1);
161 if (buf[i] == '\n') {
163 if (i && buf[i-1] == '\r') {
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));
181 fd_set rd_set, wr_set;
182 int maxfd = vpninfo->ssl_fd;
187 if (gnutls_record_get_direction(vpninfo->https_sess))
188 FD_SET(vpninfo->ssl_fd, &wr_set);
190 FD_SET(vpninfo->ssl_fd, &rd_set);
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;
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"));
210 static int check_certificate_expiry(struct openconnect_info *vpninfo, gnutls_x509_crt_t cert)
212 const char *reason = NULL;
213 time_t expires = gnutls_x509_crt_get_expiration_time(cert);
214 time_t now = time(NULL);
217 vpn_progress(vpninfo, PRG_ERR,
218 _("Could not extract expiration time of certificate\n"));
223 reason = _("Client certificate has expired at");
224 else if (expires < now + vpninfo->cert_expire_warning)
225 reason = _("Client certificate expires soon at");
231 gmtime_r(&expires, &tm);
232 strftime(buf, 80, "%a, %d %b %Y %T %Z", &tm);
234 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, buf);
239 /* For systems that don't support O_CLOEXEC, just don't bother.
240 It's not open for long anyway. */
245 static int load_datum(struct openconnect_info *vpninfo,
246 gnutls_datum_t *datum, const char *fname)
251 fd = open(fname, O_RDONLY|O_CLOEXEC);
254 vpn_progress(vpninfo, PRG_ERR,
255 _("Failed to open key/certificate file %s: %s\n"),
256 fname, strerror(err));
259 if (fstat(fd, &st)) {
261 vpn_progress(vpninfo, PRG_ERR,
262 _("Failed to stat key/certificate file %s: %s\n"),
263 fname, strerror(err));
267 datum->size = st.st_size;
268 datum->data = gnutls_malloc(st.st_size + 1);
270 vpn_progress(vpninfo, PRG_ERR,
271 _("Failed to allocate certificate buffer\n"));
276 if (read(fd, datum->data, datum->size) != datum->size) {
278 vpn_progress(vpninfo, PRG_ERR,
279 _("Failed to read certificate into memory: %s\n"),
282 gnutls_free(datum->data);
285 datum->data[st.st_size] = 0;
290 /* A non-zero, non-error return to make load_certificate() continue and
291 interpreting the file as other types */
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)
307 err = gnutls_pkcs12_init(&p12);
309 vpn_progress(vpninfo, PRG_ERR,
310 _("Failed to setup PKCS#12 data structure: %s\n"),
311 gnutls_strerror(err));
315 err = gnutls_pkcs12_import(p12, datum, GNUTLS_X509_FMT_DER, 0);
317 gnutls_pkcs12_deinit(p12);
318 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN)
320 vpn_progress(vpninfo, PRG_ERR,
321 _("Failed to import PKCS#12 file: %s\n"),
322 gnutls_strerror(err));
326 pass = vpninfo->cert_password;
327 while ((err = gnutls_pkcs12_verify_mac(p12, pass)) == GNUTLS_E_MAC_VERIFY_FAILED) {
329 vpn_progress(vpninfo, PRG_ERR,
330 _("Failed to decrypt PKCS#12 certificate file\n"));
332 vpninfo->cert_password = NULL;
333 err = request_passphrase(vpninfo, "openconnect_pkcs12", &pass,
334 _("Enter PKCS#12 pass phrase:"));
336 gnutls_pkcs12_deinit(p12);
340 /* If it wasn't GNUTLS_E_MAC_VERIFY_FAILED, then the problem wasn't just a
341 bad password. Give up. */
346 gnutls_pkcs12_deinit(p12);
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... */
357 vpn_progress(vpninfo, level,
358 _("Failed to process PKCS#12 file: %s\n"),
359 gnutls_strerror(err));
362 err = gnutls_pkcs12_simple_parse(p12, pass, key, chain, chain_len,
363 extra_certs, extra_certs_len, crl, 0);
365 vpninfo->cert_password = NULL;
367 gnutls_pkcs12_deinit(p12);
369 vpn_progress(vpninfo, PRG_ERR,
370 _("Failed to load PKCS#12 certificate: %s\n"),
371 gnutls_strerror(err));
377 /* Older versions of GnuTLS didn't actually bother to check this, so we'll
379 static int check_issuer_sanity(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer)
381 #if GNUTLS_VERSION_NUMBER > 0x300014
384 unsigned char id1[512], id2[512];
385 size_t id1_size = 512, id2_size = 512;
388 err = gnutls_x509_crt_get_authority_key_id(cert, id1, &id1_size, NULL);
392 err = gnutls_x509_crt_get_subject_key_id(issuer, id2, &id2_size, NULL);
395 if (id1_size == id2_size && !memcmp(id1, id2, id1_size))
403 static int count_x509_certificates(gnutls_datum_t *datum)
406 char *p = (char *)datum->data;
409 p = strstr(p, "-----BEGIN ");
413 if (!strncmp(p, "CERTIFICATE", 11) ||
414 !strncmp(p, "X509 CERTIFICATE", 16))
420 static int get_cert_name(gnutls_x509_crt_t cert, char *name, size_t namelen)
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)) {
426 snprintf(name, namelen-1, "<unknown>");
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
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) {
444 struct openconnect_info *vpninfo = gnutls_session_get_ptr(sess);
445 int algo = GNUTLS_PK_RSA; /* TPM */
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);
455 for (i = 0; i < pk_algos_length; i++) {
456 if (algo == pk_algos[i])
459 if (i == pk_algos_length)
460 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
462 st->cert_type = GNUTLS_CRT_X509;
463 st->cert.x509 = vpninfo->my_certs;
464 st->ncerts = vpninfo->nr_my_certs;
470 /* For GnuTLS 2.12, this has to set the cert_callback to the function
471 above, which will return the pkey and certs on demand. Or in the
472 case of TPM we can't make a suitable pkey, so we have to set a
473 sign_callback too (which is done in openconnect_open_https() since
474 it has to be done on the *session*). */
475 static int assign_privkey(struct openconnect_info *vpninfo,
476 gnutls_privkey_t pkey,
477 gnutls_x509_crt_t *certs,
478 unsigned int nr_certs,
479 gnutls_x509_crt_t *extra_certs,
480 unsigned int nr_extra_certs)
484 vpninfo->my_certs = gnutls_calloc(nr_certs, sizeof(*certs));
485 if (!vpninfo->my_certs)
486 return GNUTLS_E_MEMORY_ERROR;
488 memcpy(vpninfo->my_certs, certs, nr_certs * sizeof(*certs));
489 vpninfo->nr_my_certs = nr_certs;
491 /* We are *keeping* the certs, unlike in GnuTLS 3 where we can
492 free them after calling gnutls_certificate_set_key(). So
493 first wipe the 'certs' array (which is either '&cert' or
494 'supporting_certs' in load_certificate())... */
495 memset(certs, 0, nr_certs * sizeof(*certs));
497 /* ... and then also zero out the entries in the extra_certs
498 array that correspond to certs that were added into the
499 supporting_certs array (but above the certs_to_free index).
501 The first one is 'cert', which was already stolen by the
502 load_certificate() function and put into our certs[0]..
504 for (i = 1; i < nr_certs; i++) {
506 for (j = 0; j < nr_extra_certs; j++) {
507 if (vpninfo->my_certs[i] == extra_certs[j]) {
508 extra_certs[j] = NULL;
514 gnutls_certificate_set_retrieve_function(vpninfo->https_cred,
516 vpninfo->my_pkey = pkey;
522 /* For GnuTLS 3+ this is saner than the GnuTLS 2.12 version. But still we
523 have to convert the array of X509 certificates to gnutls_pcert_st for
524 ourselves. There's no function that takes a gnutls_privkey_t as the key
525 and gnutls_x509_crt_t certificates. */
526 static int assign_privkey(struct openconnect_info *vpninfo,
527 gnutls_privkey_t pkey,
528 gnutls_x509_crt_t *certs,
529 unsigned int nr_certs,
530 gnutls_x509_crt_t *extra_certs,
531 unsigned int nr_extra_certs)
533 gnutls_pcert_st *pcerts = calloc(nr_certs, sizeof(*pcerts));
537 return GNUTLS_E_MEMORY_ERROR;
539 for (i=0 ; i < nr_certs; i++) {
540 err = gnutls_pcert_import_x509(pcerts + i, certs[i], 0);
542 vpn_progress(vpninfo, PRG_ERR,
543 _("Importing X509 certificate failed: %s\n"),
544 gnutls_strerror(err));
549 err = gnutls_certificate_set_key(vpninfo->https_cred, NULL, 0,
550 pcerts, nr_certs, pkey);
552 vpn_progress(vpninfo, PRG_ERR,
553 _("Setting PKCS#11 certificate failed: %s\n"),
554 gnutls_strerror(err));
556 for (i=0 ; i < nr_certs; i++)
557 gnutls_pcert_deinit(pcerts + i);
562 #endif /* !SET_KEY */
563 #endif /* (P11KIT || TROUSERS) */
565 static int load_certificate(struct openconnect_info *vpninfo)
567 gnutls_datum_t fdata;
568 gnutls_x509_privkey_t key = NULL;
569 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
570 gnutls_privkey_t pkey = NULL;
571 gnutls_datum_t pkey_sig = {NULL, 0};
572 void *dummy_hash_data = &load_certificate;
575 char *cert_url = (char *)vpninfo->cert;
576 char *key_url = (char *)vpninfo->sslkey;
577 gnutls_pkcs11_privkey_t p11key = NULL;
579 gnutls_x509_crl_t crl = NULL;
580 gnutls_x509_crt_t last_cert, cert = NULL;
581 gnutls_x509_crt_t *extra_certs = NULL, *supporting_certs = NULL;
582 unsigned int nr_supporting_certs = 0, nr_extra_certs = 0;
583 unsigned int certs_to_free = 0; /* How many of supporting_certs */
584 int err; /* GnuTLS error */
587 int cert_is_p11 = 0, key_is_p11 = 0;
588 unsigned char key_id[20];
589 size_t key_id_size = sizeof(key_id);
594 key_is_p11 = !strncmp(vpninfo->sslkey, "pkcs11:", 7);
595 cert_is_p11 = !strncmp(vpninfo->cert, "pkcs11:", 7);
597 /* Install PIN handler if either certificate or key are coming from PKCS#11 */
598 if (key_is_p11 || cert_is_p11) {
600 CK_OBJECT_CLASS class;
605 sprintf(pin_source, "openconnect:%p", vpninfo);
606 p11_kit_pin_register_callback(pin_source, pin_callback, vpninfo, NULL);
608 uri = p11_kit_uri_new();
610 attr.type = CKA_CLASS;
611 attr.pValue = &class;
612 attr.ulValueLen = sizeof(class);
614 /* Add appropriate pin-source and object-type attributes to
615 both certificate and key URLs, unless they already exist. */
617 !p11_kit_uri_parse(cert_url, P11_KIT_URI_FOR_OBJECT, uri)) {
618 if (!p11_kit_uri_get_pin_source(uri))
619 p11_kit_uri_set_pin_source(uri, pin_source);
620 if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
621 class = CKO_CERTIFICATE;
622 p11_kit_uri_set_attribute(uri, &attr);
624 p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &cert_url);
628 !p11_kit_uri_parse(key_url, P11_KIT_URI_FOR_OBJECT, uri)) {
629 if (!p11_kit_uri_get_pin_source(uri))
630 p11_kit_uri_set_pin_source(uri, pin_source);
631 if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
632 class = CKO_PRIVATE_KEY;
633 p11_kit_uri_set_attribute(uri, &attr);
635 p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &key_url);
638 p11_kit_uri_free(uri);
640 vpn_progress(vpninfo, PRG_ERR,
641 _("This binary built without PKCS#11 support\n"));
646 /* Load certificate(s) first... */
649 vpn_progress(vpninfo, PRG_TRACE,
650 _("Using PKCS#11 certificate %s\n"), cert_url);
652 err = gnutls_x509_crt_init(&cert);
657 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url, 0);
658 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
659 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url,
660 GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
662 vpn_progress(vpninfo, PRG_ERR,
663 _("Error loading certificate from PKCS#11: %s\n"),
664 gnutls_strerror(err));
670 #endif /* HAVE_P11KIT */
672 vpn_progress(vpninfo, PRG_TRACE,
673 _("Using certificate file %s\n"), vpninfo->cert);
675 ret = load_datum(vpninfo, &fdata, vpninfo->cert);
679 if (!key_is_p11 && (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
680 vpninfo->cert_type == CERT_TYPE_UNKNOWN)) {
681 /* PKCS#12 should actually contain certificates *and* private key */
682 ret = load_pkcs12_certificate(vpninfo, &fdata, &key,
683 &supporting_certs, &nr_supporting_certs,
684 &extra_certs, &nr_extra_certs,
689 if (nr_supporting_certs) {
690 cert = supporting_certs[0];
693 vpn_progress(vpninfo, PRG_ERR,
694 _("PKCS#11 file contained no certificate\n"));
699 /* It returned NOT_PKCS12.
700 Fall through to try PEM formats. */
703 /* We need to know how many there are in *advance*; it won't just allocate
704 the array for us :( */
705 nr_extra_certs = count_x509_certificates(&fdata);
707 nr_extra_certs = 1; /* wtf? Oh well, we'll fail later... */
709 extra_certs = calloc(nr_extra_certs, sizeof(cert));
715 err = gnutls_x509_crt_list_import(extra_certs, &nr_extra_certs, &fdata,
716 GNUTLS_X509_FMT_PEM, 0);
719 if (!err || err == GNUTLS_E_NO_CERTIFICATE_FOUND)
720 reason = _("No certificate found in file");
722 reason = gnutls_strerror(err);
724 vpn_progress(vpninfo, PRG_ERR,
725 _("Loading certificate failed: %s\n"),
730 nr_extra_certs = err;
735 /* Now we have the certificate(s) and we're looking for the private key... */
736 #if defined (HAVE_P11KIT)
738 vpn_progress(vpninfo, PRG_TRACE,
739 _("Using PKCS#11 key %s\n"), key_url);
741 err = gnutls_pkcs11_privkey_init(&p11key);
743 vpn_progress(vpninfo, PRG_ERR,
744 _("Error initialising PKCS#11 key structure: %s\n"),
745 gnutls_strerror(err));
750 err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0);
752 vpn_progress(vpninfo, PRG_ERR,
753 _("Error importing PKCS#11 URL %s: %s\n"),
754 key_url, gnutls_strerror(err));
755 gnutls_pkcs11_privkey_deinit(p11key);
760 err = gnutls_privkey_init(&pkey);
762 vpn_progress(vpninfo, PRG_ERR,
763 _("Error initialising private key structure: %s\n"),
764 gnutls_strerror(err));
765 gnutls_pkcs11_privkey_deinit(p11key);
770 err = gnutls_privkey_import_pkcs11(pkey, p11key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
772 vpn_progress(vpninfo, PRG_ERR,
773 _("Error importing PKCS#11 key into private key structure: %s\n"),
774 gnutls_strerror(err));
775 gnutls_pkcs11_privkey_deinit(p11key);
779 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
780 /* This can be set now and doesn't need to be separately freed.
781 It goes with the pkey. This is a PITA; it would be better
782 if there was a way to get the p11key *back* from a privkey
783 that we *know* is based on one. In fact, since this is only
784 for GnuTLS 2.12 and we *know* the gnutls_privkey_st won't
785 ever change there, so we *could* do something evil... but
787 vpninfo->my_p11key = p11key;
788 #endif /* !SET_KEY */
791 #endif /* HAVE_P11KIT */
793 /* We're loading the private key from a file. Load the file into memory
794 unless it's the same as the certificate and we already loaded that. */
795 if (!fdata.data || vpninfo->sslkey != vpninfo->cert) {
796 gnutls_free(fdata.data);
799 vpn_progress(vpninfo, PRG_TRACE,
800 _("Using private key file %s\n"), vpninfo->sslkey);
802 ret = load_datum(vpninfo, &fdata, vpninfo->sslkey);
807 if (vpninfo->cert_type == CERT_TYPE_TPM ||
808 (vpninfo->cert_type == CERT_TYPE_UNKNOWN &&
809 strstr((char *)fdata.data, "-----BEGIN TSS KEY BLOB-----"))) {
810 #ifndef HAVE_TROUSERS
811 vpn_progress(vpninfo, PRG_ERR,
812 _("This version of OpenConnect was built without TPM support\n"));
815 ret = load_tpm_key(vpninfo, &fdata, &pkey, &pkey_sig);
823 gnutls_x509_privkey_init(&key);
824 /* Try PKCS#1 (and PKCS#8 without password) first. GnuTLS doesn't
825 support OpenSSL's old PKCS#1-based encrypted format. We should
826 probably check for it and give a more coherent failure mode. */
827 err = gnutls_x509_privkey_import(key, &fdata, GNUTLS_X509_FMT_PEM);
829 /* If that fails, try PKCS#8 */
830 char *pass = vpninfo->cert_password;
832 /* Yay, just for fun this is *different* to PKCS#12. Where we could
833 try an empty password there, in this case the empty-password case
834 has already been *tried* by gnutls_x509_privkey_import(). If we
835 just call gnutls_x509_privkey_import_pkcs8() with a NULL password,
836 it'll SEGV. You have to set the GNUTLS_PKCS_PLAIN flag if you want
837 to try without a password. Passing NULL evidently isn't enough of
838 a hint. And in GnuTLS 3.1 where that crash has been fixed, passing
839 NULL will cause it to return GNUTLS_E_ENCRYPTED_STRUCTURE (a new
840 error code) rather than GNUTLS_E_DECRYPTION_FAILED. So just pass ""
841 instead of NULL, and don't worry about either case. */
842 while ((err = gnutls_x509_privkey_import_pkcs8(key, &fdata,
845 if (err != GNUTLS_E_DECRYPTION_FAILED) {
846 vpn_progress(vpninfo, PRG_ERR,
847 _("Failed to load private key as PKCS#8: %s\n"),
848 gnutls_strerror(err));
852 vpninfo->cert_password = NULL;
854 vpn_progress(vpninfo, PRG_ERR,
855 _("Failed to decrypt PKCS#8 certificate file\n"));
858 err = request_passphrase(vpninfo, "openconnect_pem",
859 &pass, _("Enter PEM pass phrase:"));
866 vpninfo->cert_password = NULL;
869 /* Now attempt to make sure we use the *correct* certificate, to match the key */
870 err = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size);
872 vpn_progress(vpninfo, PRG_ERR,
873 _("Failed to get key ID: %s\n"),
874 gnutls_strerror(err));
878 for (i = 0; i < (extra_certs?nr_extra_certs:1); i++) {
879 unsigned char cert_id[20];
880 size_t cert_id_size = sizeof(cert_id);
882 err = gnutls_x509_crt_get_key_id(extra_certs?extra_certs[i]:cert, 0, cert_id, &cert_id_size);
886 if (cert_id_size == key_id_size && !memcmp(cert_id, key_id, key_id_size)) {
888 cert = extra_certs[i];
890 /* Move the rest of the array down */
891 for (; i < nr_extra_certs - 1; i++)
892 extra_certs[i] = extra_certs[i+1];
899 /* There's no pkey (there's an x509 key), so we'll fall straight through the
900 * bit at match_cert: below, and go directly to the bit where it prints the
901 * 'no match found' error and exits. */
903 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
905 /* If we have a privkey from PKCS#11 or TPM, we can't do the simple comparison
906 of key ID that we do for software keys to find which certificate is a
907 match. So sign some dummy data and then check the signature against each
908 of the available certificates until we find the right one. */
910 /* The TPM code may have already signed it, to test authorisation. We
911 only sign here for PKCS#11 keys, in which case fdata might be
912 empty too so point it at dummy data. */
913 if (!pkey_sig.data) {
915 fdata.data = dummy_hash_data;
919 err = sign_dummy_data(vpninfo, pkey, &fdata, &pkey_sig);
921 vpn_progress(vpninfo, PRG_ERR,
922 _("Error signing test data with private key: %s\n"),
923 gnutls_strerror(err));
929 for (i=0; i < (extra_certs?nr_extra_certs:1); i++) {
930 gnutls_pubkey_t pubkey;
932 gnutls_pubkey_init(&pubkey);
933 err = gnutls_pubkey_import_x509(pubkey, extra_certs?extra_certs[i]:cert, 0);
935 vpn_progress(vpninfo, PRG_ERR,
936 _("Error validating signature against certificate: %s\n"),
937 gnutls_strerror(err));
938 /* We'll probably fail shortly if we don't find it. */
939 gnutls_pubkey_deinit(pubkey);
942 err = gnutls_pubkey_verify_data(pubkey, 0, &fdata, &pkey_sig);
943 gnutls_pubkey_deinit(pubkey);
947 cert = extra_certs[i];
949 /* Move the rest of the array down */
950 for (; i < nr_extra_certs - 1; i++)
951 extra_certs[i] = extra_certs[i+1];
955 gnutls_free(pkey_sig.data);
959 gnutls_free(pkey_sig.data);
961 #endif /* P11KIT || TROUSERS */
963 /* We shouldn't reach this. It means that we didn't find *any* matching cert */
964 vpn_progress(vpninfo, PRG_ERR,
965 _("No SSL certificate found to match private key\n"));
969 /********************************************************************/
971 /* Now we have both cert(s) and key, and we should be ready to go. */
972 check_certificate_expiry(vpninfo, cert);
973 get_cert_name(cert, name, sizeof(name));
974 vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"),
978 err = gnutls_certificate_set_x509_crl(vpninfo->https_cred, &crl, 1);
980 vpn_progress(vpninfo, PRG_ERR,
981 _("Setting certificate recovation list failed: %s\n"),
982 gnutls_strerror(err));
988 /* OpenSSL has problems with certificate chains — if there are
989 multiple certs with the same name, it doesn't necessarily
990 choose the _right_ one. (RT#1942)
991 Pick the right ones for ourselves and add them manually. */
993 if (nr_supporting_certs) {
994 /* We already got a bunch of certs from PKCS#12 file.
995 Remember how many need to be freed when we're done,
996 since we'll expand the supporting_certs array with
997 more from the cafile if we can. */
998 last_cert = supporting_certs[nr_supporting_certs-1];
999 certs_to_free = nr_supporting_certs;
1002 certs_to_free = nr_supporting_certs = 1;
1005 gnutls_x509_crt_t issuer;
1007 for (i = 0; i < nr_extra_certs; i++) {
1008 if (gnutls_x509_crt_check_issuer(last_cert, extra_certs[i]) &&
1009 !check_issuer_sanity(last_cert, extra_certs[i]))
1013 if (i < nr_extra_certs) {
1014 issuer = extra_certs[i];
1016 err = gnutls_certificate_get_issuer(vpninfo->https_cred,
1017 last_cert, &issuer, 0);
1022 /* The check_issuer_sanity() function works fine as a workaround where
1023 it was used above, but when gnutls_certificate_get_issuer() returns
1024 a bogus cert, there's nothing we can do to fix it up. We don't get
1025 to iterate over all the available certs like we can over our own
1027 if (check_issuer_sanity(last_cert, issuer)) {
1028 /* Hm, is there a bug reference for this? Or just the git commit
1029 reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
1030 vpn_progress(vpninfo, PRG_ERR,
1031 _("WARNING: GnuTLS returned incorrect issuer certs; authentication may fail!\n"));
1035 if (issuer == last_cert) {
1036 /* Don't actually include the root CA. If they don't already trust it,
1037 then handing it to them isn't going to help. But don't omit the
1038 original certificate if it's self-signed. */
1039 if (nr_supporting_certs > 1)
1040 nr_supporting_certs--;
1044 /* OK, we found a new cert to add to our chain. */
1045 supporting_certs = gnutls_realloc(supporting_certs,
1046 sizeof(cert) * ++nr_supporting_certs);
1047 if (!supporting_certs) {
1048 vpn_progress(vpninfo, PRG_ERR,
1049 _("Failed to allocate memory for supporting certificates\n"));
1050 /* The world is probably about to end, but try without them anyway */
1056 /* First time we actually allocated an array? Copy the first cert into it */
1057 if (nr_supporting_certs == 2)
1058 supporting_certs[0] = cert;
1060 /* Append the new one */
1061 supporting_certs[nr_supporting_certs-1] = issuer;
1065 for (i = 1; i < nr_supporting_certs; i++) {
1066 get_cert_name(supporting_certs[i], name, sizeof(name));
1068 vpn_progress(vpninfo, PRG_DEBUG,
1069 _("Adding supporting CA '%s'\n"), name);
1072 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1074 err = assign_privkey(vpninfo, pkey,
1075 supporting_certs?:&cert, nr_supporting_certs,
1076 extra_certs, nr_extra_certs);
1081 pkey = NULL; /* we gave it away, along with pcerts */
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,
1090 vpn_progress(vpninfo, PRG_ERR,
1091 _("Setting certificate failed: %s\n"),
1092 gnutls_strerror(err));
1098 gnutls_x509_crl_deinit(crl);
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]);
1106 gnutls_free(supporting_certs);
1108 /* Not if supporting_certs. It's supporting_certs[0] then and
1109 was already freed. */
1110 gnutls_x509_crt_deinit(cert);
1112 for (i = 0; i < nr_extra_certs; i++) {
1114 gnutls_x509_crt_deinit(extra_certs[i]);
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);
1124 if (cert_url != vpninfo->cert)
1126 if (key_url != vpninfo->sslkey)
1132 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
1133 gnutls_x509_crt_t cert,
1134 gnutls_digest_algorithm_t algo,
1137 unsigned char md[256];
1138 size_t md_size = sizeof(md);
1141 if (gnutls_x509_crt_get_fingerprint(cert, algo, md, &md_size))
1144 for (i=0; i < md_size; i++)
1145 sprintf(&buf[i*2], "%02X", md[i]);
1150 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
1151 OPENCONNECT_X509 *cert, char *buf)
1153 return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_MD5, buf);
1156 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
1157 OPENCONNECT_X509 *cert, char *buf)
1159 return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_SHA1, buf);
1162 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1163 OPENCONNECT_X509 *cert)
1168 if (gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &buf))
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);
1178 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
1179 OPENCONNECT_X509 *cert, unsigned char **buf)
1182 unsigned char *ret = NULL;
1184 if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l) !=
1185 GNUTLS_E_SHORT_MEMORY_BUFFER)
1192 if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l)) {
1200 static int verify_peer(gnutls_session_t session)
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;
1209 if (vpninfo->peer_cert) {
1210 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1211 vpninfo->peer_cert = NULL;
1214 cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
1216 vpn_progress(vpninfo, PRG_ERR, _("Server presented no certificate\n"));
1217 return GNUTLS_E_CERTIFICATE_ERROR;
1220 if (vpninfo->servercert) {
1221 unsigned char sha1bin[SHA1_SIZE];
1222 char fingerprint[(SHA1_SIZE * 2) + 1];
1225 err = openconnect_sha1(sha1bin, cert_list[0].data, cert_list[0].size);
1227 vpn_progress(vpninfo, PRG_ERR,
1228 _("Could not calculate SHA1 of server's certificate\n"));
1229 return GNUTLS_E_CERTIFICATE_ERROR;
1231 for (i=0; i < SHA1_SIZE; i++)
1232 sprintf(&fingerprint[i*2], "%02X", sha1bin[i]);
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;
1242 err = gnutls_certificate_verify_peers2 (session, &status);
1244 vpn_progress(vpninfo, PRG_ERR, _("Error checking server cert status\n"));
1245 return GNUTLS_E_CERTIFICATE_ERROR;
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");
1266 err = gnutls_x509_crt_init(&cert);
1268 vpn_progress(vpninfo, PRG_ERR, _("Error initialising X509 cert structure\n"));
1269 return GNUTLS_E_CERTIFICATE_ERROR;
1272 err = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
1274 vpn_progress(vpninfo, PRG_ERR, _("Error importing server's cert\n"));
1275 gnutls_x509_crt_deinit(cert);
1276 return GNUTLS_E_CERTIFICATE_ERROR;
1279 if (!reason && !gnutls_x509_crt_check_hostname(cert, vpninfo->hostname))
1280 reason = _("certificate does not match hostname");
1283 vpn_progress(vpninfo, PRG_INFO, "Server certificate verify failed: %s\n",
1285 if (vpninfo->validate_peer_cert)
1286 err = vpninfo->validate_peer_cert(vpninfo->cbdata,
1288 reason) ? GNUTLS_E_CERTIFICATE_ERROR : 0;
1290 err = GNUTLS_E_CERTIFICATE_ERROR;
1293 vpninfo->peer_cert = cert;
1299 int openconnect_open_https(struct openconnect_info *vpninfo)
1304 if (vpninfo->https_sess)
1307 ssl_sock = connect_https_socket(vpninfo);
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);
1316 gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1317 "/etc/pki/tls/certs/ca-bundle.crt",
1318 GNUTLS_X509_FMT_PEM);
1320 gnutls_certificate_set_verify_function (vpninfo->https_cred,
1323 if (vpninfo->cafile) {
1324 err = gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1326 GNUTLS_X509_FMT_PEM);
1328 vpn_progress(vpninfo, PRG_ERR,
1329 _("Failed to open CA file '%s': %s\n"),
1330 vpninfo->cafile, gnutls_strerror(err));
1336 if (vpninfo->cert) {
1337 err = load_certificate(vpninfo);
1339 vpn_progress(vpninfo, PRG_ERR,
1340 _("Loading certificate failed. Aborting.\n"));
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);
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);
1353 vpn_progress(vpninfo, PRG_ERR,
1354 _("Failed to set TLS priority string: %s\n"),
1355 gnutls_strerror(err));
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);
1363 vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
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;
1374 if (gnutls_record_get_direction(vpninfo->https_sess))
1375 FD_SET(ssl_sock, &wr_set);
1377 FD_SET(ssl_sock, &rd_set);
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;
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;
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;
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));
1408 vpninfo->ssl_fd = ssl_sock;
1410 vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1416 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1418 if (vpninfo->peer_cert) {
1419 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1420 vpninfo->peer_cert = NULL;
1422 if (vpninfo->https_sess) {
1423 gnutls_deinit(vpninfo->https_sess);
1424 vpninfo->https_sess = NULL;
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;
1433 if (final && vpninfo->https_cred) {
1434 gnutls_certificate_free_credentials(vpninfo->https_cred);
1435 vpninfo->https_cred = NULL;
1437 if (!strncmp(vpninfo->cert, "pkcs11:", 7) ||
1438 !strncmp(vpninfo->sslkey, "pkcs11:", 7)) {
1439 char pin_source[40];
1441 sprintf(pin_source, "openconnect:%p", vpninfo);
1442 p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
1444 while (vpninfo->pin_cache) {
1445 struct pin_cache *cache = vpninfo->pin_cache;
1448 memset(cache->pin, 0x5a, strlen(cache->pin));
1450 vpninfo->pin_cache = cache->next;
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;
1460 if (vpninfo->tpm_key) {
1461 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key);
1462 vpninfo->tpm_key = 0;
1464 if (vpninfo->srk_policy) {
1465 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
1466 vpninfo->srk_policy = 0;
1469 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
1472 if (vpninfo->tpm_context) {
1473 Tspi_Context_Close(vpninfo->tpm_context);
1474 vpninfo->tpm_context = 0;
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 */
1483 if (vpninfo->my_certs) {
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;
1494 void openconnect_init_ssl(void)
1496 gnutls_global_init();
1499 int openconnect_sha1(unsigned char *result, void *data, int datalen)
1502 size_t shalen = SHA1_SIZE;
1506 if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, result, &shalen))
1512 int openconnect_random(void *bytes, int len)
1514 if (gnutls_rnd(GNUTLS_RND_RANDOM, bytes, len))
1519 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1522 const gnutls_datum_t *d;
1527 d = gnutls_certificate_get_ours(vpninfo->https_sess);
1531 if (gnutls_fingerprint(GNUTLS_DIG_MD5, d, buf, &md5len))
1538 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
1539 const char *pin_description,
1540 P11KitPinFlags flags,
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;
1552 if (!vpninfo || !vpninfo->process_auth_form)
1555 if (p11_kit_uri_format(pin_uri, P11_KIT_URI_FOR_TOKEN, &uri))
1559 if (!strcmp(uri, (*cache)->token)) {
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;
1573 *cache = calloc(1, sizeof(struct pin_cache));
1578 (*cache)->token = uri;
1581 memset(&f, 0, sizeof(f));
1582 f.auth_id = (char *)"pkcs11_pin";
1585 message[sizeof(message)-1] = 0;
1586 snprintf(message, sizeof(message) - 1, _("PIN required for %s"), pin_description);
1587 f.message = message;
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
1595 if ((flags & P11_KIT_PIN_FLAGS_RETRY) == P11_KIT_PIN_FLAGS_RETRY)
1596 f.error = (char *)_("Wrong PIN");
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!");
1604 o.type = OC_FORM_OPT_PASSWORD;
1605 o.name = (char *)"pkcs11_pin";
1606 o.label = (char *)_("Enter PIN:");
1609 ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
1610 if (ret || !o.value)
1613 pin = p11_kit_pin_new_for_string(o.value);
1614 (*cache)->pin = o.value;