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 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)
479 vpninfo->my_certs = gnutls_calloc(nr_certs, sizeof(*certs));
480 if (!vpninfo->my_certs)
481 return GNUTLS_E_MEMORY_ERROR;
483 memcpy(vpninfo->my_certs, certs, nr_certs * sizeof(*certs));
484 vpninfo->nr_my_certs = nr_certs;
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));
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).
496 The first one is 'cert', which was already stolen by the
497 load_certificate() function and put into our certs[0]..
499 for (i = 1; i < nr_certs; i++) {
501 for (j = 0; j < nr_extra_certs; j++) {
502 if (vpninfo->my_certs[i] == extra_certs[j]) {
503 extra_certs[j] = NULL;
509 gnutls_certificate_set_retrieve_function(vpninfo->https_cred,
511 vpninfo->my_pkey = pkey;
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)
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));
530 return GNUTLS_E_MEMORY_ERROR;
532 for (i=0 ; i < nr_certs; i++) {
533 err = gnutls_pcert_import_x509(pcerts + i, certs[i], 0);
535 vpn_progress(vpninfo, PRG_ERR,
536 _("Importing X509 certificate failed: %s\n"),
537 gnutls_strerror(err));
542 err = gnutls_certificate_set_key(vpninfo->https_cred, NULL, 0,
543 pcerts, nr_certs, pkey);
545 vpn_progress(vpninfo, PRG_ERR,
546 _("Setting PKCS#11 certificate failed: %s\n"),
547 gnutls_strerror(err));
549 for (i=0 ; i < nr_certs; i++)
550 gnutls_pcert_deinit(pcerts + i);
555 #endif /* !SET_KEY */
556 #endif /* (P11KIT || TROUSERS) */
558 static int load_certificate(struct openconnect_info *vpninfo)
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;
568 char *cert_url = (char *)vpninfo->cert;
569 char *key_url = (char *)vpninfo->sslkey;
570 gnutls_pkcs11_privkey_t p11key = NULL;
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 */
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);
587 key_is_p11 = !strncmp(vpninfo->sslkey, "pkcs11:", 7);
588 cert_is_p11 = !strncmp(vpninfo->cert, "pkcs11:", 7);
590 /* Install PIN handler if either certificate or key are coming from PKCS#11 */
591 if (key_is_p11 || cert_is_p11) {
593 CK_OBJECT_CLASS class;
598 sprintf(pin_source, "openconnect:%p", vpninfo);
599 p11_kit_pin_register_callback(pin_source, pin_callback, vpninfo, NULL);
601 uri = p11_kit_uri_new();
603 attr.type = CKA_CLASS;
604 attr.pValue = &class;
605 attr.ulValueLen = sizeof(class);
607 /* Add appropriate pin-source and object-type attributes to
608 both certificate and key URLs, unless they already exist. */
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);
617 p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &cert_url);
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);
628 p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &key_url);
631 p11_kit_uri_free(uri);
633 vpn_progress(vpninfo, PRG_ERR,
634 _("This binary built without PKCS#11 support\n"));
639 /* Load certificate(s) first... */
642 vpn_progress(vpninfo, PRG_TRACE,
643 _("Using PKCS#11 certificate %s\n"), cert_url);
645 err = gnutls_x509_crt_init(&cert);
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);
655 vpn_progress(vpninfo, PRG_ERR,
656 _("Error loading certificate from PKCS#11: %s\n"),
657 gnutls_strerror(err));
663 #endif /* HAVE_P11KIT */
665 vpn_progress(vpninfo, PRG_TRACE,
666 _("Using certificate file %s\n"), vpninfo->cert);
668 ret = load_datum(vpninfo, &fdata, vpninfo->cert);
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,
682 if (nr_supporting_certs) {
683 cert = supporting_certs[0];
686 vpn_progress(vpninfo, PRG_ERR,
687 _("PKCS#11 file contained no certificate\n"));
692 /* It returned NOT_PKCS12.
693 Fall through to try PEM formats. */
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);
700 nr_extra_certs = 1; /* wtf? Oh well, we'll fail later... */
702 extra_certs = calloc(nr_extra_certs, sizeof(cert));
708 err = gnutls_x509_crt_list_import(extra_certs, &nr_extra_certs, &fdata,
709 GNUTLS_X509_FMT_PEM, 0);
712 if (!err || err == GNUTLS_E_NO_CERTIFICATE_FOUND)
713 reason = _("No certificate found in file");
715 reason = gnutls_strerror(err);
717 vpn_progress(vpninfo, PRG_ERR,
718 _("Loading certificate failed: %s\n"),
723 nr_extra_certs = err;
728 /* Now we have the certificate(s) and we're looking for the private key... */
729 #if defined (HAVE_P11KIT)
731 vpn_progress(vpninfo, PRG_TRACE,
732 _("Using PKCS#11 key %s\n"), key_url);
734 err = gnutls_pkcs11_privkey_init(&p11key);
736 vpn_progress(vpninfo, PRG_ERR,
737 _("Error initialising PKCS#11 key structure: %s\n"),
738 gnutls_strerror(err));
743 err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0);
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);
753 err = gnutls_privkey_init(&pkey);
755 vpn_progress(vpninfo, PRG_ERR,
756 _("Error initialising private key structure: %s\n"),
757 gnutls_strerror(err));
758 gnutls_pkcs11_privkey_deinit(p11key);
763 err = gnutls_privkey_import_pkcs11(pkey, p11key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
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);
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
780 vpninfo->my_p11key = p11key;
781 #endif /* !SET_KEY */
784 #endif /* HAVE_P11KIT */
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);
792 vpn_progress(vpninfo, PRG_TRACE,
793 _("Using private key file %s\n"), vpninfo->sslkey);
795 ret = load_datum(vpninfo, &fdata, vpninfo->sslkey);
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"));
808 ret = load_tpm_key(vpninfo, &fdata, &pkey, &pkey_sig);
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);
822 /* If that fails, try PKCS#8 */
823 char *pass = vpninfo->cert_password;
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,
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));
845 vpninfo->cert_password = NULL;
847 vpn_progress(vpninfo, PRG_ERR,
848 _("Failed to decrypt PKCS#8 certificate file\n"));
851 err = request_passphrase(vpninfo, "openconnect_pem",
852 &pass, _("Enter PEM pass phrase:"));
859 vpninfo->cert_password = NULL;
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);
865 vpn_progress(vpninfo, PRG_ERR,
866 _("Failed to get key ID: %s\n"),
867 gnutls_strerror(err));
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);
875 err = gnutls_x509_crt_get_key_id(extra_certs?extra_certs[i]:cert, 0, cert_id, &cert_id_size);
879 if (cert_id_size == key_id_size && !memcmp(cert_id, key_id, key_id_size)) {
881 cert = extra_certs[i];
883 /* Move the rest of the array down */
884 for (; i < nr_extra_certs - 1; i++)
885 extra_certs[i] = extra_certs[i+1];
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. */
896 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
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. */
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) {
908 fdata.data = dummy_hash_data;
912 err = sign_dummy_data(vpninfo, pkey, &fdata, &pkey_sig);
914 vpn_progress(vpninfo, PRG_ERR,
915 _("Error signing test data with private key: %s\n"),
916 gnutls_strerror(err));
922 for (i=0; i < (extra_certs?nr_extra_certs:1); i++) {
923 gnutls_pubkey_t pubkey;
925 gnutls_pubkey_init(&pubkey);
926 err = gnutls_pubkey_import_x509(pubkey, extra_certs?extra_certs[i]:cert, 0);
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);
935 err = gnutls_pubkey_verify_data(pubkey, 0, &fdata, &pkey_sig);
936 gnutls_pubkey_deinit(pubkey);
940 cert = extra_certs[i];
942 /* Move the rest of the array down */
943 for (; i < nr_extra_certs - 1; i++)
944 extra_certs[i] = extra_certs[i+1];
948 gnutls_free(pkey_sig.data);
952 gnutls_free(pkey_sig.data);
954 #endif /* P11KIT || TROUSERS */
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"));
962 /********************************************************************/
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"),
971 err = gnutls_certificate_set_x509_crl(vpninfo->https_cred, &crl, 1);
973 vpn_progress(vpninfo, PRG_ERR,
974 _("Setting certificate recovation list failed: %s\n"),
975 gnutls_strerror(err));
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. */
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;
995 certs_to_free = nr_supporting_certs = 1;
998 gnutls_x509_crt_t issuer;
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]))
1006 if (i < nr_extra_certs) {
1007 issuer = extra_certs[i];
1009 err = gnutls_certificate_get_issuer(vpninfo->https_cred,
1010 last_cert, &issuer, 0);
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
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"));
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--;
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 */
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;
1053 /* Append the new one */
1054 supporting_certs[nr_supporting_certs-1] = issuer;
1058 for (i = 1; i < nr_supporting_certs; i++) {
1059 get_cert_name(supporting_certs[i], name, sizeof(name));
1061 vpn_progress(vpninfo, PRG_DEBUG,
1062 _("Adding supporting CA '%s'\n"), name);
1065 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1067 #if defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY)
1068 err = assign_privkey_gtls3(vpninfo, pkey, supporting_certs?:&cert, nr_supporting_certs);
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);
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;