mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-31 01:35:11 +02:00
- markus@cvs.openbsd.org 2010/02/08 10:50:20
[pathnames.h readconf.c readconf.h scp.1 sftp.1 ssh-add.1 ssh-add.c] [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config.5] replace our obsolete smartcard code with PKCS#11. ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs-11v2-20.pdf ssh(1) and ssh-keygen(1) use dlopen(3) directly to talk to a PKCS#11 provider (shared library) while ssh-agent(1) delegates PKCS#11 to a forked a ssh-pkcs11-helper process. PKCS#11 is currently a compile time option. feedback and ok djm@; inspired by patches from Alon Bar-Lev `
This commit is contained in:
parent
17751bcab2
commit
7ea845e48d
10
ChangeLog
10
ChangeLog
@ -5,6 +5,16 @@
|
|||||||
make buffer_get_string_ret() really non-fatal in all cases (it was
|
make buffer_get_string_ret() really non-fatal in all cases (it was
|
||||||
using buffer_get_int(), which could fatal() on buffer empty);
|
using buffer_get_int(), which could fatal() on buffer empty);
|
||||||
ok markus dtucker
|
ok markus dtucker
|
||||||
|
- markus@cvs.openbsd.org 2010/02/08 10:50:20
|
||||||
|
[pathnames.h readconf.c readconf.h scp.1 sftp.1 ssh-add.1 ssh-add.c]
|
||||||
|
[ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config.5]
|
||||||
|
replace our obsolete smartcard code with PKCS#11.
|
||||||
|
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs-11v2-20.pdf
|
||||||
|
ssh(1) and ssh-keygen(1) use dlopen(3) directly to talk to a PKCS#11
|
||||||
|
provider (shared library) while ssh-agent(1) delegates PKCS#11 to
|
||||||
|
a forked a ssh-pkcs11-helper process.
|
||||||
|
PKCS#11 is currently a compile time option.
|
||||||
|
feedback and ok djm@; inspired by patches from Alon Bar-Lev
|
||||||
|
|
||||||
20100210
|
20100210
|
||||||
- (djm) add -lselinux to LIBS before calling AC_CHECK_FUNCS for
|
- (djm) add -lselinux to LIBS before calling AC_CHECK_FUNCS for
|
||||||
|
20
Makefile.in
20
Makefile.in
@ -1,4 +1,4 @@
|
|||||||
# $Id: Makefile.in,v 1.303 2010/01/08 08:27:57 dtucker Exp $
|
# $Id: Makefile.in,v 1.304 2010/02/11 22:21:02 djm Exp $
|
||||||
|
|
||||||
# uncomment if you run a non bourne compatable shell. Ie. csh
|
# uncomment if you run a non bourne compatable shell. Ie. csh
|
||||||
#SHELL = @SH@
|
#SHELL = @SH@
|
||||||
@ -25,6 +25,7 @@ SSH_PROGRAM=@bindir@/ssh
|
|||||||
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
|
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
|
||||||
SFTP_SERVER=$(libexecdir)/sftp-server
|
SFTP_SERVER=$(libexecdir)/sftp-server
|
||||||
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
|
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
|
||||||
|
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
|
||||||
RAND_HELPER=$(libexecdir)/ssh-rand-helper
|
RAND_HELPER=$(libexecdir)/ssh-rand-helper
|
||||||
PRIVSEP_PATH=@PRIVSEP_PATH@
|
PRIVSEP_PATH=@PRIVSEP_PATH@
|
||||||
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
|
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
|
||||||
@ -35,6 +36,7 @@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \
|
|||||||
-D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
|
-D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
|
||||||
-D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
|
-D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
|
||||||
-D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
|
-D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
|
||||||
|
-D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
|
||||||
-D_PATH_SSH_PIDDIR=\"$(piddir)\" \
|
-D_PATH_SSH_PIDDIR=\"$(piddir)\" \
|
||||||
-D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
|
-D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
|
||||||
-DSSH_RAND_HELPER=\"$(RAND_HELPER)\"
|
-DSSH_RAND_HELPER=\"$(RAND_HELPER)\"
|
||||||
@ -60,7 +62,7 @@ EXEEXT=@EXEEXT@
|
|||||||
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
|
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
|
||||||
INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
|
INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
|
||||||
|
|
||||||
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT)
|
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT)
|
||||||
|
|
||||||
LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
|
LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
|
||||||
canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
|
canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
|
||||||
@ -71,7 +73,8 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
|
|||||||
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
|
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
|
||||||
monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
|
monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
|
||||||
kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
|
kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
|
||||||
entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o
|
entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o \
|
||||||
|
ssh-pkcs11.o
|
||||||
|
|
||||||
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
||||||
sshconnect.o sshconnect1.o sshconnect2.o mux.o \
|
sshconnect.o sshconnect1.o sshconnect2.o mux.o \
|
||||||
@ -147,8 +150,8 @@ scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
|
|||||||
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
|
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
|
||||||
$(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
$(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
|
||||||
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o
|
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
|
||||||
$(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
$(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
|
||||||
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
|
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
|
||||||
$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
@ -156,6 +159,9 @@ ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
|
|||||||
ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o
|
ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o
|
||||||
$(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
$(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
|
||||||
|
ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
|
||||||
|
$(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
|
||||||
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
|
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
|
||||||
$(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
|
$(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
|
||||||
|
|
||||||
@ -265,6 +271,7 @@ install-files: scard-install
|
|||||||
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-rand-helper $(DESTDIR)$(libexecdir)/ssh-rand-helper ; \
|
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-rand-helper $(DESTDIR)$(libexecdir)/ssh-rand-helper ; \
|
||||||
fi
|
fi
|
||||||
$(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign $(DESTDIR)$(SSH_KEYSIGN)
|
$(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign $(DESTDIR)$(SSH_KEYSIGN)
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper $(DESTDIR)$(SSH_PKCS11_HELPER)
|
||||||
$(INSTALL) -m 0755 $(STRIP_OPT) sftp $(DESTDIR)$(bindir)/sftp
|
$(INSTALL) -m 0755 $(STRIP_OPT) sftp $(DESTDIR)$(bindir)/sftp
|
||||||
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server $(DESTDIR)$(SFTP_SERVER)
|
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server $(DESTDIR)$(SFTP_SERVER)
|
||||||
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
|
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
|
||||||
@ -368,6 +375,7 @@ uninstall:
|
|||||||
-rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
|
-rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
|
||||||
-rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
|
-rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
|
||||||
-rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
|
-rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
|
||||||
|
-rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
|
||||||
-rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT)
|
-rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT)
|
||||||
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
|
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
|
||||||
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
|
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
|
||||||
@ -393,6 +401,7 @@ tests interop-tests: $(TARGETS)
|
|||||||
TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \
|
TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \
|
||||||
TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add"; \
|
TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add"; \
|
||||||
TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
|
TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
|
||||||
|
TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
|
||||||
TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
|
TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
|
||||||
TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
|
TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
|
||||||
TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
|
TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
|
||||||
@ -413,6 +422,7 @@ tests interop-tests: $(TARGETS)
|
|||||||
TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
|
TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
|
||||||
TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
|
TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
|
||||||
TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
|
TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
|
||||||
|
TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \
|
||||||
TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
|
TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
|
||||||
TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
|
TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
|
||||||
TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
|
TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $Id: configure.ac,v 1.440 2010/02/09 23:19:29 djm Exp $
|
# $Id: configure.ac,v 1.441 2010/02/11 22:21:02 djm Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 1999-2004 Damien Miller
|
# Copyright (c) 1999-2004 Damien Miller
|
||||||
#
|
#
|
||||||
@ -15,7 +15,7 @@
|
|||||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org)
|
AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org)
|
||||||
AC_REVISION($Revision: 1.440 $)
|
AC_REVISION($Revision: 1.441 $)
|
||||||
AC_CONFIG_SRCDIR([ssh.c])
|
AC_CONFIG_SRCDIR([ssh.c])
|
||||||
|
|
||||||
AC_CONFIG_HEADER(config.h)
|
AC_CONFIG_HEADER(config.h)
|
||||||
@ -4197,6 +4197,10 @@ else
|
|||||||
AC_SUBST(TEST_SSH_IPV6, yes)
|
AC_SUBST(TEST_SSH_IPV6, yes)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "x$enable_pkcs11" != "xno" ; then
|
||||||
|
AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support])
|
||||||
|
fi
|
||||||
|
|
||||||
AC_EXEEXT
|
AC_EXEEXT
|
||||||
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
|
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
|
||||||
openbsd-compat/Makefile openbsd-compat/regress/Makefile \
|
openbsd-compat/Makefile openbsd-compat/regress/Makefile \
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: pathnames.h,v 1.17 2008/12/29 02:23:26 stevesk Exp $ */
|
/* $OpenBSD: pathnames.h,v 1.18 2010/02/08 10:50:20 markus Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -125,6 +125,11 @@
|
|||||||
#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign"
|
#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Location of ssh-keysign for hostbased authentication */
|
||||||
|
#ifndef _PATH_SSH_PKCS11_HELPER
|
||||||
|
#define _PATH_SSH_PKCS11_HELPER "/usr/libexec/ssh-pkcs11-helper"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* xauth for X11 forwarding */
|
/* xauth for X11 forwarding */
|
||||||
#ifndef _PATH_XAUTH
|
#ifndef _PATH_XAUTH
|
||||||
#define _PATH_XAUTH "/usr/X11R6/bin/xauth"
|
#define _PATH_XAUTH "/usr/X11R6/bin/xauth"
|
||||||
|
16
readconf.c
16
readconf.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.c,v 1.182 2010/01/09 23:04:13 dtucker Exp $ */
|
/* $OpenBSD: readconf.c,v 1.183 2010/02/08 10:50:20 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -123,7 +123,7 @@ typedef enum {
|
|||||||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
|
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
|
||||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
|
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
|
||||||
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
|
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
|
||||||
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
|
oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
|
||||||
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
|
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
|
||||||
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
|
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
|
||||||
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
|
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
|
||||||
@ -205,10 +205,12 @@ static struct {
|
|||||||
{ "preferredauthentications", oPreferredAuthentications },
|
{ "preferredauthentications", oPreferredAuthentications },
|
||||||
{ "hostkeyalgorithms", oHostKeyAlgorithms },
|
{ "hostkeyalgorithms", oHostKeyAlgorithms },
|
||||||
{ "bindaddress", oBindAddress },
|
{ "bindaddress", oBindAddress },
|
||||||
#ifdef SMARTCARD
|
#ifdef ENABLE_PKCS11
|
||||||
{ "smartcarddevice", oSmartcardDevice },
|
{ "smartcarddevice", oPKCS11Provider },
|
||||||
|
{ "pkcs11provider", oPKCS11Provider },
|
||||||
#else
|
#else
|
||||||
{ "smartcarddevice", oUnsupported },
|
{ "smartcarddevice", oUnsupported },
|
||||||
|
{ "pkcs11provider", oUnsupported },
|
||||||
#endif
|
#endif
|
||||||
{ "clearallforwardings", oClearAllForwardings },
|
{ "clearallforwardings", oClearAllForwardings },
|
||||||
{ "enablesshkeysign", oEnableSSHKeysign },
|
{ "enablesshkeysign", oEnableSSHKeysign },
|
||||||
@ -609,8 +611,8 @@ parse_string:
|
|||||||
charptr = &options->bind_address;
|
charptr = &options->bind_address;
|
||||||
goto parse_string;
|
goto parse_string;
|
||||||
|
|
||||||
case oSmartcardDevice:
|
case oPKCS11Provider:
|
||||||
charptr = &options->smartcard_device;
|
charptr = &options->pkcs11_provider;
|
||||||
goto parse_string;
|
goto parse_string;
|
||||||
|
|
||||||
case oProxyCommand:
|
case oProxyCommand:
|
||||||
@ -1051,7 +1053,7 @@ initialize_options(Options * options)
|
|||||||
options->log_level = SYSLOG_LEVEL_NOT_SET;
|
options->log_level = SYSLOG_LEVEL_NOT_SET;
|
||||||
options->preferred_authentications = NULL;
|
options->preferred_authentications = NULL;
|
||||||
options->bind_address = NULL;
|
options->bind_address = NULL;
|
||||||
options->smartcard_device = NULL;
|
options->pkcs11_provider = NULL;
|
||||||
options->enable_ssh_keysign = - 1;
|
options->enable_ssh_keysign = - 1;
|
||||||
options->no_host_authentication_for_localhost = - 1;
|
options->no_host_authentication_for_localhost = - 1;
|
||||||
options->identities_only = - 1;
|
options->identities_only = - 1;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.h,v 1.81 2010/01/09 23:04:13 dtucker Exp $ */
|
/* $OpenBSD: readconf.h,v 1.82 2010/02/08 10:50:20 markus Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -84,7 +84,7 @@ typedef struct {
|
|||||||
char *user_hostfile2;
|
char *user_hostfile2;
|
||||||
char *preferred_authentications;
|
char *preferred_authentications;
|
||||||
char *bind_address; /* local socket address for connection to sshd */
|
char *bind_address; /* local socket address for connection to sshd */
|
||||||
char *smartcard_device; /* Smartcard reader device */
|
char *pkcs11_provider; /* PKCS#11 provider */
|
||||||
int verify_host_key_dns; /* Verify host key using DNS */
|
int verify_host_key_dns; /* Verify host key using DNS */
|
||||||
|
|
||||||
int num_identity_files; /* Number of files for RSA/DSA identities. */
|
int num_identity_files; /* Number of files for RSA/DSA identities. */
|
||||||
|
6
scp.1
6
scp.1
@ -9,9 +9,9 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" Created: Sun May 7 00:14:37 1995 ylo
|
.\" Created: Sun May 7 00:14:37 1995 ylo
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: scp.1,v 1.49 2010/01/09 23:04:13 dtucker Exp $
|
.\" $OpenBSD: scp.1,v 1.50 2010/02/08 10:50:20 markus Exp $
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: January 9 2010 $
|
.Dd $Mdocdate: February 8 2010 $
|
||||||
.Dt SCP 1
|
.Dt SCP 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -153,6 +153,7 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It NoHostAuthenticationForLocalhost
|
.It NoHostAuthenticationForLocalhost
|
||||||
.It NumberOfPasswordPrompts
|
.It NumberOfPasswordPrompts
|
||||||
.It PasswordAuthentication
|
.It PasswordAuthentication
|
||||||
|
.It PKCS11Provider
|
||||||
.It Port
|
.It Port
|
||||||
.It PreferredAuthentications
|
.It PreferredAuthentications
|
||||||
.It Protocol
|
.It Protocol
|
||||||
@ -164,7 +165,6 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It SendEnv
|
.It SendEnv
|
||||||
.It ServerAliveInterval
|
.It ServerAliveInterval
|
||||||
.It ServerAliveCountMax
|
.It ServerAliveCountMax
|
||||||
.It SmartcardDevice
|
|
||||||
.It StrictHostKeyChecking
|
.It StrictHostKeyChecking
|
||||||
.It TCPKeepAlive
|
.It TCPKeepAlive
|
||||||
.It UsePrivilegedPort
|
.It UsePrivilegedPort
|
||||||
|
6
sftp.1
6
sftp.1
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: sftp.1,v 1.82 2010/01/13 12:48:34 jmc Exp $
|
.\" $OpenBSD: sftp.1,v 1.83 2010/02/08 10:50:20 markus Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
|
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -22,7 +22,7 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: January 13 2010 $
|
.Dd $Mdocdate: February 8 2010 $
|
||||||
.Dt SFTP 1
|
.Dt SFTP 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -202,6 +202,7 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It NoHostAuthenticationForLocalhost
|
.It NoHostAuthenticationForLocalhost
|
||||||
.It NumberOfPasswordPrompts
|
.It NumberOfPasswordPrompts
|
||||||
.It PasswordAuthentication
|
.It PasswordAuthentication
|
||||||
|
.It PKCS11Provider
|
||||||
.It Port
|
.It Port
|
||||||
.It PreferredAuthentications
|
.It PreferredAuthentications
|
||||||
.It Protocol
|
.It Protocol
|
||||||
@ -213,7 +214,6 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It SendEnv
|
.It SendEnv
|
||||||
.It ServerAliveInterval
|
.It ServerAliveInterval
|
||||||
.It ServerAliveCountMax
|
.It ServerAliveCountMax
|
||||||
.It SmartcardDevice
|
|
||||||
.It StrictHostKeyChecking
|
.It StrictHostKeyChecking
|
||||||
.It TCPKeepAlive
|
.It TCPKeepAlive
|
||||||
.It UsePrivilegedPort
|
.It UsePrivilegedPort
|
||||||
|
16
ssh-add.1
16
ssh-add.1
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: ssh-add.1,v 1.48 2009/10/22 15:02:12 sobrado Exp $
|
.\" $OpenBSD: ssh-add.1,v 1.49 2010/02/08 10:50:20 markus Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" -*- nroff -*-
|
.\" -*- nroff -*-
|
||||||
.\"
|
.\"
|
||||||
@ -37,7 +37,7 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: October 22 2009 $
|
.Dd $Mdocdate: February 8 2010 $
|
||||||
.Dt SSH-ADD 1
|
.Dt SSH-ADD 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -101,17 +101,17 @@ If no public key is found at a given path,
|
|||||||
will append
|
will append
|
||||||
.Pa .pub
|
.Pa .pub
|
||||||
and retry.
|
and retry.
|
||||||
.It Fl e Ar reader
|
.It Fl e Ar pkcs11
|
||||||
Remove key in smartcard
|
Remove key provided by
|
||||||
.Ar reader .
|
.Ar pkcs11 .
|
||||||
.It Fl L
|
.It Fl L
|
||||||
Lists public key parameters of all identities currently represented
|
Lists public key parameters of all identities currently represented
|
||||||
by the agent.
|
by the agent.
|
||||||
.It Fl l
|
.It Fl l
|
||||||
Lists fingerprints of all identities currently represented by the agent.
|
Lists fingerprints of all identities currently represented by the agent.
|
||||||
.It Fl s Ar reader
|
.It Fl s Ar pkcs11
|
||||||
Add key in smartcard
|
Add key provider by
|
||||||
.Ar reader .
|
.Ar pkcs11 .
|
||||||
.It Fl t Ar life
|
.It Fl t Ar life
|
||||||
Set a maximum lifetime when adding identities to an agent.
|
Set a maximum lifetime when adding identities to an agent.
|
||||||
The lifetime may be specified in seconds or in a time format
|
The lifetime may be specified in seconds or in a time format
|
||||||
|
20
ssh-add.c
20
ssh-add.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-add.c,v 1.91 2009/08/27 17:44:52 djm Exp $ */
|
/* $OpenBSD: ssh-add.c,v 1.92 2010/02/08 10:50:20 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -211,7 +211,7 @@ update_card(AuthenticationConnection *ac, int add, const char *id)
|
|||||||
char *pin;
|
char *pin;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
pin = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
|
pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN);
|
||||||
if (pin == NULL)
|
if (pin == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -317,10 +317,8 @@ usage(void)
|
|||||||
fprintf(stderr, " -X Unlock agent.\n");
|
fprintf(stderr, " -X Unlock agent.\n");
|
||||||
fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
|
fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
|
||||||
fprintf(stderr, " -c Require confirmation to sign using identities\n");
|
fprintf(stderr, " -c Require confirmation to sign using identities\n");
|
||||||
#ifdef SMARTCARD
|
fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n");
|
||||||
fprintf(stderr, " -s reader Add key in smartcard reader.\n");
|
fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n");
|
||||||
fprintf(stderr, " -e reader Remove key in smartcard reader.\n");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -329,7 +327,7 @@ main(int argc, char **argv)
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
extern int optind;
|
||||||
AuthenticationConnection *ac = NULL;
|
AuthenticationConnection *ac = NULL;
|
||||||
char *sc_reader_id = NULL;
|
char *pkcs11provider = NULL;
|
||||||
int i, ch, deleting = 0, ret = 0;
|
int i, ch, deleting = 0, ret = 0;
|
||||||
|
|
||||||
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
|
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
|
||||||
@ -371,11 +369,11 @@ main(int argc, char **argv)
|
|||||||
ret = 1;
|
ret = 1;
|
||||||
goto done;
|
goto done;
|
||||||
case 's':
|
case 's':
|
||||||
sc_reader_id = optarg;
|
pkcs11provider = optarg;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
deleting = 1;
|
deleting = 1;
|
||||||
sc_reader_id = optarg;
|
pkcs11provider = optarg;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
if ((lifetime = convtime(optarg)) == -1) {
|
if ((lifetime = convtime(optarg)) == -1) {
|
||||||
@ -392,8 +390,8 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
if (sc_reader_id != NULL) {
|
if (pkcs11provider != NULL) {
|
||||||
if (update_card(ac, !deleting, sc_reader_id) == -1)
|
if (update_card(ac, !deleting, pkcs11provider) == -1)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
101
ssh-agent.c
101
ssh-agent.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-agent.c,v 1.162 2009/09/01 14:43:17 djm Exp $ */
|
/* $OpenBSD: ssh-agent.c,v 1.163 2010/02/08 10:50:20 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -76,8 +76,8 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
#ifdef SMARTCARD
|
#ifdef ENABLE_PKCS11
|
||||||
#include "scard.h"
|
#include "ssh-pkcs11.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_SYS_PRCTL_H)
|
#if defined(HAVE_SYS_PRCTL_H)
|
||||||
@ -105,6 +105,7 @@ typedef struct identity {
|
|||||||
TAILQ_ENTRY(identity) next;
|
TAILQ_ENTRY(identity) next;
|
||||||
Key *key;
|
Key *key;
|
||||||
char *comment;
|
char *comment;
|
||||||
|
char *provider;
|
||||||
u_int death;
|
u_int death;
|
||||||
u_int confirm;
|
u_int confirm;
|
||||||
} Identity;
|
} Identity;
|
||||||
@ -171,6 +172,7 @@ static void
|
|||||||
free_identity(Identity *id)
|
free_identity(Identity *id)
|
||||||
{
|
{
|
||||||
key_free(id->key);
|
key_free(id->key);
|
||||||
|
xfree(id->provider);
|
||||||
xfree(id->comment);
|
xfree(id->comment);
|
||||||
xfree(id);
|
xfree(id);
|
||||||
}
|
}
|
||||||
@ -549,7 +551,7 @@ process_add_identity(SocketEntry *e, int version)
|
|||||||
if (lifetime && !death)
|
if (lifetime && !death)
|
||||||
death = time(NULL) + lifetime;
|
death = time(NULL) + lifetime;
|
||||||
if ((id = lookup_identity(k, version)) == NULL) {
|
if ((id = lookup_identity(k, version)) == NULL) {
|
||||||
id = xmalloc(sizeof(Identity));
|
id = xcalloc(1, sizeof(Identity));
|
||||||
id->key = k;
|
id->key = k;
|
||||||
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
||||||
/* Increment the number of identities. */
|
/* Increment the number of identities. */
|
||||||
@ -609,17 +611,17 @@ no_identities(SocketEntry *e, u_int type)
|
|||||||
buffer_free(&msg);
|
buffer_free(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SMARTCARD
|
#ifdef ENABLE_PKCS11
|
||||||
static void
|
static void
|
||||||
process_add_smartcard_key(SocketEntry *e)
|
process_add_smartcard_key(SocketEntry *e)
|
||||||
{
|
{
|
||||||
char *sc_reader_id = NULL, *pin;
|
char *provider = NULL, *pin;
|
||||||
int i, type, version, success = 0, death = 0, confirm = 0;
|
int i, type, version, count = 0, success = 0, death = 0, confirm = 0;
|
||||||
Key **keys, *k;
|
Key **keys = NULL, *k;
|
||||||
Identity *id;
|
Identity *id;
|
||||||
Idtab *tab;
|
Idtab *tab;
|
||||||
|
|
||||||
sc_reader_id = buffer_get_string(&e->request, NULL);
|
provider = buffer_get_string(&e->request, NULL);
|
||||||
pin = buffer_get_string(&e->request, NULL);
|
pin = buffer_get_string(&e->request, NULL);
|
||||||
|
|
||||||
while (buffer_len(&e->request)) {
|
while (buffer_len(&e->request)) {
|
||||||
@ -633,30 +635,22 @@ process_add_smartcard_key(SocketEntry *e)
|
|||||||
default:
|
default:
|
||||||
error("process_add_smartcard_key: "
|
error("process_add_smartcard_key: "
|
||||||
"Unknown constraint type %d", type);
|
"Unknown constraint type %d", type);
|
||||||
xfree(sc_reader_id);
|
|
||||||
xfree(pin);
|
|
||||||
goto send;
|
goto send;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lifetime && !death)
|
if (lifetime && !death)
|
||||||
death = time(NULL) + lifetime;
|
death = time(NULL) + lifetime;
|
||||||
|
|
||||||
keys = sc_get_keys(sc_reader_id, pin);
|
count = pkcs11_add_provider(provider, pin, &keys);
|
||||||
xfree(sc_reader_id);
|
for (i = 0; i < count; i++) {
|
||||||
xfree(pin);
|
|
||||||
|
|
||||||
if (keys == NULL || keys[0] == NULL) {
|
|
||||||
error("sc_get_keys failed");
|
|
||||||
goto send;
|
|
||||||
}
|
|
||||||
for (i = 0; keys[i] != NULL; i++) {
|
|
||||||
k = keys[i];
|
k = keys[i];
|
||||||
version = k->type == KEY_RSA1 ? 1 : 2;
|
version = k->type == KEY_RSA1 ? 1 : 2;
|
||||||
tab = idtab_lookup(version);
|
tab = idtab_lookup(version);
|
||||||
if (lookup_identity(k, version) == NULL) {
|
if (lookup_identity(k, version) == NULL) {
|
||||||
id = xmalloc(sizeof(Identity));
|
id = xcalloc(1, sizeof(Identity));
|
||||||
id->key = k;
|
id->key = k;
|
||||||
id->comment = sc_get_key_label(k);
|
id->provider = xstrdup(provider);
|
||||||
|
id->comment = xstrdup(provider); /* XXX */
|
||||||
id->death = death;
|
id->death = death;
|
||||||
id->confirm = confirm;
|
id->confirm = confirm;
|
||||||
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
||||||
@ -667,8 +661,13 @@ process_add_smartcard_key(SocketEntry *e)
|
|||||||
}
|
}
|
||||||
keys[i] = NULL;
|
keys[i] = NULL;
|
||||||
}
|
}
|
||||||
xfree(keys);
|
|
||||||
send:
|
send:
|
||||||
|
if (pin)
|
||||||
|
xfree(pin);
|
||||||
|
if (provider)
|
||||||
|
xfree(provider);
|
||||||
|
if (keys)
|
||||||
|
xfree(keys);
|
||||||
buffer_put_int(&e->output, 1);
|
buffer_put_int(&e->output, 1);
|
||||||
buffer_put_char(&e->output,
|
buffer_put_char(&e->output,
|
||||||
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
|
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
|
||||||
@ -677,42 +676,37 @@ send:
|
|||||||
static void
|
static void
|
||||||
process_remove_smartcard_key(SocketEntry *e)
|
process_remove_smartcard_key(SocketEntry *e)
|
||||||
{
|
{
|
||||||
char *sc_reader_id = NULL, *pin;
|
char *provider = NULL, *pin = NULL;
|
||||||
int i, version, success = 0;
|
int version, success = 0;
|
||||||
Key **keys, *k = NULL;
|
Identity *id, *nxt;
|
||||||
Identity *id;
|
|
||||||
Idtab *tab;
|
Idtab *tab;
|
||||||
|
|
||||||
sc_reader_id = buffer_get_string(&e->request, NULL);
|
provider = buffer_get_string(&e->request, NULL);
|
||||||
pin = buffer_get_string(&e->request, NULL);
|
pin = buffer_get_string(&e->request, NULL);
|
||||||
keys = sc_get_keys(sc_reader_id, pin);
|
|
||||||
xfree(sc_reader_id);
|
|
||||||
xfree(pin);
|
xfree(pin);
|
||||||
|
|
||||||
if (keys == NULL || keys[0] == NULL) {
|
for (version = 1; version < 3; version++) {
|
||||||
error("sc_get_keys failed");
|
tab = idtab_lookup(version);
|
||||||
goto send;
|
for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
|
||||||
}
|
nxt = TAILQ_NEXT(id, next);
|
||||||
for (i = 0; keys[i] != NULL; i++) {
|
if (!strcmp(provider, id->provider)) {
|
||||||
k = keys[i];
|
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||||
version = k->type == KEY_RSA1 ? 1 : 2;
|
free_identity(id);
|
||||||
if ((id = lookup_identity(k, version)) != NULL) {
|
tab->nentries--;
|
||||||
tab = idtab_lookup(version);
|
}
|
||||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
|
||||||
tab->nentries--;
|
|
||||||
free_identity(id);
|
|
||||||
success = 1;
|
|
||||||
}
|
}
|
||||||
key_free(k);
|
|
||||||
keys[i] = NULL;
|
|
||||||
}
|
}
|
||||||
xfree(keys);
|
if (pkcs11_del_provider(provider) == 0)
|
||||||
send:
|
success = 1;
|
||||||
|
else
|
||||||
|
error("process_remove_smartcard_key:"
|
||||||
|
" pkcs11_del_provider failed");
|
||||||
|
xfree(provider);
|
||||||
buffer_put_int(&e->output, 1);
|
buffer_put_int(&e->output, 1);
|
||||||
buffer_put_char(&e->output,
|
buffer_put_char(&e->output,
|
||||||
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
|
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
|
||||||
}
|
}
|
||||||
#endif /* SMARTCARD */
|
#endif /* ENABLE_PKCS11 */
|
||||||
|
|
||||||
/* dispatch incoming messages */
|
/* dispatch incoming messages */
|
||||||
|
|
||||||
@ -797,7 +791,7 @@ process_message(SocketEntry *e)
|
|||||||
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
||||||
process_remove_all_identities(e, 2);
|
process_remove_all_identities(e, 2);
|
||||||
break;
|
break;
|
||||||
#ifdef SMARTCARD
|
#ifdef ENABLE_PKCS11
|
||||||
case SSH_AGENTC_ADD_SMARTCARD_KEY:
|
case SSH_AGENTC_ADD_SMARTCARD_KEY:
|
||||||
case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
|
case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
|
||||||
process_add_smartcard_key(e);
|
process_add_smartcard_key(e);
|
||||||
@ -805,7 +799,7 @@ process_message(SocketEntry *e)
|
|||||||
case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
|
case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
|
||||||
process_remove_smartcard_key(e);
|
process_remove_smartcard_key(e);
|
||||||
break;
|
break;
|
||||||
#endif /* SMARTCARD */
|
#endif /* ENABLE_PKCS11 */
|
||||||
default:
|
default:
|
||||||
/* Unknown message. Respond with failure. */
|
/* Unknown message. Respond with failure. */
|
||||||
error("Unknown message %d", type);
|
error("Unknown message %d", type);
|
||||||
@ -1009,6 +1003,9 @@ static void
|
|||||||
cleanup_handler(int sig)
|
cleanup_handler(int sig)
|
||||||
{
|
{
|
||||||
cleanup_socket();
|
cleanup_socket();
|
||||||
|
#ifdef ENABLE_PKCS11
|
||||||
|
pkcs11_terminate();
|
||||||
|
#endif
|
||||||
_exit(2);
|
_exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1255,6 +1252,10 @@ main(int ac, char **av)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
|
|
||||||
|
#ifdef ENABLE_PKCS11
|
||||||
|
pkcs11_init(0);
|
||||||
|
#endif
|
||||||
new_socket(AUTH_SOCKET, sock);
|
new_socket(AUTH_SOCKET, sock);
|
||||||
if (ac > 0)
|
if (ac > 0)
|
||||||
parent_alive_interval = 10;
|
parent_alive_interval = 10;
|
||||||
|
14
ssh-keygen.1
14
ssh-keygen.1
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: ssh-keygen.1,v 1.80 2009/10/24 00:48:34 dtucker Exp $
|
.\" $OpenBSD: ssh-keygen.1,v 1.81 2010/02/08 10:50:20 markus Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" -*- nroff -*-
|
.\" -*- nroff -*-
|
||||||
.\"
|
.\"
|
||||||
@ -37,7 +37,7 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: October 24 2009 $
|
.Dd $Mdocdate: February 8 2010 $
|
||||||
.Dt SSH-KEYGEN 1
|
.Dt SSH-KEYGEN 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -201,9 +201,10 @@ Requests changing the comment in the private and public key files.
|
|||||||
This operation is only supported for RSA1 keys.
|
This operation is only supported for RSA1 keys.
|
||||||
The program will prompt for the file containing the private keys, for
|
The program will prompt for the file containing the private keys, for
|
||||||
the passphrase if the key has one, and for the new comment.
|
the passphrase if the key has one, and for the new comment.
|
||||||
.It Fl D Ar reader
|
.It Fl D Ar pkcs11
|
||||||
Download the RSA public key stored in the smartcard in
|
Download the RSA public keys stored in the
|
||||||
.Ar reader .
|
.Ar pkcs11
|
||||||
|
provider.
|
||||||
.It Fl e
|
.It Fl e
|
||||||
This option will read a private or public OpenSSH key file and
|
This option will read a private or public OpenSSH key file and
|
||||||
print the key in
|
print the key in
|
||||||
@ -313,9 +314,6 @@ for protocol version 1 and
|
|||||||
or
|
or
|
||||||
.Dq dsa
|
.Dq dsa
|
||||||
for protocol version 2.
|
for protocol version 2.
|
||||||
.It Fl U Ar reader
|
|
||||||
Upload an existing RSA private key into the smartcard in
|
|
||||||
.Ar reader .
|
|
||||||
.It Fl v
|
.It Fl v
|
||||||
Verbose mode.
|
Verbose mode.
|
||||||
Causes
|
Causes
|
||||||
|
84
ssh-keygen.c
84
ssh-keygen.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-keygen.c,v 1.176 2010/01/11 10:51:07 djm Exp $ */
|
/* $OpenBSD: ssh-keygen.c,v 1.177 2010/02/08 10:50:20 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -49,8 +49,8 @@
|
|||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
|
|
||||||
#ifdef SMARTCARD
|
#ifdef ENABLE_PKCS11
|
||||||
#include "scard.h"
|
#include "ssh-pkcs11.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
|
/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
|
||||||
@ -459,51 +459,29 @@ do_print_public(struct passwd *pw)
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SMARTCARD
|
|
||||||
static void
|
static void
|
||||||
do_upload(struct passwd *pw, const char *sc_reader_id)
|
do_download(struct passwd *pw, const char *pkcs11provider)
|
||||||
{
|
|
||||||
Key *prv = NULL;
|
|
||||||
struct stat st;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!have_identity)
|
|
||||||
ask_filename(pw, "Enter file in which the key is");
|
|
||||||
if (stat(identity_file, &st) < 0) {
|
|
||||||
perror(identity_file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
prv = load_identity(identity_file);
|
|
||||||
if (prv == NULL) {
|
|
||||||
error("load failed");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
ret = sc_put_key(prv, sc_reader_id);
|
|
||||||
key_free(prv);
|
|
||||||
if (ret < 0)
|
|
||||||
exit(1);
|
|
||||||
logit("loading key done");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_download(struct passwd *pw, const char *sc_reader_id)
|
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_PKCS11
|
||||||
Key **keys = NULL;
|
Key **keys = NULL;
|
||||||
int i;
|
int i, nkeys;
|
||||||
|
|
||||||
keys = sc_get_keys(sc_reader_id, NULL);
|
pkcs11_init(0);
|
||||||
if (keys == NULL)
|
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
|
||||||
fatal("cannot read public key from smartcard");
|
if (nkeys <= 0)
|
||||||
for (i = 0; keys[i]; i++) {
|
fatal("cannot read public key from pkcs11");
|
||||||
|
for (i = 0; i < nkeys; i++) {
|
||||||
key_write(keys[i], stdout);
|
key_write(keys[i], stdout);
|
||||||
key_free(keys[i]);
|
key_free(keys[i]);
|
||||||
fprintf(stdout, "\n");
|
fprintf(stdout, "\n");
|
||||||
}
|
}
|
||||||
xfree(keys);
|
xfree(keys);
|
||||||
|
pkcs11_terminate();
|
||||||
exit(0);
|
exit(0);
|
||||||
|
#else
|
||||||
|
fatal("no pkcs11 support");
|
||||||
|
#endif /* ENABLE_PKCS11 */
|
||||||
}
|
}
|
||||||
#endif /* SMARTCARD */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_fingerprint(struct passwd *pw)
|
do_fingerprint(struct passwd *pw)
|
||||||
@ -1044,9 +1022,9 @@ usage(void)
|
|||||||
fprintf(stderr, " -b bits Number of bits in the key to create.\n");
|
fprintf(stderr, " -b bits Number of bits in the key to create.\n");
|
||||||
fprintf(stderr, " -C comment Provide new comment.\n");
|
fprintf(stderr, " -C comment Provide new comment.\n");
|
||||||
fprintf(stderr, " -c Change comment in private and public key files.\n");
|
fprintf(stderr, " -c Change comment in private and public key files.\n");
|
||||||
#ifdef SMARTCARD
|
#ifdef ENABLE_PKCS11
|
||||||
fprintf(stderr, " -D reader Download public key from smartcard.\n");
|
fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n");
|
||||||
#endif /* SMARTCARD */
|
#endif
|
||||||
fprintf(stderr, " -e Convert OpenSSH to RFC 4716 key file.\n");
|
fprintf(stderr, " -e Convert OpenSSH to RFC 4716 key file.\n");
|
||||||
fprintf(stderr, " -F hostname Find hostname in known hosts file.\n");
|
fprintf(stderr, " -F hostname Find hostname in known hosts file.\n");
|
||||||
fprintf(stderr, " -f filename Filename of the key file.\n");
|
fprintf(stderr, " -f filename Filename of the key file.\n");
|
||||||
@ -1065,9 +1043,6 @@ usage(void)
|
|||||||
fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n");
|
fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n");
|
||||||
fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n");
|
fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n");
|
||||||
fprintf(stderr, " -t type Specify type of key to create.\n");
|
fprintf(stderr, " -t type Specify type of key to create.\n");
|
||||||
#ifdef SMARTCARD
|
|
||||||
fprintf(stderr, " -U reader Upload private key to smartcard.\n");
|
|
||||||
#endif /* SMARTCARD */
|
|
||||||
fprintf(stderr, " -v Verbose.\n");
|
fprintf(stderr, " -v Verbose.\n");
|
||||||
fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
|
fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
|
||||||
fprintf(stderr, " -y Read private key file and print public key.\n");
|
fprintf(stderr, " -y Read private key file and print public key.\n");
|
||||||
@ -1082,12 +1057,12 @@ int
|
|||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
|
char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
|
||||||
char out_file[MAXPATHLEN], *reader_id = NULL;
|
char out_file[MAXPATHLEN], *pkcs11provider = NULL;
|
||||||
char *rr_hostname = NULL;
|
char *rr_hostname = NULL;
|
||||||
Key *private, *public;
|
Key *private, *public;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int opt, type, fd, download = 0;
|
int opt, type, fd;
|
||||||
u_int32_t memory = 0, generator_wanted = 0, trials = 100;
|
u_int32_t memory = 0, generator_wanted = 0, trials = 100;
|
||||||
int do_gen_candidates = 0, do_screen_candidates = 0;
|
int do_gen_candidates = 0, do_screen_candidates = 0;
|
||||||
BIGNUM *start = NULL;
|
BIGNUM *start = NULL;
|
||||||
@ -1120,7 +1095,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv,
|
while ((opt = getopt(argc, argv,
|
||||||
"degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
|
"degiqpclBHvxXyF:b:f:t:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'b':
|
case 'b':
|
||||||
bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
|
bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
|
||||||
@ -1192,10 +1167,7 @@ main(int argc, char **argv)
|
|||||||
key_type_name = optarg;
|
key_type_name = optarg;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
download = 1;
|
pkcs11provider = optarg;
|
||||||
/*FALLTHROUGH*/
|
|
||||||
case 'U':
|
|
||||||
reader_id = optarg;
|
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
if (log_level == SYSLOG_LEVEL_INFO)
|
if (log_level == SYSLOG_LEVEL_INFO)
|
||||||
@ -1303,16 +1275,8 @@ main(int argc, char **argv)
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reader_id != NULL) {
|
if (pkcs11provider != NULL)
|
||||||
#ifdef SMARTCARD
|
do_download(pw, pkcs11provider);
|
||||||
if (download)
|
|
||||||
do_download(pw, reader_id);
|
|
||||||
else
|
|
||||||
do_upload(pw, reader_id);
|
|
||||||
#else /* SMARTCARD */
|
|
||||||
fatal("no support for smartcards.");
|
|
||||||
#endif /* SMARTCARD */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (do_gen_candidates) {
|
if (do_gen_candidates) {
|
||||||
FILE *out = fopen(out_file, "w");
|
FILE *out = fopen(out_file, "w");
|
||||||
|
229
ssh-pkcs11-client.c
Normal file
229
ssh-pkcs11-client.c
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "key.h"
|
||||||
|
#include "authfd.h"
|
||||||
|
#include "atomicio.h"
|
||||||
|
#include "ssh-pkcs11.h"
|
||||||
|
|
||||||
|
/* borrows code from sftp-server and ssh-agent */
|
||||||
|
|
||||||
|
int fd = -1;
|
||||||
|
pid_t pid = -1;
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_msg(Buffer *m)
|
||||||
|
{
|
||||||
|
u_char buf[4];
|
||||||
|
int mlen = buffer_len(m);
|
||||||
|
|
||||||
|
put_u32(buf, mlen);
|
||||||
|
if (atomicio(vwrite, fd, buf, 4) != 4 ||
|
||||||
|
atomicio(vwrite, fd, buffer_ptr(m),
|
||||||
|
buffer_len(m)) != buffer_len(m))
|
||||||
|
error("write to helper failed");
|
||||||
|
buffer_consume(m, mlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
recv_msg(Buffer *m)
|
||||||
|
{
|
||||||
|
u_int l, len;
|
||||||
|
u_char buf[1024];
|
||||||
|
|
||||||
|
if ((len = atomicio(read, fd, buf, 4)) != 4) {
|
||||||
|
error("read from helper failed: %u", len);
|
||||||
|
return (0); /* XXX */
|
||||||
|
}
|
||||||
|
len = get_u32(buf);
|
||||||
|
if (len > 256 * 1024)
|
||||||
|
fatal("response too long: %u", len);
|
||||||
|
/* read len bytes into m */
|
||||||
|
buffer_clear(m);
|
||||||
|
while (len > 0) {
|
||||||
|
l = len;
|
||||||
|
if (l > sizeof(buf))
|
||||||
|
l = sizeof(buf);
|
||||||
|
if (atomicio(read, fd, buf, l) != l) {
|
||||||
|
error("response from helper failed.");
|
||||||
|
return (0); /* XXX */
|
||||||
|
}
|
||||||
|
buffer_append(m, buf, l);
|
||||||
|
len -= l;
|
||||||
|
}
|
||||||
|
return (buffer_get_char(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pkcs11_init(int interactive)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pkcs11_terminate(void)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
|
||||||
|
int padding)
|
||||||
|
{
|
||||||
|
Key key;
|
||||||
|
u_char *blob, *signature = NULL;
|
||||||
|
u_int blen, slen = 0;
|
||||||
|
int ret = -1;
|
||||||
|
Buffer msg;
|
||||||
|
|
||||||
|
if (padding != RSA_PKCS1_PADDING)
|
||||||
|
return (-1);
|
||||||
|
key.type = KEY_RSA;
|
||||||
|
key.rsa = rsa;
|
||||||
|
if (key_to_blob(&key, &blob, &blen) == 0)
|
||||||
|
return -1;
|
||||||
|
buffer_init(&msg);
|
||||||
|
buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
|
||||||
|
buffer_put_string(&msg, blob, blen);
|
||||||
|
buffer_put_string(&msg, from, flen);
|
||||||
|
buffer_put_int(&msg, 0);
|
||||||
|
xfree(blob);
|
||||||
|
send_msg(&msg);
|
||||||
|
|
||||||
|
if (recv_msg(&msg) == SSH2_AGENT_SIGN_RESPONSE) {
|
||||||
|
signature = buffer_get_string(&msg, &slen);
|
||||||
|
if (slen <= (u_int)RSA_size(rsa)) {
|
||||||
|
memcpy(to, signature, slen);
|
||||||
|
ret = slen;
|
||||||
|
}
|
||||||
|
xfree(signature);
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* redirect the private key encrypt operation to the ssh-pkcs11-helper */
|
||||||
|
static int
|
||||||
|
wrap_key(RSA *rsa)
|
||||||
|
{
|
||||||
|
static RSA_METHOD helper_rsa;
|
||||||
|
|
||||||
|
memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa));
|
||||||
|
helper_rsa.name = "ssh-pkcs11-helper";
|
||||||
|
helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt;
|
||||||
|
RSA_set_method(rsa, &helper_rsa);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pkcs11_start_helper(void)
|
||||||
|
{
|
||||||
|
int pair[2];
|
||||||
|
|
||||||
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
|
||||||
|
error("socketpair: %s", strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if ((pid = fork()) == -1) {
|
||||||
|
error("fork: %s", strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
} else if (pid == 0) {
|
||||||
|
if ((dup2(pair[1], STDIN_FILENO) == -1) ||
|
||||||
|
(dup2(pair[1], STDOUT_FILENO) == -1)) {
|
||||||
|
fprintf(stderr, "dup2: %s\n", strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
close(pair[0]);
|
||||||
|
close(pair[1]);
|
||||||
|
execlp(_PATH_SSH_PKCS11_HELPER, _PATH_SSH_PKCS11_HELPER,
|
||||||
|
(char *) 0);
|
||||||
|
fprintf(stderr, "exec: %s: %s\n", _PATH_SSH_PKCS11_HELPER,
|
||||||
|
strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
close(pair[1]);
|
||||||
|
fd = pair[0];
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pkcs11_add_provider(char *name, char *pin, Key ***keysp)
|
||||||
|
{
|
||||||
|
Key *k;
|
||||||
|
int i, nkeys;
|
||||||
|
u_char *blob;
|
||||||
|
u_int blen;
|
||||||
|
Buffer msg;
|
||||||
|
|
||||||
|
if (fd < 0 && pkcs11_start_helper() < 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
buffer_init(&msg);
|
||||||
|
buffer_put_char(&msg, SSH_AGENTC_ADD_SMARTCARD_KEY);
|
||||||
|
buffer_put_cstring(&msg, name);
|
||||||
|
buffer_put_cstring(&msg, pin);
|
||||||
|
send_msg(&msg);
|
||||||
|
buffer_clear(&msg);
|
||||||
|
|
||||||
|
if (recv_msg(&msg) == SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||||
|
nkeys = buffer_get_int(&msg);
|
||||||
|
*keysp = xcalloc(nkeys, sizeof(Key *));
|
||||||
|
for (i = 0; i < nkeys; i++) {
|
||||||
|
blob = buffer_get_string(&msg, &blen);
|
||||||
|
xfree(buffer_get_string(&msg, NULL));
|
||||||
|
k = key_from_blob(blob, blen);
|
||||||
|
wrap_key(k->rsa);
|
||||||
|
(*keysp)[i] = k;
|
||||||
|
xfree(blob);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nkeys = -1;
|
||||||
|
}
|
||||||
|
buffer_free(&msg);
|
||||||
|
return (nkeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pkcs11_del_provider(char *name)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
Buffer msg;
|
||||||
|
|
||||||
|
buffer_init(&msg);
|
||||||
|
buffer_put_char(&msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY);
|
||||||
|
buffer_put_cstring(&msg, name);
|
||||||
|
buffer_put_cstring(&msg, "");
|
||||||
|
send_msg(&msg);
|
||||||
|
buffer_clear(&msg);
|
||||||
|
|
||||||
|
if (recv_msg(&msg) == SSH_AGENT_SUCCESS)
|
||||||
|
ret = 0;
|
||||||
|
buffer_free(&msg);
|
||||||
|
return (ret);
|
||||||
|
}
|
349
ssh-pkcs11-helper.c
Normal file
349
ssh-pkcs11-helper.c
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 <sys/queue.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "key.h"
|
||||||
|
#include "authfd.h"
|
||||||
|
#include "ssh-pkcs11.h"
|
||||||
|
|
||||||
|
/* borrows code from sftp-server and ssh-agent */
|
||||||
|
|
||||||
|
struct pkcs11_keyinfo {
|
||||||
|
Key *key;
|
||||||
|
char *providername;
|
||||||
|
TAILQ_ENTRY(pkcs11_keyinfo) next;
|
||||||
|
};
|
||||||
|
|
||||||
|
TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist;
|
||||||
|
|
||||||
|
#define MAX_MSG_LENGTH 10240 /*XXX*/
|
||||||
|
|
||||||
|
/* helper */
|
||||||
|
#define get_int() buffer_get_int(&iqueue);
|
||||||
|
#define get_string(lenp) buffer_get_string(&iqueue, lenp);
|
||||||
|
|
||||||
|
/* input and output queue */
|
||||||
|
Buffer iqueue;
|
||||||
|
Buffer oqueue;
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_key(Key *k, char *name)
|
||||||
|
{
|
||||||
|
struct pkcs11_keyinfo *ki;
|
||||||
|
|
||||||
|
ki = xcalloc(1, sizeof(*ki));
|
||||||
|
ki->providername = xstrdup(name);
|
||||||
|
ki->key = k;
|
||||||
|
TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
del_keys_by_name(char *name)
|
||||||
|
{
|
||||||
|
struct pkcs11_keyinfo *ki, *nxt;
|
||||||
|
|
||||||
|
for (ki = TAILQ_FIRST(&pkcs11_keylist); ki; ki = nxt) {
|
||||||
|
nxt = TAILQ_NEXT(ki, next);
|
||||||
|
if (!strcmp(ki->providername, name)) {
|
||||||
|
TAILQ_REMOVE(&pkcs11_keylist, ki, next);
|
||||||
|
xfree(ki->providername);
|
||||||
|
key_free(ki->key);
|
||||||
|
free(ki);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lookup matching 'private' key */
|
||||||
|
static Key *
|
||||||
|
lookup_key(Key *k)
|
||||||
|
{
|
||||||
|
struct pkcs11_keyinfo *ki;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(ki, &pkcs11_keylist, next) {
|
||||||
|
debug("check %p %s", ki, ki->providername);
|
||||||
|
if (key_equal(k, ki->key))
|
||||||
|
return (ki->key);
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_msg(Buffer *m)
|
||||||
|
{
|
||||||
|
int mlen = buffer_len(m);
|
||||||
|
|
||||||
|
buffer_put_int(&oqueue, mlen);
|
||||||
|
buffer_append(&oqueue, buffer_ptr(m), mlen);
|
||||||
|
buffer_consume(m, mlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_add(void)
|
||||||
|
{
|
||||||
|
char *name, *pin;
|
||||||
|
Key **keys;
|
||||||
|
int i, nkeys;
|
||||||
|
u_char *blob;
|
||||||
|
u_int blen;
|
||||||
|
Buffer msg;
|
||||||
|
|
||||||
|
buffer_init(&msg);
|
||||||
|
name = get_string(NULL);
|
||||||
|
pin = get_string(NULL);
|
||||||
|
if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) {
|
||||||
|
buffer_put_char(&msg, SSH2_AGENT_IDENTITIES_ANSWER);
|
||||||
|
buffer_put_int(&msg, nkeys);
|
||||||
|
for (i = 0; i < nkeys; i++) {
|
||||||
|
key_to_blob(keys[i], &blob, &blen);
|
||||||
|
buffer_put_string(&msg, blob, blen);
|
||||||
|
buffer_put_cstring(&msg, name);
|
||||||
|
xfree(blob);
|
||||||
|
add_key(keys[i], name);
|
||||||
|
}
|
||||||
|
xfree(keys);
|
||||||
|
} else {
|
||||||
|
buffer_put_char(&msg, SSH_AGENT_FAILURE);
|
||||||
|
}
|
||||||
|
xfree(pin);
|
||||||
|
xfree(name);
|
||||||
|
send_msg(&msg);
|
||||||
|
buffer_free(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_del(void)
|
||||||
|
{
|
||||||
|
char *name, *pin;
|
||||||
|
Buffer msg;
|
||||||
|
|
||||||
|
buffer_init(&msg);
|
||||||
|
name = get_string(NULL);
|
||||||
|
pin = get_string(NULL);
|
||||||
|
del_keys_by_name(name);
|
||||||
|
if (pkcs11_del_provider(name) == 0)
|
||||||
|
buffer_put_char(&msg, SSH_AGENT_SUCCESS);
|
||||||
|
else
|
||||||
|
buffer_put_char(&msg, SSH_AGENT_FAILURE);
|
||||||
|
xfree(pin);
|
||||||
|
xfree(name);
|
||||||
|
send_msg(&msg);
|
||||||
|
buffer_free(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_sign(void)
|
||||||
|
{
|
||||||
|
u_char *blob, *data, *signature = NULL;
|
||||||
|
u_int blen, dlen, slen = 0;
|
||||||
|
int ok = -1, flags, ret;
|
||||||
|
Key *key, *found;
|
||||||
|
Buffer msg;
|
||||||
|
|
||||||
|
blob = get_string(&blen);
|
||||||
|
data = get_string(&dlen);
|
||||||
|
flags = get_int(); /* XXX ignore */
|
||||||
|
|
||||||
|
if ((key = key_from_blob(blob, blen)) != NULL) {
|
||||||
|
if ((found = lookup_key(key)) != NULL) {
|
||||||
|
slen = RSA_size(key->rsa);
|
||||||
|
signature = xmalloc(slen);
|
||||||
|
if ((ret = RSA_private_encrypt(dlen, data, signature,
|
||||||
|
found->rsa, RSA_PKCS1_PADDING)) != -1) {
|
||||||
|
slen = ret;
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
key_free(key);
|
||||||
|
}
|
||||||
|
buffer_init(&msg);
|
||||||
|
if (ok == 0) {
|
||||||
|
buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
|
||||||
|
buffer_put_string(&msg, signature, slen);
|
||||||
|
} else {
|
||||||
|
buffer_put_char(&msg, SSH_AGENT_FAILURE);
|
||||||
|
}
|
||||||
|
xfree(data);
|
||||||
|
xfree(blob);
|
||||||
|
if (signature != NULL)
|
||||||
|
xfree(signature);
|
||||||
|
send_msg(&msg);
|
||||||
|
buffer_free(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process(void)
|
||||||
|
{
|
||||||
|
u_int msg_len;
|
||||||
|
u_int buf_len;
|
||||||
|
u_int consumed;
|
||||||
|
u_int type;
|
||||||
|
u_char *cp;
|
||||||
|
|
||||||
|
buf_len = buffer_len(&iqueue);
|
||||||
|
if (buf_len < 5)
|
||||||
|
return; /* Incomplete message. */
|
||||||
|
cp = buffer_ptr(&iqueue);
|
||||||
|
msg_len = get_u32(cp);
|
||||||
|
if (msg_len > MAX_MSG_LENGTH) {
|
||||||
|
error("bad message len %d", msg_len);
|
||||||
|
cleanup_exit(11);
|
||||||
|
}
|
||||||
|
if (buf_len < msg_len + 4)
|
||||||
|
return;
|
||||||
|
buffer_consume(&iqueue, 4);
|
||||||
|
buf_len -= 4;
|
||||||
|
type = buffer_get_char(&iqueue);
|
||||||
|
switch (type) {
|
||||||
|
case SSH_AGENTC_ADD_SMARTCARD_KEY:
|
||||||
|
debug("process_add");
|
||||||
|
process_add();
|
||||||
|
break;
|
||||||
|
case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
|
||||||
|
debug("process_del");
|
||||||
|
process_del();
|
||||||
|
break;
|
||||||
|
case SSH2_AGENTC_SIGN_REQUEST:
|
||||||
|
debug("process_sign");
|
||||||
|
process_sign();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Unknown message %d", type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* discard the remaining bytes from the current packet */
|
||||||
|
if (buf_len < buffer_len(&iqueue)) {
|
||||||
|
error("iqueue grew unexpectedly");
|
||||||
|
cleanup_exit(255);
|
||||||
|
}
|
||||||
|
consumed = buf_len - buffer_len(&iqueue);
|
||||||
|
if (msg_len < consumed) {
|
||||||
|
error("msg_len %d < consumed %d", msg_len, consumed);
|
||||||
|
cleanup_exit(255);
|
||||||
|
}
|
||||||
|
if (msg_len > consumed)
|
||||||
|
buffer_consume(&iqueue, msg_len - consumed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cleanup_exit(int i)
|
||||||
|
{
|
||||||
|
/* XXX */
|
||||||
|
_exit(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
fd_set *rset, *wset;
|
||||||
|
int in, out, max, log_stderr = 0;
|
||||||
|
ssize_t len, olen, set_size;
|
||||||
|
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
|
||||||
|
LogLevel log_level = SYSLOG_LEVEL_ERROR;
|
||||||
|
char buf[4*4096];
|
||||||
|
|
||||||
|
TAILQ_INIT(&pkcs11_keylist);
|
||||||
|
pkcs11_init(0);
|
||||||
|
|
||||||
|
extern char *optarg;
|
||||||
|
extern char *__progname;
|
||||||
|
|
||||||
|
log_init(__progname, log_level, log_facility, log_stderr);
|
||||||
|
|
||||||
|
in = STDIN_FILENO;
|
||||||
|
out = STDOUT_FILENO;
|
||||||
|
|
||||||
|
max = 0;
|
||||||
|
if (in > max)
|
||||||
|
max = in;
|
||||||
|
if (out > max)
|
||||||
|
max = out;
|
||||||
|
|
||||||
|
buffer_init(&iqueue);
|
||||||
|
buffer_init(&oqueue);
|
||||||
|
|
||||||
|
set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
|
||||||
|
rset = (fd_set *)xmalloc(set_size);
|
||||||
|
wset = (fd_set *)xmalloc(set_size);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
memset(rset, 0, set_size);
|
||||||
|
memset(wset, 0, set_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that we can read a full buffer and handle
|
||||||
|
* the worst-case length packet it can generate,
|
||||||
|
* otherwise apply backpressure by stopping reads.
|
||||||
|
*/
|
||||||
|
if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
|
||||||
|
buffer_check_alloc(&oqueue, MAX_MSG_LENGTH))
|
||||||
|
FD_SET(in, rset);
|
||||||
|
|
||||||
|
olen = buffer_len(&oqueue);
|
||||||
|
if (olen > 0)
|
||||||
|
FD_SET(out, wset);
|
||||||
|
|
||||||
|
if (select(max+1, rset, wset, NULL, NULL) < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
error("select: %s", strerror(errno));
|
||||||
|
cleanup_exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy stdin to iqueue */
|
||||||
|
if (FD_ISSET(in, rset)) {
|
||||||
|
len = read(in, buf, sizeof buf);
|
||||||
|
if (len == 0) {
|
||||||
|
debug("read eof");
|
||||||
|
cleanup_exit(0);
|
||||||
|
} else if (len < 0) {
|
||||||
|
error("read: %s", strerror(errno));
|
||||||
|
cleanup_exit(1);
|
||||||
|
} else {
|
||||||
|
buffer_append(&iqueue, buf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* send oqueue to stdout */
|
||||||
|
if (FD_ISSET(out, wset)) {
|
||||||
|
len = write(out, buffer_ptr(&oqueue), olen);
|
||||||
|
if (len < 0) {
|
||||||
|
error("write: %s", strerror(errno));
|
||||||
|
cleanup_exit(1);
|
||||||
|
} else {
|
||||||
|
buffer_consume(&oqueue, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process requests from client if we can fit the results
|
||||||
|
* into the output buffer, otherwise stop processing input
|
||||||
|
* and let the output queue drain.
|
||||||
|
*/
|
||||||
|
if (buffer_check_alloc(&oqueue, MAX_MSG_LENGTH))
|
||||||
|
process();
|
||||||
|
}
|
||||||
|
}
|
544
ssh-pkcs11.c
Normal file
544
ssh-pkcs11.c
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 <sys/types.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#define CRYPTOKI_COMPAT
|
||||||
|
#include "pkcs11.h"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "key.h"
|
||||||
|
#include "ssh-pkcs11.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
struct pkcs11_slotinfo {
|
||||||
|
CK_TOKEN_INFO token;
|
||||||
|
CK_SESSION_HANDLE session;
|
||||||
|
int logged_in;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pkcs11_provider {
|
||||||
|
char *name;
|
||||||
|
void *handle;
|
||||||
|
CK_FUNCTION_LIST *function_list;
|
||||||
|
CK_INFO info;
|
||||||
|
CK_ULONG nslots;
|
||||||
|
CK_SLOT_ID *slotlist;
|
||||||
|
struct pkcs11_slotinfo *slotinfo;
|
||||||
|
int valid;
|
||||||
|
int refcount;
|
||||||
|
TAILQ_ENTRY(pkcs11_provider) next;
|
||||||
|
};
|
||||||
|
|
||||||
|
TAILQ_HEAD(, pkcs11_provider) pkcs11_providers;
|
||||||
|
|
||||||
|
struct pkcs11_key {
|
||||||
|
struct pkcs11_provider *provider;
|
||||||
|
CK_ULONG slotidx;
|
||||||
|
int (*orig_finish)(RSA *rsa);
|
||||||
|
RSA_METHOD rsa_method;
|
||||||
|
char *keyid;
|
||||||
|
int keyid_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
int pkcs11_interactive = 0;
|
||||||
|
|
||||||
|
int
|
||||||
|
pkcs11_init(int interactive)
|
||||||
|
{
|
||||||
|
pkcs11_interactive = interactive;
|
||||||
|
TAILQ_INIT(&pkcs11_providers);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* finalize a provider shared libarary, it's no longer usable.
|
||||||
|
* however, there might still be keys referencing this provider,
|
||||||
|
* so the actuall freeing of memory is handled by pkcs11_provider_unref().
|
||||||
|
* this is called when a provider gets unregistered.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pkcs11_provider_finalize(struct pkcs11_provider *p)
|
||||||
|
{
|
||||||
|
CK_RV rv;
|
||||||
|
CK_ULONG i;
|
||||||
|
|
||||||
|
debug("pkcs11_provider_finalize: %p refcount %d valid %d",
|
||||||
|
p, p->refcount, p->valid);
|
||||||
|
if (!p->valid)
|
||||||
|
return;
|
||||||
|
for (i = 0; i < p->nslots; i++) {
|
||||||
|
if (p->slotinfo[i].session &&
|
||||||
|
(rv = p->function_list->C_CloseSession(
|
||||||
|
p->slotinfo[i].session)) != CKR_OK)
|
||||||
|
error("C_CloseSession failed: %lu", rv);
|
||||||
|
}
|
||||||
|
if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK)
|
||||||
|
error("C_Finalize failed: %lu", rv);
|
||||||
|
p->valid = 0;
|
||||||
|
p->function_list = NULL;
|
||||||
|
dlclose(p->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* remove a reference to the provider.
|
||||||
|
* called when a key gets destroyed or when the provider is unregistered.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pkcs11_provider_unref(struct pkcs11_provider *p)
|
||||||
|
{
|
||||||
|
debug("pkcs11_provider_unref: %p refcount %d", p, p->refcount);
|
||||||
|
if (--p->refcount <= 0) {
|
||||||
|
if (p->valid)
|
||||||
|
error("pkcs11_provider_unref: %p still valid", p);
|
||||||
|
xfree(p->slotlist);
|
||||||
|
xfree(p->slotinfo);
|
||||||
|
xfree(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unregister all providers, keys might still point to the providers */
|
||||||
|
void
|
||||||
|
pkcs11_terminate(void)
|
||||||
|
{
|
||||||
|
struct pkcs11_provider *p;
|
||||||
|
|
||||||
|
while ((p = TAILQ_FIRST(&pkcs11_providers)) != NULL) {
|
||||||
|
TAILQ_REMOVE(&pkcs11_providers, p, next);
|
||||||
|
pkcs11_provider_finalize(p);
|
||||||
|
pkcs11_provider_unref(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lookup provider by name */
|
||||||
|
static struct pkcs11_provider *
|
||||||
|
pkcs11_provider_lookup(char *provider_id)
|
||||||
|
{
|
||||||
|
struct pkcs11_provider *p;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(p, &pkcs11_providers, next) {
|
||||||
|
debug("check %p %s", p, p->name);
|
||||||
|
if (!strcmp(provider_id, p->name))
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unregister provider by name */
|
||||||
|
int
|
||||||
|
pkcs11_del_provider(char *provider_id)
|
||||||
|
{
|
||||||
|
struct pkcs11_provider *p;
|
||||||
|
|
||||||
|
if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
|
||||||
|
TAILQ_REMOVE(&pkcs11_providers, p, next);
|
||||||
|
pkcs11_provider_finalize(p);
|
||||||
|
pkcs11_provider_unref(p);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* openssl callback for freeing an RSA key */
|
||||||
|
static int
|
||||||
|
pkcs11_rsa_finish(RSA *rsa)
|
||||||
|
{
|
||||||
|
struct pkcs11_key *k11;
|
||||||
|
int rv = -1;
|
||||||
|
|
||||||
|
if ((k11 = RSA_get_app_data(rsa)) != NULL) {
|
||||||
|
if (k11->orig_finish)
|
||||||
|
rv = k11->orig_finish(rsa);
|
||||||
|
if (k11->provider)
|
||||||
|
pkcs11_provider_unref(k11->provider);
|
||||||
|
if (k11->keyid)
|
||||||
|
xfree(k11->keyid);
|
||||||
|
xfree(k11);
|
||||||
|
}
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* openssl callback doing the actual signing operation */
|
||||||
|
static int
|
||||||
|
pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
|
||||||
|
int padding)
|
||||||
|
{
|
||||||
|
struct pkcs11_key *k11;
|
||||||
|
struct pkcs11_slotinfo *si;
|
||||||
|
CK_FUNCTION_LIST *f;
|
||||||
|
CK_OBJECT_HANDLE obj;
|
||||||
|
CK_ULONG tlen = 0, nfound = 0;
|
||||||
|
CK_RV rv;
|
||||||
|
CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
|
||||||
|
CK_BBOOL true = CK_TRUE;
|
||||||
|
CK_MECHANISM mech = {
|
||||||
|
CKM_RSA_PKCS, NULL_PTR, 0
|
||||||
|
};
|
||||||
|
CK_ATTRIBUTE key_filter[] = {
|
||||||
|
{CKA_CLASS, &private_key_class, sizeof(private_key_class) },
|
||||||
|
{CKA_ID, NULL, 0},
|
||||||
|
{CKA_SIGN, &true, sizeof(true) }
|
||||||
|
};
|
||||||
|
char *pin, prompt[1024];
|
||||||
|
int rval = -1;
|
||||||
|
|
||||||
|
if ((k11 = RSA_get_app_data(rsa)) == NULL) {
|
||||||
|
error("RSA_get_app_data failed for rsa %p", rsa);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (!k11->provider || !k11->provider->valid) {
|
||||||
|
error("no pkcs11 (valid) provider for rsa %p", rsa);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
f = k11->provider->function_list;
|
||||||
|
si = &k11->provider->slotinfo[k11->slotidx];
|
||||||
|
if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
|
||||||
|
if (!pkcs11_interactive) {
|
||||||
|
error("need pin");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
|
||||||
|
si->token.label);
|
||||||
|
pin = read_passphrase(prompt, RP_ALLOW_EOF);
|
||||||
|
if (pin == NULL)
|
||||||
|
return (-1); /* bail out */
|
||||||
|
if ((rv = f->C_Login(si->session, CKU_USER, pin, strlen(pin)))
|
||||||
|
!= CKR_OK) {
|
||||||
|
xfree(pin);
|
||||||
|
error("C_Login failed: %lu", rv);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
xfree(pin);
|
||||||
|
si->logged_in = 1;
|
||||||
|
}
|
||||||
|
key_filter[1].pValue = k11->keyid;
|
||||||
|
key_filter[1].ulValueLen = k11->keyid_len;
|
||||||
|
if ((rv = f->C_FindObjectsInit(si->session, key_filter, 3)) != CKR_OK) {
|
||||||
|
error("C_FindObjectsInit failed: %lu", rv);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if ((rv = f->C_FindObjects(si->session, &obj, 1, &nfound)) != CKR_OK ||
|
||||||
|
nfound != 1) {
|
||||||
|
error("C_FindObjects failed (%lu nfound): %lu", nfound, rv);
|
||||||
|
} else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
|
||||||
|
error("C_SignInit failed: %lu", rv);
|
||||||
|
} else {
|
||||||
|
/* XXX handle CKR_BUFFER_TOO_SMALL */
|
||||||
|
tlen = RSA_size(rsa);
|
||||||
|
rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
|
||||||
|
if (rv == CKR_OK)
|
||||||
|
rval = tlen;
|
||||||
|
else
|
||||||
|
error("C_Sign failed: %lu", rv);
|
||||||
|
}
|
||||||
|
if ((rv = f->C_FindObjectsFinal(si->session)) != CKR_OK)
|
||||||
|
error("C_FindObjectsFinal failed: %lu", rv);
|
||||||
|
return (rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
|
||||||
|
int padding)
|
||||||
|
{
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* redirect private key operations for rsa key to pkcs11 token */
|
||||||
|
static int
|
||||||
|
pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
||||||
|
CK_ATTRIBUTE *keyid_attrib, RSA *rsa)
|
||||||
|
{
|
||||||
|
struct pkcs11_key *k11;
|
||||||
|
const RSA_METHOD *def = RSA_get_default_method();
|
||||||
|
|
||||||
|
k11 = xcalloc(1, sizeof(*k11));
|
||||||
|
k11->provider = provider;
|
||||||
|
provider->refcount++; /* provider referenced by RSA key */
|
||||||
|
k11->slotidx = slotidx;
|
||||||
|
/* identify key object on smartcard */
|
||||||
|
k11->keyid_len = keyid_attrib->ulValueLen;
|
||||||
|
k11->keyid = xmalloc(k11->keyid_len);
|
||||||
|
memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
|
||||||
|
k11->orig_finish = def->finish;
|
||||||
|
memcpy(&k11->rsa_method, def, sizeof(k11->rsa_method));
|
||||||
|
k11->rsa_method.name = "pkcs11";
|
||||||
|
k11->rsa_method.rsa_priv_enc = pkcs11_rsa_private_encrypt;
|
||||||
|
k11->rsa_method.rsa_priv_dec = pkcs11_rsa_private_decrypt;
|
||||||
|
k11->rsa_method.finish = pkcs11_rsa_finish;
|
||||||
|
RSA_set_method(rsa, &k11->rsa_method);
|
||||||
|
RSA_set_app_data(rsa, k11);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove trailing spaces */
|
||||||
|
static void
|
||||||
|
rmspace(char *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
return;
|
||||||
|
for (i = len - 1; i > 0; i--)
|
||||||
|
if (i == len - 1 || buf[i] == ' ')
|
||||||
|
buf[i] = '\0';
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open a pkcs11 session and login if required.
|
||||||
|
* if pin == NULL we delay login until key use
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin)
|
||||||
|
{
|
||||||
|
CK_RV rv;
|
||||||
|
CK_FUNCTION_LIST *f;
|
||||||
|
CK_SESSION_HANDLE session;
|
||||||
|
int login_required;
|
||||||
|
|
||||||
|
f = p->function_list;
|
||||||
|
login_required = p->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED;
|
||||||
|
if (pin && login_required && !strlen(pin)) {
|
||||||
|
error("pin required");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION|
|
||||||
|
CKF_SERIAL_SESSION, NULL, NULL, &session))
|
||||||
|
!= CKR_OK) {
|
||||||
|
error("C_OpenSession failed: %lu", rv);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (login_required && pin) {
|
||||||
|
if ((rv = f->C_Login(session, CKU_USER, pin, strlen(pin)))
|
||||||
|
!= CKR_OK) {
|
||||||
|
error("C_Login failed: %lu", rv);
|
||||||
|
if ((rv = f->C_CloseSession(session)) != CKR_OK)
|
||||||
|
error("C_CloseSession failed: %lu", rv);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
p->slotinfo[slotidx].logged_in = 1;
|
||||||
|
}
|
||||||
|
p->slotinfo[slotidx].session = session;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lookup public keys for token in slot identified by slotidx,
|
||||||
|
* add 'wrapped' public keys to the 'keysp' array and increment nkeys.
|
||||||
|
* keysp points to an (possibly empty) array with *nkeys keys.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp,
|
||||||
|
int *nkeys)
|
||||||
|
{
|
||||||
|
Key *key;
|
||||||
|
RSA *rsa;
|
||||||
|
int i;
|
||||||
|
CK_RV rv;
|
||||||
|
CK_OBJECT_HANDLE obj;
|
||||||
|
CK_ULONG nfound;
|
||||||
|
CK_SESSION_HANDLE session;
|
||||||
|
CK_FUNCTION_LIST *f;
|
||||||
|
CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
|
||||||
|
CK_ATTRIBUTE pubkey_filter[] = {
|
||||||
|
{ CKA_CLASS, &pubkey_class, sizeof(pubkey_class) }
|
||||||
|
};
|
||||||
|
CK_ATTRIBUTE attribs[] = {
|
||||||
|
{ CKA_ID, NULL, 0 },
|
||||||
|
{ CKA_MODULUS, NULL, 0 },
|
||||||
|
{ CKA_PUBLIC_EXPONENT, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
f = p->function_list;
|
||||||
|
session = p->slotinfo[slotidx].session;
|
||||||
|
/* setup a filter the looks for public keys */
|
||||||
|
if ((rv = f->C_FindObjectsInit(session, pubkey_filter, 1)) != CKR_OK) {
|
||||||
|
error("C_FindObjectsInit failed: %lu", rv);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
/* XXX 3 attributes in attribs[] */
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
attribs[i].pValue = NULL;
|
||||||
|
attribs[i].ulValueLen = 0;
|
||||||
|
}
|
||||||
|
if ((rv = f->C_FindObjects(session, &obj, 1, &nfound)) != CKR_OK
|
||||||
|
|| nfound == 0)
|
||||||
|
break;
|
||||||
|
/* found a key, so figure out size of the attributes */
|
||||||
|
if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
|
||||||
|
!= CKR_OK) {
|
||||||
|
error("C_GetAttributeValue failed: %lu", rv);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* allocate buffers for attributes, XXX check ulValueLen? */
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
attribs[i].pValue = xmalloc(attribs[i].ulValueLen);
|
||||||
|
/* retrieve ID, modulus and public exponent of RSA key */
|
||||||
|
if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
|
||||||
|
!= CKR_OK) {
|
||||||
|
error("C_GetAttributeValue failed: %lu", rv);
|
||||||
|
} else if ((rsa = RSA_new()) == NULL) {
|
||||||
|
error("RSA_new failed");
|
||||||
|
} else {
|
||||||
|
rsa->n = BN_bin2bn(attribs[1].pValue,
|
||||||
|
attribs[1].ulValueLen, NULL);
|
||||||
|
rsa->e = BN_bin2bn(attribs[2].pValue,
|
||||||
|
attribs[2].ulValueLen, NULL);
|
||||||
|
if (rsa->n && rsa->e &&
|
||||||
|
pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
|
||||||
|
key = key_new(KEY_UNSPEC);
|
||||||
|
key->rsa = rsa;
|
||||||
|
key->type = KEY_RSA;
|
||||||
|
key->flags |= KEY_FLAG_EXT;
|
||||||
|
/* expand key array and add key */
|
||||||
|
*keysp = xrealloc(*keysp, *nkeys + 1,
|
||||||
|
sizeof(Key *));
|
||||||
|
(*keysp)[*nkeys] = key;
|
||||||
|
*nkeys = *nkeys + 1;
|
||||||
|
debug("have %d keys", *nkeys);
|
||||||
|
} else {
|
||||||
|
RSA_free(rsa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
xfree(attribs[i].pValue);
|
||||||
|
}
|
||||||
|
if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)
|
||||||
|
error("C_FindObjectsFinal failed: %lu", rv);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* register a new provider, fails if provider already exists */
|
||||||
|
int
|
||||||
|
pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp)
|
||||||
|
{
|
||||||
|
int nkeys, need_finalize = 0;
|
||||||
|
struct pkcs11_provider *p = NULL;
|
||||||
|
void *handle = NULL;
|
||||||
|
CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
|
||||||
|
CK_RV rv;
|
||||||
|
CK_FUNCTION_LIST *f = NULL;
|
||||||
|
CK_TOKEN_INFO *token;
|
||||||
|
CK_ULONG i;
|
||||||
|
|
||||||
|
*keyp = NULL;
|
||||||
|
if (pkcs11_provider_lookup(provider_id) != NULL) {
|
||||||
|
error("provider already registered: %s", provider_id);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* open shared pkcs11-libarary */
|
||||||
|
if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
|
||||||
|
error("dlopen %s failed: %s", provider_id, dlerror());
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) {
|
||||||
|
error("dlsym(C_GetFunctionList) failed: %s", dlerror());
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
p = xcalloc(1, sizeof(*p));
|
||||||
|
p->name = xstrdup(provider_id);
|
||||||
|
p->handle = handle;
|
||||||
|
/* setup the pkcs11 callbacks */
|
||||||
|
if ((rv = (*getfunctionlist)(&f)) != CKR_OK) {
|
||||||
|
error("C_GetFunctionList failed: %lu", rv);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
p->function_list = f;
|
||||||
|
if ((rv = f->C_Initialize(NULL)) != CKR_OK) {
|
||||||
|
error("C_Initialize failed: %lu", rv);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
need_finalize = 1;
|
||||||
|
if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) {
|
||||||
|
error("C_GetInfo failed: %lu", rv);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID));
|
||||||
|
rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription));
|
||||||
|
debug("manufacturerID <%s> cryptokiVersion %d.%d"
|
||||||
|
" libraryDescription <%s> libraryVersion %d.%d",
|
||||||
|
p->info.manufacturerID,
|
||||||
|
p->info.cryptokiVersion.major,
|
||||||
|
p->info.cryptokiVersion.minor,
|
||||||
|
p->info.libraryDescription,
|
||||||
|
p->info.libraryVersion.major,
|
||||||
|
p->info.libraryVersion.minor);
|
||||||
|
if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) {
|
||||||
|
error("C_GetSlotList failed: %lu", rv);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (p->nslots == 0) {
|
||||||
|
error("no slots");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
|
||||||
|
if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))
|
||||||
|
!= CKR_OK) {
|
||||||
|
error("C_GetSlotList failed: %lu", rv);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));
|
||||||
|
p->valid = 1;
|
||||||
|
nkeys = 0;
|
||||||
|
for (i = 0; i < p->nslots; i++) {
|
||||||
|
token = &p->slotinfo[i].token;
|
||||||
|
if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))
|
||||||
|
!= CKR_OK) {
|
||||||
|
error("C_GetTokenInfo failed: %lu", rv);
|
||||||
|
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));
|
||||||
|
debug("label <%s> manufacturerID <%s> model <%s> serial <%s>"
|
||||||
|
" flags 0x%lx",
|
||||||
|
token->label, token->manufacturerID, token->model,
|
||||||
|
token->serialNumber, token->flags);
|
||||||
|
/* open session, login with pin and retrieve public keys */
|
||||||
|
if (pkcs11_open_session(p, i, pin) == 0)
|
||||||
|
pkcs11_fetch_keys(p, i, keyp, &nkeys);
|
||||||
|
}
|
||||||
|
if (nkeys > 0) {
|
||||||
|
TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
|
||||||
|
p->refcount++; /* add to provider list */
|
||||||
|
return (nkeys);
|
||||||
|
}
|
||||||
|
error("no keys");
|
||||||
|
/* don't add the provider, since it does not have any keys */
|
||||||
|
fail:
|
||||||
|
if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
|
||||||
|
error("C_Finalize failed: %lu", rv);
|
||||||
|
if (p) {
|
||||||
|
if (p->slotlist)
|
||||||
|
xfree(p->slotlist);
|
||||||
|
if (p->slotinfo)
|
||||||
|
xfree(p->slotinfo);
|
||||||
|
xfree(p);
|
||||||
|
}
|
||||||
|
if (handle)
|
||||||
|
dlclose(handle);
|
||||||
|
return (-1);
|
||||||
|
}
|
19
ssh-pkcs11.h
Normal file
19
ssh-pkcs11.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
int pkcs11_init(int);
|
||||||
|
void pkcs11_terminate(void);
|
||||||
|
int pkcs11_add_provider(char *, char *, Key ***);
|
||||||
|
int pkcs11_del_provider(char *);
|
14
ssh.1
14
ssh.1
@ -34,8 +34,8 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh.1,v 1.290 2010/01/11 01:39:46 dtucker Exp $
|
.\" $OpenBSD: ssh.1,v 1.291 2010/02/08 10:50:20 markus Exp $
|
||||||
.Dd $Mdocdate: January 11 2010 $
|
.Dd $Mdocdate: February 8 2010 $
|
||||||
.Dt SSH 1
|
.Dt SSH 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -284,12 +284,12 @@ will wait for all remote port forwards to be successfully established
|
|||||||
before placing itself in the background.
|
before placing itself in the background.
|
||||||
.It Fl g
|
.It Fl g
|
||||||
Allows remote hosts to connect to local forwarded ports.
|
Allows remote hosts to connect to local forwarded ports.
|
||||||
.It Fl I Ar smartcard_device
|
.It Fl I Ar pkcs11
|
||||||
Specify the device
|
Specify the PKCS#11 shared libarary
|
||||||
.Nm
|
.Nm
|
||||||
should use to communicate with a smartcard used for storing the user's
|
should use to communicate with a PKCS#11 token used for storing the user's
|
||||||
private RSA key.
|
private RSA key.
|
||||||
This option is only available if support for smartcard devices
|
This option is only available if support for PKCS#11
|
||||||
is compiled in (default is no support).
|
is compiled in (default is no support).
|
||||||
.It Fl i Ar identity_file
|
.It Fl i Ar identity_file
|
||||||
Selects a file from which the identity (private key) for
|
Selects a file from which the identity (private key) for
|
||||||
@ -469,6 +469,7 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It NumberOfPasswordPrompts
|
.It NumberOfPasswordPrompts
|
||||||
.It PasswordAuthentication
|
.It PasswordAuthentication
|
||||||
.It PermitLocalCommand
|
.It PermitLocalCommand
|
||||||
|
.It PKCS11Provider
|
||||||
.It Port
|
.It Port
|
||||||
.It PreferredAuthentications
|
.It PreferredAuthentications
|
||||||
.It Protocol
|
.It Protocol
|
||||||
@ -481,7 +482,6 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It SendEnv
|
.It SendEnv
|
||||||
.It ServerAliveInterval
|
.It ServerAliveInterval
|
||||||
.It ServerAliveCountMax
|
.It ServerAliveCountMax
|
||||||
.It SmartcardDevice
|
|
||||||
.It StrictHostKeyChecking
|
.It StrictHostKeyChecking
|
||||||
.It TCPKeepAlive
|
.It TCPKeepAlive
|
||||||
.It Tunnel
|
.It Tunnel
|
||||||
|
29
ssh.c
29
ssh.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh.c,v 1.332 2010/01/26 01:28:35 djm Exp $ */
|
/* $OpenBSD: ssh.c,v 1.333 2010/02/08 10:50:20 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -103,8 +103,8 @@
|
|||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#ifdef SMARTCARD
|
#ifdef ENABLE_PKCS11
|
||||||
#include "scard.h"
|
#include "ssh-pkcs11.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
@ -362,10 +362,10 @@ main(int ac, char **av)
|
|||||||
xstrdup(optarg);
|
xstrdup(optarg);
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
#ifdef SMARTCARD
|
#ifdef ENABLE_PKCS11
|
||||||
options.smartcard_device = xstrdup(optarg);
|
options.pkcs11_provider = xstrdup(optarg);
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "no support for smartcards.\n");
|
fprintf(stderr, "no support for PKCS#11.\n");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
@ -1305,14 +1305,17 @@ load_public_identity_files(void)
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
Key *public;
|
Key *public;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
#ifdef SMARTCARD
|
#ifdef ENABLE_PKCS11
|
||||||
Key **keys;
|
Key **keys;
|
||||||
|
int nkeys;
|
||||||
|
|
||||||
if (options.smartcard_device != NULL &&
|
if (options.pkcs11_provider != NULL &&
|
||||||
options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
|
options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
|
||||||
(keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) {
|
(pkcs11_init(!options.batch_mode) == 0) &&
|
||||||
|
(nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
|
||||||
|
&keys)) > 0) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (i = 0; keys[i] != NULL; i++) {
|
for (i = 0; i < nkeys; i++) {
|
||||||
count++;
|
count++;
|
||||||
memmove(&options.identity_files[1],
|
memmove(&options.identity_files[1],
|
||||||
&options.identity_files[0],
|
&options.identity_files[0],
|
||||||
@ -1322,14 +1325,16 @@ load_public_identity_files(void)
|
|||||||
sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
|
sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
|
||||||
options.num_identity_files++;
|
options.num_identity_files++;
|
||||||
options.identity_keys[0] = keys[i];
|
options.identity_keys[0] = keys[i];
|
||||||
options.identity_files[0] = sc_get_key_label(keys[i]);
|
options.identity_files[0] =
|
||||||
|
xstrdup(options.pkcs11_provider); /* XXX */
|
||||||
}
|
}
|
||||||
if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
|
if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
|
||||||
options.num_identity_files = SSH_MAX_IDENTITY_FILES;
|
options.num_identity_files = SSH_MAX_IDENTITY_FILES;
|
||||||
i = count;
|
i = count;
|
||||||
xfree(keys);
|
xfree(keys);
|
||||||
|
/* XXX leaks some keys */
|
||||||
}
|
}
|
||||||
#endif /* SMARTCARD */
|
#endif /* ENABLE_PKCS11 */
|
||||||
if ((pw = getpwuid(original_real_uid)) == NULL)
|
if ((pw = getpwuid(original_real_uid)) == NULL)
|
||||||
fatal("load_public_identity_files: getpwuid failed");
|
fatal("load_public_identity_files: getpwuid failed");
|
||||||
pwname = xstrdup(pw->pw_name);
|
pwname = xstrdup(pw->pw_name);
|
||||||
|
18
ssh_config.5
18
ssh_config.5
@ -34,8 +34,8 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh_config.5,v 1.126 2010/01/09 23:04:13 dtucker Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.127 2010/02/08 10:50:20 markus Exp $
|
||||||
.Dd $Mdocdate: January 9 2010 $
|
.Dd $Mdocdate: February 8 2010 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -711,6 +711,13 @@ or
|
|||||||
.Dq no .
|
.Dq no .
|
||||||
The default is
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
|
.It Cm PKCS11Provider
|
||||||
|
Specifies which PKCS#11 provider to use.
|
||||||
|
The argument to this keyword is the PKCS#11 shared libary
|
||||||
|
.Xr ssh 1
|
||||||
|
should use to communicate with a PKCS#11 token used for storing the user's
|
||||||
|
private RSA key.
|
||||||
|
By default, no device is specified and PKCS#11 support is not activated.
|
||||||
.It Cm Port
|
.It Cm Port
|
||||||
Specifies the port number to connect on the remote host.
|
Specifies the port number to connect on the remote host.
|
||||||
The default is 22.
|
The default is 22.
|
||||||
@ -927,13 +934,6 @@ channel to request a response from the server.
|
|||||||
The default
|
The default
|
||||||
is 0, indicating that these messages will not be sent to the server.
|
is 0, indicating that these messages will not be sent to the server.
|
||||||
This option applies to protocol version 2 only.
|
This option applies to protocol version 2 only.
|
||||||
.It Cm SmartcardDevice
|
|
||||||
Specifies which smartcard device to use.
|
|
||||||
The argument to this keyword is the device
|
|
||||||
.Xr ssh 1
|
|
||||||
should use to communicate with a smartcard used for storing the user's
|
|
||||||
private RSA key.
|
|
||||||
By default, no device is specified and smartcard support is not activated.
|
|
||||||
.It Cm StrictHostKeyChecking
|
.It Cm StrictHostKeyChecking
|
||||||
If this flag is set to
|
If this flag is set to
|
||||||
.Dq yes ,
|
.Dq yes ,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user