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 #include <gnutls/gnutls.h>
41 #include <gnutls/x509.h>
42 #include <gnutls/crypto.h>
43 #include <gnutls/pkcs12.h>
44 #include <gnutls/abstract.h>
47 #include <trousers/tss.h>
48 #include <trousers/trousers.h>
51 #include <p11-kit/p11-kit.h>
52 #include <p11-kit/pkcs11.h>
53 #include <p11-kit/pin.h>
55 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
56 const char *pin_description,
61 #include "openconnect-internal.h"
63 /* Helper functions for reading/writing lines over SSL.
64 We could use cURL for the HTTP stuff, but it's overkill */
66 int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t len)
68 size_t orig_len = len;
71 int done = gnutls_record_send(vpninfo->https_sess, buf, len);
74 else if (done != GNUTLS_E_AGAIN) {
75 vpn_progress(vpninfo, PRG_ERR, _("Failed to write to SSL socket: %s"),
76 gnutls_strerror(done));
79 fd_set wr_set, rd_set;
80 int maxfd = vpninfo->ssl_fd;
85 if (gnutls_record_get_direction(vpninfo->https_sess))
86 FD_SET(vpninfo->ssl_fd, &wr_set);
88 FD_SET(vpninfo->ssl_fd, &rd_set);
90 if (vpninfo->cancel_fd != -1) {
91 FD_SET(vpninfo->cancel_fd, &rd_set);
92 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
93 maxfd = vpninfo->cancel_fd;
95 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
96 if (vpninfo->cancel_fd != -1 &&
97 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
98 vpn_progress(vpninfo, PRG_ERR, _("SSL write cancelled\n"));
106 int openconnect_SSL_read(struct openconnect_info *vpninfo, char *buf, size_t len)
110 while ((done = gnutls_record_recv(vpninfo->https_sess, buf, len)) < 0) {
111 fd_set wr_set, rd_set;
112 int maxfd = vpninfo->ssl_fd;
114 if (done != GNUTLS_E_AGAIN) {
115 vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s"),
116 gnutls_strerror(done));
122 if (gnutls_record_get_direction(vpninfo->https_sess))
123 FD_SET(vpninfo->ssl_fd, &wr_set);
125 FD_SET(vpninfo->ssl_fd, &rd_set);
127 if (vpninfo->cancel_fd != -1) {
128 FD_SET(vpninfo->cancel_fd, &rd_set);
129 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
130 maxfd = vpninfo->cancel_fd;
132 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
133 if (vpninfo->cancel_fd != -1 &&
134 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
135 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
143 int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
152 ret = gnutls_record_recv(vpninfo->https_sess, buf + i, 1);
154 if (buf[i] == '\n') {
156 if (i && buf[i-1] == '\r') {
168 } else if (ret != GNUTLS_E_AGAIN) {
169 vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s\n"),
170 gnutls_strerror(ret));
174 fd_set rd_set, wr_set;
175 int maxfd = vpninfo->ssl_fd;
180 if (gnutls_record_get_direction(vpninfo->https_sess))
181 FD_SET(vpninfo->ssl_fd, &wr_set);
183 FD_SET(vpninfo->ssl_fd, &rd_set);
185 if (vpninfo->cancel_fd != -1) {
186 FD_SET(vpninfo->cancel_fd, &rd_set);
187 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
188 maxfd = vpninfo->cancel_fd;
190 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
191 if (vpninfo->cancel_fd != -1 &&
192 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
193 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
203 static int check_certificate_expiry(struct openconnect_info *vpninfo, gnutls_x509_crt_t cert)
205 const char *reason = NULL;
206 time_t expires = gnutls_x509_crt_get_expiration_time(cert);
207 time_t now = time(NULL);
210 vpn_progress(vpninfo, PRG_ERR,
211 _("Could not extract expiration time of certificate\n"));
216 reason = _("Client certificate has expired at");
217 else if (expires < now + vpninfo->cert_expire_warning)
218 reason = _("Client certificate expires soon at");
224 gmtime_r(&expires, &tm);
225 strftime(buf, 80, "%a, %d %b %Y %T %Z", &tm);
227 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, buf);
232 /* For systems that don't support O_CLOEXEC, just don't bother.
233 It's not open for long anyway. */
238 static int load_datum(struct openconnect_info *vpninfo,
239 gnutls_datum_t *datum, const char *fname)
244 fd = open(fname, O_RDONLY|O_CLOEXEC);
247 vpn_progress(vpninfo, PRG_ERR,
248 _("Failed to open key/certificate file %s: %s\n"),
249 fname, strerror(err));
252 if (fstat(fd, &st)) {
254 vpn_progress(vpninfo, PRG_ERR,
255 _("Failed to stat key/certificate file %s: %s\n"),
256 fname, strerror(err));
260 datum->size = st.st_size;
261 datum->data = gnutls_malloc(st.st_size + 1);
263 vpn_progress(vpninfo, PRG_ERR,
264 _("Failed to allocate certificate buffer\n"));
269 if (read(fd, datum->data, datum->size) != datum->size) {
271 vpn_progress(vpninfo, PRG_ERR,
272 _("Failed to read certificate into memory: %s\n"),
275 gnutls_free(datum->data);
278 datum->data[st.st_size] = 0;
283 #ifndef HAVE_GNUTLS_PKCS12_SIMPLE_PARSE
284 /* If we're using a version of GnuTLS from before this was
285 exported, pull in our local copy. */
286 #include "gnutls_pkcs12.c"
289 /* A non-zero, non-error return to make load_certificate() continue and
290 interpreting the file as other types */
293 static int load_pkcs12_certificate(struct openconnect_info *vpninfo,
294 gnutls_datum_t *datum,
295 gnutls_x509_privkey_t *key,
296 gnutls_x509_crt_t **chain,
297 unsigned int *chain_len,
298 gnutls_x509_crt_t **extra_certs,
299 unsigned int *extra_certs_len,
300 gnutls_x509_crl_t *crl)
306 err = gnutls_pkcs12_init(&p12);
308 vpn_progress(vpninfo, PRG_ERR,
309 _("Failed to setup PKCS#12 data structure: %s\n"),
310 gnutls_strerror(err));
314 err = gnutls_pkcs12_import(p12, datum, GNUTLS_X509_FMT_DER, 0);
316 gnutls_pkcs12_deinit(p12);
317 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN)
319 vpn_progress(vpninfo, PRG_ERR,
320 _("Failed to import PKCS#12 file: %s\n"),
321 gnutls_strerror(err));
325 pass = vpninfo->cert_password;
326 while ((err = gnutls_pkcs12_verify_mac(p12, pass)) == GNUTLS_E_MAC_VERIFY_FAILED) {
328 vpn_progress(vpninfo, PRG_ERR,
329 _("Failed to decrypt PKCS#12 certificate file\n"));
331 vpninfo->cert_password = NULL;
332 err = request_passphrase(vpninfo, &pass,
333 _("Enter PKCS#12 pass phrase:"));
335 gnutls_pkcs12_deinit(p12);
339 /* If it wasn't GNUTLS_E_MAC_VERIFY_FAILED, then the problem wasn't just a
340 bad password. Give up. */
345 gnutls_pkcs12_deinit(p12);
347 /* If the first attempt, and we didn't know for sure it was PKCS#12
348 anyway, bail out and try loading it as something different. */
349 if (pass == vpninfo->cert_password &&
350 vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
351 /* Make it non-fatal... */
356 vpn_progress(vpninfo, level,
357 _("Failed to process PKCS#12 file: %s\n"),
358 gnutls_strerror(err));
361 err = gnutls_pkcs12_simple_parse(p12, pass, key, chain, chain_len,
362 extra_certs, extra_certs_len, crl, 0);
364 vpninfo->cert_password = NULL;
366 gnutls_pkcs12_deinit(p12);
368 vpn_progress(vpninfo, PRG_ERR,
369 _("Failed to load PKCS#12 certificate: %s\n"),
370 gnutls_strerror(err));
376 /* Older versions of GnuTLS didn't actually bother to check this, so we'll
378 static int check_issuer_sanity(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer)
380 #if GNUTLS_VERSION_NUMBER > 0x300014
383 unsigned char id1[512], id2[512];
384 size_t id1_size = 512, id2_size = 512;
387 err = gnutls_x509_crt_get_authority_key_id(cert, id1, &id1_size, NULL);
391 err = gnutls_x509_crt_get_subject_key_id(issuer, id2, &id2_size, NULL);
394 if (id1_size == id2_size && !memcmp(id1, id2, id1_size))
402 static int count_x509_certificates(gnutls_datum_t *datum)
405 char *p = (char *)datum->data;
408 p = strstr(p, "-----BEGIN ");
412 if (!strncmp(p, "CERTIFICATE", 11) ||
413 !strncmp(p, "X509 CERTIFICATE", 16))
419 static int get_cert_name(gnutls_x509_crt_t cert, char *name, size_t namelen)
421 if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME,
422 0, 0, name, &namelen) &&
423 gnutls_x509_crt_get_dn(cert, name, &namelen)) {
425 snprintf(name, namelen-1, "<unknown>");
433 /* TPM code based on client-tpm.c from Carolin Latze <latze@angry-red-pla.net>
435 static int tpm_sign_fn(gnutls_privkey_t key, void *_vpninfo,
436 const gnutls_datum_t *data, gnutls_datum_t *sig)
438 struct openconnect_info *vpninfo = _vpninfo;
442 vpn_progress(vpninfo, PRG_TRACE,
443 _("TPM sign function called for %d bytes.\n"),
446 err = Tspi_Context_CreateObject(vpninfo->tpm_context, TSS_OBJECT_TYPE_HASH,
447 TSS_HASH_OTHER, &hash);
449 vpn_progress(vpninfo, PRG_ERR,
450 _("Failed to create TPM hash object.\n"));
451 return GNUTLS_E_PK_SIGN_FAILED;
453 err = Tspi_Hash_SetHashValue(hash, data->size, data->data);
455 vpn_progress(vpninfo, PRG_ERR,
456 _("Failed to set value in TPM hash object.\n"));
457 Tspi_Context_CloseObject(vpninfo->tpm_context, hash);
458 return GNUTLS_E_PK_SIGN_FAILED;
460 err = Tspi_Hash_Sign(hash, vpninfo->tpm_key, &sig->size, &sig->data);
461 Tspi_Context_CloseObject(vpninfo->tpm_context, hash);
463 vpn_progress(vpninfo, PRG_ERR,
464 _("TPM hash signature failed\n"));
465 return GNUTLS_E_PK_SIGN_FAILED;
470 static int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, gnutls_privkey_t *pkey)
472 static const TSS_UUID SRK_UUID = TSS_UUID_SRK;
474 unsigned int tss_len;
478 err = gnutls_pem_base64_decode_alloc("TSS KEY BLOB", fdata, &asn1);
480 vpn_progress(vpninfo, PRG_ERR,
481 _("Error decoding TSS key blob: %s\n"),
482 gnutls_strerror(err));
485 /* Ick. We have to parse the ASN1 OCTET_STRING for ourselves. */
486 if (asn1.size < 2 || asn1.data[0] != 0x04 /* OCTET_STRING */) {
487 vpn_progress(vpninfo, PRG_ERR,
488 _("Error in TSS key blob\n"));
492 tss_len = asn1.data[1];
494 if (tss_len & 0x80) {
495 int lenlen = tss_len & 0x7f;
497 if (asn1.size < 2 + lenlen || lenlen > 3) {
498 vpn_progress(vpninfo, PRG_ERR,
499 _("Error in TSS key blob\n"));
506 tss_len |= asn1.data[ofs++];
510 if (tss_len + ofs != asn1.size) {
511 vpn_progress(vpninfo, PRG_ERR,
512 _("Error in TSS key blob\n"));
516 err = Tspi_Context_Create(&vpninfo->tpm_context);
518 vpn_progress(vpninfo, PRG_ERR,
519 _("Failed to create TPM context: %s\n"),
520 Trspi_Error_String(err));
523 err = Tspi_Context_Connect(vpninfo->tpm_context, NULL);
525 vpn_progress(vpninfo, PRG_ERR,
526 _("Failed to connect TPM context: %s\n"),
527 Trspi_Error_String(err));
530 err = Tspi_Context_LoadKeyByUUID(vpninfo->tpm_context, TSS_PS_TYPE_SYSTEM,
531 SRK_UUID, &vpninfo->srk);
533 vpn_progress(vpninfo, PRG_ERR,
534 _("Failed to load TPM SRK key: %s\n"),
535 Trspi_Error_String(err));
538 err = Tspi_GetPolicyObject(vpninfo->srk, TSS_POLICY_USAGE, &vpninfo->srk_policy);
540 vpn_progress(vpninfo, PRG_ERR,
541 _("Failed to load TPM SRK policy object: %s\n"),
542 Trspi_Error_String(err));
546 pass = vpninfo->cert_password;
547 vpninfo->cert_password = NULL;
550 err = request_passphrase(vpninfo, &pass, _("Enter TPM SRK PIN:"));
554 /* We don't seem to get the error here... */
555 err = Tspi_Policy_SetSecret(vpninfo->srk_policy, TSS_SECRET_MODE_PLAIN,
556 strlen(pass), (void *)pass);
558 vpn_progress(vpninfo, PRG_ERR,
559 _("Failed to set TPM PIN: %s\n"),
560 Trspi_Error_String(err));
567 /* ... we get it here instead. */
568 err = Tspi_Context_LoadKeyByBlob(vpninfo->tpm_context, vpninfo->srk,
569 tss_len, asn1.data + ofs, &vpninfo->tpm_key);
573 vpn_progress(vpninfo, PRG_ERR,
574 _("Failed to load TPM key blob: %s\n"),
575 Trspi_Error_String(err));
577 if (err != TPM_E_AUTHFAIL)
581 gnutls_privkey_init(pkey);
582 /* This would be nicer if there was a destructor callback. I could
583 allocate a data structure with the TPM handles and the vpninfo
584 pointer, and destroy that properly when the key is destroyed. */
585 gnutls_privkey_import_ext(*pkey, GNUTLS_PK_RSA, vpninfo, tpm_sign_fn, NULL, 0);
587 /* FIXME: Get key id using TSS_TSPATTRIB_KEYINFO_RSA_MODULUS etc. so
588 that we can ensure we have a matching cert. */
593 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
594 vpninfo->srk_policy = 0;
596 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
599 Tspi_Context_Close(vpninfo->tpm_context);
600 vpninfo->tpm_context = 0;
605 #endif /* HAVE_TROUSERS */
607 static int load_certificate(struct openconnect_info *vpninfo)
609 gnutls_datum_t fdata;
610 gnutls_x509_privkey_t key = NULL;
611 #ifdef HAVE_GNUTLS_CERTIFICATE_SET_KEY
612 gnutls_privkey_t pkey = NULL;
615 char *cert_url = (char *)vpninfo->cert;
616 char *key_url = (char *)vpninfo->sslkey;
618 gnutls_x509_crl_t crl = NULL;
619 gnutls_x509_crt_t last_cert, cert = NULL;
620 gnutls_x509_crt_t *extra_certs = NULL, *supporting_certs = NULL;
621 unsigned int nr_supporting_certs = 0, nr_extra_certs = 0;
622 unsigned int certs_to_free = 0; /* How many of supporting_certs */
623 int err; /* GnuTLS error */
624 int ret = 0; /* our error (zero or -errno) */
626 int cert_is_p11 = 0, key_is_p11 = 0;
627 unsigned char key_id[20];
628 size_t key_id_size = sizeof(key_id);
633 key_is_p11 = !strncmp(vpninfo->sslkey, "pkcs11:", 7);
634 cert_is_p11 = !strncmp(vpninfo->cert, "pkcs11:", 7);
636 /* Install PIN handler if either certificate or key are coming from PKCS#11 */
637 if (key_is_p11 || cert_is_p11) {
639 CK_OBJECT_CLASS class;
644 sprintf(pin_source, "openconnect:%p", vpninfo);
645 p11_kit_pin_register_callback(pin_source, pin_callback, vpninfo, NULL);
647 uri = p11_kit_uri_new();
649 attr.type = CKA_CLASS;
650 attr.pValue = &class;
651 attr.ulValueLen = sizeof(class);
653 /* Add appropriate pin-source and object-type attributes to
654 both certificate and key URLs, unless they already exist. */
656 !p11_kit_uri_parse(cert_url, P11_KIT_URI_FOR_OBJECT, uri)) {
657 if (!p11_kit_uri_get_pin_source(uri))
658 p11_kit_uri_set_pin_source(uri, pin_source);
659 if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
660 class = CKO_CERTIFICATE;
661 p11_kit_uri_set_attribute(uri, &attr);
663 p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &cert_url);
667 !p11_kit_uri_parse(key_url, P11_KIT_URI_FOR_OBJECT, uri)) {
668 if (!p11_kit_uri_get_pin_source(uri))
669 p11_kit_uri_set_pin_source(uri, pin_source);
670 if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
671 class = CKO_PRIVATE_KEY;
672 p11_kit_uri_set_attribute(uri, &attr);
674 p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &key_url);
677 p11_kit_uri_free(uri);
679 vpn_progress(vpninfo, PRG_ERR,
680 _("This binary built without PKCS#11 support\n"));
685 /* Load certificate(s) first... */
687 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
689 /* With GnuTLS 2.12 we can't *see* the key so we can't
690 do the expiry check or fill in intermediate CAs. */
691 err = gnutls_certificate_set_x509_key_file(vpninfo->https_cred,
693 GNUTLS_X509_FMT_PEM);
695 vpn_progress(vpninfo, PRG_ERR,
696 _("Error loading PKCS#11 certificate: %s\n"),
697 gnutls_strerror(err));
704 #endif /* PKCS#11 for GnuTLS v2.12 */
706 /* GnuTLS 2.12 *can* handle the cert being in PKCS#11, if the key
707 isn't. Although it's not clear why anyone would ever do that. */
709 vpn_progress(vpninfo, PRG_TRACE,
710 _("Using PKCS#11 certificate %s\n"), cert_url);
712 err = gnutls_x509_crt_init(&cert);
717 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url, 0);
718 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
719 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url,
720 GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
722 vpn_progress(vpninfo, PRG_ERR,
723 _("Error loading certificate from PKCS#11: %s\n"),
724 gnutls_strerror(err));
730 #endif /* HAVE_P11KIT */
732 vpn_progress(vpninfo, PRG_TRACE,
733 _("Using certificate file %s\n"), vpninfo->cert);
735 ret = load_datum(vpninfo, &fdata, vpninfo->cert);
739 if (!key_is_p11 && (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
740 vpninfo->cert_type == CERT_TYPE_UNKNOWN)) {
741 /* PKCS#12 should actually contain certificates *and* private key */
742 ret = load_pkcs12_certificate(vpninfo, &fdata, &key,
743 &supporting_certs, &nr_supporting_certs,
744 &extra_certs, &nr_extra_certs,
749 if (nr_supporting_certs) {
750 cert = supporting_certs[0];
753 vpn_progress(vpninfo, PRG_ERR,
754 _("PKCS#11 file contained no certificate\n"));
759 /* It returned NOT_PKCS12.
760 Fall through to try PEM formats. */
763 /* We need to know how many there are in *advance*; it won't just allocate
764 the array for us :( */
765 nr_extra_certs = count_x509_certificates(&fdata);
767 nr_extra_certs = 1; /* wtf? Oh well, we'll fail later... */
769 extra_certs = calloc(nr_extra_certs, sizeof(cert));
775 err = gnutls_x509_crt_list_import(extra_certs, &nr_extra_certs, &fdata,
776 GNUTLS_X509_FMT_PEM, 0);
779 if (!err || err == GNUTLS_E_NO_CERTIFICATE_FOUND)
780 reason = _("No certificate found in file");
782 reason = gnutls_strerror(err);
784 vpn_progress(vpninfo, PRG_ERR,
785 _("Loading certificate failed: %s\n"),
790 nr_extra_certs = err;
795 /* Now we have the certificate(s) and we're looking for the private key... */
796 #if defined (HAVE_P11KIT) && defined (HAVE_GNUTLS_CERTIFICATE_SET_KEY)
798 gnutls_pkcs11_privkey_t p11key = NULL;
800 vpn_progress(vpninfo, PRG_TRACE,
801 _("Using PKCS#11 key %s\n"), key_url);
803 err = gnutls_pkcs11_privkey_init(&p11key);
805 vpn_progress(vpninfo, PRG_ERR,
806 _("Error initialising PKCS#11 key structure: %s\n"),
807 gnutls_strerror(err));
812 err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0);
814 vpn_progress(vpninfo, PRG_ERR,
815 _("Error importing PKCS#11 URL %s: %s\n"),
816 key_url, gnutls_strerror(err));
817 gnutls_pkcs11_privkey_deinit(p11key);
822 err = gnutls_privkey_init(&pkey);
824 vpn_progress(vpninfo, PRG_ERR,
825 _("Error initialising private key structure: %s\n"),
826 gnutls_strerror(err));
827 gnutls_pkcs11_privkey_deinit(p11key);
832 err = gnutls_privkey_import_pkcs11(pkey, p11key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
834 vpn_progress(vpninfo, PRG_ERR,
835 _("Error importing PKCS#11 key into private key structure: %s\n"),
836 gnutls_strerror(err));
837 gnutls_pkcs11_privkey_deinit(p11key);
846 /* We're loading the private key from a file. Load the file into memory
847 unless it's the same as the certificate and we already loaded that. */
848 if (!fdata.data || vpninfo->sslkey != vpninfo->cert) {
849 gnutls_free(fdata.data);
852 vpn_progress(vpninfo, PRG_TRACE,
853 _("Using private key file %s\n"), vpninfo->sslkey);
855 ret = load_datum(vpninfo, &fdata, vpninfo->sslkey);
860 if (vpninfo->cert_type == CERT_TYPE_TPM ||
861 (vpninfo->cert_type == CERT_TYPE_UNKNOWN &&
862 strstr((char *)fdata.data, "-----BEGIN TSS KEY BLOB-----"))) {
863 #ifndef HAVE_TROUSERS
864 vpn_progress(vpninfo, PRG_ERR,
865 _("This version of OpenConnect was built without TPM support\n"));
868 ret = load_tpm_key(vpninfo, &fdata, &pkey);
876 gnutls_x509_privkey_init(&key);
877 /* Try PKCS#1 (and PKCS#8 without password) first. GnuTLS doesn't
878 support OpenSSL's old PKCS#1-based encrypted format. We should
879 probably check for it and give a more coherent failure mode. */
880 err = gnutls_x509_privkey_import(key, &fdata, GNUTLS_X509_FMT_PEM);
882 /* If that fails, try PKCS#8 */
883 char *pass = vpninfo->cert_password;
885 /* Yay, just for fun this is *different* to PKCS#12. Where we could
886 try an empty password there, in this case the empty-password case
887 has already been *tried* by gnutls_x509_privkey_import(). If we
888 just call gnutls_x509_privkey_import_pkcs8() with a NULL password,
889 it'll SEGV. You have to set the GNUTLS_PKCS_PLAIN flag if you want
890 to try without a password. Passing NULL evidently isn't enough of
891 a hint. And in GnuTLS 3.1 where that crash has been fixed, passing
892 NULL will cause it to return GNUTLS_E_ENCRYPTED_STRUCTURE (a new
893 error code) rather than GNUTLS_E_DECRYPTION_FAILED. So just pass ""
894 instead of NULL, and don't worry about either case. */
895 while ((err = gnutls_x509_privkey_import_pkcs8(key, &fdata,
898 if (err != GNUTLS_E_DECRYPTION_FAILED) {
899 vpn_progress(vpninfo, PRG_ERR,
900 _("Failed to load private key as PKCS#8: %s\n"),
901 gnutls_strerror(err));
905 vpninfo->cert_password = NULL;
907 vpn_progress(vpninfo, PRG_ERR,
908 _("Failed to decrypt PKCS#8 certificate file\n"));
911 err = request_passphrase(vpninfo, &pass,
912 _("Enter PEM pass phrase:"));
919 vpninfo->cert_password = NULL;
922 /* Now attempt to make sure we use the *correct* certificate, to match the key */
923 err = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size);
925 vpn_progress(vpninfo, PRG_ERR,
926 _("Failed to get key ID: %s\n"),
927 gnutls_strerror(err));
930 for (i = 0; i < (extra_certs?nr_extra_certs:1); i++) {
931 unsigned char cert_id[20];
932 size_t cert_id_size = sizeof(cert_id);
934 err = gnutls_x509_crt_get_key_id(extra_certs?extra_certs[i]:cert, 0, cert_id, &cert_id_size);
938 if (cert_id_size == key_id_size && !memcmp(cert_id, key_id, key_id_size)) {
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];
951 /* We shouldn't reach this. It means that we didn't find *any* matching cert */
952 vpn_progress(vpninfo, PRG_ERR,
953 _("No SSL certificate found to match private key\n"));
957 #ifdef HAVE_GNUTLS_CERTIFICATE_SET_KEY
960 /* FIXME: How do we check which cert matches the pkey?
961 For now we just assume that the first one in the list is the right one. */
962 cert = extra_certs[0];
964 /* Move the rest of the array down */
965 for (i = 0; i < nr_extra_certs - 1; i++)
966 extra_certs[i] = extra_certs[i+1];
973 /* Now we have both cert(s) and key, and we should be ready to go. */
974 check_certificate_expiry(vpninfo, cert);
975 get_cert_name(cert, name, sizeof(name));
976 vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"),
980 err = gnutls_certificate_set_x509_crl(vpninfo->https_cred, &crl, 1);
982 vpn_progress(vpninfo, PRG_ERR,
983 _("Setting certificate recovation list failed: %s\n"),
984 gnutls_strerror(err));
989 /* OpenSSL has problems with certificate chains — if there are
990 multiple certs with the same name, it doesn't necessarily
991 choose the _right_ one. (RT#1942)
992 Pick the right ones for ourselves and add them manually. */
994 if (nr_supporting_certs) {
995 /* We already got a bunch of certs from PKCS#12 file.
996 Remember how many need to be freed when we're done,
997 since we'll expand the supporting_certs array with
998 more from the cafile if we can. */
999 last_cert = supporting_certs[nr_supporting_certs-1];
1000 certs_to_free = nr_supporting_certs;
1003 certs_to_free = nr_supporting_certs = 1;
1006 gnutls_x509_crt_t issuer;
1008 for (i = 0; i < nr_extra_certs; i++) {
1009 if (gnutls_x509_crt_check_issuer(last_cert, extra_certs[i]) &&
1010 !check_issuer_sanity(last_cert, extra_certs[i]))
1014 if (i < nr_extra_certs) {
1015 issuer = extra_certs[i];
1017 err = gnutls_certificate_get_issuer(vpninfo->https_cred,
1018 last_cert, &issuer, 0);
1023 /* The check_issuer_sanity() function works fine as a workaround where
1024 it was used above, but when gnutls_certificate_get_issuer() returns
1025 a bogus cert, there's nothing we can do to fix it up. We don't get
1026 to iterate over all the available certs like we can over our own
1028 if (check_issuer_sanity(last_cert, issuer)) {
1029 /* Hm, is there a bug reference for this? Or just the git commit
1030 reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
1031 vpn_progress(vpninfo, PRG_ERR,
1032 _("WARNING: GnuTLS returned incorrect issuer certs; authentication may fail!\n"));
1036 if (issuer == last_cert) {
1037 /* Don't actually include the root CA. If they don't already trust it,
1038 then handing it to them isn't going to help. But don't omit the
1039 original certificate if it's self-signed. */
1040 if (nr_supporting_certs > 1)
1041 nr_supporting_certs--;
1045 /* OK, we found a new cert to add to our chain. */
1046 supporting_certs = gnutls_realloc(supporting_certs,
1047 sizeof(cert) * ++nr_supporting_certs);
1048 if (!supporting_certs) {
1049 vpn_progress(vpninfo, PRG_ERR,
1050 _("Failed to allocate memory for supporting certificates\n"));
1051 /* The world is probably about to end, but try without them anyway */
1057 /* First time we actually allocated an array? Copy the first cert into it */
1058 if (nr_supporting_certs == 2)
1059 supporting_certs[0] = cert;
1061 /* Append the new one */
1062 supporting_certs[nr_supporting_certs-1] = issuer;
1066 for (i = 1; i < nr_supporting_certs; i++) {
1067 get_cert_name(supporting_certs[i], name, sizeof(name));
1069 vpn_progress(vpninfo, PRG_DEBUG,
1070 _("Adding supporting CA '%s'\n"), name);
1073 #if defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY)
1075 /* Ug. If we got a gnutls_privkey_t from PKCS#11 rather than the
1076 gnutls_x509_privkey_t that we get from PEM or PKCS#12 files, then
1077 we can't use gnutls_certificate_set_x509_key(). Instead we have
1078 to convert our chain of X509 certificates to gnutls_pcert_st and
1079 then use gnutls_certificate_set_key() with that instead. */
1080 gnutls_pcert_st *pcerts = calloc(nr_supporting_certs, sizeof(*pcerts));
1087 for (i=0 ; i < nr_supporting_certs; i++) {
1088 err = gnutls_pcert_import_x509(pcerts + i, supporting_certs?supporting_certs[i]:cert, 0);
1090 vpn_progress(vpninfo, PRG_ERR,
1091 _("Importing X509 certificate failed: %s\n"),
1092 gnutls_strerror(err));
1097 err = gnutls_certificate_set_key(vpninfo->https_cred, NULL, 0, pcerts, nr_supporting_certs, pkey);
1099 vpn_progress(vpninfo, PRG_ERR,
1100 _("Setting PKCS#11 certificate failed: %s\n"),
1101 gnutls_strerror(err));
1103 for (i=0 ; i < nr_supporting_certs; i++)
1104 gnutls_pcert_deinit(pcerts + i);
1109 pkey = NULL; /* we gave it away, along with pcerts */
1112 err = gnutls_certificate_set_x509_key(vpninfo->https_cred,
1113 supporting_certs ? supporting_certs : &cert,
1114 supporting_certs ? nr_supporting_certs : 1,
1118 vpn_progress(vpninfo, PRG_ERR,
1119 _("Setting certificate failed: %s\n"),
1120 gnutls_strerror(err));
1125 gnutls_x509_crl_deinit(crl);
1127 gnutls_x509_privkey_deinit(key);
1129 gnutls_x509_crt_deinit(cert);
1130 /* From 1 because cert is the first one (and might exist
1131 even if supporting_certs is NULL) */
1132 for (i = 1; i < certs_to_free; i++) {
1133 if (supporting_certs[i])
1134 gnutls_x509_crt_deinit(supporting_certs[i]);
1136 for (i = 0; i < nr_extra_certs; i++) {
1138 gnutls_x509_crt_deinit(extra_certs[i]);
1140 gnutls_free(extra_certs);
1141 gnutls_free(supporting_certs);
1142 gnutls_free(fdata.data);
1143 #ifdef HAVE_GNUTLS_CERTIFICATE_SET_KEY
1145 gnutls_privkey_deinit(pkey);
1148 if (cert_url != vpninfo->cert)
1150 if (key_url != vpninfo->sslkey)
1156 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
1157 gnutls_x509_crt_t cert,
1158 gnutls_digest_algorithm_t algo,
1161 unsigned char md[256];
1162 size_t md_size = sizeof(md);
1165 if (gnutls_x509_crt_get_fingerprint(cert, algo, md, &md_size))
1168 for (i=0; i < md_size; i++)
1169 sprintf(&buf[i*2], "%02X", md[i]);
1174 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
1175 OPENCONNECT_X509 *cert, char *buf)
1177 return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_MD5, buf);
1180 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
1181 OPENCONNECT_X509 *cert, char *buf)
1183 return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_SHA1, buf);
1186 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1187 OPENCONNECT_X509 *cert)
1192 if (gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &buf))
1195 /* Just in case gnutls_free() isn't free(), we can't steal it. */
1196 ret = strdup((char *)buf.data);
1197 gnutls_free(buf.data);
1202 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
1203 OPENCONNECT_X509 *cert, unsigned char **buf)
1206 unsigned char *ret = NULL;
1208 if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l) !=
1209 GNUTLS_E_SHORT_MEMORY_BUFFER)
1216 if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l)) {
1224 static int verify_peer(gnutls_session_t session)
1226 struct openconnect_info *vpninfo = gnutls_session_get_ptr(session);
1227 const gnutls_datum_t *cert_list;
1228 gnutls_x509_crt_t cert;
1229 unsigned int status, cert_list_size;
1230 const char *reason = NULL;
1233 if (vpninfo->peer_cert) {
1234 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1235 vpninfo->peer_cert = NULL;
1238 cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
1240 vpn_progress(vpninfo, PRG_ERR, _("Server presented no certificate\n"));
1241 return GNUTLS_E_CERTIFICATE_ERROR;
1244 if (vpninfo->servercert) {
1245 unsigned char sha1bin[SHA1_SIZE];
1246 char fingerprint[(SHA1_SIZE * 2) + 1];
1249 err = openconnect_sha1(sha1bin, cert_list[0].data, cert_list[0].size);
1251 vpn_progress(vpninfo, PRG_ERR,
1252 _("Could not calculate SHA1 of server's certificate\n"));
1253 return GNUTLS_E_CERTIFICATE_ERROR;
1255 for (i=0; i < SHA1_SIZE; i++)
1256 sprintf(&fingerprint[i*2], "%02X", sha1bin[i]);
1258 if (strcasecmp(vpninfo->servercert, fingerprint)) {
1259 vpn_progress(vpninfo, PRG_ERR,
1260 _("Server SSL certificate didn't match: %s\n"), fingerprint);
1261 return GNUTLS_E_CERTIFICATE_ERROR;
1266 err = gnutls_certificate_verify_peers2 (session, &status);
1268 vpn_progress(vpninfo, PRG_ERR, _("Error checking server cert status\n"));
1269 return GNUTLS_E_CERTIFICATE_ERROR;
1272 if (status & GNUTLS_CERT_REVOKED)
1273 reason = _("certificate revoked");
1274 else if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1275 reason = _("signer not found");
1276 else if (status & GNUTLS_CERT_SIGNER_NOT_CA)
1277 reason = _("signer not a CA certificate");
1278 else if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1279 reason = _("insecure algorithm");
1280 else if (status & GNUTLS_CERT_NOT_ACTIVATED)
1281 reason = _("certificate not yet activated");
1282 else if (status & GNUTLS_CERT_EXPIRED)
1283 reason = _("certificate expired");
1284 else if (status & GNUTLS_CERT_INVALID)
1285 /* If this is set and no other reason, it apparently means
1286 that signature verification failed. Not entirely sure
1287 why we don't just set a bit for that too. */
1288 reason = _("signature verification failed");
1290 err = gnutls_x509_crt_init(&cert);
1292 vpn_progress(vpninfo, PRG_ERR, _("Error initialising X509 cert structure\n"));
1293 return GNUTLS_E_CERTIFICATE_ERROR;
1296 err = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
1298 vpn_progress(vpninfo, PRG_ERR, _("Error importing server's cert\n"));
1299 gnutls_x509_crt_deinit(cert);
1300 return GNUTLS_E_CERTIFICATE_ERROR;
1303 if (!reason && !gnutls_x509_crt_check_hostname(cert, vpninfo->hostname))
1304 reason = _("certificate does not match hostname");
1307 vpn_progress(vpninfo, PRG_INFO, "Server certificate verify failed: %s\n",
1309 if (vpninfo->validate_peer_cert)
1310 err = vpninfo->validate_peer_cert(vpninfo->cbdata,
1312 reason) ? GNUTLS_E_CERTIFICATE_ERROR : 0;
1314 err = GNUTLS_E_CERTIFICATE_ERROR;
1317 vpninfo->peer_cert = cert;
1323 int openconnect_open_https(struct openconnect_info *vpninfo)
1328 if (vpninfo->https_sess)
1331 ssl_sock = connect_https_socket(vpninfo);
1335 if (!vpninfo->https_cred) {
1336 gnutls_certificate_allocate_credentials(&vpninfo->https_cred);
1337 #ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST
1338 gnutls_certificate_set_x509_system_trust(vpninfo->https_cred);
1340 gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1341 "/etc/pki/tls/certs/ca-bundle.crt",
1342 GNUTLS_X509_FMT_PEM);
1344 gnutls_certificate_set_verify_function (vpninfo->https_cred,
1347 if (vpninfo->cafile) {
1348 err = gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1350 GNUTLS_X509_FMT_PEM);
1352 vpn_progress(vpninfo, PRG_ERR,
1353 _("Failed to open CA file '%s': %s\n"),
1354 vpninfo->cafile, gnutls_strerror(err));
1360 if (vpninfo->cert) {
1361 err = load_certificate(vpninfo);
1363 vpn_progress(vpninfo, PRG_ERR,
1364 _("Loading certificate failed. Aborting.\n"));
1369 gnutls_init (&vpninfo->https_sess, GNUTLS_CLIENT);
1370 gnutls_session_set_ptr (vpninfo->https_sess, (void *) vpninfo);
1371 err = gnutls_priority_set_direct (vpninfo->https_sess, "NONE:+VERS-TLS1.0:+SHA1:+AES-128-CBC:+RSA:+COMP-NULL:%COMPAT:%DISABLE_SAFE_RENEGOTIATION", NULL);
1373 vpn_progress(vpninfo, PRG_ERR,
1374 _("Failed to set TLS priority string: %s\n"),
1375 gnutls_strerror(err));
1379 gnutls_record_disable_padding (vpninfo->https_sess);
1380 gnutls_credentials_set (vpninfo->https_sess, GNUTLS_CRD_CERTIFICATE, vpninfo->https_cred);
1381 gnutls_transport_set_ptr(vpninfo->https_sess, /* really? */(gnutls_transport_ptr_t)(long) ssl_sock);
1383 vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1386 while ((err = gnutls_handshake (vpninfo->https_sess))) {
1387 if (err == GNUTLS_E_AGAIN) {
1388 fd_set rd_set, wr_set;
1389 int maxfd = ssl_sock;
1394 if (gnutls_record_get_direction(vpninfo->https_sess))
1395 FD_SET(ssl_sock, &wr_set);
1397 FD_SET(ssl_sock, &rd_set);
1399 if (vpninfo->cancel_fd != -1) {
1400 FD_SET(vpninfo->cancel_fd, &rd_set);
1401 if (vpninfo->cancel_fd > ssl_sock)
1402 maxfd = vpninfo->cancel_fd;
1404 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1405 if (vpninfo->cancel_fd != -1 &&
1406 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1407 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1408 gnutls_deinit(vpninfo->https_sess);
1409 vpninfo->https_sess = NULL;
1413 } else if (err == GNUTLS_E_INTERRUPTED || gnutls_error_is_fatal(err)) {
1414 vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure: %s\n"),
1415 gnutls_strerror(err));
1416 gnutls_deinit(vpninfo->https_sess);
1417 vpninfo->https_sess = NULL;
1421 /* non-fatal error or warning. Ignore it and continue */
1422 vpn_progress(vpninfo, PRG_TRACE,
1423 _("GnuTLS non-fatal return during handshake: %s\n"),
1424 gnutls_strerror(err));
1428 vpninfo->ssl_fd = ssl_sock;
1430 vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1436 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1438 if (vpninfo->peer_cert) {
1439 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1440 vpninfo->peer_cert = NULL;
1442 if (vpninfo->https_sess) {
1443 gnutls_deinit(vpninfo->https_sess);
1444 vpninfo->https_sess = NULL;
1446 if (vpninfo->ssl_fd != -1) {
1447 close(vpninfo->ssl_fd);
1448 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1449 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1450 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1451 vpninfo->ssl_fd = -1;
1453 if (final && vpninfo->https_cred) {
1454 gnutls_certificate_free_credentials(vpninfo->https_cred);
1455 vpninfo->https_cred = NULL;
1457 if (!strncmp(vpninfo->cert, "pkcs11:", 7)) {
1458 char pin_source[40];
1460 sprintf(pin_source, "openconnect:%p", vpninfo);
1461 p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
1463 while (vpninfo->pin_cache) {
1464 struct pin_cache *cache = vpninfo->pin_cache;
1467 memset(cache->pin, 0x5a, strlen(cache->pin));
1469 vpninfo->pin_cache = cache->next;
1474 #ifdef HAVE_TROUSERS
1475 if (vpninfo->tpm_key) {
1476 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key);
1477 vpninfo->tpm_key = 0;
1479 if (vpninfo->srk_policy) {
1480 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
1481 vpninfo->srk_policy = 0;
1484 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
1487 if (vpninfo->tpm_context) {
1488 Tspi_Context_Close(vpninfo->tpm_context);
1489 vpninfo->tpm_context = 0;
1495 void openconnect_init_ssl(void)
1497 gnutls_global_init();
1500 int openconnect_sha1(unsigned char *result, void *data, int datalen)
1503 size_t shalen = SHA1_SIZE;
1507 if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, result, &shalen))
1513 int openconnect_random(void *bytes, int len)
1515 if (gnutls_rnd(GNUTLS_RND_RANDOM, bytes, len))
1520 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1523 const gnutls_datum_t *d;
1528 d = gnutls_certificate_get_ours(vpninfo->https_sess);
1532 if (gnutls_fingerprint(GNUTLS_DIG_MD5, d, buf, &md5len))
1539 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
1540 const char *pin_description,
1541 P11KitPinFlags flags,
1544 struct openconnect_info *vpninfo = _vpninfo;
1545 struct pin_cache **cache = &vpninfo->pin_cache;
1546 struct oc_auth_form f;
1547 struct oc_form_opt o;
1553 if (!vpninfo || !vpninfo->process_auth_form)
1556 if (p11_kit_uri_format(pin_uri, P11_KIT_URI_FOR_TOKEN, &uri))
1560 if (!strcmp(uri, (*cache)->token)) {
1563 if ((*cache)->pin) {
1564 if ((flags & P11_KIT_PIN_FLAGS_RETRY) != P11_KIT_PIN_FLAGS_RETRY)
1565 return p11_kit_pin_new_for_string((*cache)->pin);
1566 memset((*cache)->pin, 0x5a, strlen((*cache)->pin));
1567 free((*cache)->pin);
1568 (*cache)->pin = NULL;
1574 *cache = calloc(1, sizeof(struct pin_cache));
1579 (*cache)->token = uri;
1582 memset(&f, 0, sizeof(f));
1583 f.auth_id = (char *)"pkcs11_pin";
1586 message[sizeof(message)-1] = 0;
1587 snprintf(message, sizeof(message) - 1, _("PIN required for %s"), pin_description);
1588 f.message = message;
1591 * In p11-kit <= 0.12, these flags are *odd*.
1592 * RETRY is 0xa, FINAL_TRY is 0x14 and MANY_TRIES is 0x28.
1593 * So don't treat it like a sane bitmask. Fixed in
1594 * http://cgit.freedesktop.org/p11-glue/p11-kit/commit/?id=59774b11
1596 if ((flags & P11_KIT_PIN_FLAGS_RETRY) == P11_KIT_PIN_FLAGS_RETRY)
1597 f.error = (char *)_("Wrong PIN");
1599 if ((flags & P11_KIT_PIN_FLAGS_FINAL_TRY) == P11_KIT_PIN_FLAGS_FINAL_TRY)
1600 f.banner = (char *)_("This is the final try before locking!");
1601 else if ((flags & P11_KIT_PIN_FLAGS_MANY_TRIES) == P11_KIT_PIN_FLAGS_MANY_TRIES)
1602 f.banner = (char *)_("Only a few tries left before locking!");
1605 o.type = OC_FORM_OPT_PASSWORD;
1606 o.name = (char *)"pkcs11_pin";
1607 o.label = (char *)_("Enter PIN:");
1610 ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
1611 if (ret || !o.value)
1614 pin = p11_kit_pin_new_for_string(o.value);
1615 (*cache)->pin = o.value;