Blame SOURCES/gnutls-3.6.8-pkcs11-login-error.patch

cde47b
From fa5147c86941512921282b84819b896a0d4f29bb Mon Sep 17 00:00:00 2001
cde47b
From: Daiki Ueno <dueno@redhat.com>
cde47b
Date: Wed, 19 Jun 2019 17:21:16 +0200
cde47b
Subject: [PATCH] pkcs11: ignore login error when traversing tokens
cde47b
cde47b
If a token is a general access device, it is expected that login
cde47b
attempt to that token returns error:
cde47b
https://github.com/p11-glue/p11-kit/blob/master/trust/module.c#L852
cde47b
cde47b
On the other hand, _pkcs11_traverse_tokens treats the error as fatal
cde47b
and stops iteration.  This behavior prevents object search without
cde47b
token specifier if such tokens are registered in the system.
cde47b
cde47b
Reported by Stanislav Zidek in
cde47b
https://bugzilla.redhat.com/show_bug.cgi?id=1705478
cde47b
cde47b
Signed-off-by: Daiki Ueno <dueno@redhat.com>
cde47b
---
cde47b
 .gitignore                  |   1 +
cde47b
 lib/pkcs11.c                |   8 +-
cde47b
 tests/Makefile.am           |   2 +-
cde47b
 tests/p11-kit-load.sh       |  23 ++++++
cde47b
 tests/pkcs11/list-objects.c | 150 ++++++++++++++++++++++++++++++++++++
cde47b
 5 files changed, 182 insertions(+), 2 deletions(-)
cde47b
 create mode 100644 tests/pkcs11/list-objects.c
cde47b
cde47b
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
cde47b
index de5309b29..2ef0e3e02 100644
cde47b
--- a/lib/pkcs11.c
cde47b
+++ b/lib/pkcs11.c
cde47b
@@ -1617,7 +1617,13 @@ _pkcs11_traverse_tokens(find_func_t find_func, void *input,
cde47b
 					 info, flags);
cde47b
 			if (ret < 0) {
cde47b
 				gnutls_assert();
cde47b
-				return ret;
cde47b
+				pkcs11_close_session(&sinfo);
cde47b
+
cde47b
+				/* treat the error as fatal only if
cde47b
+				 * the token requires login */
cde47b
+				if (l_tinfo.flags & CKF_LOGIN_REQUIRED)
cde47b
+					return ret;
cde47b
+				continue;
cde47b
 			}
cde47b
 
cde47b
 			ret =
cde47b
diff --git a/tests/Makefile.am b/tests/Makefile.am
cde47b
index a67f1549c..7fe954f63 100644
cde47b
--- a/tests/Makefile.am
cde47b
+++ b/tests/Makefile.am
cde47b
@@ -496,7 +496,7 @@ dist_check_SCRIPTS += p11-kit-trust.sh testpkcs11.sh certtool-pkcs11.sh
cde47b
 if HAVE_PKCS11_TRUST_STORE
cde47b
 if P11KIT_0_23_11_API
cde47b
 dist_check_SCRIPTS += p11-kit-load.sh
cde47b
-indirect_tests += pkcs11/list-tokens
cde47b
+indirect_tests += pkcs11/list-tokens pkcs11/list-objects
cde47b
 endif
cde47b
 endif
cde47b
 
cde47b
diff --git a/tests/p11-kit-load.sh b/tests/p11-kit-load.sh
cde47b
index 3201a2c5f..419900f6a 100755
cde47b
--- a/tests/p11-kit-load.sh
cde47b
+++ b/tests/p11-kit-load.sh
cde47b
@@ -22,6 +22,7 @@
cde47b
 srcdir="${srcdir:-.}"
cde47b
 builddir="${builddir:-.}"
cde47b
 CERTTOOL="${CERTTOOL:-../src/certtool${EXEEXT}}"
cde47b
+P11TOOL="${P11TOOL:-../src/p11tool${EXEEXT}}"
cde47b
 DIFF="${DIFF:-diff}"
cde47b
 PKGCONFIG="${PKG_CONFIG:-$(which pkg-config)}"
cde47b
 TMP_SOFTHSM_DIR="./softhsm-load.$$.tmp"
cde47b
@@ -90,6 +91,12 @@ if test $? != 0; then
cde47b
 	exit 1
cde47b
 fi
cde47b
 
cde47b
+GNUTLS_PIN="${PIN}" ${P11TOOL} --login --label GnuTLS-Test-RSA --generate-privkey rsa --provider "${SOFTHSM_MODULE}" pkcs11: --outfile /dev/null
cde47b
+if test $? != 0; then
cde47b
+	echo "failed to generate privkey"
cde47b
+	exit 1
cde47b
+fi
cde47b
+
cde47b
 FILTERTOKEN="sed s/token=.*//g"
cde47b
 
cde47b
 # Check whether both are listed
cde47b
@@ -175,6 +182,22 @@ if test "$nr" != 2;then
cde47b
 	exit 1
cde47b
 fi
cde47b
 
cde47b
+# Check whether public key and privkey are listed.
cde47b
+nr=$(GNUTLS_PIN="${PIN}" ${builddir}/pkcs11/list-objects -o ${P11DIR} -t all pkcs11:token=GnuTLS-Test|sort -u|wc -l)
cde47b
+if test "$nr" != 2;then
cde47b
+	echo "Error in test 8: did not find all objects"
cde47b
+	${builddir}/pkcs11/list-objects -o ${P11DIR} -t all pkcs11:token=GnuTLS-Test
cde47b
+	exit 1
cde47b
+fi
cde47b
+
cde47b
+# Check whether all privkeys are listed even if trust module is registered.
cde47b
+nr=$(GNUTLS_PIN="${PIN}" ${builddir}/pkcs11/list-objects -o ${P11DIR} -t privkey pkcs11:|sort -u|wc -l)
cde47b
+if test "$nr" != 1;then
cde47b
+	echo "Error in test 9: did not find privkey objects"
cde47b
+	${builddir}/pkcs11/list-objects -o ${P11DIR} -t privkey pkcs11:
cde47b
+	exit 1
cde47b
+fi
cde47b
+
cde47b
 rm -f ${P11DIR}/*
cde47b
 rm -rf ${TMP_SOFTHSM_DIR}
cde47b
 
cde47b
diff --git a/tests/pkcs11/list-objects.c b/tests/pkcs11/list-objects.c
cde47b
new file mode 100644
cde47b
index 000000000..ab30cd568
cde47b
--- /dev/null
cde47b
+++ b/tests/pkcs11/list-objects.c
cde47b
@@ -0,0 +1,150 @@
cde47b
+/*
cde47b
+ * Copyright (C) 2016-2017 Red Hat, Inc.
cde47b
+ *
cde47b
+ * Author: Nikos Mavrogiannopoulos
cde47b
+ *
cde47b
+ * This file is part of GnuTLS.
cde47b
+ *
cde47b
+ * GnuTLS is free software; you can redistribute it and/or modify it
cde47b
+ * under the terms of the GNU General Public License as published by
cde47b
+ * the Free Software Foundation; either version 3 of the License, or
cde47b
+ * (at your option) any later version.
cde47b
+ *
cde47b
+ * GnuTLS is distributed in the hope that it will be useful, but
cde47b
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
cde47b
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
cde47b
+ * General Public License for more details.
cde47b
+ *
cde47b
+ * You should have received a copy of the GNU Lesser General Public License
cde47b
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>
cde47b
+ */
cde47b
+
cde47b
+#ifdef HAVE_CONFIG_H
cde47b
+#include <config.h>
cde47b
+#endif
cde47b
+
cde47b
+#include <stdio.h>
cde47b
+#include <stdlib.h>
cde47b
+#include <string.h>
cde47b
+#include <unistd.h>
cde47b
+#include <sys/types.h>
cde47b
+#include <sys/wait.h>
cde47b
+
cde47b
+#include <gnutls/gnutls.h>
cde47b
+#include <gnutls/x509.h>
cde47b
+#include <gnutls/abstract.h>
cde47b
+#include <getopt.h>
cde47b
+#define P11_KIT_FUTURE_UNSTABLE_API
cde47b
+#include <p11-kit/p11-kit.h>
cde47b
+#include "cert-common.h"
cde47b
+
cde47b
+/* lists the registered PKCS#11 modules by p11-kit.
cde47b
+ */
cde47b
+
cde47b
+static void tls_log_func(int level, const char *str)
cde47b
+{
cde47b
+	fprintf(stderr, "|<%d>| %s", level, str);
cde47b
+}
cde47b
+
cde47b
+static const char *opt_pin;
cde47b
+
cde47b
+static
cde47b
+int pin_func(void* userdata, int attempt, const char* url, const char *label,
cde47b
+	     unsigned flags, char *pin, size_t pin_max)
cde47b
+{
cde47b
+	if (attempt == 0) {
cde47b
+		strcpy(pin, opt_pin);
cde47b
+		return 0;
cde47b
+	}
cde47b
+	return -1;
cde47b
+}
cde47b
+
cde47b
+int main(int argc, char **argv)
cde47b
+{
cde47b
+	int ret;
cde47b
+	unsigned i;
cde47b
+	int opt;
cde47b
+	char *url, *mod;
cde47b
+	unsigned flags;
cde47b
+	unsigned obj_flags = 0;
cde47b
+	int attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL;
cde47b
+	gnutls_pkcs11_obj_t *crt_list;
cde47b
+	unsigned int crt_list_size = 0;
cde47b
+	const char *envvar;
cde47b
+
cde47b
+	ret = gnutls_global_init();
cde47b
+	if (ret != 0) {
cde47b
+		fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
cde47b
+		exit(1);
cde47b
+	}
cde47b
+
cde47b
+	gnutls_global_set_log_function(tls_log_func);
cde47b
+
cde47b
+	while((opt = getopt(argc, argv, "o:t:")) != -1) {
cde47b
+		switch(opt) {
cde47b
+			case 'o':
cde47b
+				mod = strdup(optarg);
cde47b
+				p11_kit_override_system_files(NULL, NULL, mod, mod, NULL);
cde47b
+				break;
cde47b
+			case 't':
cde47b
+				/* specify the object type to list */
cde47b
+				if (strcmp(optarg, "all") == 0)
cde47b
+					attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL;
cde47b
+				else if (strcmp(optarg, "privkey") == 0)
cde47b
+					attrs = GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY;
cde47b
+				else {
cde47b
+					fprintf(stderr, "Unknown object type %s\n", optarg);
cde47b
+					exit(1);
cde47b
+				}
cde47b
+				break;
cde47b
+			default:
cde47b
+				fprintf(stderr, "Unknown option %c\n", (char)opt);
cde47b
+				exit(1);
cde47b
+		}
cde47b
+	}
cde47b
+
cde47b
+	if (optind == argc) {
cde47b
+		fprintf(stderr, "specify URL\n");
cde47b
+		exit(1);
cde47b
+	}
cde47b
+	url = argv[optind];
cde47b
+
cde47b
+	envvar = getenv("GNUTLS_PIN");
cde47b
+	if (envvar && *envvar != '\0') {
cde47b
+		opt_pin = envvar;
cde47b
+		obj_flags |= GNUTLS_PKCS11_OBJ_FLAG_LOGIN;
cde47b
+		gnutls_pkcs11_set_pin_function(pin_func, NULL);
cde47b
+	}
cde47b
+
cde47b
+	ret = gnutls_pkcs11_token_get_flags(url, &flags);
cde47b
+	if (ret < 0) {
cde47b
+		flags = 0;
cde47b
+	}
cde47b
+
cde47b
+	ret =
cde47b
+	    gnutls_pkcs11_obj_list_import_url2(&crt_list, &crt_list_size,
cde47b
+					       url, attrs, obj_flags);
cde47b
+	if (ret != 0) {
cde47b
+		fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
cde47b
+		exit(1);
cde47b
+	}
cde47b
+
cde47b
+	for (i = 0; i < crt_list_size; i++) {
cde47b
+		char *output;
cde47b
+
cde47b
+		ret =
cde47b
+		    gnutls_pkcs11_obj_export_url(crt_list[i], 0,
cde47b
+						 &output);
cde47b
+		if (ret != 0) {
cde47b
+			fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
cde47b
+			exit(1);
cde47b
+		}
cde47b
+
cde47b
+		fprintf(stdout, "%s\n", output);
cde47b
+		gnutls_free(output);
cde47b
+		gnutls_pkcs11_obj_deinit(crt_list[i]);
cde47b
+	}
cde47b
+	gnutls_free(crt_list);
cde47b
+
cde47b
+	gnutls_global_deinit();
cde47b
+}
cde47b
-- 
cde47b
2.21.0
cde47b