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 our caller
492 can free them after gnutls_certificate_set_key() has been called.
493 So 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 extra_certs[] that
498 correspond to the certs that we're stealing.
499 We know certs[0] was already stolen by the load_certificate()
500 function so we might as well start at certs[1]. */
501 for (i = 1; i < nr_certs; i++) {
503 for (j = 0; j < nr_extra_certs; j++) {
504 if (vpninfo->my_certs[i] == extra_certs[j]) {
505 extra_certs[j] = NULL;
511 gnutls_certificate_set_retrieve_function(vpninfo->https_cred,
513 vpninfo->my_pkey = pkey;
519 /* For GnuTLS 3+ this is saner than the GnuTLS 2.12 version. But still we
520 have to convert the array of X509 certificates to gnutls_pcert_st for
521 ourselves. There's no function that takes a gnutls_privkey_t as the key
522 and gnutls_x509_crt_t certificates. */
523 static int assign_privkey(struct openconnect_info *vpninfo,
524 gnutls_privkey_t pkey,
525 gnutls_x509_crt_t *certs,
526 unsigned int nr_certs,
527 gnutls_x509_crt_t *extra_certs,
528 unsigned int nr_extra_certs)
530 gnutls_pcert_st *pcerts = calloc(nr_certs, sizeof(*pcerts));
534 return GNUTLS_E_MEMORY_ERROR;
536 for (i=0 ; i < nr_certs; i++) {
537 err = gnutls_pcert_import_x509(pcerts + i, certs[i], 0);
539 vpn_progress(vpninfo, PRG_ERR,
540 _("Importing X509 certificate failed: %s\n"),
541 gnutls_strerror(err));
546 err = gnutls_certificate_set_key(vpninfo->https_cred, NULL, 0,
547 pcerts, nr_certs, pkey);
549 vpn_progress(vpninfo, PRG_ERR,
550 _("Setting PKCS#11 certificate failed: %s\n"),
551 gnutls_strerror(err));
553 for (i=0 ; i < nr_certs; i++)
554 gnutls_pcert_deinit(pcerts + i);
559 #endif /* !SET_KEY */
560 #endif /* (P11KIT || TROUSERS) */
562 static int load_certificate(struct openconnect_info *vpninfo)
564 gnutls_datum_t fdata;
565 gnutls_x509_privkey_t key = NULL;
566 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
567 gnutls_privkey_t pkey = NULL;
568 gnutls_datum_t pkey_sig = {NULL, 0};
569 void *dummy_hash_data = &load_certificate;
572 char *cert_url = (char *)vpninfo->cert;
573 char *key_url = (char *)vpninfo->sslkey;
574 gnutls_pkcs11_privkey_t p11key = NULL;
576 gnutls_x509_crl_t crl = NULL;
577 gnutls_x509_crt_t last_cert, cert = NULL;
578 gnutls_x509_crt_t *extra_certs = NULL, *supporting_certs = NULL;
579 unsigned int nr_supporting_certs = 0, nr_extra_certs = 0;
580 unsigned int certs_to_free = 0; /* How many of supporting_certs */
581 int err; /* GnuTLS error */
584 int cert_is_p11 = 0, key_is_p11 = 0;
585 unsigned char key_id[20];
586 size_t key_id_size = sizeof(key_id);
591 key_is_p11 = !strncmp(vpninfo->sslkey, "pkcs11:", 7);
592 cert_is_p11 = !strncmp(vpninfo->cert, "pkcs11:", 7);
595 if (key_is_p11 || cert_is_p11) {
596 vpn_progress(vpninfo, PRG_ERR,
597 _("This binary built without PKCS#11 support\n"));
601 /* Install PIN handler if either certificate or key are coming from PKCS#11 */
602 if (key_is_p11 || cert_is_p11) {
603 CK_OBJECT_CLASS class;
608 sprintf(pin_source, "openconnect:%p", vpninfo);
609 p11_kit_pin_register_callback(pin_source, pin_callback, vpninfo, NULL);
611 uri = p11_kit_uri_new();
613 attr.type = CKA_CLASS;
614 attr.pValue = &class;
615 attr.ulValueLen = sizeof(class);
617 /* Add appropriate pin-source and object-type attributes to
618 both certificate and key URLs, unless they already exist. */
620 !p11_kit_uri_parse(cert_url, P11_KIT_URI_FOR_OBJECT, uri)) {
621 if (!p11_kit_uri_get_pin_source(uri))
622 p11_kit_uri_set_pin_source(uri, pin_source);
623 if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
624 class = CKO_CERTIFICATE;
625 p11_kit_uri_set_attribute(uri, &attr);
627 p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &cert_url);
631 !p11_kit_uri_parse(key_url, P11_KIT_URI_FOR_OBJECT, uri)) {
632 if (!p11_kit_uri_get_pin_source(uri))
633 p11_kit_uri_set_pin_source(uri, pin_source);
634 if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
635 class = CKO_PRIVATE_KEY;
636 p11_kit_uri_set_attribute(uri, &attr);
638 p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &key_url);
641 p11_kit_uri_free(uri);
644 /* Load certificate(s) first... */
646 vpn_progress(vpninfo, PRG_TRACE,
647 _("Using PKCS#11 certificate %s\n"), cert_url);
649 err = gnutls_x509_crt_init(&cert);
654 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url, 0);
655 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
656 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url,
657 GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
659 vpn_progress(vpninfo, PRG_ERR,
660 _("Error loading certificate from PKCS#11: %s\n"),
661 gnutls_strerror(err));
667 #endif /* HAVE_P11KIT */
669 /* OK, not a PKCS#11 certificate so it must be coming from a file... */
670 vpn_progress(vpninfo, PRG_TRACE,
671 _("Using certificate file %s\n"), vpninfo->cert);
673 /* Load file contents */
674 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 either a single certificate in 'cert', or an array of
736 them in extra_certs[]. Next we look for the private key ... */
737 #if defined (HAVE_P11KIT)
739 vpn_progress(vpninfo, PRG_TRACE,
740 _("Using PKCS#11 key %s\n"), key_url);
742 err = gnutls_pkcs11_privkey_init(&p11key);
744 vpn_progress(vpninfo, PRG_ERR,
745 _("Error initialising PKCS#11 key structure: %s\n"),
746 gnutls_strerror(err));
751 err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0);
753 vpn_progress(vpninfo, PRG_ERR,
754 _("Error importing PKCS#11 URL %s: %s\n"),
755 key_url, gnutls_strerror(err));
756 gnutls_pkcs11_privkey_deinit(p11key);
761 err = gnutls_privkey_init(&pkey);
763 vpn_progress(vpninfo, PRG_ERR,
764 _("Error initialising private key structure: %s\n"),
765 gnutls_strerror(err));
766 gnutls_pkcs11_privkey_deinit(p11key);
771 err = gnutls_privkey_import_pkcs11(pkey, p11key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
773 vpn_progress(vpninfo, PRG_ERR,
774 _("Error importing PKCS#11 key into private key structure: %s\n"),
775 gnutls_strerror(err));
776 gnutls_pkcs11_privkey_deinit(p11key);
780 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
781 /* This can be set now and doesn't need to be separately freed.
782 It goes with the pkey. This is a PITA; it would be better
783 if there was a way to get the p11key *back* from a privkey
784 that we *know* is based on one. In fact, since this is only
785 for GnuTLS 2.12 and we *know* the gnutls_privkey_st won't
786 ever change there, so we *could* do something evil... but
788 vpninfo->my_p11key = p11key;
789 #endif /* !SET_KEY */
792 #endif /* HAVE_P11KIT */
794 /* OK, not a PKCS#11 key so it must be coming from a file... load the
795 file into memory, unless it's the same as the cert file and we
796 already loaded that. */
797 if (!fdata.data || vpninfo->sslkey != vpninfo->cert) {
798 gnutls_free(fdata.data);
801 vpn_progress(vpninfo, PRG_TRACE,
802 _("Using private key file %s\n"), vpninfo->sslkey);
804 ret = load_datum(vpninfo, &fdata, vpninfo->sslkey);
809 /* Is it a PEM file with a TPM key blob? */
810 if (vpninfo->cert_type == CERT_TYPE_TPM ||
811 (vpninfo->cert_type == CERT_TYPE_UNKNOWN &&
812 strstr((char *)fdata.data, "-----BEGIN TSS KEY BLOB-----"))) {
813 #ifndef HAVE_TROUSERS
814 vpn_progress(vpninfo, PRG_ERR,
815 _("This version of OpenConnect was built without TPM support\n"));
818 ret = load_tpm_key(vpninfo, &fdata, &pkey, &pkey_sig);
826 /* OK, try other PEM files... */
827 gnutls_x509_privkey_init(&key);
828 /* Try PKCS#1 (and PKCS#8 without password) first. GnuTLS doesn't
829 support OpenSSL's old PKCS#1-based encrypted format. We should
830 probably check for it and give a more coherent failure mode. */
831 err = gnutls_x509_privkey_import(key, &fdata, GNUTLS_X509_FMT_PEM);
833 /* If that fails, try PKCS#8 */
834 char *pass = vpninfo->cert_password;
836 /* Yay, just for fun this is *different* to PKCS#12. Where we could
837 try an empty password there, in this case the empty-password case
838 has already been *tried* by gnutls_x509_privkey_import(). If we
839 just call gnutls_x509_privkey_import_pkcs8() with a NULL password,
840 it'll SEGV. You have to set the GNUTLS_PKCS_PLAIN flag if you want
841 to try without a password. Passing NULL evidently isn't enough of
842 a hint. And in GnuTLS 3.1 where that crash has been fixed, passing
843 NULL will cause it to return GNUTLS_E_ENCRYPTED_STRUCTURE (a new
844 error code) rather than GNUTLS_E_DECRYPTION_FAILED. So just pass ""
845 instead of NULL, and don't worry about either case. */
846 while ((err = gnutls_x509_privkey_import_pkcs8(key, &fdata,
849 if (err != GNUTLS_E_DECRYPTION_FAILED) {
850 vpn_progress(vpninfo, PRG_ERR,
851 _("Failed to load private key as PKCS#8: %s\n"),
852 gnutls_strerror(err));
856 vpninfo->cert_password = NULL;
858 vpn_progress(vpninfo, PRG_ERR,
859 _("Failed to decrypt PKCS#8 certificate file\n"));
862 err = request_passphrase(vpninfo, "openconnect_pem",
863 &pass, _("Enter PEM pass phrase:"));
870 vpninfo->cert_password = NULL;
873 /* Now attempt to make sure we use the *correct* certificate, to match
874 the key. Since we have a software key, we can easily query it and
875 compare its key_id with each certificate till we find a match. */
876 err = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size);
878 vpn_progress(vpninfo, PRG_ERR,
879 _("Failed to get key ID: %s\n"),
880 gnutls_strerror(err));
884 /* If extra_certs[] is NULL, we have one candidate in 'cert' to check. */
885 for (i = 0; i < (extra_certs?nr_extra_certs:1); i++) {
886 unsigned char cert_id[20];
887 size_t cert_id_size = sizeof(cert_id);
889 err = gnutls_x509_crt_get_key_id(extra_certs?extra_certs[i]:cert, 0, cert_id, &cert_id_size);
893 if (cert_id_size == key_id_size && !memcmp(cert_id, key_id, key_id_size)) {
895 cert = extra_certs[i];
897 /* Move the rest of the array down */
898 for (; i < nr_extra_certs - 1; i++)
899 extra_certs[i] = extra_certs[i+1];
906 /* There's no pkey (there's an x509 key), so even if p11-kit or trousers is
907 enabled we'll fall straight through the bit at match_cert: below, and go
908 directly to the bit where it prints the 'no match found' error and exits. */
910 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
912 /* If we have a privkey from PKCS#11 or TPM, we can't do the simple comparison
913 of key ID that we do for software keys to find which certificate is a
914 match. So sign some dummy data and then check the signature against each
915 of the available certificates until we find the right one. */
917 /* The TPM code may have already signed it, to test authorisation. We
918 only sign here for PKCS#11 keys, in which case fdata might be
919 empty too so point it at dummy data. */
920 if (!pkey_sig.data) {
922 fdata.data = dummy_hash_data;
926 err = sign_dummy_data(vpninfo, pkey, &fdata, &pkey_sig);
928 vpn_progress(vpninfo, PRG_ERR,
929 _("Error signing test data with private key: %s\n"),
930 gnutls_strerror(err));
936 /* If extra_certs[] is NULL, we have one candidate in 'cert' to check. */
937 for (i=0; i < (extra_certs?nr_extra_certs:1); i++) {
938 gnutls_pubkey_t pubkey;
940 gnutls_pubkey_init(&pubkey);
941 err = gnutls_pubkey_import_x509(pubkey, extra_certs?extra_certs[i]:cert, 0);
943 vpn_progress(vpninfo, PRG_ERR,
944 _("Error validating signature against certificate: %s\n"),
945 gnutls_strerror(err));
946 /* We'll probably fail shortly if we don't find it. */
947 gnutls_pubkey_deinit(pubkey);
950 err = gnutls_pubkey_verify_data(pubkey, 0, &fdata, &pkey_sig);
951 gnutls_pubkey_deinit(pubkey);
955 cert = extra_certs[i];
957 /* Move the rest of the array down */
958 for (; i < nr_extra_certs - 1; i++)
959 extra_certs[i] = extra_certs[i+1];
963 gnutls_free(pkey_sig.data);
967 gnutls_free(pkey_sig.data);
969 #endif /* P11KIT || TROUSERS */
971 /* We shouldn't reach this. It means that we didn't find *any* matching cert */
972 vpn_progress(vpninfo, PRG_ERR,
973 _("No SSL certificate found to match private key\n"));
977 /********************************************************************/
979 /* Now we have a key in either 'key' or 'pkey', a matching cert in 'cert',
980 and potentially a list of other certs in 'extra_certs[]'. If we loaded
981 a PKCS#12 file we may have a trust chain in 'supporting_certs[]' too. */
982 check_certificate_expiry(vpninfo, cert);
983 get_cert_name(cert, name, sizeof(name));
984 vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"),
988 err = gnutls_certificate_set_x509_crl(vpninfo->https_cred, &crl, 1);
990 vpn_progress(vpninfo, PRG_ERR,
991 _("Setting certificate recovation list failed: %s\n"),
992 gnutls_strerror(err));
998 /* OpenSSL has problems with certificate chains — if there are
999 multiple certs with the same name, it doesn't necessarily
1000 choose the _right_ one. (RT#1942)
1001 Pick the right ones for ourselves and add them manually. */
1003 if (nr_supporting_certs) {
1004 /* We already got a bunch of certs from PKCS#12 file. Remember
1005 how many need to be freed when we're done, since we'll
1006 expand the supporting_certs array with more from the cafile
1007 and extra_certs[] array if we can, and those extra certs
1008 must not be freed (twice). */
1009 last_cert = supporting_certs[nr_supporting_certs-1];
1010 certs_to_free = nr_supporting_certs;
1013 certs_to_free = nr_supporting_certs = 1;
1016 gnutls_x509_crt_t issuer;
1018 for (i = 0; i < nr_extra_certs; i++) {
1019 if (gnutls_x509_crt_check_issuer(last_cert, extra_certs[i]) &&
1020 !check_issuer_sanity(last_cert, extra_certs[i]))
1024 if (i < nr_extra_certs) {
1025 /* We found the next cert in the chain in extra_certs[] */
1026 issuer = extra_certs[i];
1028 /* Look for it in the system trust cafile too. */
1029 err = gnutls_certificate_get_issuer(vpninfo->https_cred,
1030 last_cert, &issuer, 0);
1034 /* The check_issuer_sanity() function works fine as a workaround where
1035 it was used above, but when gnutls_certificate_get_issuer() returns
1036 a bogus cert, there's nothing we can do to fix it up. We don't get
1037 to iterate over all the available certs like we can over our own
1039 if (check_issuer_sanity(last_cert, issuer)) {
1040 /* Hm, is there a bug reference for this? Or just the git commit
1041 reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
1042 vpn_progress(vpninfo, PRG_ERR,
1043 _("WARNING: GnuTLS returned incorrect issuer certs; authentication may fail!\n"));
1048 if (issuer == last_cert) {
1049 /* Don't actually include the root CA. If they don't already trust it,
1050 then handing it to them isn't going to help. But don't omit the
1051 original certificate if it's self-signed. */
1052 if (nr_supporting_certs > 1)
1053 nr_supporting_certs--;
1057 /* OK, we found a new cert to add to our chain. */
1058 supporting_certs = gnutls_realloc(supporting_certs,
1059 sizeof(cert) * ++nr_supporting_certs);
1060 if (!supporting_certs) {
1061 vpn_progress(vpninfo, PRG_ERR,
1062 _("Failed to allocate memory for supporting certificates\n"));
1063 /* The world is probably about to end, but try without them anyway */
1069 /* First time we actually allocated an array? Copy the first cert into it */
1070 if (nr_supporting_certs == 2)
1071 supporting_certs[0] = cert;
1073 /* Append the new one */
1074 supporting_certs[nr_supporting_certs-1] = issuer;
1077 for (i = 1; i < nr_supporting_certs; i++) {
1078 get_cert_name(supporting_certs[i], name, sizeof(name));
1080 vpn_progress(vpninfo, PRG_DEBUG,
1081 _("Adding supporting CA '%s'\n"), name);
1084 /* OK, now we've checked the cert expiry and warned the user if it's
1085 going to expire soon, and we've built up as much of a trust chain
1086 in supporting_certs[] as we can find, to help the server work around
1087 OpenSSL RT#1942. Set up the GnuTLS credentials with the appropriate
1088 key and certs. GnuTLS makes us do this differently for X509 privkeys
1089 vs. TPM/PKCS#11 "generic" privkeys, and the latter is particularly
1090 'fun' for GnuTLS 2.12... */
1091 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1093 err = assign_privkey(vpninfo, pkey,
1094 supporting_certs ? supporting_certs : &cert,
1095 nr_supporting_certs,
1096 extra_certs, nr_extra_certs);
1098 pkey = NULL; /* we gave it away, and potentially also some
1099 of extra_certs[] may have been zeroed. */
1102 #endif /* P11KIT || TROUSERS */
1103 err = gnutls_certificate_set_x509_key(vpninfo->https_cred,
1104 supporting_certs ? supporting_certs : &cert,
1105 nr_supporting_certs, key);
1108 vpn_progress(vpninfo, PRG_ERR,
1109 _("Setting certificate failed: %s\n"),
1110 gnutls_strerror(err));
1116 gnutls_x509_crl_deinit(crl);
1118 gnutls_x509_privkey_deinit(key);
1119 if (supporting_certs) {
1120 for (i = 0; i < certs_to_free; i++) {
1121 if (supporting_certs[i])
1122 gnutls_x509_crt_deinit(supporting_certs[i]);
1124 gnutls_free(supporting_certs);
1126 /* Not if supporting_certs. It's supporting_certs[0] then and
1127 was already freed. */
1128 gnutls_x509_crt_deinit(cert);
1130 for (i = 0; i < nr_extra_certs; i++) {
1132 gnutls_x509_crt_deinit(extra_certs[i]);
1134 gnutls_free(extra_certs);
1136 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1137 if (pkey && pkey != OPENCONNECT_TPM_PKEY)
1138 gnutls_privkey_deinit(pkey);
1139 /* If we support arbitrary privkeys, we might have abused fdata.data
1140 just to point to something to hash. Don't free it in that case! */
1141 if (fdata.data != dummy_hash_data)
1143 gnutls_free(fdata.data);
1146 if (cert_url != vpninfo->cert)
1148 if (key_url != vpninfo->sslkey)
1154 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
1155 gnutls_x509_crt_t cert,
1156 gnutls_digest_algorithm_t algo,
1159 unsigned char md[256];
1160 size_t md_size = sizeof(md);
1163 if (gnutls_x509_crt_get_fingerprint(cert, algo, md, &md_size))
1166 for (i=0; i < md_size; i++)
1167 sprintf(&buf[i*2], "%02X", md[i]);
1172 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
1173 OPENCONNECT_X509 *cert, char *buf)
1175 return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_MD5, buf);
1178 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
1179 OPENCONNECT_X509 *cert, char *buf)
1181 return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_SHA1, buf);
1184 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1185 OPENCONNECT_X509 *cert)
1190 if (gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &buf))
1193 /* Just in case gnutls_free() isn't free(), we can't steal it. */
1194 ret = strdup((char *)buf.data);
1195 gnutls_free(buf.data);
1200 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
1201 OPENCONNECT_X509 *cert, unsigned char **buf)
1204 unsigned char *ret = NULL;
1206 if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l) !=
1207 GNUTLS_E_SHORT_MEMORY_BUFFER)
1214 if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l)) {
1222 static int verify_peer(gnutls_session_t session)
1224 struct openconnect_info *vpninfo = gnutls_session_get_ptr(session);
1225 const gnutls_datum_t *cert_list;
1226 gnutls_x509_crt_t cert;
1227 unsigned int status, cert_list_size;
1228 const char *reason = NULL;
1231 if (vpninfo->peer_cert) {
1232 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1233 vpninfo->peer_cert = NULL;
1236 cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
1238 vpn_progress(vpninfo, PRG_ERR, _("Server presented no certificate\n"));
1239 return GNUTLS_E_CERTIFICATE_ERROR;
1242 if (vpninfo->servercert) {
1243 unsigned char sha1bin[SHA1_SIZE];
1244 char fingerprint[(SHA1_SIZE * 2) + 1];
1247 err = openconnect_sha1(sha1bin, cert_list[0].data, cert_list[0].size);
1249 vpn_progress(vpninfo, PRG_ERR,
1250 _("Could not calculate SHA1 of server's certificate\n"));
1251 return GNUTLS_E_CERTIFICATE_ERROR;
1253 for (i=0; i < SHA1_SIZE; i++)
1254 sprintf(&fingerprint[i*2], "%02X", sha1bin[i]);
1256 if (strcasecmp(vpninfo->servercert, fingerprint)) {
1257 vpn_progress(vpninfo, PRG_ERR,
1258 _("Server SSL certificate didn't match: %s\n"), fingerprint);
1259 return GNUTLS_E_CERTIFICATE_ERROR;
1264 err = gnutls_certificate_verify_peers2 (session, &status);
1266 vpn_progress(vpninfo, PRG_ERR, _("Error checking server cert status\n"));
1267 return GNUTLS_E_CERTIFICATE_ERROR;
1270 if (status & GNUTLS_CERT_REVOKED)
1271 reason = _("certificate revoked");
1272 else if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1273 reason = _("signer not found");
1274 else if (status & GNUTLS_CERT_SIGNER_NOT_CA)
1275 reason = _("signer not a CA certificate");
1276 else if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1277 reason = _("insecure algorithm");
1278 else if (status & GNUTLS_CERT_NOT_ACTIVATED)
1279 reason = _("certificate not yet activated");
1280 else if (status & GNUTLS_CERT_EXPIRED)
1281 reason = _("certificate expired");
1282 else if (status & GNUTLS_CERT_INVALID)
1283 /* If this is set and no other reason, it apparently means
1284 that signature verification failed. Not entirely sure
1285 why we don't just set a bit for that too. */
1286 reason = _("signature verification failed");
1288 err = gnutls_x509_crt_init(&cert);
1290 vpn_progress(vpninfo, PRG_ERR, _("Error initialising X509 cert structure\n"));
1291 return GNUTLS_E_CERTIFICATE_ERROR;
1294 err = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
1296 vpn_progress(vpninfo, PRG_ERR, _("Error importing server's cert\n"));
1297 gnutls_x509_crt_deinit(cert);
1298 return GNUTLS_E_CERTIFICATE_ERROR;
1301 if (!reason && !gnutls_x509_crt_check_hostname(cert, vpninfo->hostname))
1302 reason = _("certificate does not match hostname");
1305 vpn_progress(vpninfo, PRG_INFO, "Server certificate verify failed: %s\n",
1307 if (vpninfo->validate_peer_cert)
1308 err = vpninfo->validate_peer_cert(vpninfo->cbdata,
1310 reason) ? GNUTLS_E_CERTIFICATE_ERROR : 0;
1312 err = GNUTLS_E_CERTIFICATE_ERROR;
1315 vpninfo->peer_cert = cert;
1321 int openconnect_open_https(struct openconnect_info *vpninfo)
1326 if (vpninfo->https_sess)
1329 ssl_sock = connect_https_socket(vpninfo);
1333 if (!vpninfo->https_cred) {
1334 gnutls_certificate_allocate_credentials(&vpninfo->https_cred);
1335 #ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST
1336 gnutls_certificate_set_x509_system_trust(vpninfo->https_cred);
1338 gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1339 "/etc/pki/tls/certs/ca-bundle.crt",
1340 GNUTLS_X509_FMT_PEM);
1342 gnutls_certificate_set_verify_function (vpninfo->https_cred,
1345 if (vpninfo->cafile) {
1346 err = gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1348 GNUTLS_X509_FMT_PEM);
1350 vpn_progress(vpninfo, PRG_ERR,
1351 _("Failed to open CA file '%s': %s\n"),
1352 vpninfo->cafile, gnutls_strerror(err));
1358 if (vpninfo->cert) {
1359 err = load_certificate(vpninfo);
1361 vpn_progress(vpninfo, PRG_ERR,
1362 _("Loading certificate failed. Aborting.\n"));
1367 gnutls_init (&vpninfo->https_sess, GNUTLS_CLIENT);
1368 gnutls_session_set_ptr (vpninfo->https_sess, (void *) vpninfo);
1369 #if defined(HAVE_TROUSERS) && !defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY)
1370 if (vpninfo->my_pkey == OPENCONNECT_TPM_PKEY)
1371 gnutls_sign_callback_set(vpninfo->https_sess, gtls2_tpm_sign_cb, vpninfo);
1373 err = gnutls_priority_set_direct (vpninfo->https_sess, "NONE:+VERS-TLS1.0:+SHA1:+AES-128-CBC:+RSA:+COMP-NULL:%COMPAT:%DISABLE_SAFE_RENEGOTIATION", NULL);
1375 vpn_progress(vpninfo, PRG_ERR,
1376 _("Failed to set TLS priority string: %s\n"),
1377 gnutls_strerror(err));
1381 gnutls_record_disable_padding (vpninfo->https_sess);
1382 gnutls_credentials_set (vpninfo->https_sess, GNUTLS_CRD_CERTIFICATE, vpninfo->https_cred);
1383 gnutls_transport_set_ptr(vpninfo->https_sess, /* really? */(gnutls_transport_ptr_t)(long) ssl_sock);
1385 vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1388 while ((err = gnutls_handshake (vpninfo->https_sess))) {
1389 if (err == GNUTLS_E_AGAIN) {
1390 fd_set rd_set, wr_set;
1391 int maxfd = ssl_sock;
1396 if (gnutls_record_get_direction(vpninfo->https_sess))
1397 FD_SET(ssl_sock, &wr_set);
1399 FD_SET(ssl_sock, &rd_set);
1401 if (vpninfo->cancel_fd != -1) {
1402 FD_SET(vpninfo->cancel_fd, &rd_set);
1403 if (vpninfo->cancel_fd > ssl_sock)
1404 maxfd = vpninfo->cancel_fd;
1406 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1407 if (vpninfo->cancel_fd != -1 &&
1408 FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1409 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1410 gnutls_deinit(vpninfo->https_sess);
1411 vpninfo->https_sess = NULL;
1415 } else if (err == GNUTLS_E_INTERRUPTED || gnutls_error_is_fatal(err)) {
1416 vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure: %s\n"),
1417 gnutls_strerror(err));
1418 gnutls_deinit(vpninfo->https_sess);
1419 vpninfo->https_sess = NULL;
1423 /* non-fatal error or warning. Ignore it and continue */
1424 vpn_progress(vpninfo, PRG_TRACE,
1425 _("GnuTLS non-fatal return during handshake: %s\n"),
1426 gnutls_strerror(err));
1430 vpninfo->ssl_fd = ssl_sock;
1432 vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1438 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1440 if (vpninfo->peer_cert) {
1441 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1442 vpninfo->peer_cert = NULL;
1444 if (vpninfo->https_sess) {
1445 gnutls_deinit(vpninfo->https_sess);
1446 vpninfo->https_sess = NULL;
1448 if (vpninfo->ssl_fd != -1) {
1449 close(vpninfo->ssl_fd);
1450 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1451 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1452 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1453 vpninfo->ssl_fd = -1;
1455 if (final && vpninfo->https_cred) {
1456 gnutls_certificate_free_credentials(vpninfo->https_cred);
1457 vpninfo->https_cred = NULL;
1459 if (!strncmp(vpninfo->cert, "pkcs11:", 7) ||
1460 !strncmp(vpninfo->sslkey, "pkcs11:", 7)) {
1461 char pin_source[40];
1463 sprintf(pin_source, "openconnect:%p", vpninfo);
1464 p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
1466 while (vpninfo->pin_cache) {
1467 struct pin_cache *cache = vpninfo->pin_cache;
1470 memset(cache->pin, 0x5a, strlen(cache->pin));
1472 vpninfo->pin_cache = cache->next;
1477 #ifdef HAVE_TROUSERS
1478 if (vpninfo->tpm_key_policy) {
1479 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key_policy);
1480 vpninfo->tpm_key = 0;
1482 if (vpninfo->tpm_key) {
1483 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key);
1484 vpninfo->tpm_key = 0;
1486 if (vpninfo->srk_policy) {
1487 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
1488 vpninfo->srk_policy = 0;
1491 Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
1494 if (vpninfo->tpm_context) {
1495 Tspi_Context_Close(vpninfo->tpm_context);
1496 vpninfo->tpm_context = 0;
1499 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
1500 if (vpninfo->my_pkey && vpninfo->my_pkey != OPENCONNECT_TPM_PKEY) {
1501 gnutls_privkey_deinit(vpninfo->my_pkey);
1502 vpninfo->my_pkey = NULL;
1503 /* my_p11key went with it */
1505 if (vpninfo->my_certs) {
1507 for (i = 0; i < vpninfo->nr_my_certs; i++)
1508 gnutls_x509_crt_deinit(vpninfo->my_certs[i]);
1509 free(vpninfo->my_certs);
1510 vpninfo->my_certs = NULL;
1516 void openconnect_init_ssl(void)
1518 gnutls_global_init();
1521 int openconnect_sha1(unsigned char *result, void *data, int datalen)
1524 size_t shalen = SHA1_SIZE;
1528 if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, result, &shalen))
1534 int openconnect_random(void *bytes, int len)
1536 if (gnutls_rnd(GNUTLS_RND_RANDOM, bytes, len))
1541 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1544 const gnutls_datum_t *d;
1549 d = gnutls_certificate_get_ours(vpninfo->https_sess);
1553 if (gnutls_fingerprint(GNUTLS_DIG_MD5, d, buf, &md5len))
1560 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
1561 const char *pin_description,
1562 P11KitPinFlags flags,
1565 struct openconnect_info *vpninfo = _vpninfo;
1566 struct pin_cache **cache = &vpninfo->pin_cache;
1567 struct oc_auth_form f;
1568 struct oc_form_opt o;
1574 if (!vpninfo || !vpninfo->process_auth_form)
1577 if (p11_kit_uri_format(pin_uri, P11_KIT_URI_FOR_TOKEN, &uri))
1581 if (!strcmp(uri, (*cache)->token)) {
1584 if ((*cache)->pin) {
1585 if ((flags & P11_KIT_PIN_FLAGS_RETRY) != P11_KIT_PIN_FLAGS_RETRY)
1586 return p11_kit_pin_new_for_string((*cache)->pin);
1587 memset((*cache)->pin, 0x5a, strlen((*cache)->pin));
1588 free((*cache)->pin);
1589 (*cache)->pin = NULL;
1595 *cache = calloc(1, sizeof(struct pin_cache));
1600 (*cache)->token = uri;
1603 memset(&f, 0, sizeof(f));
1604 f.auth_id = (char *)"pkcs11_pin";
1607 message[sizeof(message)-1] = 0;
1608 snprintf(message, sizeof(message) - 1, _("PIN required for %s"), pin_description);
1609 f.message = message;
1612 * In p11-kit <= 0.12, these flags are *odd*.
1613 * RETRY is 0xa, FINAL_TRY is 0x14 and MANY_TRIES is 0x28.
1614 * So don't treat it like a sane bitmask. Fixed in
1615 * http://cgit.freedesktop.org/p11-glue/p11-kit/commit/?id=59774b11
1617 if ((flags & P11_KIT_PIN_FLAGS_RETRY) == P11_KIT_PIN_FLAGS_RETRY)
1618 f.error = (char *)_("Wrong PIN");
1620 if ((flags & P11_KIT_PIN_FLAGS_FINAL_TRY) == P11_KIT_PIN_FLAGS_FINAL_TRY)
1621 f.banner = (char *)_("This is the final try before locking!");
1622 else if ((flags & P11_KIT_PIN_FLAGS_MANY_TRIES) == P11_KIT_PIN_FLAGS_MANY_TRIES)
1623 f.banner = (char *)_("Only a few tries left before locking!");
1626 o.type = OC_FORM_OPT_PASSWORD;
1627 o.name = (char *)"pkcs11_pin";
1628 o.label = (char *)_("Enter PIN:");
1631 ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
1632 if (ret || !o.value)
1635 pin = p11_kit_pin_new_for_string(o.value);
1636 (*cache)->pin = o.value;