- 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
|
||||
using buffer_get_int(), which could fatal() on buffer empty);
|
||||
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
|
||||
- (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
|
||||
#SHELL = @SH@
|
||||
|
@ -25,6 +25,7 @@ SSH_PROGRAM=@bindir@/ssh
|
|||
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
|
||||
SFTP_SERVER=$(libexecdir)/sftp-server
|
||||
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
|
||||
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
|
||||
RAND_HELPER=$(libexecdir)/ssh-rand-helper
|
||||
PRIVSEP_PATH=@PRIVSEP_PATH@
|
||||
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
|
||||
|
@ -35,6 +36,7 @@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \
|
|||
-D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
|
||||
-D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
|
||||
-D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
|
||||
-D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
|
||||
-D_PATH_SSH_PIDDIR=\"$(piddir)\" \
|
||||
-D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
|
||||
-DSSH_RAND_HELPER=\"$(RAND_HELPER)\"
|
||||
|
@ -60,7 +62,7 @@ EXEEXT=@EXEEXT@
|
|||
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
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
|
||||
$(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||
|
||||
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o
|
||||
$(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
|
||||
$(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||
|
||||
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
|
||||
$(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
|
||||
$(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
|
||||
$(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 ; \
|
||||
fi
|
||||
$(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-server $(DESTDIR)$(SFTP_SERVER)
|
||||
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
|
||||
|
@ -368,6 +375,7 @@ uninstall:
|
|||
-rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
|
||||
-rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
|
||||
-rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
|
||||
-rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
|
||||
-rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT)
|
||||
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.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_SSHADD="$${BUILDDIR}/ssh-add"; \
|
||||
TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
|
||||
TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
|
||||
TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
|
||||
TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
|
||||
TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
|
||||
|
@ -413,6 +422,7 @@ tests interop-tests: $(TARGETS)
|
|||
TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
|
||||
TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
|
||||
TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
|
||||
TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \
|
||||
TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
|
||||
TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
|
||||
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
|
||||
#
|
||||
|
@ -15,7 +15,7 @@
|
|||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
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_HEADER(config.h)
|
||||
|
@ -4197,6 +4197,10 @@ else
|
|||
AC_SUBST(TEST_SSH_IPV6, yes)
|
||||
fi
|
||||
|
||||
if test "x$enable_pkcs11" != "xno" ; then
|
||||
AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support])
|
||||
fi
|
||||
|
||||
AC_EXEEXT
|
||||
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
|
||||
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>
|
||||
|
@ -125,6 +125,11 @@
|
|||
#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign"
|
||||
#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 */
|
||||
#ifndef _PATH_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>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -123,7 +123,7 @@ typedef enum {
|
|||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
|
||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
|
||||
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
|
||||
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
|
||||
oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
|
||||
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
|
||||
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
|
||||
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
|
||||
|
@ -205,10 +205,12 @@ static struct {
|
|||
{ "preferredauthentications", oPreferredAuthentications },
|
||||
{ "hostkeyalgorithms", oHostKeyAlgorithms },
|
||||
{ "bindaddress", oBindAddress },
|
||||
#ifdef SMARTCARD
|
||||
{ "smartcarddevice", oSmartcardDevice },
|
||||
#ifdef ENABLE_PKCS11
|
||||
{ "smartcarddevice", oPKCS11Provider },
|
||||
{ "pkcs11provider", oPKCS11Provider },
|
||||
#else
|
||||
{ "smartcarddevice", oUnsupported },
|
||||
{ "pkcs11provider", oUnsupported },
|
||||
#endif
|
||||
{ "clearallforwardings", oClearAllForwardings },
|
||||
{ "enablesshkeysign", oEnableSSHKeysign },
|
||||
|
@ -609,8 +611,8 @@ parse_string:
|
|||
charptr = &options->bind_address;
|
||||
goto parse_string;
|
||||
|
||||
case oSmartcardDevice:
|
||||
charptr = &options->smartcard_device;
|
||||
case oPKCS11Provider:
|
||||
charptr = &options->pkcs11_provider;
|
||||
goto parse_string;
|
||||
|
||||
case oProxyCommand:
|
||||
|
@ -1051,7 +1053,7 @@ initialize_options(Options * options)
|
|||
options->log_level = SYSLOG_LEVEL_NOT_SET;
|
||||
options->preferred_authentications = NULL;
|
||||
options->bind_address = NULL;
|
||||
options->smartcard_device = NULL;
|
||||
options->pkcs11_provider = NULL;
|
||||
options->enable_ssh_keysign = - 1;
|
||||
options->no_host_authentication_for_localhost = - 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>
|
||||
|
@ -84,7 +84,7 @@ typedef struct {
|
|||
char *user_hostfile2;
|
||||
char *preferred_authentications;
|
||||
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 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
|
||||
.\"
|
||||
.\" $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
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -153,6 +153,7 @@ For full details of the options listed below, and their possible values, see
|
|||
.It NoHostAuthenticationForLocalhost
|
||||
.It NumberOfPasswordPrompts
|
||||
.It PasswordAuthentication
|
||||
.It PKCS11Provider
|
||||
.It Port
|
||||
.It PreferredAuthentications
|
||||
.It Protocol
|
||||
|
@ -164,7 +165,6 @@ For full details of the options listed below, and their possible values, see
|
|||
.It SendEnv
|
||||
.It ServerAliveInterval
|
||||
.It ServerAliveCountMax
|
||||
.It SmartcardDevice
|
||||
.It StrictHostKeyChecking
|
||||
.It TCPKeepAlive
|
||||
.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.
|
||||
.\"
|
||||
|
@ -22,7 +22,7 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd $Mdocdate: January 13 2010 $
|
||||
.Dd $Mdocdate: February 8 2010 $
|
||||
.Dt SFTP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -202,6 +202,7 @@ For full details of the options listed below, and their possible values, see
|
|||
.It NoHostAuthenticationForLocalhost
|
||||
.It NumberOfPasswordPrompts
|
||||
.It PasswordAuthentication
|
||||
.It PKCS11Provider
|
||||
.It Port
|
||||
.It PreferredAuthentications
|
||||
.It Protocol
|
||||
|
@ -213,7 +214,6 @@ For full details of the options listed below, and their possible values, see
|
|||
.It SendEnv
|
||||
.It ServerAliveInterval
|
||||
.It ServerAliveCountMax
|
||||
.It SmartcardDevice
|
||||
.It StrictHostKeyChecking
|
||||
.It TCPKeepAlive
|
||||
.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 -*-
|
||||
.\"
|
||||
|
@ -37,7 +37,7 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" 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
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -101,17 +101,17 @@ If no public key is found at a given path,
|
|||
will append
|
||||
.Pa .pub
|
||||
and retry.
|
||||
.It Fl e Ar reader
|
||||
Remove key in smartcard
|
||||
.Ar reader .
|
||||
.It Fl e Ar pkcs11
|
||||
Remove key provided by
|
||||
.Ar pkcs11 .
|
||||
.It Fl L
|
||||
Lists public key parameters of all identities currently represented
|
||||
by the agent.
|
||||
.It Fl l
|
||||
Lists fingerprints of all identities currently represented by the agent.
|
||||
.It Fl s Ar reader
|
||||
Add key in smartcard
|
||||
.Ar reader .
|
||||
.It Fl s Ar pkcs11
|
||||
Add key provider by
|
||||
.Ar pkcs11 .
|
||||
.It Fl t Ar life
|
||||
Set a maximum lifetime when adding identities to an agent.
|
||||
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>
|
||||
* 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;
|
||||
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)
|
||||
return -1;
|
||||
|
||||
|
@ -317,10 +317,8 @@ usage(void)
|
|||
fprintf(stderr, " -X Unlock agent.\n");
|
||||
fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
|
||||
fprintf(stderr, " -c Require confirmation to sign using identities\n");
|
||||
#ifdef SMARTCARD
|
||||
fprintf(stderr, " -s reader Add key in smartcard reader.\n");
|
||||
fprintf(stderr, " -e reader Remove key in smartcard reader.\n");
|
||||
#endif
|
||||
fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n");
|
||||
fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -329,7 +327,7 @@ main(int argc, char **argv)
|
|||
extern char *optarg;
|
||||
extern int optind;
|
||||
AuthenticationConnection *ac = NULL;
|
||||
char *sc_reader_id = NULL;
|
||||
char *pkcs11provider = NULL;
|
||||
int i, ch, deleting = 0, ret = 0;
|
||||
|
||||
/* 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;
|
||||
goto done;
|
||||
case 's':
|
||||
sc_reader_id = optarg;
|
||||
pkcs11provider = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
deleting = 1;
|
||||
sc_reader_id = optarg;
|
||||
pkcs11provider = optarg;
|
||||
break;
|
||||
case 't':
|
||||
if ((lifetime = convtime(optarg)) == -1) {
|
||||
|
@ -392,8 +390,8 @@ main(int argc, char **argv)
|
|||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (sc_reader_id != NULL) {
|
||||
if (update_card(ac, !deleting, sc_reader_id) == -1)
|
||||
if (pkcs11provider != NULL) {
|
||||
if (update_card(ac, !deleting, pkcs11provider) == -1)
|
||||
ret = 1;
|
||||
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>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -76,8 +76,8 @@
|
|||
#include "log.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef SMARTCARD
|
||||
#include "scard.h"
|
||||
#ifdef ENABLE_PKCS11
|
||||
#include "ssh-pkcs11.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_PRCTL_H)
|
||||
|
@ -105,6 +105,7 @@ typedef struct identity {
|
|||
TAILQ_ENTRY(identity) next;
|
||||
Key *key;
|
||||
char *comment;
|
||||
char *provider;
|
||||
u_int death;
|
||||
u_int confirm;
|
||||
} Identity;
|
||||
|
@ -171,6 +172,7 @@ static void
|
|||
free_identity(Identity *id)
|
||||
{
|
||||
key_free(id->key);
|
||||
xfree(id->provider);
|
||||
xfree(id->comment);
|
||||
xfree(id);
|
||||
}
|
||||
|
@ -549,7 +551,7 @@ process_add_identity(SocketEntry *e, int version)
|
|||
if (lifetime && !death)
|
||||
death = time(NULL) + lifetime;
|
||||
if ((id = lookup_identity(k, version)) == NULL) {
|
||||
id = xmalloc(sizeof(Identity));
|
||||
id = xcalloc(1, sizeof(Identity));
|
||||
id->key = k;
|
||||
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
||||
/* Increment the number of identities. */
|
||||
|
@ -609,17 +611,17 @@ no_identities(SocketEntry *e, u_int type)
|
|||
buffer_free(&msg);
|
||||
}
|
||||
|
||||
#ifdef SMARTCARD
|
||||
#ifdef ENABLE_PKCS11
|
||||
static void
|
||||
process_add_smartcard_key(SocketEntry *e)
|
||||
{
|
||||
char *sc_reader_id = NULL, *pin;
|
||||
int i, type, version, success = 0, death = 0, confirm = 0;
|
||||
Key **keys, *k;
|
||||
char *provider = NULL, *pin;
|
||||
int i, type, version, count = 0, success = 0, death = 0, confirm = 0;
|
||||
Key **keys = NULL, *k;
|
||||
Identity *id;
|
||||
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);
|
||||
|
||||
while (buffer_len(&e->request)) {
|
||||
|
@ -633,30 +635,22 @@ process_add_smartcard_key(SocketEntry *e)
|
|||
default:
|
||||
error("process_add_smartcard_key: "
|
||||
"Unknown constraint type %d", type);
|
||||
xfree(sc_reader_id);
|
||||
xfree(pin);
|
||||
goto send;
|
||||
}
|
||||
}
|
||||
if (lifetime && !death)
|
||||
death = time(NULL) + lifetime;
|
||||
|
||||
keys = sc_get_keys(sc_reader_id, pin);
|
||||
xfree(sc_reader_id);
|
||||
xfree(pin);
|
||||
|
||||
if (keys == NULL || keys[0] == NULL) {
|
||||
error("sc_get_keys failed");
|
||||
goto send;
|
||||
}
|
||||
for (i = 0; keys[i] != NULL; i++) {
|
||||
count = pkcs11_add_provider(provider, pin, &keys);
|
||||
for (i = 0; i < count; i++) {
|
||||
k = keys[i];
|
||||
version = k->type == KEY_RSA1 ? 1 : 2;
|
||||
tab = idtab_lookup(version);
|
||||
if (lookup_identity(k, version) == NULL) {
|
||||
id = xmalloc(sizeof(Identity));
|
||||
id = xcalloc(1, sizeof(Identity));
|
||||
id->key = k;
|
||||
id->comment = sc_get_key_label(k);
|
||||
id->provider = xstrdup(provider);
|
||||
id->comment = xstrdup(provider); /* XXX */
|
||||
id->death = death;
|
||||
id->confirm = confirm;
|
||||
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
||||
|
@ -667,8 +661,13 @@ process_add_smartcard_key(SocketEntry *e)
|
|||
}
|
||||
keys[i] = NULL;
|
||||
}
|
||||
xfree(keys);
|
||||
send:
|
||||
if (pin)
|
||||
xfree(pin);
|
||||
if (provider)
|
||||
xfree(provider);
|
||||
if (keys)
|
||||
xfree(keys);
|
||||
buffer_put_int(&e->output, 1);
|
||||
buffer_put_char(&e->output,
|
||||
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
|
||||
|
@ -677,42 +676,37 @@ send:
|
|||
static void
|
||||
process_remove_smartcard_key(SocketEntry *e)
|
||||
{
|
||||
char *sc_reader_id = NULL, *pin;
|
||||
int i, version, success = 0;
|
||||
Key **keys, *k = NULL;
|
||||
Identity *id;
|
||||
char *provider = NULL, *pin = NULL;
|
||||
int version, success = 0;
|
||||
Identity *id, *nxt;
|
||||
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);
|
||||
keys = sc_get_keys(sc_reader_id, pin);
|
||||
xfree(sc_reader_id);
|
||||
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];
|
||||
version = k->type == KEY_RSA1 ? 1 : 2;
|
||||
if ((id = lookup_identity(k, version)) != NULL) {
|
||||
tab = idtab_lookup(version);
|
||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||
tab->nentries--;
|
||||
free_identity(id);
|
||||
success = 1;
|
||||
for (version = 1; version < 3; version++) {
|
||||
tab = idtab_lookup(version);
|
||||
for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
|
||||
nxt = TAILQ_NEXT(id, next);
|
||||
if (!strcmp(provider, id->provider)) {
|
||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||
free_identity(id);
|
||||
tab->nentries--;
|
||||
}
|
||||
}
|
||||
key_free(k);
|
||||
keys[i] = NULL;
|
||||
}
|
||||
xfree(keys);
|
||||
send:
|
||||
if (pkcs11_del_provider(provider) == 0)
|
||||
success = 1;
|
||||
else
|
||||
error("process_remove_smartcard_key:"
|
||||
" pkcs11_del_provider failed");
|
||||
xfree(provider);
|
||||
buffer_put_int(&e->output, 1);
|
||||
buffer_put_char(&e->output,
|
||||
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
|
||||
}
|
||||
#endif /* SMARTCARD */
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
|
||||
/* dispatch incoming messages */
|
||||
|
||||
|
@ -797,7 +791,7 @@ process_message(SocketEntry *e)
|
|||
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
||||
process_remove_all_identities(e, 2);
|
||||
break;
|
||||
#ifdef SMARTCARD
|
||||
#ifdef ENABLE_PKCS11
|
||||
case SSH_AGENTC_ADD_SMARTCARD_KEY:
|
||||
case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
|
||||
process_add_smartcard_key(e);
|
||||
|
@ -805,7 +799,7 @@ process_message(SocketEntry *e)
|
|||
case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
|
||||
process_remove_smartcard_key(e);
|
||||
break;
|
||||
#endif /* SMARTCARD */
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
default:
|
||||
/* Unknown message. Respond with failure. */
|
||||
error("Unknown message %d", type);
|
||||
|
@ -1009,6 +1003,9 @@ static void
|
|||
cleanup_handler(int sig)
|
||||
{
|
||||
cleanup_socket();
|
||||
#ifdef ENABLE_PKCS11
|
||||
pkcs11_terminate();
|
||||
#endif
|
||||
_exit(2);
|
||||
}
|
||||
|
||||
|
@ -1255,6 +1252,10 @@ main(int ac, char **av)
|
|||
#endif
|
||||
|
||||
skip:
|
||||
|
||||
#ifdef ENABLE_PKCS11
|
||||
pkcs11_init(0);
|
||||
#endif
|
||||
new_socket(AUTH_SOCKET, sock);
|
||||
if (ac > 0)
|
||||
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 -*-
|
||||
.\"
|
||||
|
@ -37,7 +37,7 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" 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
|
||||
.Os
|
||||
.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.
|
||||
The program will prompt for the file containing the private keys, for
|
||||
the passphrase if the key has one, and for the new comment.
|
||||
.It Fl D Ar reader
|
||||
Download the RSA public key stored in the smartcard in
|
||||
.Ar reader .
|
||||
.It Fl D Ar pkcs11
|
||||
Download the RSA public keys stored in the
|
||||
.Ar pkcs11
|
||||
provider.
|
||||
.It Fl e
|
||||
This option will read a private or public OpenSSH key file and
|
||||
print the key in
|
||||
|
@ -313,9 +314,6 @@ for protocol version 1 and
|
|||
or
|
||||
.Dq dsa
|
||||
for protocol version 2.
|
||||
.It Fl U Ar reader
|
||||
Upload an existing RSA private key into the smartcard in
|
||||
.Ar reader .
|
||||
.It Fl v
|
||||
Verbose mode.
|
||||
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>
|
||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -49,8 +49,8 @@
|
|||
#include "hostfile.h"
|
||||
#include "dns.h"
|
||||
|
||||
#ifdef SMARTCARD
|
||||
#include "scard.h"
|
||||
#ifdef ENABLE_PKCS11
|
||||
#include "ssh-pkcs11.h"
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#ifdef SMARTCARD
|
||||
static void
|
||||
do_upload(struct passwd *pw, const char *sc_reader_id)
|
||||
{
|
||||
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)
|
||||
do_download(struct passwd *pw, const char *pkcs11provider)
|
||||
{
|
||||
#ifdef ENABLE_PKCS11
|
||||
Key **keys = NULL;
|
||||
int i;
|
||||
int i, nkeys;
|
||||
|
||||
keys = sc_get_keys(sc_reader_id, NULL);
|
||||
if (keys == NULL)
|
||||
fatal("cannot read public key from smartcard");
|
||||
for (i = 0; keys[i]; i++) {
|
||||
pkcs11_init(0);
|
||||
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
|
||||
if (nkeys <= 0)
|
||||
fatal("cannot read public key from pkcs11");
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
key_write(keys[i], stdout);
|
||||
key_free(keys[i]);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
xfree(keys);
|
||||
pkcs11_terminate();
|
||||
exit(0);
|
||||
#else
|
||||
fatal("no pkcs11 support");
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
}
|
||||
#endif /* SMARTCARD */
|
||||
|
||||
static void
|
||||
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, " -C comment Provide new comment.\n");
|
||||
fprintf(stderr, " -c Change comment in private and public key files.\n");
|
||||
#ifdef SMARTCARD
|
||||
fprintf(stderr, " -D reader Download public key from smartcard.\n");
|
||||
#endif /* SMARTCARD */
|
||||
#ifdef ENABLE_PKCS11
|
||||
fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n");
|
||||
#endif
|
||||
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 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, " -T file Screen candidates for DH-GEX moduli.\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, " -W gen Generator to use for generating DH-GEX moduli.\n");
|
||||
fprintf(stderr, " -y Read private key file and print public key.\n");
|
||||
|
@ -1082,12 +1057,12 @@ int
|
|||
main(int argc, char **argv)
|
||||
{
|
||||
char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
|
||||
char out_file[MAXPATHLEN], *reader_id = NULL;
|
||||
char out_file[MAXPATHLEN], *pkcs11provider = NULL;
|
||||
char *rr_hostname = NULL;
|
||||
Key *private, *public;
|
||||
struct passwd *pw;
|
||||
struct stat st;
|
||||
int opt, type, fd, download = 0;
|
||||
int opt, type, fd;
|
||||
u_int32_t memory = 0, generator_wanted = 0, trials = 100;
|
||||
int do_gen_candidates = 0, do_screen_candidates = 0;
|
||||
BIGNUM *start = NULL;
|
||||
|
@ -1120,7 +1095,7 @@ main(int argc, char **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) {
|
||||
case 'b':
|
||||
bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
|
||||
|
@ -1192,10 +1167,7 @@ main(int argc, char **argv)
|
|||
key_type_name = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
download = 1;
|
||||
/*FALLTHROUGH*/
|
||||
case 'U':
|
||||
reader_id = optarg;
|
||||
pkcs11provider = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
if (log_level == SYSLOG_LEVEL_INFO)
|
||||
|
@ -1303,16 +1275,8 @@ main(int argc, char **argv)
|
|||
exit(0);
|
||||
}
|
||||
}
|
||||
if (reader_id != NULL) {
|
||||
#ifdef SMARTCARD
|
||||
if (download)
|
||||
do_download(pw, reader_id);
|
||||
else
|
||||
do_upload(pw, reader_id);
|
||||
#else /* SMARTCARD */
|
||||
fatal("no support for smartcards.");
|
||||
#endif /* SMARTCARD */
|
||||
}
|
||||
if (pkcs11provider != NULL)
|
||||
do_download(pw, pkcs11provider);
|
||||
|
||||
if (do_gen_candidates) {
|
||||
FILE *out = fopen(out_file, "w");
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
.\" 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 $
|
||||
.Dd $Mdocdate: January 11 2010 $
|
||||
.\" $OpenBSD: ssh.1,v 1.291 2010/02/08 10:50:20 markus Exp $
|
||||
.Dd $Mdocdate: February 8 2010 $
|
||||
.Dt SSH 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -284,12 +284,12 @@ will wait for all remote port forwards to be successfully established
|
|||
before placing itself in the background.
|
||||
.It Fl g
|
||||
Allows remote hosts to connect to local forwarded ports.
|
||||
.It Fl I Ar smartcard_device
|
||||
Specify the device
|
||||
.It Fl I Ar pkcs11
|
||||
Specify the PKCS#11 shared libarary
|
||||
.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.
|
||||
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).
|
||||
.It Fl i Ar identity_file
|
||||
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 PasswordAuthentication
|
||||
.It PermitLocalCommand
|
||||
.It PKCS11Provider
|
||||
.It Port
|
||||
.It PreferredAuthentications
|
||||
.It Protocol
|
||||
|
@ -481,7 +482,6 @@ For full details of the options listed below, and their possible values, see
|
|||
.It SendEnv
|
||||
.It ServerAliveInterval
|
||||
.It ServerAliveCountMax
|
||||
.It SmartcardDevice
|
||||
.It StrictHostKeyChecking
|
||||
.It TCPKeepAlive
|
||||
.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>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -103,8 +103,8 @@
|
|||
#include "roaming.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifdef SMARTCARD
|
||||
#include "scard.h"
|
||||
#ifdef ENABLE_PKCS11
|
||||
#include "ssh-pkcs11.h"
|
||||
#endif
|
||||
|
||||
extern char *__progname;
|
||||
|
@ -362,10 +362,10 @@ main(int ac, char **av)
|
|||
xstrdup(optarg);
|
||||
break;
|
||||
case 'I':
|
||||
#ifdef SMARTCARD
|
||||
options.smartcard_device = xstrdup(optarg);
|
||||
#ifdef ENABLE_PKCS11
|
||||
options.pkcs11_provider = xstrdup(optarg);
|
||||
#else
|
||||
fprintf(stderr, "no support for smartcards.\n");
|
||||
fprintf(stderr, "no support for PKCS#11.\n");
|
||||
#endif
|
||||
break;
|
||||
case 't':
|
||||
|
@ -1305,14 +1305,17 @@ load_public_identity_files(void)
|
|||
int i = 0;
|
||||
Key *public;
|
||||
struct passwd *pw;
|
||||
#ifdef SMARTCARD
|
||||
#ifdef ENABLE_PKCS11
|
||||
Key **keys;
|
||||
int nkeys;
|
||||
|
||||
if (options.smartcard_device != NULL &&
|
||||
if (options.pkcs11_provider != NULL &&
|
||||
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;
|
||||
for (i = 0; keys[i] != NULL; i++) {
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
count++;
|
||||
memmove(&options.identity_files[1],
|
||||
&options.identity_files[0],
|
||||
|
@ -1322,14 +1325,16 @@ load_public_identity_files(void)
|
|||
sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
|
||||
options.num_identity_files++;
|
||||
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)
|
||||
options.num_identity_files = SSH_MAX_IDENTITY_FILES;
|
||||
i = count;
|
||||
xfree(keys);
|
||||
/* XXX leaks some keys */
|
||||
}
|
||||
#endif /* SMARTCARD */
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
if ((pw = getpwuid(original_real_uid)) == NULL)
|
||||
fatal("load_public_identity_files: getpwuid failed");
|
||||
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
|
||||
.\" 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 $
|
||||
.Dd $Mdocdate: January 9 2010 $
|
||||
.\" $OpenBSD: ssh_config.5,v 1.127 2010/02/08 10:50:20 markus Exp $
|
||||
.Dd $Mdocdate: February 8 2010 $
|
||||
.Dt SSH_CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -711,6 +711,13 @@ or
|
|||
.Dq no .
|
||||
The default is
|
||||
.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
|
||||
Specifies the port number to connect on the remote host.
|
||||
The default is 22.
|
||||
|
@ -927,13 +934,6 @@ channel to request a response from the server.
|
|||
The default
|
||||
is 0, indicating that these messages will not be sent to the server.
|
||||
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
|
||||
If this flag is set to
|
||||
.Dq yes ,
|
||||
|
|
Loading…
Reference in New Issue