| |
@@ -1,112 +1,7 @@
|
| |
- commit ed3eaf7d68c083b6015ca3425b75932999dafaad
|
| |
- Author: Jakub Jelen <jjelen@redhat.com>
|
| |
- Date: Wed Apr 24 17:23:21 2019 +0200
|
| |
-
|
| |
- PKCS#11 URI from Fedora
|
| |
-
|
| |
- * Print PKCS#11 URIs from ssh-keygen
|
| |
- * Accept PKCS#11 URIs in -i argument to ssh
|
| |
- * Allow PKCS#11 URI specification in ssh_config
|
| |
- * Fallback to p11-kit-proxy
|
| |
- * PKCS#11 URI support for ssh-add and ssh-agent
|
| |
- * internal representation is URI
|
| |
- * Allow to specify pin-value in URI to avoid interactive prompts
|
| |
-
|
| |
- Currently recognized and used parts of PKCS#11 URI:
|
| |
- * path (optional)
|
| |
- * token
|
| |
- * id
|
| |
- * manufacturer
|
| |
- * (library-manufacturer)
|
| |
- * query (optional)
|
| |
- * module-path
|
| |
- * pin-value
|
| |
-
|
| |
- Unit test for PKCS#11 URIs
|
| |
-
|
| |
- * test PKCS#11 URI parser, generator
|
| |
- * test percent_encodeer and decoder
|
| |
-
|
| |
- Regression tests for PKCS#11 URI support
|
| |
-
|
| |
- * soft-pkcs11.so from people.su.se/~lha/soft-pkcs11
|
| |
- * Return correct CKR for unknown attributes
|
| |
- * Adjust and build it with regress tests (allowing agent-pkcs11 test)
|
| |
- * Test PKCS#11 URIs support with soft-pkcs11
|
| |
- * Direct usage from commandline (URI, provider and combination)
|
| |
- * Usage from configuration files
|
| |
- * Usage in ssh-agent (add, sign, remove)
|
| |
- * Make sure it is built with correct paths
|
| |
-
|
| |
- diff --git a/Makefile.in b/Makefile.in
|
| |
- index e7549470..4511f82a 100644
|
| |
- --- a/Makefile.in
|
| |
- +++ b/Makefile.in
|
| |
- @@ -102,7 +102,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
|
| |
- monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \
|
| |
- ssh-ed25519-sk.o ssh-rsa.o dh.o \
|
| |
- msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
|
| |
- - ssh-pkcs11.o smult_curve25519_ref.o \
|
| |
- + ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \
|
| |
- poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \
|
| |
- ssh-ed25519.o digest-openssl.o digest-libc.o \
|
| |
- hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \
|
| |
- @@ -289,6 +289,8 @@ clean: regressclean
|
| |
- rm -f regress/unittests/match/test_match$(EXEEXT)
|
| |
- rm -f regress/unittests/utf8/*.o
|
| |
- rm -f regress/unittests/utf8/test_utf8$(EXEEXT)
|
| |
- + rm -f regress/unittests/pkcs11/*.o
|
| |
- + rm -f regress/unittests/pkcs11/test_pkcs11$(EXEEXT)
|
| |
- rm -f regress/misc/sk-dummy/*.o
|
| |
- rm -f regress/misc/sk-dummy/*.lo
|
| |
- rm -f regress/misc/sk-dummy/sk-dummy.so
|
| |
- @@ -322,6 +324,8 @@ distclean: regressclean
|
| |
- rm -f regress/unittests/match/test_match
|
| |
- rm -f regress/unittests/utf8/*.o
|
| |
- rm -f regress/unittests/utf8/test_utf8
|
| |
- + rm -f regress/unittests/pkcs11/*.o
|
| |
- + rm -f regress/unittests/pkcs11/test_pkcs11
|
| |
- (cd openbsd-compat && $(MAKE) distclean)
|
| |
- if test -d pkg ; then \
|
| |
- rm -fr pkg ; \
|
| |
- @@ -490,6 +494,7 @@ regress-prep:
|
| |
- $(MKDIR_P) `pwd`/regress/unittests/kex
|
| |
- $(MKDIR_P) `pwd`/regress/unittests/match
|
| |
- $(MKDIR_P) `pwd`/regress/unittests/utf8
|
| |
- + $(MKDIR_P) `pwd`/regress/unittests/pkcs11
|
| |
- $(MKDIR_P) `pwd`/regress/misc/sk-dummy
|
| |
- [ -f `pwd`/regress/Makefile ] || \
|
| |
- ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile
|
| |
- @@ -617,6 +622,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT): \
|
| |
- regress/unittests/test_helper/libtest_helper.a \
|
| |
- -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
|
| |
-
|
| |
- +UNITTESTS_TEST_PKCS11_OBJS=\
|
| |
- + regress/unittests/pkcs11/tests.o
|
| |
- +
|
| |
- +regress/unittests/pkcs11/test_pkcs11$(EXEEXT): \
|
| |
- + ${UNITTESTS_TEST_PKCS11_OBJS} \
|
| |
- + regress/unittests/test_helper/libtest_helper.a libssh.a
|
| |
- + $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_PKCS11_OBJS) \
|
| |
- + regress/unittests/test_helper/libtest_helper.a \
|
| |
- + -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
|
| |
- +
|
| |
- # These all need to be compiled -fPIC, so they are treated differently.
|
| |
- SK_DUMMY_OBJS=\
|
| |
- regress/misc/sk-dummy/sk-dummy.lo \
|
| |
- @@ -655,6 +670,7 @@ regress-unit-binaries: regress-prep $(REGRESSLIBS) \
|
| |
- regress/unittests/kex/test_kex$(EXEEXT) \
|
| |
- regress/unittests/match/test_match$(EXEEXT) \
|
| |
- regress/unittests/utf8/test_utf8$(EXEEXT) \
|
| |
- + regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \
|
| |
-
|
| |
- tests: file-tests t-exec interop-tests unit
|
| |
- echo all tests passed
|
| |
- diff --git a/configure.ac b/configure.ac
|
| |
- index b689db4b..98d3ce4f 100644
|
| |
- --- a/configure.ac
|
| |
- +++ b/configure.ac
|
| |
- @@ -1911,12 +1911,14 @@ AC_LINK_IFELSE(
|
| |
+ diff -up openssh-8.6p1/configure.ac.pkcs11-uri openssh-8.6p1/configure.ac
|
| |
+ --- openssh-8.6p1/configure.ac.pkcs11-uri 2021-04-19 14:57:30.307370482 +0200
|
| |
+ +++ openssh-8.6p1/configure.ac 2021-04-19 14:57:30.315370543 +0200
|
| |
+ @@ -1974,12 +1974,14 @@ AC_LINK_IFELSE(
|
| |
[AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).])
|
| |
])
|
| |
|
| |
@@ -121,7 +16,7 @@
|
| |
fi
|
| |
]
|
| |
)
|
| |
- @@ -1945,6 +1947,40 @@ AC_SEARCH_LIBS([dlopen], [dl])
|
| |
+ @@ -2008,6 +2010,40 @@ AC_SEARCH_LIBS([dlopen], [dl])
|
| |
AC_CHECK_FUNCS([dlopen])
|
| |
AC_CHECK_DECL([RTLD_NOW], [], [], [#include <dlfcn.h>])
|
| |
|
| |
@@ -162,7 +57,7 @@
|
| |
# IRIX has a const char return value for gai_strerror()
|
| |
AC_CHECK_FUNCS([gai_strerror], [
|
| |
AC_DEFINE([HAVE_GAI_STRERROR])
|
| |
- @@ -5401,6 +5437,7 @@ echo " BSD Auth support: $BSD_AUTH_MSG"
|
| |
+ @@ -5564,6 +5600,7 @@ echo " BSD Auth support
|
| |
echo " Random number source: $RAND_MSG"
|
| |
echo " Privsep sandbox style: $SANDBOX_STYLE"
|
| |
echo " PKCS#11 support: $enable_pkcs11"
|
| |
@@ -170,11 +65,85 @@
|
| |
echo " U2F/FIDO support: $enable_sk"
|
| |
|
| |
echo ""
|
| |
- diff --git a/regress/Makefile b/regress/Makefile
|
| |
- index 774c10d4..6bf3b627 100644
|
| |
- --- a/regress/Makefile
|
| |
- +++ b/regress/Makefile
|
| |
- @@ -116,7 +116,8 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \
|
| |
+ diff -up openssh-8.6p1/Makefile.in.pkcs11-uri openssh-8.6p1/Makefile.in
|
| |
+ --- openssh-8.6p1/Makefile.in.pkcs11-uri 2021-04-19 14:57:30.261370134 +0200
|
| |
+ +++ openssh-8.6p1/Makefile.in 2021-04-19 15:14:38.916155695 +0200
|
| |
+ @@ -103,7 +103,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
|
| |
+ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \
|
| |
+ ssh-ed25519-sk.o ssh-rsa.o dh.o \
|
| |
+ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
|
| |
+ - ssh-pkcs11.o smult_curve25519_ref.o \
|
| |
+ + ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \
|
| |
+ poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \
|
| |
+ ssh-ed25519.o digest-openssl.o digest-libc.o \
|
| |
+ hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \
|
| |
+ @@ -300,6 +300,8 @@ clean: regressclean
|
| |
+ rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT)
|
| |
+ rm -f regress/unittests/utf8/*.o
|
| |
+ rm -f regress/unittests/utf8/test_utf8$(EXEEXT)
|
| |
+ + rm -f regress/unittests/pkcs11/*.o
|
| |
+ + rm -f regress/unittests/pkcs11/test_pkcs11$(EXEEXT)
|
| |
+ rm -f regress/misc/sk-dummy/*.o
|
| |
+ rm -f regress/misc/sk-dummy/*.lo
|
| |
+ rm -f regress/misc/sk-dummy/sk-dummy.so
|
| |
+ @@ -337,6 +339,8 @@ distclean: regressclean
|
| |
+ rm -f regress/unittests/sshsig/test_sshsig
|
| |
+ rm -f regress/unittests/utf8/*.o
|
| |
+ rm -f regress/unittests/utf8/test_utf8
|
| |
+ + rm -f regress/unittests/pkcs11/*.o
|
| |
+ + rm -f regress/unittests/pkcs11/test_pkcs11
|
| |
+ (cd openbsd-compat && $(MAKE) distclean)
|
| |
+ if test -d pkg ; then \
|
| |
+ rm -fr pkg ; \
|
| |
+ @@ -511,6 +515,7 @@ regress-prep:
|
| |
+ $(MKDIR_P) `pwd`/regress/unittests/sshkey
|
| |
+ $(MKDIR_P) `pwd`/regress/unittests/sshsig
|
| |
+ $(MKDIR_P) `pwd`/regress/unittests/utf8
|
| |
+ + $(MKDIR_P) `pwd`/regress/unittests/pkcs11
|
| |
+ $(MKDIR_P) `pwd`/regress/misc/sk-dummy
|
| |
+ [ -f `pwd`/regress/Makefile ] || \
|
| |
+ ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile
|
| |
+ @@ -674,6 +679,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT
|
| |
+ regress/unittests/test_helper/libtest_helper.a \
|
| |
+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
|
| |
+
|
| |
+ +UNITTESTS_TEST_PKCS11_OBJS=\
|
| |
+ + regress/unittests/pkcs11/tests.o
|
| |
+ +
|
| |
+ +regress/unittests/pkcs11/test_pkcs11$(EXEEXT): \
|
| |
+ + ${UNITTESTS_TEST_PKCS11_OBJS} \
|
| |
+ + regress/unittests/test_helper/libtest_helper.a libssh.a
|
| |
+ + $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_PKCS11_OBJS) \
|
| |
+ + regress/unittests/test_helper/libtest_helper.a \
|
| |
+ + -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
|
| |
+ +
|
| |
+ # These all need to be compiled -fPIC, so they are treated differently.
|
| |
+ SK_DUMMY_OBJS=\
|
| |
+ regress/misc/sk-dummy/sk-dummy.lo \
|
| |
+ @@ -709,6 +724,7 @@ regress-unit-binaries: regress-prep $(RE
|
| |
+ regress/unittests/sshkey/test_sshkey$(EXEEXT) \
|
| |
+ regress/unittests/sshsig/test_sshsig$(EXEEXT) \
|
| |
+ regress/unittests/utf8/test_utf8$(EXEEXT) \
|
| |
+ + regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \
|
| |
+
|
| |
+ tests: file-tests t-exec interop-tests unit
|
| |
+ echo all tests passed
|
| |
+ diff -up openssh-8.6p1/regress/agent-pkcs11.sh.pkcs11-uri openssh-8.6p1/regress/agent-pkcs11.sh
|
| |
+ --- openssh-8.6p1/regress/agent-pkcs11.sh.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200
|
| |
+ +++ openssh-8.6p1/regress/agent-pkcs11.sh 2021-04-19 14:57:30.316370550 +0200
|
| |
+ @@ -113,7 +113,7 @@ else
|
| |
+ done
|
| |
+
|
| |
+ trace "remove pkcs11 keys"
|
| |
+ - echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1
|
| |
+ + ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1
|
| |
+ r=$?
|
| |
+ if [ $r -ne 0 ]; then
|
| |
+ fail "ssh-add -e failed: exit code $r"
|
| |
+ diff -up openssh-8.6p1/regress/Makefile.pkcs11-uri openssh-8.6p1/regress/Makefile
|
| |
+ --- openssh-8.6p1/regress/Makefile.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200
|
| |
+ +++ openssh-8.6p1/regress/Makefile 2021-04-19 15:15:44.411651410 +0200
|
| |
+ @@ -119,7 +119,8 @@ CLEANFILES= *.core actual agent-key.* au
|
| |
known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \
|
| |
modpipe netcat no_identity_config \
|
| |
pidfile putty.rsa2 ready regress.log remote_pid \
|
| |
@@ -184,32 +153,21 @@
|
| |
rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \
|
| |
scp-ssh-wrapper.scp setuid-allowed sftp-server.log \
|
| |
sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \
|
| |
- @@ -246,6 +247,7 @@ unit:
|
| |
+ @@ -249,8 +250,9 @@ unit:
|
| |
V="" ; \
|
| |
test "x${USE_VALGRIND}" = "x" || \
|
| |
V=${.CURDIR}/valgrind-unit.sh ; \
|
| |
+ - $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
|
| |
+ - $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
|
| |
+ $$V ${.OBJDIR}/unittests/pkcs11/test_pkcs11 ; \
|
| |
- $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
|
| |
- $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
|
| |
+ + $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
|
| |
+ + $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
|
| |
-d ${.CURDIR}/unittests/sshkey/testdata ; \
|
| |
- diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh
|
| |
- index fbbaea51..5d75d69f 100644
|
| |
- --- a/regress/agent-pkcs11.sh
|
| |
- +++ b/regress/agent-pkcs11.sh
|
| |
- @@ -113,7 +113,7 @@ else
|
| |
- done
|
| |
-
|
| |
- trace "remove pkcs11 keys"
|
| |
- - echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1
|
| |
- + ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1
|
| |
- r=$?
|
| |
- if [ $r -ne 0 ]; then
|
| |
- fail "ssh-add -e failed: exit code $r"
|
| |
- diff --git a/regress/pkcs11.sh b/regress/pkcs11.sh
|
| |
- new file mode 100644
|
| |
- index 00000000..a91aee94
|
| |
- --- /dev/null
|
| |
- +++ b/regress/pkcs11.sh
|
| |
+ $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \
|
| |
+ -d ${.CURDIR}/unittests/sshsig/testdata ; \
|
| |
+ diff -up openssh-8.6p1/regress/pkcs11.sh.pkcs11-uri openssh-8.6p1/regress/pkcs11.sh
|
| |
+ --- openssh-8.6p1/regress/pkcs11.sh.pkcs11-uri 2021-04-19 14:57:30.316370550 +0200
|
| |
+ +++ openssh-8.6p1/regress/pkcs11.sh 2021-04-19 14:57:30.316370550 +0200
|
| |
@@ -0,0 +1,349 @@
|
| |
+#
|
| |
+# Copyright (c) 2017 Red Hat
|
| |
@@ -560,10 +518,9 @@
|
| |
+ trace "kill agent"
|
| |
+ ${SSHAGENT} -k > /dev/null
|
| |
+fi
|
| |
- diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile
|
| |
- index 4e56e110..2690ebeb 100644
|
| |
- --- a/regress/unittests/Makefile
|
| |
- +++ b/regress/unittests/Makefile
|
| |
+ diff -up openssh-8.6p1/regress/unittests/Makefile.pkcs11-uri openssh-8.6p1/regress/unittests/Makefile
|
| |
+ --- openssh-8.6p1/regress/unittests/Makefile.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200
|
| |
+ +++ openssh-8.6p1/regress/unittests/Makefile 2021-04-19 14:57:30.316370550 +0200
|
| |
@@ -2,6 +2,6 @@
|
| |
|
| |
REGRESS_FAIL_EARLY?= yes
|
| |
@@ -572,11 +529,9 @@
|
| |
+SUBDIR+=authopt misc sshsig pkcs11
|
| |
|
| |
.include <bsd.subdir.mk>
|
| |
- diff --git a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c
|
| |
- new file mode 100644
|
| |
- index 00000000..b637cb13
|
| |
- --- /dev/null
|
| |
- +++ b/regress/unittests/pkcs11/tests.c
|
| |
+ diff -up openssh-8.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.6p1/regress/unittests/pkcs11/tests.c
|
| |
+ --- openssh-8.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri 2021-04-19 14:57:30.317370558 +0200
|
| |
+ +++ openssh-8.6p1/regress/unittests/pkcs11/tests.c 2021-04-19 14:57:30.317370558 +0200
|
| |
@@ -0,0 +1,337 @@
|
| |
+/*
|
| |
+ * Copyright (c) 2017 Red Hat
|
| |
@@ -915,11 +870,10 @@
|
| |
+ test_parse_invalid();
|
| |
+ test_generate_valid();
|
| |
+}
|
| |
- diff --git a/ssh-add.c b/ssh-add.c
|
| |
- index 8057eb1f..0c470e32 100644
|
| |
- --- a/ssh-add.c
|
| |
- +++ b/ssh-add.c
|
| |
- @@ -67,6 +67,7 @@
|
| |
+ diff -up openssh-8.6p1/ssh-add.c.pkcs11-uri openssh-8.6p1/ssh-add.c
|
| |
+ --- openssh-8.6p1/ssh-add.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200
|
| |
+ +++ openssh-8.6p1/ssh-add.c 2021-04-19 14:57:30.317370558 +0200
|
| |
+ @@ -68,6 +68,7 @@
|
| |
#include "digest.h"
|
| |
#include "ssh-sk.h"
|
| |
#include "sk-api.h"
|
| |
@@ -927,7 +881,7 @@
|
| |
|
| |
/* argv0 */
|
| |
extern char *__progname;
|
| |
- @@ -193,6 +194,32 @@ delete_all(int agent_fd, int qflag)
|
| |
+ @@ -229,6 +230,32 @@ delete_all(int agent_fd, int qflag)
|
| |
return ret;
|
| |
}
|
| |
|
| |
@@ -960,7 +914,7 @@
|
| |
static int
|
| |
add_file(int agent_fd, const char *filename, int key_only, int qflag,
|
| |
const char *skprovider)
|
| |
- @@ -402,12 +429,11 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
|
| |
+ @@ -445,12 +472,11 @@ add_file(int agent_fd, const char *filen
|
| |
}
|
| |
|
| |
static int
|
| |
@@ -975,7 +929,7 @@
|
| |
if ((pin = read_passphrase("Enter passphrase for PKCS#11: ",
|
| |
RP_ALLOW_STDIN)) == NULL)
|
| |
return -1;
|
| |
- @@ -591,6 +617,13 @@ static int
|
| |
+ @@ -630,6 +656,13 @@ static int
|
| |
do_file(int agent_fd, int deleting, int key_only, char *file, int qflag,
|
| |
const char *skprovider)
|
| |
{
|
| |
@@ -989,7 +943,7 @@
|
| |
if (deleting) {
|
| |
if (delete_file(agent_fd, file, key_only, qflag) == -1)
|
| |
return -1;
|
| |
- @@ -773,7 +806,7 @@ main(int argc, char **argv)
|
| |
+ @@ -813,7 +846,7 @@ main(int argc, char **argv)
|
| |
}
|
| |
if (pkcs11provider != NULL) {
|
| |
if (update_card(agent_fd, !deleting, pkcs11provider,
|
| |
@@ -998,11 +952,10 @@
|
| |
ret = 1;
|
| |
goto done;
|
| |
}
|
| |
- diff --git a/ssh-agent.c b/ssh-agent.c
|
| |
- index 7eb6f0dc..27d8e4af 100644
|
| |
- --- a/ssh-agent.c
|
| |
- +++ b/ssh-agent.c
|
| |
- @@ -641,10 +641,72 @@ no_identities(SocketEntry *e)
|
| |
+ diff -up openssh-8.6p1/ssh-agent.c.pkcs11-uri openssh-8.6p1/ssh-agent.c
|
| |
+ --- openssh-8.6p1/ssh-agent.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200
|
| |
+ +++ openssh-8.6p1/ssh-agent.c 2021-04-19 14:57:30.317370558 +0200
|
| |
+ @@ -847,10 +847,72 @@ no_identities(SocketEntry *e)
|
| |
}
|
| |
|
| |
#ifdef ENABLE_PKCS11
|
| |
@@ -1076,7 +1029,7 @@
|
| |
char **comments = NULL;
|
| |
int r, i, count = 0, success = 0, confirm = 0;
|
| |
u_int seconds = 0;
|
| |
- @@ -681,33 +743,28 @@ process_add_smartcard_key(SocketEntry *e)
|
| |
+ @@ -869,33 +931,28 @@ process_add_smartcard_key(SocketEntry *e
|
| |
error_f("failed to parse constraints");
|
| |
goto send;
|
| |
}
|
| |
@@ -1118,7 +1071,7 @@
|
| |
}
|
| |
id->death = death;
|
| |
id->confirm = confirm;
|
| |
- @@ -721,6 +778,7 @@ process_add_smartcard_key(SocketEntry *e)
|
| |
+ @@ -910,6 +967,7 @@ process_add_smartcard_key(SocketEntry *e
|
| |
send:
|
| |
free(pin);
|
| |
free(provider);
|
| |
@@ -1126,7 +1079,7 @@
|
| |
free(keys);
|
| |
free(comments);
|
| |
send_status(e, success);
|
| |
- @@ -729,7 +787,7 @@ send:
|
| |
+ @@ -918,7 +976,7 @@ send:
|
| |
static void
|
| |
process_remove_smartcard_key(SocketEntry *e)
|
| |
{
|
| |
@@ -1135,7 +1088,7 @@
|
| |
int r, success = 0;
|
| |
Identity *id, *nxt;
|
| |
|
| |
- @@ -740,30 +798,29 @@ process_remove_smartcard_key(SocketEntry *e)
|
| |
+ @@ -930,30 +988,29 @@ process_remove_smartcard_key(SocketEntry
|
| |
}
|
| |
free(pin);
|
| |
|
| |
@@ -1172,523 +1125,222 @@
|
| |
send_status(e, success);
|
| |
}
|
| |
#endif /* ENABLE_PKCS11 */
|
| |
- diff --git a/ssh-keygen.c b/ssh-keygen.c
|
| |
- index 0d6ed1ff..182f4f2b 100644
|
| |
- --- a/ssh-keygen.c
|
| |
- +++ b/ssh-keygen.c
|
| |
- @@ -855,8 +855,11 @@ do_download(struct passwd *pw)
|
| |
- free(fp);
|
| |
- } else {
|
| |
- (void) sshkey_write(keys[i], stdout); /* XXX check */
|
| |
- - fprintf(stdout, "%s%s\n",
|
| |
- - *(comments[i]) == '\0' ? "" : " ", comments[i]);
|
| |
- + if (*(comments[i]) != '\0') {
|
| |
- + fprintf(stdout, " %s", comments[i]);
|
| |
+ diff -up openssh-8.6p1/ssh_config.5.pkcs11-uri openssh-8.6p1/ssh_config.5
|
| |
+ --- openssh-8.6p1/ssh_config.5.pkcs11-uri 2021-04-19 14:57:30.269370194 +0200
|
| |
+ +++ openssh-8.6p1/ssh_config.5 2021-04-19 14:57:30.321370588 +0200
|
| |
+ @@ -1063,6 +1063,21 @@ may also be used in conjunction with
|
| |
+ .Cm CertificateFile
|
| |
+ in order to provide any certificate also needed for authentication with
|
| |
+ the identity.
|
| |
+ +.Pp
|
| |
+ +The authentication identity can be also specified in a form of PKCS#11 URI
|
| |
+ +starting with a string
|
| |
+ +.Cm pkcs11: .
|
| |
+ +There is supported a subset of the PKCS#11 URI as defined
|
| |
+ +in RFC 7512 (implemented path arguments
|
| |
+ +.Cm id ,
|
| |
+ +.Cm manufacturer ,
|
| |
+ +.Cm object ,
|
| |
+ +.Cm token
|
| |
+ +and query arguments
|
| |
+ +.Cm module-path
|
| |
+ +and
|
| |
+ +.Cm pin-value
|
| |
+ +). The URI can not be in quotes.
|
| |
+ .It Cm IgnoreUnknown
|
| |
+ Specifies a pattern-list of unknown options to be ignored if they are
|
| |
+ encountered in configuration parsing.
|
| |
+ diff -up openssh-8.6p1/ssh.c.pkcs11-uri openssh-8.6p1/ssh.c
|
| |
+ --- openssh-8.6p1/ssh.c.pkcs11-uri 2021-04-19 14:57:30.269370194 +0200
|
| |
+ +++ openssh-8.6p1/ssh.c 2021-04-19 15:17:05.804267447 +0200
|
| |
+ @@ -843,6 +843,14 @@ main(int ac, char **av)
|
| |
+ options.gss_deleg_creds = 1;
|
| |
+ break;
|
| |
+ case 'i':
|
| |
+ +#ifdef ENABLE_PKCS11
|
| |
+ + if (strlen(optarg) >= strlen(PKCS11_URI_SCHEME) &&
|
| |
+ + strncmp(optarg, PKCS11_URI_SCHEME,
|
| |
+ + strlen(PKCS11_URI_SCHEME)) == 0) {
|
| |
+ + add_identity_file(&options, NULL, optarg, 1);
|
| |
+ + break;
|
| |
+ }
|
| |
- + (void) pkcs11_uri_write(keys[i], stdout);
|
| |
- + fprintf(stdout, "\n");
|
| |
- }
|
| |
- free(comments[i]);
|
| |
- sshkey_free(keys[i]);
|
| |
- diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
|
| |
- index 8a0ffef5..ead8a562 100644
|
| |
- --- a/ssh-pkcs11-client.c
|
| |
- +++ b/ssh-pkcs11-client.c
|
| |
- @@ -323,6 +323,8 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
|
| |
- u_int nkeys, i;
|
| |
- struct sshbuf *msg;
|
| |
+ +#endif
|
| |
+ p = tilde_expand_filename(optarg, getuid());
|
| |
+ if (stat(p, &st) == -1)
|
| |
+ fprintf(stderr, "Warning: Identity file %s "
|
| |
+ @@ -1695,6 +1703,7 @@ main(int ac, char **av)
|
| |
+ #ifdef ENABLE_PKCS11
|
| |
+ (void)pkcs11_del_provider(options.pkcs11_provider);
|
| |
+ #endif
|
| |
+ + pkcs11_terminate();
|
| |
|
| |
- + debug_f("called, name = %s", name);
|
| |
- +
|
| |
- if (fd < 0 && pkcs11_start_helper() < 0)
|
| |
- return (-1);
|
| |
+ skip_connect:
|
| |
+ exit_status = ssh_session2(ssh, cinfo);
|
| |
+ @@ -2211,6 +2220,45 @@ ssh_session2(struct ssh *ssh, const stru
|
| |
+ options.escape_char : SSH_ESCAPECHAR_NONE, id);
|
| |
+ }
|
| |
|
| |
- @@ -342,6 +344,7 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
|
| |
- *keysp = xcalloc(nkeys, sizeof(struct sshkey *));
|
| |
- if (labelsp)
|
| |
- *labelsp = xcalloc(nkeys, sizeof(char *));
|
| |
- + debug_f("nkeys = %u", nkeys);
|
| |
- for (i = 0; i < nkeys; i++) {
|
| |
- /* XXX clean up properly instead of fatal() */
|
| |
- if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 ||
|
| |
- diff --git a/ssh-pkcs11-uri.c b/ssh-pkcs11-uri.c
|
| |
- new file mode 100644
|
| |
- index 00000000..e1a7b4e0
|
| |
- --- /dev/null
|
| |
- +++ b/ssh-pkcs11-uri.c
|
| |
- @@ -0,0 +1,419 @@
|
| |
- +/*
|
| |
- + * Copyright (c) 2017 Red Hat
|
| |
- + *
|
| |
- + * Authors: Jakub Jelen <jjelen@redhat.com>
|
| |
- + *
|
| |
- + * Permission to use, copy, modify, and distribute this software for any
|
| |
- + * purpose with or without fee is hereby granted, provided that the above
|
| |
- + * copyright notice and this permission notice appear in all copies.
|
| |
- + *
|
| |
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
| |
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
| |
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
| |
- + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
| |
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
| |
- + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
| |
- + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
| |
- + */
|
| |
- +
|
| |
- +#include "includes.h"
|
| |
- +
|
| |
+#ifdef ENABLE_PKCS11
|
| |
+ +static void
|
| |
+ +load_pkcs11_identity(char *pkcs11_uri, char *identity_files[],
|
| |
+ + struct sshkey *identity_keys[], int *n_ids)
|
| |
+ +{
|
| |
+ + int nkeys, i;
|
| |
+ + struct sshkey **keys;
|
| |
+ + struct pkcs11_uri *uri;
|
| |
+
|
| |
- +#include <stdio.h>
|
| |
- +#include <string.h>
|
| |
+ + debug("identity file '%s' from pkcs#11", pkcs11_uri);
|
| |
+ + uri = pkcs11_uri_init();
|
| |
+ + if (uri == NULL)
|
| |
+ + fatal("Failed to init PKCS#11 URI");
|
| |
+
|
| |
- +#include "sshkey.h"
|
| |
- +#include "sshbuf.h"
|
| |
- +#include "log.h"
|
| |
+ + if (pkcs11_uri_parse(pkcs11_uri, uri) != 0)
|
| |
+ + fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri);
|
| |
+
|
| |
- +#define CRYPTOKI_COMPAT
|
| |
- +#include "pkcs11.h"
|
| |
+ + /* we need to merge URI and provider together */
|
| |
+ + if (options.pkcs11_provider != NULL && uri->module_path == NULL)
|
| |
+ + uri->module_path = strdup(options.pkcs11_provider);
|
| |
+
|
| |
- +#include "ssh-pkcs11-uri.h"
|
| |
+ + if (options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
|
| |
+ + (nkeys = pkcs11_add_provider_by_uri(uri, NULL, &keys, NULL)) > 0) {
|
| |
+ + for (i = 0; i < nkeys; i++) {
|
| |
+ + if (*n_ids >= SSH_MAX_IDENTITY_FILES) {
|
| |
+ + sshkey_free(keys[i]);
|
| |
+ + continue;
|
| |
+ + }
|
| |
+ + identity_keys[*n_ids] = keys[i];
|
| |
+ + identity_files[*n_ids] = pkcs11_uri_get(uri);
|
| |
+ + (*n_ids)++;
|
| |
+ + }
|
| |
+ + free(keys);
|
| |
+ + }
|
| |
+
|
| |
- +#define PKCS11_URI_PATH_SEPARATOR ";"
|
| |
- +#define PKCS11_URI_QUERY_SEPARATOR "&"
|
| |
- +#define PKCS11_URI_VALUE_SEPARATOR "="
|
| |
- +#define PKCS11_URI_ID "id"
|
| |
- +#define PKCS11_URI_TOKEN "token"
|
| |
- +#define PKCS11_URI_OBJECT "object"
|
| |
- +#define PKCS11_URI_LIB_MANUF "library-manufacturer"
|
| |
- +#define PKCS11_URI_MANUF "manufacturer"
|
| |
- +#define PKCS11_URI_MODULE_PATH "module-path"
|
| |
- +#define PKCS11_URI_PIN_VALUE "pin-value"
|
| |
+ + pkcs11_uri_cleanup(uri);
|
| |
+ +}
|
| |
+ +#endif /* ENABLE_PKCS11 */
|
| |
+
|
| |
- +/* Keyword tokens. */
|
| |
- +typedef enum {
|
| |
- + pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pModulePath,
|
| |
- + pPinValue, pBadOption
|
| |
- +} pkcs11uriOpCodes;
|
| |
- +
|
| |
- +/* Textual representation of the tokens. */
|
| |
- +static struct {
|
| |
- + const char *name;
|
| |
- + pkcs11uriOpCodes opcode;
|
| |
- +} keywords[] = {
|
| |
- + { PKCS11_URI_ID, pId },
|
| |
- + { PKCS11_URI_TOKEN, pToken },
|
| |
- + { PKCS11_URI_OBJECT, pObject },
|
| |
- + { PKCS11_URI_LIB_MANUF, pLibraryManufacturer },
|
| |
- + { PKCS11_URI_MANUF, pManufacturer },
|
| |
- + { PKCS11_URI_MODULE_PATH, pModulePath },
|
| |
- + { PKCS11_URI_PIN_VALUE, pPinValue },
|
| |
- + { NULL, pBadOption }
|
| |
- +};
|
| |
- +
|
| |
- +static pkcs11uriOpCodes
|
| |
- +parse_token(const char *cp)
|
| |
- +{
|
| |
- + u_int i;
|
| |
- +
|
| |
- + for (i = 0; keywords[i].name; i++)
|
| |
- + if (strncasecmp(cp, keywords[i].name,
|
| |
- + strlen(keywords[i].name)) == 0)
|
| |
- + return keywords[i].opcode;
|
| |
- +
|
| |
- + return pBadOption;
|
| |
- +}
|
| |
- +
|
| |
- +int
|
| |
- +percent_decode(char *data, char **outp)
|
| |
- +{
|
| |
- + char tmp[3];
|
| |
- + char *out, *tmp_end;
|
| |
- + char *p = data;
|
| |
- + long value;
|
| |
- + size_t outlen = 0;
|
| |
- +
|
| |
- + out = malloc(strlen(data)+1); /* upper bound */
|
| |
- + if (out == NULL)
|
| |
- + return -1;
|
| |
- + while (*p != '\0') {
|
| |
- + switch (*p) {
|
| |
- + case '%':
|
| |
- + p++;
|
| |
- + if (*p == '\0')
|
| |
- + goto fail;
|
| |
- + tmp[0] = *p++;
|
| |
- + if (*p == '\0')
|
| |
- + goto fail;
|
| |
- + tmp[1] = *p++;
|
| |
- + tmp[2] = '\0';
|
| |
- + tmp_end = NULL;
|
| |
- + value = strtol(tmp, &tmp_end, 16);
|
| |
- + if (tmp_end != tmp+2)
|
| |
- + goto fail;
|
| |
- + else
|
| |
- + out[outlen++] = (char) value;
|
| |
- + break;
|
| |
- + default:
|
| |
- + out[outlen++] = *p++;
|
| |
- + break;
|
| |
- + }
|
| |
- + }
|
| |
- +
|
| |
- + /* zero terminate */
|
| |
- + out[outlen] = '\0';
|
| |
- + *outp = out;
|
| |
- + return outlen;
|
| |
- +fail:
|
| |
- + free(out);
|
| |
- + return -1;
|
| |
- +}
|
| |
- +
|
| |
- +struct sshbuf *
|
| |
- +percent_encode(const char *data, size_t length, const char *allow_list)
|
| |
- +{
|
| |
- + struct sshbuf *b = NULL;
|
| |
- + char tmp[4], *cp;
|
| |
- + size_t i;
|
| |
- +
|
| |
- + if ((b = sshbuf_new()) == NULL)
|
| |
- + return NULL;
|
| |
- + for (i = 0; i < length; i++) {
|
| |
- + cp = strchr(allow_list, data[i]);
|
| |
- + /* if c is specified as '\0' pointer to terminator is returned !! */
|
| |
- + if (cp != NULL && *cp != '\0') {
|
| |
- + if (sshbuf_put(b, &data[i], 1) != 0)
|
| |
- + goto err;
|
| |
- + } else
|
| |
- + if (snprintf(tmp, 4, "%%%02X", (unsigned char) data[i]) < 3
|
| |
- + || sshbuf_put(b, tmp, 3) != 0)
|
| |
- + goto err;
|
| |
- + }
|
| |
- + if (sshbuf_put(b, "\0", 1) == 0)
|
| |
- + return b;
|
| |
- +err:
|
| |
- + sshbuf_free(b);
|
| |
- + return NULL;
|
| |
- +}
|
| |
- +
|
| |
- +char *
|
| |
- +pkcs11_uri_append(char *part, const char *separator, const char *key,
|
| |
- + struct sshbuf *value)
|
| |
- +{
|
| |
- + char *new_part;
|
| |
- + size_t size = 0;
|
| |
- +
|
| |
- + if (value == NULL)
|
| |
- + return NULL;
|
| |
- +
|
| |
- + size = asprintf(&new_part,
|
| |
- + "%s%s%s" PKCS11_URI_VALUE_SEPARATOR "%s",
|
| |
- + (part != NULL ? part : ""),
|
| |
- + (part != NULL ? separator : ""),
|
| |
- + key, sshbuf_ptr(value));
|
| |
- + sshbuf_free(value);
|
| |
- + free(part);
|
| |
- +
|
| |
- + if (size <= 0)
|
| |
- + return NULL;
|
| |
- + return new_part;
|
| |
- +}
|
| |
- +
|
| |
- +char *
|
| |
- +pkcs11_uri_get(struct pkcs11_uri *uri)
|
| |
- +{
|
| |
- + size_t size = 0;
|
| |
- + char *p = NULL, *path = NULL, *query = NULL;
|
| |
- +
|
| |
- + /* compose a percent-encoded ID */
|
| |
- + if (uri->id_len > 0) {
|
| |
- + struct sshbuf *key_id = percent_encode(uri->id, uri->id_len, "");
|
| |
- + path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,
|
| |
- + PKCS11_URI_ID, key_id);
|
| |
- + if (path == NULL)
|
| |
- + goto err;
|
| |
- + }
|
| |
- +
|
| |
- + /* Write object label */
|
| |
- + if (uri->object) {
|
| |
- + struct sshbuf *label = percent_encode(uri->object, strlen(uri->object),
|
| |
- + PKCS11_URI_WHITELIST);
|
| |
- + path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,
|
| |
- + PKCS11_URI_OBJECT, label);
|
| |
- + if (path == NULL)
|
| |
- + goto err;
|
| |
- + }
|
| |
- +
|
| |
- + /* Write token label */
|
| |
- + if (uri->token) {
|
| |
- + struct sshbuf *label = percent_encode(uri->token, strlen(uri->token),
|
| |
- + PKCS11_URI_WHITELIST);
|
| |
- + path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,
|
| |
- + PKCS11_URI_TOKEN, label);
|
| |
- + if (path == NULL)
|
| |
- + goto err;
|
| |
- + }
|
| |
- +
|
| |
- + /* Write manufacturer */
|
| |
- + if (uri->manuf) {
|
| |
- + struct sshbuf *manuf = percent_encode(uri->manuf,
|
| |
- + strlen(uri->manuf), PKCS11_URI_WHITELIST);
|
| |
- + path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,
|
| |
- + PKCS11_URI_MANUF, manuf);
|
| |
- + if (path == NULL)
|
| |
- + goto err;
|
| |
- + }
|
| |
- +
|
| |
- + /* Write module_path */
|
| |
- + if (uri->module_path) {
|
| |
- + struct sshbuf *module = percent_encode(uri->module_path,
|
| |
- + strlen(uri->module_path), PKCS11_URI_WHITELIST "/");
|
| |
- + query = pkcs11_uri_append(query, PKCS11_URI_QUERY_SEPARATOR,
|
| |
- + PKCS11_URI_MODULE_PATH, module);
|
| |
- + if (query == NULL)
|
| |
- + goto err;
|
| |
- + }
|
| |
- +
|
| |
- + size = asprintf(&p, PKCS11_URI_SCHEME "%s%s%s",
|
| |
- + path != NULL ? path : "",
|
| |
- + query != NULL ? "?" : "",
|
| |
- + query != NULL ? query : "");
|
| |
- +err:
|
| |
- + free(query);
|
| |
- + free(path);
|
| |
- + if (size <= 0)
|
| |
- + return NULL;
|
| |
- + return p;
|
| |
- +}
|
| |
- +
|
| |
- +struct pkcs11_uri *
|
| |
- +pkcs11_uri_init()
|
| |
- +{
|
| |
- + struct pkcs11_uri *d = calloc(1, sizeof(struct pkcs11_uri));
|
| |
- + return d;
|
| |
- +}
|
| |
- +
|
| |
- +void
|
| |
- +pkcs11_uri_cleanup(struct pkcs11_uri *pkcs11)
|
| |
- +{
|
| |
- + if (pkcs11 == NULL) {
|
| |
- + return;
|
| |
- + }
|
| |
- +
|
| |
- + free(pkcs11->id);
|
| |
- + free(pkcs11->module_path);
|
| |
- + free(pkcs11->token);
|
| |
- + free(pkcs11->object);
|
| |
- + free(pkcs11->lib_manuf);
|
| |
- + free(pkcs11->manuf);
|
| |
- + if (pkcs11->pin)
|
| |
- + freezero(pkcs11->pin, strlen(pkcs11->pin));
|
| |
- + free(pkcs11);
|
| |
- +}
|
| |
- +
|
| |
- +int
|
| |
- +pkcs11_uri_parse(const char *uri, struct pkcs11_uri *pkcs11)
|
| |
- +{
|
| |
- + char *saveptr1, *saveptr2, *str1, *str2, *tok;
|
| |
- + int rv = 0, len;
|
| |
- + char *p = NULL;
|
| |
- +
|
| |
- + size_t scheme_len = strlen(PKCS11_URI_SCHEME);
|
| |
- + if (strlen(uri) < scheme_len || /* empty URI matches everything */
|
| |
- + strncmp(uri, PKCS11_URI_SCHEME, scheme_len) != 0) {
|
| |
- + error_f("The '%s' does not look like PKCS#11 URI", uri);
|
| |
- + return -1;
|
| |
- + }
|
| |
- +
|
| |
- + if (pkcs11 == NULL) {
|
| |
- + error_f("Bad arguments. The pkcs11 can't be null");
|
| |
- + return -1;
|
| |
- + }
|
| |
- +
|
| |
- + /* skip URI schema name */
|
| |
- + p = strdup(uri);
|
| |
- + str1 = p;
|
| |
- +
|
| |
- + /* everything before ? */
|
| |
- + tok = strtok_r(str1, "?", &saveptr1);
|
| |
- + if (tok == NULL) {
|
| |
- + error_f("pk11-path expected, got EOF");
|
| |
- + rv = -1;
|
| |
- + goto out;
|
| |
- + }
|
| |
- +
|
| |
- + /* skip URI schema name:
|
| |
- + * the scheme ensures that there is at least something before "?"
|
| |
- + * allowing empty pk11-path. Resulting token at worst pointing to
|
| |
- + * \0 byte */
|
| |
- + tok = tok + scheme_len;
|
| |
- +
|
| |
- + /* parse pk11-path */
|
| |
- + for (str2 = tok; ; str2 = NULL) {
|
| |
- + char **charptr, *arg = NULL;
|
| |
- + pkcs11uriOpCodes opcode;
|
| |
- + tok = strtok_r(str2, PKCS11_URI_PATH_SEPARATOR, &saveptr2);
|
| |
- + if (tok == NULL)
|
| |
- + break;
|
| |
- + opcode = parse_token(tok);
|
| |
- + if (opcode != pBadOption)
|
| |
- + arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */
|
| |
- +
|
| |
- + switch (opcode) {
|
| |
- + case pId:
|
| |
- + /* CKA_ID */
|
| |
- + if (pkcs11->id != NULL) {
|
| |
- + verbose_f("The id already set in the PKCS#11 URI");
|
| |
- + rv = -1;
|
| |
- + goto out;
|
| |
- + }
|
| |
- + len = percent_decode(arg, &pkcs11->id);
|
| |
- + if (len <= 0) {
|
| |
- + verbose_f("Failed to percent-decode CKA_ID: %s", arg);
|
| |
- + rv = -1;
|
| |
- + goto out;
|
| |
- + } else
|
| |
- + pkcs11->id_len = len;
|
| |
- + debug3_f("Setting CKA_ID = %s from PKCS#11 URI", arg);
|
| |
- + break;
|
| |
- + case pToken:
|
| |
- + /* CK_TOKEN_INFO -> label */
|
| |
- + charptr = &pkcs11->token;
|
| |
- + parse_string:
|
| |
- + if (*charptr != NULL) {
|
| |
- + verbose_f("The %s already set in the PKCS#11 URI",
|
| |
- + keywords[opcode].name);
|
| |
- + rv = -1;
|
| |
- + goto out;
|
| |
- + }
|
| |
- + percent_decode(arg, charptr);
|
| |
- + debug3_f("Setting %s = %s from PKCS#11 URI",
|
| |
- + keywords[opcode].name, *charptr);
|
| |
- + break;
|
| |
- +
|
| |
- + case pObject:
|
| |
- + /* CK_TOKEN_INFO -> manufacturerID */
|
| |
- + charptr = &pkcs11->object;
|
| |
- + goto parse_string;
|
| |
- +
|
| |
- + case pManufacturer:
|
| |
- + /* CK_TOKEN_INFO -> manufacturerID */
|
| |
- + charptr = &pkcs11->manuf;
|
| |
- + goto parse_string;
|
| |
- +
|
| |
- + case pLibraryManufacturer:
|
| |
- + /* CK_INFO -> manufacturerID */
|
| |
- + charptr = &pkcs11->lib_manuf;
|
| |
- + goto parse_string;
|
| |
+ /* Loads all IdentityFile and CertificateFile keys */
|
| |
+ static void
|
| |
+ load_public_identity_files(const struct ssh_conn_info *cinfo)
|
| |
+ @@ -2225,11 +2273,6 @@ load_public_identity_files(const struct
|
| |
+ char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
|
| |
+ struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
|
| |
+ int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];
|
| |
+ -#ifdef ENABLE_PKCS11
|
| |
+ - struct sshkey **keys = NULL;
|
| |
+ - char **comments = NULL;
|
| |
+ - int nkeys;
|
| |
+ -#endif /* PKCS11 */
|
| |
+
|
| |
+ n_ids = n_certs = 0;
|
| |
+ memset(identity_files, 0, sizeof(identity_files));
|
| |
+ @@ -2242,33 +2285,46 @@ load_public_identity_files(const struct
|
| |
+ sizeof(certificate_file_userprovided));
|
| |
+
|
| |
+ #ifdef ENABLE_PKCS11
|
| |
+ - if (options.pkcs11_provider != NULL &&
|
| |
+ - options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
|
| |
+ - (pkcs11_init(!options.batch_mode) == 0) &&
|
| |
+ - (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
|
| |
+ - &keys, &comments)) > 0) {
|
| |
+ - for (i = 0; i < nkeys; i++) {
|
| |
+ - if (n_ids >= SSH_MAX_IDENTITY_FILES) {
|
| |
+ - sshkey_free(keys[i]);
|
| |
+ - free(comments[i]);
|
| |
+ - continue;
|
| |
+ - }
|
| |
+ - identity_keys[n_ids] = keys[i];
|
| |
+ - identity_files[n_ids] = comments[i]; /* transferred */
|
| |
+ - n_ids++;
|
| |
+ - }
|
| |
+ - free(keys);
|
| |
+ - free(comments);
|
| |
+ + /* handle fallback from PKCS11Provider option */
|
| |
+ + pkcs11_init(!options.batch_mode);
|
| |
+
|
| |
- + default:
|
| |
- + /* Unrecognized attribute in the URI path SHOULD be error */
|
| |
- + verbose_f("Unknown part of path in PKCS#11 URI: %s", tok);
|
| |
- + }
|
| |
- + }
|
| |
+ + if (options.pkcs11_provider != NULL) {
|
| |
+ + struct pkcs11_uri *uri;
|
| |
+
|
| |
- + tok = strtok_r(NULL, "?", &saveptr1);
|
| |
- + if (tok == NULL) {
|
| |
- + goto out;
|
| |
- + }
|
| |
- + /* parse pk11-query (optional) */
|
| |
- + for (str2 = tok; ; str2 = NULL) {
|
| |
- + char *arg;
|
| |
- + pkcs11uriOpCodes opcode;
|
| |
- + tok = strtok_r(str2, PKCS11_URI_QUERY_SEPARATOR, &saveptr2);
|
| |
- + if (tok == NULL)
|
| |
- + break;
|
| |
- + opcode = parse_token(tok);
|
| |
- + if (opcode != pBadOption)
|
| |
- + arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */
|
| |
+ + uri = pkcs11_uri_init();
|
| |
+ + if (uri == NULL)
|
| |
+ + fatal("Failed to init PKCS#11 URI");
|
| |
+
|
| |
- + switch (opcode) {
|
| |
- + case pModulePath:
|
| |
- + /* module-path is PKCS11Provider */
|
| |
- + if (pkcs11->module_path != NULL) {
|
| |
- + verbose_f("Multiple module-path attributes are"
|
| |
- + "not supported the PKCS#11 URI");
|
| |
- + rv = -1;
|
| |
- + goto out;
|
| |
- + }
|
| |
- + percent_decode(arg, &pkcs11->module_path);
|
| |
- + debug3_f("Setting PKCS11Provider = %s from PKCS#11 URI",
|
| |
- + pkcs11->module_path);
|
| |
- + break;
|
| |
+ + /* Construct simple PKCS#11 URI to simplify access */
|
| |
+ + uri->module_path = strdup(options.pkcs11_provider);
|
| |
+
|
| |
- + case pPinValue:
|
| |
- + /* pin-value */
|
| |
- + if (pkcs11->pin != NULL) {
|
| |
- + verbose_f("Multiple pin-value attributes are"
|
| |
- + "not supported the PKCS#11 URI");
|
| |
- + rv = -1;
|
| |
- + goto out;
|
| |
- + }
|
| |
- + percent_decode(arg, &pkcs11->pin);
|
| |
- + debug3_f("Setting PIN from PKCS#11 URI");
|
| |
- + break;
|
| |
+ + /* Add it as any other IdentityFile */
|
| |
+ + cp = pkcs11_uri_get(uri);
|
| |
+ + add_identity_file(&options, NULL, cp, 1);
|
| |
+ + free(cp);
|
| |
+
|
| |
- + default:
|
| |
- + /* Unrecognized attribute in the URI query SHOULD be ignored */
|
| |
- + verbose_f("Unknown part of query in PKCS#11 URI: %s", tok);
|
| |
+ + pkcs11_uri_cleanup(uri);
|
| |
+ }
|
| |
+ #endif /* ENABLE_PKCS11 */
|
| |
+ for (i = 0; i < options.num_identity_files; i++) {
|
| |
+ + char *name = options.identity_files[i];
|
| |
+ if (n_ids >= SSH_MAX_IDENTITY_FILES ||
|
| |
+ - strcasecmp(options.identity_files[i], "none") == 0) {
|
| |
+ + strcasecmp(name, "none") == 0) {
|
| |
+ free(options.identity_files[i]);
|
| |
+ options.identity_files[i] = NULL;
|
| |
+ continue;
|
| |
+ }
|
| |
+ - cp = tilde_expand_filename(options.identity_files[i], getuid());
|
| |
+ +#ifdef ENABLE_PKCS11
|
| |
+ + if (strlen(name) >= strlen(PKCS11_URI_SCHEME) &&
|
| |
+ + strncmp(name, PKCS11_URI_SCHEME,
|
| |
+ + strlen(PKCS11_URI_SCHEME)) == 0) {
|
| |
+ + load_pkcs11_identity(name, identity_files,
|
| |
+ + identity_keys, &n_ids);
|
| |
+ + free(options.identity_files[i]);
|
| |
+ + continue;
|
| |
+ }
|
| |
- + }
|
| |
- +out:
|
| |
- + free(p);
|
| |
- + return rv;
|
| |
- +}
|
| |
- +
|
| |
+#endif /* ENABLE_PKCS11 */
|
| |
- diff --git a/ssh-pkcs11-uri.h b/ssh-pkcs11-uri.h
|
| |
- new file mode 100644
|
| |
- index 00000000..942a5a5a
|
| |
- --- /dev/null
|
| |
- +++ b/ssh-pkcs11-uri.h
|
| |
- @@ -0,0 +1,42 @@
|
| |
- +/*
|
| |
- + * Copyright (c) 2017 Red Hat
|
| |
- + *
|
| |
- + * Authors: Jakub Jelen <jjelen@redhat.com>
|
| |
- + *
|
| |
- + * Permission to use, copy, modify, and distribute this software for any
|
| |
- + * purpose with or without fee is hereby granted, provided that the above
|
| |
- + * copyright notice and this permission notice appear in all copies.
|
| |
- + *
|
| |
- + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
| |
- + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
| |
- + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
| |
- + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
| |
- + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
| |
- + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
| |
- + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
| |
- + */
|
| |
- +
|
| |
- +#define PKCS11_URI_SCHEME "pkcs11:"
|
| |
- +#define PKCS11_URI_WHITELIST "abcdefghijklmnopqrstuvwxyz" \
|
| |
- + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
| |
- + "0123456789_-.()"
|
| |
- +
|
| |
- +struct pkcs11_uri {
|
| |
- + /* path */
|
| |
- + char *id;
|
| |
- + size_t id_len;
|
| |
- + char *token;
|
| |
- + char *object;
|
| |
- + char *lib_manuf;
|
| |
- + char *manuf;
|
| |
- + /* query */
|
| |
- + char *module_path;
|
| |
- + char *pin; /* Only parsed, but not printed */
|
| |
- +};
|
| |
- +
|
| |
- +struct pkcs11_uri *pkcs11_uri_init();
|
| |
- +void pkcs11_uri_cleanup(struct pkcs11_uri *);
|
| |
- +int pkcs11_uri_parse(const char *, struct pkcs11_uri *);
|
| |
- +struct pkcs11_uri *pkcs11_uri_init();
|
| |
- +char *pkcs11_uri_get(struct pkcs11_uri *uri);
|
| |
+ + cp = tilde_expand_filename(name, getuid());
|
| |
+ filename = default_client_percent_dollar_expand(cp, cinfo);
|
| |
+ free(cp);
|
| |
+ check_load(sshkey_load_public(filename, &public, NULL),
|
| |
+ diff -up openssh-8.6p1/ssh-keygen.c.pkcs11-uri openssh-8.6p1/ssh-keygen.c
|
| |
+ --- openssh-8.6p1/ssh-keygen.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200
|
| |
+ +++ openssh-8.6p1/ssh-keygen.c 2021-04-19 14:57:30.318370565 +0200
|
| |
+ @@ -860,8 +860,11 @@ do_download(struct passwd *pw)
|
| |
+ free(fp);
|
| |
+ } else {
|
| |
+ (void) sshkey_write(keys[i], stdout); /* XXX check */
|
| |
+ - fprintf(stdout, "%s%s\n",
|
| |
+ - *(comments[i]) == '\0' ? "" : " ", comments[i]);
|
| |
+ + if (*(comments[i]) != '\0') {
|
| |
+ + fprintf(stdout, " %s", comments[i]);
|
| |
+ + }
|
| |
+ + (void) pkcs11_uri_write(keys[i], stdout);
|
| |
+ + fprintf(stdout, "\n");
|
| |
+ }
|
| |
+ free(comments[i]);
|
| |
+ sshkey_free(keys[i]);
|
| |
+ diff -up openssh-8.6p1/ssh-pkcs11-client.c.pkcs11-uri openssh-8.6p1/ssh-pkcs11-client.c
|
| |
+ --- openssh-8.6p1/ssh-pkcs11-client.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200
|
| |
+ +++ openssh-8.6p1/ssh-pkcs11-client.c 2021-04-19 14:57:30.318370565 +0200
|
| |
+ @@ -323,6 +323,8 @@ pkcs11_add_provider(char *name, char *pi
|
| |
+ u_int nkeys, i;
|
| |
+ struct sshbuf *msg;
|
| |
+
|
| |
+ + debug_f("called, name = %s", name);
|
| |
+
|
| |
- diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
|
| |
- index a302c79c..879fe917 100644
|
| |
- --- a/ssh-pkcs11.c
|
| |
- +++ b/ssh-pkcs11.c
|
| |
- @@ -54,8 +54,8 @@ struct pkcs11_slotinfo {
|
| |
+ if (fd < 0 && pkcs11_start_helper() < 0)
|
| |
+ return (-1);
|
| |
+
|
| |
+ @@ -342,6 +344,7 @@ pkcs11_add_provider(char *name, char *pi
|
| |
+ *keysp = xcalloc(nkeys, sizeof(struct sshkey *));
|
| |
+ if (labelsp)
|
| |
+ *labelsp = xcalloc(nkeys, sizeof(char *));
|
| |
+ + debug_f("nkeys = %u", nkeys);
|
| |
+ for (i = 0; i < nkeys; i++) {
|
| |
+ /* XXX clean up properly instead of fatal() */
|
| |
+ if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 ||
|
| |
+ diff -up openssh-8.6p1/ssh-pkcs11.c.pkcs11-uri openssh-8.6p1/ssh-pkcs11.c
|
| |
+ --- openssh-8.6p1/ssh-pkcs11.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200
|
| |
+ +++ openssh-8.6p1/ssh-pkcs11.c 2021-04-19 14:57:30.320370580 +0200
|
| |
+ @@ -55,8 +55,8 @@ struct pkcs11_slotinfo {
|
| |
int logged_in;
|
| |
};
|
| |
|
| |
@@ -1699,7 +1351,7 @@
|
| |
void *handle;
|
| |
CK_FUNCTION_LIST *function_list;
|
| |
CK_INFO info;
|
| |
- @@ -64,6 +64,13 @@ struct pkcs11_provider {
|
| |
+ @@ -65,6 +65,13 @@ struct pkcs11_provider {
|
| |
struct pkcs11_slotinfo *slotinfo;
|
| |
int valid;
|
| |
int refcount;
|
| |
@@ -1713,7 +1365,7 @@
|
| |
TAILQ_ENTRY(pkcs11_provider) next;
|
| |
};
|
| |
|
| |
- @@ -74,6 +81,7 @@ struct pkcs11_key {
|
| |
+ @@ -75,6 +82,7 @@ struct pkcs11_key {
|
| |
CK_ULONG slotidx;
|
| |
char *keyid;
|
| |
int keyid_len;
|
| |
@@ -1794,7 +1446,7 @@
|
| |
}
|
| |
|
| |
/*
|
| |
- @@ -135,13 +180,11 @@ pkcs11_provider_finalize(struct pkcs11_provider *p)
|
| |
+ @@ -135,13 +178,11 @@ pkcs11_provider_finalize(struct pkcs11_p
|
| |
static void
|
| |
pkcs11_provider_unref(struct pkcs11_provider *p)
|
| |
{
|
| |
@@ -1811,7 +1463,7 @@
|
| |
free(p);
|
| |
}
|
| |
}
|
| |
- @@ -159,6 +202,20 @@ pkcs11_terminate(void)
|
| |
+ @@ -159,6 +200,20 @@ pkcs11_terminate(void)
|
| |
}
|
| |
}
|
| |
|
| |
@@ -1832,7 +1484,7 @@
|
| |
/* lookup provider by name */
|
| |
static struct pkcs11_provider *
|
| |
pkcs11_provider_lookup(char *provider_id)
|
| |
- @@ -173,19 +230,52 @@ pkcs11_provider_lookup(char *provider_id)
|
| |
+ @@ -173,19 +228,52 @@ pkcs11_provider_lookup(char *provider_id
|
| |
return (NULL);
|
| |
}
|
| |
|
| |
@@ -1841,7 +1493,7 @@
|
| |
/* unregister provider by name */
|
| |
int
|
| |
pkcs11_del_provider(char *provider_id)
|
| |
- +{
|
| |
+ {
|
| |
+ int rv;
|
| |
+ struct pkcs11_uri *uri;
|
| |
+
|
| |
@@ -1867,7 +1519,7 @@
|
| |
+/* unregister provider by PKCS#11 URI */
|
| |
+int
|
| |
+pkcs11_del_provider_by_uri(struct pkcs11_uri *uri)
|
| |
- {
|
| |
+ +{
|
| |
struct pkcs11_provider *p;
|
| |
+ int rv = -1;
|
| |
+ char *provider_uri = pkcs11_uri_get(uri);
|
| |
@@ -1888,7 +1540,7 @@
|
| |
}
|
| |
|
| |
static RSA_METHOD *rsa_method;
|
| |
- @@ -195,6 +285,55 @@ static EC_KEY_METHOD *ec_key_method;
|
| |
+ @@ -195,6 +283,55 @@ static EC_KEY_METHOD *ec_key_method;
|
| |
static int ec_key_idx = 0;
|
| |
#endif
|
| |
|
| |
@@ -1944,7 +1596,7 @@
|
| |
/* release a wrapped object */
|
| |
static void
|
| |
pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
|
| |
- @@ -208,6 +347,7 @@ pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
|
| |
+ @@ -208,6 +345,7 @@ pkcs11_k11_free(void *parent, void *ptr,
|
| |
if (k11->provider)
|
| |
pkcs11_provider_unref(k11->provider);
|
| |
free(k11->keyid);
|
| |
@@ -1952,7 +1604,7 @@
|
| |
free(k11);
|
| |
}
|
| |
|
| |
- @@ -222,8 +362,8 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
|
| |
+ @@ -222,8 +360,8 @@ pkcs11_find(struct pkcs11_provider *p, C
|
| |
CK_RV rv;
|
| |
int ret = -1;
|
| |
|
| |
@@ -1963,7 +1615,7 @@
|
| |
if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) {
|
| |
error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv);
|
| |
return (-1);
|
| |
- @@ -262,12 +402,12 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si,
|
| |
+ @@ -262,12 +400,12 @@ pkcs11_login_slot(struct pkcs11_provider
|
| |
else {
|
| |
snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
|
| |
si->token.label);
|
| |
@@ -1978,7 +1630,7 @@
|
| |
(pin != NULL) ? strlen(pin) : 0);
|
| |
if (pin != NULL)
|
| |
freezero(pin, strlen(pin));
|
| |
- @@ -282,13 +422,14 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si,
|
| |
+ @@ -297,13 +435,14 @@ pkcs11_login_slot(struct pkcs11_provider
|
| |
static int
|
| |
pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type)
|
| |
{
|
| |
@@ -1995,7 +1647,7 @@
|
| |
}
|
| |
|
| |
|
| |
- @@ -304,13 +445,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj,
|
| |
+ @@ -319,13 +458,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs
|
| |
|
| |
*val = 0;
|
| |
|
| |
@@ -2013,7 +1665,7 @@
|
| |
|
| |
attr.type = type;
|
| |
attr.pValue = &flag;
|
| |
- @@ -341,13 +483,14 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
|
| |
+ @@ -356,13 +496,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C
|
| |
int always_auth = 0;
|
| |
int did_login = 0;
|
| |
|
| |
@@ -2031,7 +1683,7 @@
|
| |
|
| |
if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
|
| |
if (pkcs11_login(k11, CKU_USER) < 0) {
|
| |
- @@ -424,8 +567,8 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
|
| |
+ @@ -439,8 +580,8 @@ pkcs11_rsa_private_encrypt(int flen, con
|
| |
return (-1);
|
| |
}
|
| |
|
| |
@@ -2042,7 +1694,7 @@
|
| |
tlen = RSA_size(rsa);
|
| |
|
| |
/* XXX handle CKR_BUFFER_TOO_SMALL */
|
| |
- @@ -469,7 +612,7 @@ pkcs11_rsa_start_wrapper(void)
|
| |
+ @@ -484,7 +625,7 @@ pkcs11_rsa_start_wrapper(void)
|
| |
/* redirect private key operations for rsa key to pkcs11 token */
|
| |
static int
|
| |
pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
| |
@@ -2051,7 +1703,7 @@
|
| |
{
|
| |
struct pkcs11_key *k11;
|
| |
|
| |
- @@ -487,6 +630,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
| |
+ @@ -502,6 +643,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider *
|
| |
memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
|
| |
}
|
| |
|
| |
@@ -2064,7 +1716,7 @@
|
| |
RSA_set_method(rsa, rsa_method);
|
| |
RSA_set_ex_data(rsa, rsa_idx, k11);
|
| |
return (0);
|
| |
- @@ -517,8 +666,8 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
| |
+ @@ -532,8 +679,8 @@ ecdsa_do_sign(const unsigned char *dgst,
|
| |
return (NULL);
|
| |
}
|
| |
|
| |
@@ -2075,7 +1727,7 @@
|
| |
|
| |
siglen = ECDSA_size(ec);
|
| |
sig = xmalloc(siglen);
|
| |
- @@ -583,7 +732,7 @@ pkcs11_ecdsa_start_wrapper(void)
|
| |
+ @@ -598,7 +745,7 @@ pkcs11_ecdsa_start_wrapper(void)
|
| |
|
| |
static int
|
| |
pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
| |
@@ -2084,7 +1736,7 @@
|
| |
{
|
| |
struct pkcs11_key *k11;
|
| |
|
| |
- @@ -599,6 +748,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
| |
+ @@ -614,6 +761,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider
|
| |
k11->keyid = xmalloc(k11->keyid_len);
|
| |
memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
|
| |
|
| |
@@ -2097,7 +1749,7 @@
|
| |
EC_KEY_set_method(ec, ec_key_method);
|
| |
EC_KEY_set_ex_data(ec, ec_key_idx, k11);
|
| |
|
| |
- @@ -635,8 +790,8 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
|
| |
+ @@ -650,8 +803,8 @@ pkcs11_open_session(struct pkcs11_provid
|
| |
CK_SESSION_HANDLE session;
|
| |
int login_required, ret;
|
| |
|
| |
@@ -2108,7 +1760,7 @@
|
| |
|
| |
login_required = si->token.flags & CKF_LOGIN_REQUIRED;
|
| |
|
| |
- @@ -646,9 +801,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
|
| |
+ @@ -661,9 +814,9 @@ pkcs11_open_session(struct pkcs11_provid
|
| |
error("pin required");
|
| |
return (-SSH_PKCS11_ERR_PIN_REQUIRED);
|
| |
}
|
| |
@@ -2120,7 +1772,7 @@
|
| |
return (-1);
|
| |
}
|
| |
if (login_required && pin != NULL && strlen(pin) != 0) {
|
| |
- @@ -684,7 +839,8 @@ static struct sshkey *
|
| |
+ @@ -699,7 +852,8 @@ static struct sshkey *
|
| |
pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
CK_OBJECT_HANDLE *obj)
|
| |
{
|
| |
@@ -2130,7 +1782,7 @@
|
| |
CK_SESSION_HANDLE session;
|
| |
CK_FUNCTION_LIST *f = NULL;
|
| |
CK_RV rv;
|
| |
- @@ -698,14 +854,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -713,14 +867,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_
|
| |
|
| |
memset(&key_attr, 0, sizeof(key_attr));
|
| |
key_attr[0].type = CKA_ID;
|
| |
@@ -2151,7 +1803,7 @@
|
| |
if (rv != CKR_OK) {
|
| |
error("C_GetAttributeValue failed: %lu", rv);
|
| |
return (NULL);
|
| |
- @@ -717,19 +874,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -731,19 +886,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_
|
| |
* ensure that none of the others are zero length.
|
| |
* XXX assumes CKA_ID is always first.
|
| |
*/
|
| |
@@ -2175,7 +1827,7 @@
|
| |
if (rv != CKR_OK) {
|
| |
error("C_GetAttributeValue failed: %lu", rv);
|
| |
goto fail;
|
| |
- @@ -740,8 +898,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -755,8 +910,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_
|
| |
goto fail;
|
| |
}
|
| |
|
| |
@@ -2186,7 +1838,7 @@
|
| |
if (group == NULL) {
|
| |
ossl_error("d2i_ECPKParameters failed");
|
| |
goto fail;
|
| |
- @@ -752,13 +910,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -767,13 +922,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_
|
| |
goto fail;
|
| |
}
|
| |
|
| |
@@ -2203,7 +1855,7 @@
|
| |
if (octet == NULL) {
|
| |
ossl_error("d2i_ASN1_OCTET_STRING failed");
|
| |
goto fail;
|
| |
- @@ -775,7 +933,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -790,7 +945,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_
|
| |
goto fail;
|
| |
}
|
| |
|
| |
@@ -2212,7 +1864,7 @@
|
| |
goto fail;
|
| |
|
| |
key = sshkey_new(KEY_UNSPEC);
|
| |
- @@ -791,7 +949,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -806,7 +961,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_
|
| |
ec = NULL; /* now owned by key */
|
| |
|
| |
fail:
|
| |
@@ -2221,7 +1873,7 @@
|
| |
free(key_attr[i].pValue);
|
| |
if (ec)
|
| |
EC_KEY_free(ec);
|
| |
- @@ -808,7 +966,8 @@ static struct sshkey *
|
| |
+ @@ -823,7 +978,8 @@ static struct sshkey *
|
| |
pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
CK_OBJECT_HANDLE *obj)
|
| |
{
|
| |
@@ -2231,7 +1883,7 @@
|
| |
CK_SESSION_HANDLE session;
|
| |
CK_FUNCTION_LIST *f = NULL;
|
| |
CK_RV rv;
|
| |
- @@ -819,14 +978,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -834,14 +990,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr
|
| |
|
| |
memset(&key_attr, 0, sizeof(key_attr));
|
| |
key_attr[0].type = CKA_ID;
|
| |
@@ -2252,7 +1904,7 @@
|
| |
if (rv != CKR_OK) {
|
| |
error("C_GetAttributeValue failed: %lu", rv);
|
| |
return (NULL);
|
| |
- @@ -838,19 +998,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -852,19 +1009,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr
|
| |
* ensure that none of the others are zero length.
|
| |
* XXX assumes CKA_ID is always first.
|
| |
*/
|
| |
@@ -2276,7 +1928,7 @@
|
| |
if (rv != CKR_OK) {
|
| |
error("C_GetAttributeValue failed: %lu", rv);
|
| |
goto fail;
|
| |
- @@ -861,8 +1022,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -876,8 +1033,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr
|
| |
goto fail;
|
| |
}
|
| |
|
| |
@@ -2287,7 +1939,7 @@
|
| |
if (rsa_n == NULL || rsa_e == NULL) {
|
| |
error("BN_bin2bn failed");
|
| |
goto fail;
|
| |
- @@ -871,7 +1032,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -886,7 +1043,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr
|
| |
fatal_f("set key");
|
| |
rsa_n = rsa_e = NULL; /* transferred */
|
| |
|
| |
@@ -2296,7 +1948,7 @@
|
| |
goto fail;
|
| |
|
| |
key = sshkey_new(KEY_UNSPEC);
|
| |
- @@ -886,7 +1047,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -901,7 +1058,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr
|
| |
rsa = NULL; /* now owned by key */
|
| |
|
| |
fail:
|
| |
@@ -2305,7 +1957,7 @@
|
| |
free(key_attr[i].pValue);
|
| |
RSA_free(rsa);
|
| |
|
| |
- @@ -897,7 +1058,8 @@ static int
|
| |
+ @@ -912,7 +1069,8 @@ static int
|
| |
pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp)
|
| |
{
|
| |
@@ -2315,7 +1967,7 @@
|
| |
CK_SESSION_HANDLE session;
|
| |
CK_FUNCTION_LIST *f = NULL;
|
| |
CK_RV rv;
|
| |
- @@ -921,14 +1083,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -936,14 +1094,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p
|
| |
|
| |
memset(&cert_attr, 0, sizeof(cert_attr));
|
| |
cert_attr[0].type = CKA_ID;
|
| |
@@ -2336,7 +1988,7 @@
|
| |
if (rv != CKR_OK) {
|
| |
error("C_GetAttributeValue failed: %lu", rv);
|
| |
return -1;
|
| |
- @@ -940,18 +1103,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -955,18 +1114,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p
|
| |
* XXX assumes CKA_ID is always first.
|
| |
*/
|
| |
if (cert_attr[1].ulValueLen == 0 ||
|
| |
@@ -2359,7 +2011,7 @@
|
| |
if (rv != CKR_OK) {
|
| |
error("C_GetAttributeValue failed: %lu", rv);
|
| |
goto out;
|
| |
- @@ -965,8 +1129,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -980,8 +1140,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p
|
| |
subject = xstrdup("invalid subject");
|
| |
X509_NAME_free(x509_name);
|
| |
|
| |
@@ -2370,7 +2022,7 @@
|
| |
error("d2i_x509 failed");
|
| |
goto out;
|
| |
}
|
| |
- @@ -986,7 +1150,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -1001,7 +1161,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p
|
| |
goto out;
|
| |
}
|
| |
|
| |
@@ -2379,7 +2031,7 @@
|
| |
goto out;
|
| |
|
| |
key = sshkey_new(KEY_UNSPEC);
|
| |
- @@ -1016,7 +1180,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -1031,7 +1191,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p
|
| |
goto out;
|
| |
}
|
| |
|
| |
@@ -2388,7 +2040,7 @@
|
| |
goto out;
|
| |
|
| |
key = sshkey_new(KEY_UNSPEC);
|
| |
- @@ -1036,7 +1200,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -1051,7 +1211,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p
|
| |
goto out;
|
| |
}
|
| |
out:
|
| |
@@ -2397,7 +2049,7 @@
|
| |
free(cert_attr[i].pValue);
|
| |
X509_free(x509);
|
| |
RSA_free(rsa);
|
| |
- @@ -1071,11 +1235,12 @@ have_rsa_key(const RSA *rsa)
|
| |
+ @@ -1102,11 +1262,12 @@ note_key(struct pkcs11_provider *p, CK_U
|
| |
*/
|
| |
static int
|
| |
pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
@@ -2412,7 +2064,7 @@
|
| |
CK_SESSION_HANDLE session;
|
| |
CK_FUNCTION_LIST *f = NULL;
|
| |
CK_RV rv;
|
| |
- @@ -1092,10 +1257,23 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -1123,10 +1284,23 @@ pkcs11_fetch_certs(struct pkcs11_provide
|
| |
key_attr[0].pValue = &key_class;
|
| |
key_attr[0].ulValueLen = sizeof(key_class);
|
| |
|
| |
@@ -2439,7 +2091,7 @@
|
| |
if (rv != CKR_OK) {
|
| |
error("C_FindObjectsInit failed: %lu", rv);
|
| |
goto fail;
|
| |
- @@ -1175,11 +1353,12 @@ fail:
|
| |
+ @@ -1207,11 +1381,12 @@ fail:
|
| |
*/
|
| |
static int
|
| |
pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
@@ -2454,7 +2106,7 @@
|
| |
CK_SESSION_HANDLE session;
|
| |
CK_FUNCTION_LIST *f = NULL;
|
| |
CK_RV rv;
|
| |
- @@ -1195,10 +1374,23 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -1227,10 +1402,23 @@ pkcs11_fetch_keys(struct pkcs11_provider
|
| |
key_attr[0].pValue = &key_class;
|
| |
key_attr[0].ulValueLen = sizeof(key_class);
|
| |
|
| |
@@ -2481,7 +2133,7 @@
|
| |
if (rv != CKR_OK) {
|
| |
error("C_FindObjectsInit failed: %lu", rv);
|
| |
goto fail;
|
| |
- @@ -1466,16 +1658,10 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
|
| |
+ @@ -1499,16 +1687,10 @@ pkcs11_ecdsa_generate_private_key(struct
|
| |
}
|
| |
#endif /* WITH_PKCS11_KEYGEN */
|
| |
|
| |
@@ -2500,39 +2152,37 @@
|
| |
int ret = -1;
|
| |
struct pkcs11_provider *p = NULL;
|
| |
void *handle = NULL;
|
| |
- @@ -1484,164 +1670,298 @@ pkcs11_register_provider(char *provider_id, char *pin,
|
| |
+ @@ -1517,164 +1699,298 @@ pkcs11_register_provider(char *provider_
|
| |
CK_FUNCTION_LIST *f = NULL;
|
| |
CK_TOKEN_INFO *token;
|
| |
CK_ULONG i;
|
| |
- -
|
| |
- - if (providerp == NULL)
|
| |
+ char *provider_module = NULL;
|
| |
+ struct pkcs11_module *m = NULL;
|
| |
- +
|
| |
+
|
| |
+ - if (providerp == NULL)
|
| |
+ /* if no provider specified, fallback to p11-kit */
|
| |
+ if (uri->module_path == NULL) {
|
| |
+#ifdef PKCS11_DEFAULT_PROVIDER
|
| |
+ provider_module = strdup(PKCS11_DEFAULT_PROVIDER);
|
| |
+#else
|
| |
- + error_f("No module path provided");
|
| |
- goto fail;
|
| |
- - *providerp = NULL;
|
| |
- -
|
| |
- - if (keyp != NULL)
|
| |
- - *keyp = NULL;
|
| |
- - if (labelsp != NULL)
|
| |
- - *labelsp = NULL;
|
| |
+ + error_f("No module path provided");
|
| |
+ goto fail;
|
| |
+ - *providerp = NULL;
|
| |
+#endif
|
| |
+ } else {
|
| |
+ provider_module = strdup(uri->module_path);
|
| |
+ }
|
| |
|
| |
+ - if (keyp != NULL)
|
| |
+ - *keyp = NULL;
|
| |
+ - if (labelsp != NULL)
|
| |
+ - *labelsp = NULL;
|
| |
+ + p = xcalloc(1, sizeof(*p));
|
| |
+ + p->name = pkcs11_uri_get(uri);
|
| |
+
|
| |
- if (pkcs11_provider_lookup(provider_id) != NULL) {
|
| |
- debug_f("provider already registered: %s", provider_id);
|
| |
- goto fail;
|
| |
- + p = xcalloc(1, sizeof(*p));
|
| |
- + p->name = pkcs11_uri_get(uri);
|
| |
- +
|
| |
+ if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL
|
| |
+ && m->valid) {
|
| |
+ debug_f("provider module already initialized: %s", provider_module);
|
| |
@@ -2623,8 +2273,8 @@
|
| |
goto fail;
|
| |
}
|
| |
- if (p->nslots == 0) {
|
| |
- + if (m->nslots == 0) {
|
| |
- debug_f("provider %s returned no slots", provider_id);
|
| |
+ + if (m->nslots == 0) {
|
| |
+ debug_f("provider %s returned no slots", provider_module);
|
| |
ret = -SSH_PKCS11_ERR_NO_SLOTS;
|
| |
goto fail;
|
| |
@@ -2653,14 +2303,19 @@
|
| |
!= CKR_OK) {
|
| |
error("C_GetTokenInfo for provider %s slot %lu "
|
| |
- "failed: %lu", provider_id, (u_long)i, rv);
|
| |
+ - continue;
|
| |
+ - }
|
| |
+ - if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {
|
| |
+ - debug2_f("ignoring uninitialised token in "
|
| |
+ - "provider %s slot %lu", provider_id, (u_long)i);
|
| |
+ "failed: %lu", provider_module, (u_long)i, rv);
|
| |
+ token->flags = 0;
|
| |
continue;
|
| |
}
|
| |
- + rmspace(token->label, sizeof(token->label));
|
| |
- + rmspace(token->manufacturerID, sizeof(token->manufacturerID));
|
| |
- + rmspace(token->model, sizeof(token->model));
|
| |
- + rmspace(token->serialNumber, sizeof(token->serialNumber));
|
| |
+ rmspace(token->label, sizeof(token->label));
|
| |
+ rmspace(token->manufacturerID, sizeof(token->manufacturerID));
|
| |
+ rmspace(token->model, sizeof(token->model));
|
| |
+ rmspace(token->serialNumber, sizeof(token->serialNumber));
|
| |
+ }
|
| |
+ m->module_path = provider_module;
|
| |
+ provider_module = NULL;
|
| |
@@ -2723,9 +2378,8 @@
|
| |
+ nkeys = 0;
|
| |
+ for (i = 0; i < p->module->nslots; i++) {
|
| |
+ token = &p->module->slotinfo[i].token;
|
| |
- if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {
|
| |
- debug2_f("ignoring uninitialised token in "
|
| |
- - "provider %s slot %lu", provider_id, (u_long)i);
|
| |
+ + if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {
|
| |
+ + debug2_f("ignoring uninitialised token in "
|
| |
+ "provider %s slot %lu", provider_uri, (u_long)i);
|
| |
+ continue;
|
| |
+ }
|
| |
@@ -2741,12 +2395,8 @@
|
| |
+ debug2_f("ignoring token not matching requrested "
|
| |
+ "manufacturerID (%s) specified by PKCS#11 URI in "
|
| |
+ "slot %lu", token->manufacturerID, (unsigned long)i);
|
| |
- continue;
|
| |
- }
|
| |
- - rmspace(token->label, sizeof(token->label));
|
| |
- - rmspace(token->manufacturerID, sizeof(token->manufacturerID));
|
| |
- - rmspace(token->model, sizeof(token->model));
|
| |
- - rmspace(token->serialNumber, sizeof(token->serialNumber));
|
| |
+ + continue;
|
| |
+ + }
|
| |
debug("provider %s slot %lu: label <%s> manufacturerID <%s> "
|
| |
"model <%s> serial <%s> flags 0x%lx",
|
| |
- provider_id, (unsigned long)i,
|
| |
@@ -2835,279 +2485,570 @@
|
| |
+pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,
|
| |
+ char ***labelsp, struct pkcs11_provider **providerp, CK_ULONG user)
|
| |
+{
|
| |
- + struct pkcs11_uri *uri = NULL;
|
| |
- + int r;
|
| |
+ + struct pkcs11_uri *uri = NULL;
|
| |
+ + int r;
|
| |
+ +
|
| |
+ + debug_f("called, provider_id = %s", provider_id);
|
| |
+ +
|
| |
+ + uri = pkcs11_uri_init();
|
| |
+ + if (uri == NULL)
|
| |
+ + fatal("failed to init PKCS#11 URI");
|
| |
+ +
|
| |
+ + if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) &&
|
| |
+ + strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) {
|
| |
+ + if (pkcs11_uri_parse(provider_id, uri) != 0)
|
| |
+ + fatal("Failed to parse PKCS#11 URI");
|
| |
+ + } else {
|
| |
+ + uri->module_path = strdup(provider_id);
|
| |
+ + }
|
| |
+ +
|
| |
+ + r = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, providerp, user);
|
| |
+ + pkcs11_uri_cleanup(uri);
|
| |
+ +
|
| |
+ + return r;
|
| |
+ +}
|
| |
+ +
|
| |
+ int
|
| |
+ -pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
|
| |
+ - char ***labelsp)
|
| |
+ +pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin,
|
| |
+ + struct sshkey ***keyp, char ***labelsp)
|
| |
+ {
|
| |
+ struct pkcs11_provider *p = NULL;
|
| |
+ int nkeys;
|
| |
+ + char *provider_uri = pkcs11_uri_get(uri);
|
| |
+ +
|
| |
+ + debug_f("called, provider_uri = %s", provider_uri);
|
| |
+
|
| |
+ - nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
|
| |
+ - &p, CKU_USER);
|
| |
+ + nkeys = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, &p, CKU_USER);
|
| |
+
|
| |
+ /* no keys found or some other error, de-register provider */
|
| |
+ if (nkeys <= 0 && p != NULL) {
|
| |
+ @@ -1683,7 +1999,37 @@ pkcs11_add_provider(char *provider_id, c
|
| |
+ pkcs11_provider_unref(p);
|
| |
+ }
|
| |
+ if (nkeys == 0)
|
| |
+ - debug_f("provider %s returned no keys", provider_id);
|
| |
+ + debug_f("provider %s returned no keys", provider_uri);
|
| |
+ +
|
| |
+ + free(provider_uri);
|
| |
+ + return nkeys;
|
| |
+ +}
|
| |
+ +
|
| |
+ +/*
|
| |
+ + * register a new provider and get number of keys hold by the token,
|
| |
+ + * fails if provider already exists
|
| |
+ + */
|
| |
+ +int
|
| |
+ +pkcs11_add_provider(char *provider_id, char *pin,
|
| |
+ + struct sshkey ***keyp, char ***labelsp)
|
| |
+ +{
|
| |
+ + struct pkcs11_uri *uri;
|
| |
+ + int nkeys;
|
| |
+ +
|
| |
+ + uri = pkcs11_uri_init();
|
| |
+ + if (uri == NULL)
|
| |
+ + fatal("Failed to init PKCS#11 URI");
|
| |
+ +
|
| |
+ + if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) &&
|
| |
+ + strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) {
|
| |
+ + if (pkcs11_uri_parse(provider_id, uri) != 0)
|
| |
+ + fatal("Failed to parse PKCS#11 URI");
|
| |
+ + } else {
|
| |
+ + uri->module_path = strdup(provider_id);
|
| |
+ + }
|
| |
+ +
|
| |
+ + nkeys = pkcs11_add_provider_by_uri(uri, pin, keyp, labelsp);
|
| |
+ + pkcs11_uri_cleanup(uri);
|
| |
+
|
| |
+ return (nkeys);
|
| |
+ }
|
| |
+ diff -up openssh-8.6p1/ssh-pkcs11.h.pkcs11-uri openssh-8.6p1/ssh-pkcs11.h
|
| |
+ --- openssh-8.6p1/ssh-pkcs11.h.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200
|
| |
+ +++ openssh-8.6p1/ssh-pkcs11.h 2021-04-19 14:57:30.320370580 +0200
|
| |
+ @@ -22,10 +22,14 @@
|
| |
+ #define SSH_PKCS11_ERR_PIN_REQUIRED 4
|
| |
+ #define SSH_PKCS11_ERR_PIN_LOCKED 5
|
| |
+
|
| |
+ +#include "ssh-pkcs11-uri.h"
|
| |
+ +
|
| |
+ int pkcs11_init(int);
|
| |
+ void pkcs11_terminate(void);
|
| |
+ int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***);
|
| |
+ +int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***, char ***);
|
| |
+ int pkcs11_del_provider(char *);
|
| |
+ +int pkcs11_uri_write(const struct sshkey *, FILE *);
|
| |
+ #ifdef WITH_PKCS11_KEYGEN
|
| |
+ struct sshkey *
|
| |
+ pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int,
|
| |
+ diff -up openssh-8.6p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.6p1/ssh-pkcs11-uri.c
|
| |
+ --- openssh-8.6p1/ssh-pkcs11-uri.c.pkcs11-uri 2021-04-19 14:57:30.318370565 +0200
|
| |
+ +++ openssh-8.6p1/ssh-pkcs11-uri.c 2021-04-19 14:57:30.318370565 +0200
|
| |
+ @@ -0,0 +1,419 @@
|
| |
+ +/*
|
| |
+ + * Copyright (c) 2017 Red Hat
|
| |
+ + *
|
| |
+ + * Authors: Jakub Jelen <jjelen@redhat.com>
|
| |
+ + *
|
| |
+ + * Permission to use, copy, modify, and distribute this software for any
|
| |
+ + * purpose with or without fee is hereby granted, provided that the above
|
| |
+ + * copyright notice and this permission notice appear in all copies.
|
| |
+ + *
|
| |
+ + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
| |
+ + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
| |
+ + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
| |
+ + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
| |
+ + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
| |
+ + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
| |
+ + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
| |
+ + */
|
| |
+ +
|
| |
+ +#include "includes.h"
|
| |
+ +
|
| |
+ +#ifdef ENABLE_PKCS11
|
| |
+ +
|
| |
+ +#include <stdio.h>
|
| |
+ +#include <string.h>
|
| |
+ +
|
| |
+ +#include "sshkey.h"
|
| |
+ +#include "sshbuf.h"
|
| |
+ +#include "log.h"
|
| |
+ +
|
| |
+ +#define CRYPTOKI_COMPAT
|
| |
+ +#include "pkcs11.h"
|
| |
+ +
|
| |
+ +#include "ssh-pkcs11-uri.h"
|
| |
+ +
|
| |
+ +#define PKCS11_URI_PATH_SEPARATOR ";"
|
| |
+ +#define PKCS11_URI_QUERY_SEPARATOR "&"
|
| |
+ +#define PKCS11_URI_VALUE_SEPARATOR "="
|
| |
+ +#define PKCS11_URI_ID "id"
|
| |
+ +#define PKCS11_URI_TOKEN "token"
|
| |
+ +#define PKCS11_URI_OBJECT "object"
|
| |
+ +#define PKCS11_URI_LIB_MANUF "library-manufacturer"
|
| |
+ +#define PKCS11_URI_MANUF "manufacturer"
|
| |
+ +#define PKCS11_URI_MODULE_PATH "module-path"
|
| |
+ +#define PKCS11_URI_PIN_VALUE "pin-value"
|
| |
+ +
|
| |
+ +/* Keyword tokens. */
|
| |
+ +typedef enum {
|
| |
+ + pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pModulePath,
|
| |
+ + pPinValue, pBadOption
|
| |
+ +} pkcs11uriOpCodes;
|
| |
+ +
|
| |
+ +/* Textual representation of the tokens. */
|
| |
+ +static struct {
|
| |
+ + const char *name;
|
| |
+ + pkcs11uriOpCodes opcode;
|
| |
+ +} keywords[] = {
|
| |
+ + { PKCS11_URI_ID, pId },
|
| |
+ + { PKCS11_URI_TOKEN, pToken },
|
| |
+ + { PKCS11_URI_OBJECT, pObject },
|
| |
+ + { PKCS11_URI_LIB_MANUF, pLibraryManufacturer },
|
| |
+ + { PKCS11_URI_MANUF, pManufacturer },
|
| |
+ + { PKCS11_URI_MODULE_PATH, pModulePath },
|
| |
+ + { PKCS11_URI_PIN_VALUE, pPinValue },
|
| |
+ + { NULL, pBadOption }
|
| |
+ +};
|
| |
+ +
|
| |
+ +static pkcs11uriOpCodes
|
| |
+ +parse_token(const char *cp)
|
| |
+ +{
|
| |
+ + u_int i;
|
| |
+ +
|
| |
+ + for (i = 0; keywords[i].name; i++)
|
| |
+ + if (strncasecmp(cp, keywords[i].name,
|
| |
+ + strlen(keywords[i].name)) == 0)
|
| |
+ + return keywords[i].opcode;
|
| |
+ +
|
| |
+ + return pBadOption;
|
| |
+ +}
|
| |
+ +
|
| |
+ +int
|
| |
+ +percent_decode(char *data, char **outp)
|
| |
+ +{
|
| |
+ + char tmp[3];
|
| |
+ + char *out, *tmp_end;
|
| |
+ + char *p = data;
|
| |
+ + long value;
|
| |
+ + size_t outlen = 0;
|
| |
+ +
|
| |
+ + out = malloc(strlen(data)+1); /* upper bound */
|
| |
+ + if (out == NULL)
|
| |
+ + return -1;
|
| |
+ + while (*p != '\0') {
|
| |
+ + switch (*p) {
|
| |
+ + case '%':
|
| |
+ + p++;
|
| |
+ + if (*p == '\0')
|
| |
+ + goto fail;
|
| |
+ + tmp[0] = *p++;
|
| |
+ + if (*p == '\0')
|
| |
+ + goto fail;
|
| |
+ + tmp[1] = *p++;
|
| |
+ + tmp[2] = '\0';
|
| |
+ + tmp_end = NULL;
|
| |
+ + value = strtol(tmp, &tmp_end, 16);
|
| |
+ + if (tmp_end != tmp+2)
|
| |
+ + goto fail;
|
| |
+ + else
|
| |
+ + out[outlen++] = (char) value;
|
| |
+ + break;
|
| |
+ + default:
|
| |
+ + out[outlen++] = *p++;
|
| |
+ + break;
|
| |
+ + }
|
| |
+ + }
|
| |
+ +
|
| |
+ + /* zero terminate */
|
| |
+ + out[outlen] = '\0';
|
| |
+ + *outp = out;
|
| |
+ + return outlen;
|
| |
+ +fail:
|
| |
+ + free(out);
|
| |
+ + return -1;
|
| |
+ +}
|
| |
+ +
|
| |
+ +struct sshbuf *
|
| |
+ +percent_encode(const char *data, size_t length, const char *allow_list)
|
| |
+ +{
|
| |
+ + struct sshbuf *b = NULL;
|
| |
+ + char tmp[4], *cp;
|
| |
+ + size_t i;
|
| |
+ +
|
| |
+ + if ((b = sshbuf_new()) == NULL)
|
| |
+ + return NULL;
|
| |
+ + for (i = 0; i < length; i++) {
|
| |
+ + cp = strchr(allow_list, data[i]);
|
| |
+ + /* if c is specified as '\0' pointer to terminator is returned !! */
|
| |
+ + if (cp != NULL && *cp != '\0') {
|
| |
+ + if (sshbuf_put(b, &data[i], 1) != 0)
|
| |
+ + goto err;
|
| |
+ + } else
|
| |
+ + if (snprintf(tmp, 4, "%%%02X", (unsigned char) data[i]) < 3
|
| |
+ + || sshbuf_put(b, tmp, 3) != 0)
|
| |
+ + goto err;
|
| |
+ + }
|
| |
+ + if (sshbuf_put(b, "\0", 1) == 0)
|
| |
+ + return b;
|
| |
+ +err:
|
| |
+ + sshbuf_free(b);
|
| |
+ + return NULL;
|
| |
+ +}
|
| |
+ +
|
| |
+ +char *
|
| |
+ +pkcs11_uri_append(char *part, const char *separator, const char *key,
|
| |
+ + struct sshbuf *value)
|
| |
+ +{
|
| |
+ + char *new_part;
|
| |
+ + size_t size = 0;
|
| |
+
|
| |
- + debug_f("called, provider_id = %s", provider_id);
|
| |
+ + if (value == NULL)
|
| |
+ + return NULL;
|
| |
+
|
| |
- + uri = pkcs11_uri_init();
|
| |
- + if (uri == NULL)
|
| |
- + fatal("failed to init PKCS#11 URI");
|
| |
+ + size = asprintf(&new_part,
|
| |
+ + "%s%s%s" PKCS11_URI_VALUE_SEPARATOR "%s",
|
| |
+ + (part != NULL ? part : ""),
|
| |
+ + (part != NULL ? separator : ""),
|
| |
+ + key, sshbuf_ptr(value));
|
| |
+ + sshbuf_free(value);
|
| |
+ + free(part);
|
| |
+
|
| |
- + if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) &&
|
| |
- + strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) {
|
| |
- + if (pkcs11_uri_parse(provider_id, uri) != 0)
|
| |
- + fatal("Failed to parse PKCS#11 URI");
|
| |
- + } else {
|
| |
- + uri->module_path = strdup(provider_id);
|
| |
+ + if (size <= 0)
|
| |
+ + return NULL;
|
| |
+ + return new_part;
|
| |
+ +}
|
| |
+ +
|
| |
+ +char *
|
| |
+ +pkcs11_uri_get(struct pkcs11_uri *uri)
|
| |
+ +{
|
| |
+ + size_t size = 0;
|
| |
+ + char *p = NULL, *path = NULL, *query = NULL;
|
| |
+ +
|
| |
+ + /* compose a percent-encoded ID */
|
| |
+ + if (uri->id_len > 0) {
|
| |
+ + struct sshbuf *key_id = percent_encode(uri->id, uri->id_len, "");
|
| |
+ + path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,
|
| |
+ + PKCS11_URI_ID, key_id);
|
| |
+ + if (path == NULL)
|
| |
+ + goto err;
|
| |
+ }
|
| |
+
|
| |
- + r = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, providerp, user);
|
| |
- + pkcs11_uri_cleanup(uri);
|
| |
+ + /* Write object label */
|
| |
+ + if (uri->object) {
|
| |
+ + struct sshbuf *label = percent_encode(uri->object, strlen(uri->object),
|
| |
+ + PKCS11_URI_WHITELIST);
|
| |
+ + path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,
|
| |
+ + PKCS11_URI_OBJECT, label);
|
| |
+ + if (path == NULL)
|
| |
+ + goto err;
|
| |
+ + }
|
| |
+
|
| |
- + return r;
|
| |
+ + /* Write token label */
|
| |
+ + if (uri->token) {
|
| |
+ + struct sshbuf *label = percent_encode(uri->token, strlen(uri->token),
|
| |
+ + PKCS11_URI_WHITELIST);
|
| |
+ + path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,
|
| |
+ + PKCS11_URI_TOKEN, label);
|
| |
+ + if (path == NULL)
|
| |
+ + goto err;
|
| |
+ + }
|
| |
+ +
|
| |
+ + /* Write manufacturer */
|
| |
+ + if (uri->manuf) {
|
| |
+ + struct sshbuf *manuf = percent_encode(uri->manuf,
|
| |
+ + strlen(uri->manuf), PKCS11_URI_WHITELIST);
|
| |
+ + path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR,
|
| |
+ + PKCS11_URI_MANUF, manuf);
|
| |
+ + if (path == NULL)
|
| |
+ + goto err;
|
| |
+ + }
|
| |
+ +
|
| |
+ + /* Write module_path */
|
| |
+ + if (uri->module_path) {
|
| |
+ + struct sshbuf *module = percent_encode(uri->module_path,
|
| |
+ + strlen(uri->module_path), PKCS11_URI_WHITELIST "/");
|
| |
+ + query = pkcs11_uri_append(query, PKCS11_URI_QUERY_SEPARATOR,
|
| |
+ + PKCS11_URI_MODULE_PATH, module);
|
| |
+ + if (query == NULL)
|
| |
+ + goto err;
|
| |
+ + }
|
| |
+ +
|
| |
+ + size = asprintf(&p, PKCS11_URI_SCHEME "%s%s%s",
|
| |
+ + path != NULL ? path : "",
|
| |
+ + query != NULL ? "?" : "",
|
| |
+ + query != NULL ? query : "");
|
| |
+ +err:
|
| |
+ + free(query);
|
| |
+ + free(path);
|
| |
+ + if (size <= 0)
|
| |
+ + return NULL;
|
| |
+ + return p;
|
| |
+}
|
| |
+
|
| |
- int
|
| |
- -pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
|
| |
- - char ***labelsp)
|
| |
- +pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin,
|
| |
- + struct sshkey ***keyp, char ***labelsp)
|
| |
- {
|
| |
- struct pkcs11_provider *p = NULL;
|
| |
- int nkeys;
|
| |
- + char *provider_uri = pkcs11_uri_get(uri);
|
| |
+ +struct pkcs11_uri *
|
| |
+ +pkcs11_uri_init()
|
| |
+ +{
|
| |
+ + struct pkcs11_uri *d = calloc(1, sizeof(struct pkcs11_uri));
|
| |
+ + return d;
|
| |
+ +}
|
| |
+
|
| |
- + debug_f("called, provider_uri = %s", provider_uri);
|
| |
-
|
| |
- - nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
|
| |
- - &p, CKU_USER);
|
| |
- + nkeys = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, &p, CKU_USER);
|
| |
-
|
| |
- /* no keys found or some other error, de-register provider */
|
| |
- if (nkeys <= 0 && p != NULL) {
|
| |
- @@ -1652,7 +1974,37 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
|
| |
- pkcs11_provider_unref(p);
|
| |
- }
|
| |
- if (nkeys == 0)
|
| |
- - debug_f("provider %s returned no keys", provider_id);
|
| |
- + debug_f("provider %s returned no keys", provider_uri);
|
| |
+ +void
|
| |
+ +pkcs11_uri_cleanup(struct pkcs11_uri *pkcs11)
|
| |
+ +{
|
| |
+ + if (pkcs11 == NULL) {
|
| |
+ + return;
|
| |
+ + }
|
| |
+
|
| |
- + free(provider_uri);
|
| |
- + return nkeys;
|
| |
+ + free(pkcs11->id);
|
| |
+ + free(pkcs11->module_path);
|
| |
+ + free(pkcs11->token);
|
| |
+ + free(pkcs11->object);
|
| |
+ + free(pkcs11->lib_manuf);
|
| |
+ + free(pkcs11->manuf);
|
| |
+ + if (pkcs11->pin)
|
| |
+ + freezero(pkcs11->pin, strlen(pkcs11->pin));
|
| |
+ + free(pkcs11);
|
| |
+}
|
| |
+
|
| |
- +/*
|
| |
- + * register a new provider and get number of keys hold by the token,
|
| |
- + * fails if provider already exists
|
| |
- + */
|
| |
+int
|
| |
- +pkcs11_add_provider(char *provider_id, char *pin,
|
| |
- + struct sshkey ***keyp, char ***labelsp)
|
| |
+ +pkcs11_uri_parse(const char *uri, struct pkcs11_uri *pkcs11)
|
| |
+{
|
| |
- + struct pkcs11_uri *uri;
|
| |
- + int nkeys;
|
| |
+ + char *saveptr1, *saveptr2, *str1, *str2, *tok;
|
| |
+ + int rv = 0, len;
|
| |
+ + char *p = NULL;
|
| |
+
|
| |
- + uri = pkcs11_uri_init();
|
| |
- + if (uri == NULL)
|
| |
- + fatal("Failed to init PKCS#11 URI");
|
| |
+ + size_t scheme_len = strlen(PKCS11_URI_SCHEME);
|
| |
+ + if (strlen(uri) < scheme_len || /* empty URI matches everything */
|
| |
+ + strncmp(uri, PKCS11_URI_SCHEME, scheme_len) != 0) {
|
| |
+ + error_f("The '%s' does not look like PKCS#11 URI", uri);
|
| |
+ + return -1;
|
| |
+ + }
|
| |
+
|
| |
- + if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) &&
|
| |
- + strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) {
|
| |
- + if (pkcs11_uri_parse(provider_id, uri) != 0)
|
| |
- + fatal("Failed to parse PKCS#11 URI");
|
| |
- + } else {
|
| |
- + uri->module_path = strdup(provider_id);
|
| |
+ + if (pkcs11 == NULL) {
|
| |
+ + error_f("Bad arguments. The pkcs11 can't be null");
|
| |
+ + return -1;
|
| |
+ }
|
| |
+
|
| |
- + nkeys = pkcs11_add_provider_by_uri(uri, pin, keyp, labelsp);
|
| |
- + pkcs11_uri_cleanup(uri);
|
| |
-
|
| |
- return (nkeys);
|
| |
- }
|
| |
- diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h
|
| |
- index 81f1d7c5..feaf74de 100644
|
| |
- --- a/ssh-pkcs11.h
|
| |
- +++ b/ssh-pkcs11.h
|
| |
- @@ -22,10 +22,14 @@
|
| |
- #define SSH_PKCS11_ERR_PIN_REQUIRED 4
|
| |
- #define SSH_PKCS11_ERR_PIN_LOCKED 5
|
| |
-
|
| |
- +#include "ssh-pkcs11-uri.h"
|
| |
+ + /* skip URI schema name */
|
| |
+ + p = strdup(uri);
|
| |
+ + str1 = p;
|
| |
+
|
| |
- int pkcs11_init(int);
|
| |
- void pkcs11_terminate(void);
|
| |
- int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***);
|
| |
- +int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***, char ***);
|
| |
- int pkcs11_del_provider(char *);
|
| |
- +int pkcs11_uri_write(const struct sshkey *, FILE *);
|
| |
- #ifdef WITH_PKCS11_KEYGEN
|
| |
- struct sshkey *
|
| |
- pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int,
|
| |
- diff --git a/ssh.c b/ssh.c
|
| |
- index 15aee569..976844cb 100644
|
| |
- --- a/ssh.c
|
| |
- +++ b/ssh.c
|
| |
- @@ -795,6 +795,14 @@ main(int ac, char **av)
|
| |
- options.gss_deleg_creds = 1;
|
| |
- break;
|
| |
- case 'i':
|
| |
- +#ifdef ENABLE_PKCS11
|
| |
- + if (strlen(optarg) >= strlen(PKCS11_URI_SCHEME) &&
|
| |
- + strncmp(optarg, PKCS11_URI_SCHEME,
|
| |
- + strlen(PKCS11_URI_SCHEME)) == 0) {
|
| |
- + add_identity_file(&options, NULL, optarg, 1);
|
| |
- + break;
|
| |
+ + /* everything before ? */
|
| |
+ + tok = strtok_r(str1, "?", &saveptr1);
|
| |
+ + if (tok == NULL) {
|
| |
+ + error_f("pk11-path expected, got EOF");
|
| |
+ + rv = -1;
|
| |
+ + goto out;
|
| |
+ + }
|
| |
+ +
|
| |
+ + /* skip URI schema name:
|
| |
+ + * the scheme ensures that there is at least something before "?"
|
| |
+ + * allowing empty pk11-path. Resulting token at worst pointing to
|
| |
+ + * \0 byte */
|
| |
+ + tok = tok + scheme_len;
|
| |
+ +
|
| |
+ + /* parse pk11-path */
|
| |
+ + for (str2 = tok; ; str2 = NULL) {
|
| |
+ + char **charptr, *arg = NULL;
|
| |
+ + pkcs11uriOpCodes opcode;
|
| |
+ + tok = strtok_r(str2, PKCS11_URI_PATH_SEPARATOR, &saveptr2);
|
| |
+ + if (tok == NULL)
|
| |
+ + break;
|
| |
+ + opcode = parse_token(tok);
|
| |
+ + if (opcode != pBadOption)
|
| |
+ + arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */
|
| |
+ +
|
| |
+ + switch (opcode) {
|
| |
+ + case pId:
|
| |
+ + /* CKA_ID */
|
| |
+ + if (pkcs11->id != NULL) {
|
| |
+ + verbose_f("The id already set in the PKCS#11 URI");
|
| |
+ + rv = -1;
|
| |
+ + goto out;
|
| |
+ + }
|
| |
+ + len = percent_decode(arg, &pkcs11->id);
|
| |
+ + if (len <= 0) {
|
| |
+ + verbose_f("Failed to percent-decode CKA_ID: %s", arg);
|
| |
+ + rv = -1;
|
| |
+ + goto out;
|
| |
+ + } else
|
| |
+ + pkcs11->id_len = len;
|
| |
+ + debug3_f("Setting CKA_ID = %s from PKCS#11 URI", arg);
|
| |
+ + break;
|
| |
+ + case pToken:
|
| |
+ + /* CK_TOKEN_INFO -> label */
|
| |
+ + charptr = &pkcs11->token;
|
| |
+ + parse_string:
|
| |
+ + if (*charptr != NULL) {
|
| |
+ + verbose_f("The %s already set in the PKCS#11 URI",
|
| |
+ + keywords[opcode].name);
|
| |
+ + rv = -1;
|
| |
+ + goto out;
|
| |
+ }
|
| |
- +#endif
|
| |
- p = tilde_expand_filename(optarg, getuid());
|
| |
- if (stat(p, &st) == -1)
|
| |
- fprintf(stderr, "Warning: Identity file %s "
|
| |
- @@ -1603,6 +1611,7 @@ main(int ac, char **av)
|
| |
- free(options.certificate_files[i]);
|
| |
- options.certificate_files[i] = NULL;
|
| |
- }
|
| |
- + pkcs11_terminate();
|
| |
-
|
| |
- skip_connect:
|
| |
- exit_status = ssh_session2(ssh, cinfo);
|
| |
- @@ -2076,6 +2085,45 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
|
| |
- options.escape_char : SSH_ESCAPECHAR_NONE, id);
|
| |
- }
|
| |
-
|
| |
- +#ifdef ENABLE_PKCS11
|
| |
- +static void
|
| |
- +load_pkcs11_identity(char *pkcs11_uri, char *identity_files[],
|
| |
- + struct sshkey *identity_keys[], int *n_ids)
|
| |
- +{
|
| |
- + int nkeys, i;
|
| |
- + struct sshkey **keys;
|
| |
- + struct pkcs11_uri *uri;
|
| |
+ + percent_decode(arg, charptr);
|
| |
+ + debug3_f("Setting %s = %s from PKCS#11 URI",
|
| |
+ + keywords[opcode].name, *charptr);
|
| |
+ + break;
|
| |
+
|
| |
- + debug("identity file '%s' from pkcs#11", pkcs11_uri);
|
| |
- + uri = pkcs11_uri_init();
|
| |
- + if (uri == NULL)
|
| |
- + fatal("Failed to init PKCS#11 URI");
|
| |
+ + case pObject:
|
| |
+ + /* CK_TOKEN_INFO -> manufacturerID */
|
| |
+ + charptr = &pkcs11->object;
|
| |
+ + goto parse_string;
|
| |
+
|
| |
- + if (pkcs11_uri_parse(pkcs11_uri, uri) != 0)
|
| |
- + fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri);
|
| |
+ + case pManufacturer:
|
| |
+ + /* CK_TOKEN_INFO -> manufacturerID */
|
| |
+ + charptr = &pkcs11->manuf;
|
| |
+ + goto parse_string;
|
| |
+
|
| |
- + /* we need to merge URI and provider together */
|
| |
- + if (options.pkcs11_provider != NULL && uri->module_path == NULL)
|
| |
- + uri->module_path = strdup(options.pkcs11_provider);
|
| |
+ + case pLibraryManufacturer:
|
| |
+ + /* CK_INFO -> manufacturerID */
|
| |
+ + charptr = &pkcs11->lib_manuf;
|
| |
+ + goto parse_string;
|
| |
+
|
| |
- + if (options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
|
| |
- + (nkeys = pkcs11_add_provider_by_uri(uri, NULL, &keys, NULL)) > 0) {
|
| |
- + for (i = 0; i < nkeys; i++) {
|
| |
- + if (*n_ids >= SSH_MAX_IDENTITY_FILES) {
|
| |
- + sshkey_free(keys[i]);
|
| |
- + continue;
|
| |
- + }
|
| |
- + identity_keys[*n_ids] = keys[i];
|
| |
- + identity_files[*n_ids] = pkcs11_uri_get(uri);
|
| |
- + (*n_ids)++;
|
| |
+ + default:
|
| |
+ + /* Unrecognized attribute in the URI path SHOULD be error */
|
| |
+ + verbose_f("Unknown part of path in PKCS#11 URI: %s", tok);
|
| |
+ }
|
| |
- + free(keys);
|
| |
+ }
|
| |
+
|
| |
- + pkcs11_uri_cleanup(uri);
|
| |
- +}
|
| |
- +#endif /* ENABLE_PKCS11 */
|
| |
+ + tok = strtok_r(NULL, "?", &saveptr1);
|
| |
+ + if (tok == NULL) {
|
| |
+ + goto out;
|
| |
+ + }
|
| |
+ + /* parse pk11-query (optional) */
|
| |
+ + for (str2 = tok; ; str2 = NULL) {
|
| |
+ + char *arg;
|
| |
+ + pkcs11uriOpCodes opcode;
|
| |
+ + tok = strtok_r(str2, PKCS11_URI_QUERY_SEPARATOR, &saveptr2);
|
| |
+ + if (tok == NULL)
|
| |
+ + break;
|
| |
+ + opcode = parse_token(tok);
|
| |
+ + if (opcode != pBadOption)
|
| |
+ + arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */
|
| |
+
|
| |
- /* Loads all IdentityFile and CertificateFile keys */
|
| |
- static void
|
| |
- load_public_identity_files(const struct ssh_conn_info *cinfo)
|
| |
- @@ -2090,11 +2138,6 @@ load_public_identity_files(struct passwd *pw)
|
| |
- char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
|
| |
- struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
|
| |
- int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];
|
| |
- -#ifdef ENABLE_PKCS11
|
| |
- - struct sshkey **keys = NULL;
|
| |
- - char **comments = NULL;
|
| |
- - int nkeys;
|
| |
- -#endif /* PKCS11 */
|
| |
-
|
| |
- n_ids = n_certs = 0;
|
| |
- memset(identity_files, 0, sizeof(identity_files));
|
| |
- @@ -2107,33 +2150,46 @@ load_public_identity_files(struct passwd *pw)
|
| |
- sizeof(certificate_file_userprovided));
|
| |
-
|
| |
- #ifdef ENABLE_PKCS11
|
| |
- - if (options.pkcs11_provider != NULL &&
|
| |
- - options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
|
| |
- - (pkcs11_init(!options.batch_mode) == 0) &&
|
| |
- - (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
|
| |
- - &keys, &comments)) > 0) {
|
| |
- - for (i = 0; i < nkeys; i++) {
|
| |
- - if (n_ids >= SSH_MAX_IDENTITY_FILES) {
|
| |
- - sshkey_free(keys[i]);
|
| |
- - free(comments[i]);
|
| |
- - continue;
|
| |
- - }
|
| |
- - identity_keys[n_ids] = keys[i];
|
| |
- - identity_files[n_ids] = comments[i]; /* transferred */
|
| |
- - n_ids++;
|
| |
- - }
|
| |
- - free(keys);
|
| |
- - free(comments);
|
| |
- + /* handle fallback from PKCS11Provider option */
|
| |
- + pkcs11_init(!options.batch_mode);
|
| |
+ + switch (opcode) {
|
| |
+ + case pModulePath:
|
| |
+ + /* module-path is PKCS11Provider */
|
| |
+ + if (pkcs11->module_path != NULL) {
|
| |
+ + verbose_f("Multiple module-path attributes are"
|
| |
+ + "not supported the PKCS#11 URI");
|
| |
+ + rv = -1;
|
| |
+ + goto out;
|
| |
+ + }
|
| |
+ + percent_decode(arg, &pkcs11->module_path);
|
| |
+ + debug3_f("Setting PKCS11Provider = %s from PKCS#11 URI",
|
| |
+ + pkcs11->module_path);
|
| |
+ + break;
|
| |
+
|
| |
- + if (options.pkcs11_provider != NULL) {
|
| |
- + struct pkcs11_uri *uri;
|
| |
+ + case pPinValue:
|
| |
+ + /* pin-value */
|
| |
+ + if (pkcs11->pin != NULL) {
|
| |
+ + verbose_f("Multiple pin-value attributes are"
|
| |
+ + "not supported the PKCS#11 URI");
|
| |
+ + rv = -1;
|
| |
+ + goto out;
|
| |
+ + }
|
| |
+ + percent_decode(arg, &pkcs11->pin);
|
| |
+ + debug3_f("Setting PIN from PKCS#11 URI");
|
| |
+ + break;
|
| |
+
|
| |
- + uri = pkcs11_uri_init();
|
| |
- + if (uri == NULL)
|
| |
- + fatal("Failed to init PKCS#11 URI");
|
| |
+ + default:
|
| |
+ + /* Unrecognized attribute in the URI query SHOULD be ignored */
|
| |
+ + verbose_f("Unknown part of query in PKCS#11 URI: %s", tok);
|
| |
+ + }
|
| |
+ + }
|
| |
+ +out:
|
| |
+ + free(p);
|
| |
+ + return rv;
|
| |
+ +}
|
| |
+
|
| |
- + /* Construct simple PKCS#11 URI to simplify access */
|
| |
- + uri->module_path = strdup(options.pkcs11_provider);
|
| |
+ +#endif /* ENABLE_PKCS11 */
|
| |
+ diff -up openssh-8.6p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-8.6p1/ssh-pkcs11-uri.h
|
| |
+ --- openssh-8.6p1/ssh-pkcs11-uri.h.pkcs11-uri 2021-04-19 14:57:30.318370565 +0200
|
| |
+ +++ openssh-8.6p1/ssh-pkcs11-uri.h 2021-04-19 14:57:30.318370565 +0200
|
| |
+ @@ -0,0 +1,42 @@
|
| |
+ +/*
|
| |
+ + * Copyright (c) 2017 Red Hat
|
| |
+ + *
|
| |
+ + * Authors: Jakub Jelen <jjelen@redhat.com>
|
| |
+ + *
|
| |
+ + * Permission to use, copy, modify, and distribute this software for any
|
| |
+ + * purpose with or without fee is hereby granted, provided that the above
|
| |
+ + * copyright notice and this permission notice appear in all copies.
|
| |
+ + *
|
| |
+ + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
| |
+ + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
| |
+ + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
| |
+ + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
| |
+ + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
| |
+ + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
| |
+ + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
| |
+ + */
|
| |
+
|
| |
- + /* Add it as any other IdentityFile */
|
| |
- + cp = pkcs11_uri_get(uri);
|
| |
- + add_identity_file(&options, NULL, cp, 1);
|
| |
- + free(cp);
|
| |
+ +#define PKCS11_URI_SCHEME "pkcs11:"
|
| |
+ +#define PKCS11_URI_WHITELIST "abcdefghijklmnopqrstuvwxyz" \
|
| |
+ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
| |
+ + "0123456789_-.()"
|
| |
+ +
|
| |
+ +struct pkcs11_uri {
|
| |
+ + /* path */
|
| |
+ + char *id;
|
| |
+ + size_t id_len;
|
| |
+ + char *token;
|
| |
+ + char *object;
|
| |
+ + char *lib_manuf;
|
| |
+ + char *manuf;
|
| |
+ + /* query */
|
| |
+ + char *module_path;
|
| |
+ + char *pin; /* Only parsed, but not printed */
|
| |
+ +};
|
| |
+ +
|
| |
+ +struct pkcs11_uri *pkcs11_uri_init();
|
| |
+ +void pkcs11_uri_cleanup(struct pkcs11_uri *);
|
| |
+ +int pkcs11_uri_parse(const char *, struct pkcs11_uri *);
|
| |
+ +struct pkcs11_uri *pkcs11_uri_init();
|
| |
+ +char *pkcs11_uri_get(struct pkcs11_uri *uri);
|
| |
+
|
| |
- + pkcs11_uri_cleanup(uri);
|
| |
- }
|
| |
- #endif /* ENABLE_PKCS11 */
|
| |
- for (i = 0; i < options.num_identity_files; i++) {
|
| |
- + char *name = options.identity_files[i];
|
| |
- if (n_ids >= SSH_MAX_IDENTITY_FILES ||
|
| |
- - strcasecmp(options.identity_files[i], "none") == 0) {
|
| |
- + strcasecmp(name, "none") == 0) {
|
| |
- free(options.identity_files[i]);
|
| |
- options.identity_files[i] = NULL;
|
| |
- continue;
|
| |
- }
|
| |
- - cp = tilde_expand_filename(options.identity_files[i], getuid());
|
| |
- +#ifdef ENABLE_PKCS11
|
| |
- + if (strlen(name) >= strlen(PKCS11_URI_SCHEME) &&
|
| |
- + strncmp(name, PKCS11_URI_SCHEME,
|
| |
- + strlen(PKCS11_URI_SCHEME)) == 0) {
|
| |
- + load_pkcs11_identity(name, identity_files,
|
| |
- + identity_keys, &n_ids);
|
| |
- + free(options.identity_files[i]);
|
| |
- + continue;
|
| |
- + }
|
| |
- +#endif /* ENABLE_PKCS11 */
|
| |
- + cp = tilde_expand_filename(name, getuid());
|
| |
- filename = default_client_percent_dollar_expand(cp, cinfo);
|
| |
- free(cp);
|
| |
- check_load(sshkey_load_public(filename, &public, NULL),
|
| |
- diff --git a/ssh_config.5 b/ssh_config.5
|
| |
- index 06a32d31..4b2763bd 100644
|
| |
- --- a/ssh_config.5
|
| |
- +++ b/ssh_config.5
|
| |
- @@ -986,6 +986,21 @@ may also be used in conjunction with
|
| |
- .Cm CertificateFile
|
| |
- in order to provide any certificate also needed for authentication with
|
| |
- the identity.
|
| |
- +.Pp
|
| |
- +The authentication identity can be also specified in a form of PKCS#11 URI
|
| |
- +starting with a string
|
| |
- +.Cm pkcs11: .
|
| |
- +There is supported a subset of the PKCS#11 URI as defined
|
| |
- +in RFC 7512 (implemented path arguments
|
| |
- +.Cm id ,
|
| |
- +.Cm manufacturer ,
|
| |
- +.Cm object ,
|
| |
- +.Cm token
|
| |
- +and query arguments
|
| |
- +.Cm module-path
|
| |
- +and
|
| |
- +.Cm pin-value
|
| |
- +). The URI can not be in quotes.
|
| |
- .It Cm IgnoreUnknown
|
| |
- Specifies a pattern-list of unknown options to be ignored if they are
|
| |
- encountered in configuration parsing.
|
| |
Resolves: rhbz#1950819