upstream commit
add ssh_config CertificateFile option to explicitly list a certificate; patch from Meghana Bhat on bz#2436; ok markus@ Upstream-ID: 58648ec53c510b41c1f46d8fe293aadc87229ab8
This commit is contained in:
parent
e3cbb06ade
commit
4e44a79a07
47
readconf.c
47
readconf.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: readconf.c,v 1.240 2015/08/21 23:53:08 djm Exp $ */
|
/* $OpenBSD: readconf.c,v 1.241 2015/09/24 06:15:11 djm 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
|
||||||
|
@ -135,6 +135,7 @@ typedef enum {
|
||||||
oPasswordAuthentication, oRSAAuthentication,
|
oPasswordAuthentication, oRSAAuthentication,
|
||||||
oChallengeResponseAuthentication, oXAuthLocation,
|
oChallengeResponseAuthentication, oXAuthLocation,
|
||||||
oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
|
oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
|
||||||
|
oCertificateFile,
|
||||||
oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
|
oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
|
||||||
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
|
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
|
||||||
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
|
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
|
||||||
|
@ -202,6 +203,7 @@ static struct {
|
||||||
{ "identityfile", oIdentityFile },
|
{ "identityfile", oIdentityFile },
|
||||||
{ "identityfile2", oIdentityFile }, /* obsolete */
|
{ "identityfile2", oIdentityFile }, /* obsolete */
|
||||||
{ "identitiesonly", oIdentitiesOnly },
|
{ "identitiesonly", oIdentitiesOnly },
|
||||||
|
{ "certificatefile", oCertificateFile },
|
||||||
{ "hostname", oHostName },
|
{ "hostname", oHostName },
|
||||||
{ "hostkeyalias", oHostKeyAlias },
|
{ "hostkeyalias", oHostKeyAlias },
|
||||||
{ "proxycommand", oProxyCommand },
|
{ "proxycommand", oProxyCommand },
|
||||||
|
@ -365,6 +367,30 @@ clear_forwardings(Options *options)
|
||||||
options->tun_open = SSH_TUNMODE_NO;
|
options->tun_open = SSH_TUNMODE_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add_certificate_file(Options *options, const char *path, int userprovided)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
|
||||||
|
fatal("Too many certificate files specified (max %d)",
|
||||||
|
SSH_MAX_CERTIFICATE_FILES);
|
||||||
|
|
||||||
|
/* Avoid registering duplicates */
|
||||||
|
for (i = 0; i < options->num_certificate_files; i++) {
|
||||||
|
if (options->certificate_file_userprovided[i] == userprovided &&
|
||||||
|
strcmp(options->certificate_files[i], path) == 0) {
|
||||||
|
debug2("%s: ignoring duplicate key %s", __func__, path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
options->certificate_file_userprovided[options->num_certificate_files] =
|
||||||
|
userprovided;
|
||||||
|
options->certificate_files[options->num_certificate_files++] =
|
||||||
|
xstrdup(path);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
add_identity_file(Options *options, const char *dir, const char *filename,
|
add_identity_file(Options *options, const char *dir, const char *filename,
|
||||||
int userprovided)
|
int userprovided)
|
||||||
|
@ -981,6 +1007,24 @@ parse_time:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case oCertificateFile:
|
||||||
|
arg = strdelim(&s);
|
||||||
|
if (!arg || *arg == '\0')
|
||||||
|
fatal("%.200s line %d: Missing argument.",
|
||||||
|
filename, linenum);
|
||||||
|
if (*activep) {
|
||||||
|
intptr = &options->num_certificate_files;
|
||||||
|
if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
|
||||||
|
fatal("%.200s line %d: Too many certificate "
|
||||||
|
"files specified (max %d).",
|
||||||
|
filename, linenum,
|
||||||
|
SSH_MAX_CERTIFICATE_FILES);
|
||||||
|
}
|
||||||
|
add_certificate_file(options, arg,
|
||||||
|
flags & SSHCONF_USERCONF);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case oXAuthLocation:
|
case oXAuthLocation:
|
||||||
charptr=&options->xauth_location;
|
charptr=&options->xauth_location;
|
||||||
goto parse_string;
|
goto parse_string;
|
||||||
|
@ -1625,6 +1669,7 @@ initialize_options(Options * options)
|
||||||
options->hostkeyalgorithms = NULL;
|
options->hostkeyalgorithms = NULL;
|
||||||
options->protocol = SSH_PROTO_UNKNOWN;
|
options->protocol = SSH_PROTO_UNKNOWN;
|
||||||
options->num_identity_files = 0;
|
options->num_identity_files = 0;
|
||||||
|
options->num_certificate_files = 0;
|
||||||
options->hostname = NULL;
|
options->hostname = NULL;
|
||||||
options->host_key_alias = NULL;
|
options->host_key_alias = NULL;
|
||||||
options->proxy_command = NULL;
|
options->proxy_command = NULL;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: readconf.h,v 1.110 2015/07/10 06:21:53 markus Exp $ */
|
/* $OpenBSD: readconf.h,v 1.111 2015/09/24 06:15:11 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -95,6 +95,11 @@ typedef struct {
|
||||||
int identity_file_userprovided[SSH_MAX_IDENTITY_FILES];
|
int identity_file_userprovided[SSH_MAX_IDENTITY_FILES];
|
||||||
struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES];
|
struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES];
|
||||||
|
|
||||||
|
int num_certificate_files; /* Number of extra certificates for ssh. */
|
||||||
|
char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
|
||||||
|
int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];
|
||||||
|
struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
|
||||||
|
|
||||||
/* Local TCP/IP forward requests. */
|
/* Local TCP/IP forward requests. */
|
||||||
int num_local_forwards;
|
int num_local_forwards;
|
||||||
struct Forward *local_forwards;
|
struct Forward *local_forwards;
|
||||||
|
@ -194,5 +199,6 @@ void dump_client_config(Options *o, const char *host);
|
||||||
void add_local_forward(Options *, const struct Forward *);
|
void add_local_forward(Options *, const struct Forward *);
|
||||||
void add_remote_forward(Options *, const struct Forward *);
|
void add_remote_forward(Options *, const struct Forward *);
|
||||||
void add_identity_file(Options *, const char *, const char *, int);
|
void add_identity_file(Options *, const char *, const char *, int);
|
||||||
|
void add_certificate_file(Options *, const char *, int);
|
||||||
|
|
||||||
#endif /* READCONF_H */
|
#endif /* READCONF_H */
|
||||||
|
|
8
ssh.1
8
ssh.1
|
@ -33,8 +33,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.362 2015/09/11 03:42:32 djm Exp $
|
.\" $OpenBSD: ssh.1,v 1.363 2015/09/24 06:15:11 djm Exp $
|
||||||
.Dd $Mdocdate: September 11 2015 $
|
.Dd $Mdocdate: September 24 2015 $
|
||||||
.Dt SSH 1
|
.Dt SSH 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -304,6 +304,9 @@ It is possible to have multiple
|
||||||
.Fl i
|
.Fl i
|
||||||
options (and multiple identities specified in
|
options (and multiple identities specified in
|
||||||
configuration files).
|
configuration files).
|
||||||
|
If no certificates have been explicitly specified by
|
||||||
|
.Cm CertificateFile
|
||||||
|
directive,
|
||||||
.Nm
|
.Nm
|
||||||
will also try to load certificate information from the filename obtained
|
will also try to load certificate information from the filename obtained
|
||||||
by appending
|
by appending
|
||||||
|
@ -468,6 +471,7 @@ For full details of the options listed below, and their possible values, see
|
||||||
.It CanonicalizeHostname
|
.It CanonicalizeHostname
|
||||||
.It CanonicalizeMaxDots
|
.It CanonicalizeMaxDots
|
||||||
.It CanonicalizePermittedCNAMEs
|
.It CanonicalizePermittedCNAMEs
|
||||||
|
.It CertificateFile
|
||||||
.It ChallengeResponseAuthentication
|
.It ChallengeResponseAuthentication
|
||||||
.It CheckHostIP
|
.It CheckHostIP
|
||||||
.It Cipher
|
.It Cipher
|
||||||
|
|
65
ssh.c
65
ssh.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh.c,v 1.425 2015/09/11 06:55:46 jmc Exp $ */
|
/* $OpenBSD: ssh.c,v 1.426 2015/09/24 06:15:11 djm 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
|
||||||
|
@ -1354,6 +1354,10 @@ main(int ac, char **av)
|
||||||
options.identity_keys[i] = NULL;
|
options.identity_keys[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < options.num_certificate_files; i++) {
|
||||||
|
free(options.certificate_files[i]);
|
||||||
|
options.certificate_files[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
exit_status = compat20 ? ssh_session2() : ssh_session();
|
exit_status = compat20 ? ssh_session2() : ssh_session();
|
||||||
packet_close();
|
packet_close();
|
||||||
|
@ -1940,25 +1944,30 @@ ssh_session2(void)
|
||||||
options.escape_char : SSH_ESCAPECHAR_NONE, id);
|
options.escape_char : SSH_ESCAPECHAR_NONE, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Loads all IdentityFile and CertificateFile keys */
|
||||||
static void
|
static void
|
||||||
load_public_identity_files(void)
|
load_public_identity_files(void)
|
||||||
{
|
{
|
||||||
char *filename, *cp, thishost[NI_MAXHOST];
|
char *filename, *cp, thishost[NI_MAXHOST];
|
||||||
char *pwdir = NULL, *pwname = NULL;
|
char *pwdir = NULL, *pwname = NULL;
|
||||||
int i = 0;
|
|
||||||
Key *public;
|
Key *public;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
u_int n_ids;
|
int i;
|
||||||
|
u_int n_ids, n_certs;
|
||||||
char *identity_files[SSH_MAX_IDENTITY_FILES];
|
char *identity_files[SSH_MAX_IDENTITY_FILES];
|
||||||
Key *identity_keys[SSH_MAX_IDENTITY_FILES];
|
Key *identity_keys[SSH_MAX_IDENTITY_FILES];
|
||||||
|
char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
|
||||||
|
struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
|
||||||
#ifdef ENABLE_PKCS11
|
#ifdef ENABLE_PKCS11
|
||||||
Key **keys;
|
Key **keys;
|
||||||
int nkeys;
|
int nkeys;
|
||||||
#endif /* PKCS11 */
|
#endif /* PKCS11 */
|
||||||
|
|
||||||
n_ids = 0;
|
n_ids = n_certs = 0;
|
||||||
memset(identity_files, 0, sizeof(identity_files));
|
memset(identity_files, 0, sizeof(identity_files));
|
||||||
memset(identity_keys, 0, sizeof(identity_keys));
|
memset(identity_keys, 0, sizeof(identity_keys));
|
||||||
|
memset(certificate_files, 0, sizeof(certificate_files));
|
||||||
|
memset(certificates, 0, sizeof(certificates));
|
||||||
|
|
||||||
#ifdef ENABLE_PKCS11
|
#ifdef ENABLE_PKCS11
|
||||||
if (options.pkcs11_provider != NULL &&
|
if (options.pkcs11_provider != NULL &&
|
||||||
|
@ -1990,6 +1999,7 @@ load_public_identity_files(void)
|
||||||
if (n_ids >= SSH_MAX_IDENTITY_FILES ||
|
if (n_ids >= SSH_MAX_IDENTITY_FILES ||
|
||||||
strcasecmp(options.identity_files[i], "none") == 0) {
|
strcasecmp(options.identity_files[i], "none") == 0) {
|
||||||
free(options.identity_files[i]);
|
free(options.identity_files[i]);
|
||||||
|
options.identity_files[i] = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cp = tilde_expand_filename(options.identity_files[i],
|
cp = tilde_expand_filename(options.identity_files[i],
|
||||||
|
@ -2008,7 +2018,12 @@ load_public_identity_files(void)
|
||||||
if (++n_ids >= SSH_MAX_IDENTITY_FILES)
|
if (++n_ids >= SSH_MAX_IDENTITY_FILES)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Try to add the certificate variant too */
|
/*
|
||||||
|
* If no certificates have been explicitly listed then try
|
||||||
|
* to add the default certificate variant too.
|
||||||
|
*/
|
||||||
|
if (options.num_certificate_files != 0)
|
||||||
|
continue;
|
||||||
xasprintf(&cp, "%s-cert", filename);
|
xasprintf(&cp, "%s-cert", filename);
|
||||||
public = key_load_public(cp, NULL);
|
public = key_load_public(cp, NULL);
|
||||||
debug("identity file %s type %d", cp,
|
debug("identity file %s type %d", cp,
|
||||||
|
@ -2025,14 +2040,50 @@ load_public_identity_files(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
identity_keys[n_ids] = public;
|
identity_keys[n_ids] = public;
|
||||||
/* point to the original path, most likely the private key */
|
identity_files[n_ids] = cp;
|
||||||
identity_files[n_ids] = xstrdup(filename);
|
|
||||||
n_ids++;
|
n_ids++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES)
|
||||||
|
fatal("%s: too many certificates", __func__);
|
||||||
|
for (i = 0; i < options.num_certificate_files; i++) {
|
||||||
|
cp = tilde_expand_filename(options.certificate_files[i],
|
||||||
|
original_real_uid);
|
||||||
|
filename = percent_expand(cp, "d", pwdir,
|
||||||
|
"u", pwname, "l", thishost, "h", host,
|
||||||
|
"r", options.user, (char *)NULL);
|
||||||
|
free(cp);
|
||||||
|
|
||||||
|
public = key_load_public(filename, NULL);
|
||||||
|
debug("certificate file %s type %d", filename,
|
||||||
|
public ? public->type : -1);
|
||||||
|
free(options.certificate_files[i]);
|
||||||
|
options.certificate_files[i] = NULL;
|
||||||
|
if (public == NULL) {
|
||||||
|
free(filename);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!key_is_cert(public)) {
|
||||||
|
debug("%s: key %s type %s is not a certificate",
|
||||||
|
__func__, filename, key_type(public));
|
||||||
|
key_free(public);
|
||||||
|
free(filename);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
certificate_files[n_certs] = filename;
|
||||||
|
certificates[n_certs] = public;
|
||||||
|
++n_certs;
|
||||||
|
}
|
||||||
|
|
||||||
options.num_identity_files = n_ids;
|
options.num_identity_files = n_ids;
|
||||||
memcpy(options.identity_files, identity_files, sizeof(identity_files));
|
memcpy(options.identity_files, identity_files, sizeof(identity_files));
|
||||||
memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
|
memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
|
||||||
|
|
||||||
|
options.num_certificate_files = n_certs;
|
||||||
|
memcpy(options.certificate_files,
|
||||||
|
certificate_files, sizeof(certificate_files));
|
||||||
|
memcpy(options.certificates, certificates, sizeof(certificates));
|
||||||
|
|
||||||
explicit_bzero(pwname, strlen(pwname));
|
explicit_bzero(pwname, strlen(pwname));
|
||||||
free(pwname);
|
free(pwname);
|
||||||
explicit_bzero(pwdir, strlen(pwdir));
|
explicit_bzero(pwdir, strlen(pwdir));
|
||||||
|
|
8
ssh.h
8
ssh.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh.h,v 1.81 2015/08/04 05:23:06 djm Exp $ */
|
/* $OpenBSD: ssh.h,v 1.82 2015/09/24 06:15:11 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -18,6 +18,12 @@
|
||||||
/* Default port number. */
|
/* Default port number. */
|
||||||
#define SSH_DEFAULT_PORT 22
|
#define SSH_DEFAULT_PORT 22
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum number of certificate files that can be specified
|
||||||
|
* in configuration files or on the command line.
|
||||||
|
*/
|
||||||
|
#define SSH_MAX_CERTIFICATE_FILES 100
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Maximum number of RSA authentication identity files that can be specified
|
* Maximum number of RSA authentication identity files that can be specified
|
||||||
* in configuration files or on the command line.
|
* in configuration files or on the command line.
|
||||||
|
|
54
ssh_config.5
54
ssh_config.5
|
@ -33,8 +33,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.220 2015/09/22 08:33:23 sobrado Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.221 2015/09/24 06:15:11 djm Exp $
|
||||||
.Dd $Mdocdate: September 22 2015 $
|
.Dd $Mdocdate: September 24 2015 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -325,6 +325,41 @@ to be canonicalized to names in the
|
||||||
or
|
or
|
||||||
.Dq *.c.example.com
|
.Dq *.c.example.com
|
||||||
domains.
|
domains.
|
||||||
|
.It Cm CertificateFile
|
||||||
|
Specifies a file from which the user's certificate is read.
|
||||||
|
A corresponding private key must be provided separately in order
|
||||||
|
to use this certificate either
|
||||||
|
from an
|
||||||
|
.Cm IdentityFile
|
||||||
|
directive or
|
||||||
|
.Fl i
|
||||||
|
flag to
|
||||||
|
.Xr ssh 1 ,
|
||||||
|
via
|
||||||
|
.Xr ssh-agent 1 ,
|
||||||
|
or via a
|
||||||
|
.Cm PKCS11Provider .
|
||||||
|
.Pp
|
||||||
|
The file name may use the tilde
|
||||||
|
syntax to refer to a user's home directory or one of the following
|
||||||
|
escape characters:
|
||||||
|
.Ql %d
|
||||||
|
(local user's home directory),
|
||||||
|
.Ql %u
|
||||||
|
(local user name),
|
||||||
|
.Ql %l
|
||||||
|
(local host name),
|
||||||
|
.Ql %h
|
||||||
|
(remote host name) or
|
||||||
|
.Ql %r
|
||||||
|
(remote user name).
|
||||||
|
.Pp
|
||||||
|
It is possible to have multiple certificate files specified in
|
||||||
|
configuration files; these certificates will be tried in sequence.
|
||||||
|
Multiple
|
||||||
|
.Cm CertificateFile
|
||||||
|
directives will add to the list of certificates used for
|
||||||
|
authentication.
|
||||||
.It Cm ChallengeResponseAuthentication
|
.It Cm ChallengeResponseAuthentication
|
||||||
Specifies whether to use challenge-response authentication.
|
Specifies whether to use challenge-response authentication.
|
||||||
The argument to this keyword must be
|
The argument to this keyword must be
|
||||||
|
@ -869,9 +904,13 @@ specifications).
|
||||||
.It Cm IdentitiesOnly
|
.It Cm IdentitiesOnly
|
||||||
Specifies that
|
Specifies that
|
||||||
.Xr ssh 1
|
.Xr ssh 1
|
||||||
should only use the authentication identity files configured in the
|
should only use the authentication identity and certificate files explicitly
|
||||||
|
configured in the
|
||||||
.Nm
|
.Nm
|
||||||
files,
|
files
|
||||||
|
or passed on the
|
||||||
|
.Xr ssh 1
|
||||||
|
command-line,
|
||||||
even if
|
even if
|
||||||
.Xr ssh-agent 1
|
.Xr ssh-agent 1
|
||||||
or a
|
or a
|
||||||
|
@ -901,6 +940,8 @@ Additionally, any identities represented by the authentication agent
|
||||||
will be used for authentication unless
|
will be used for authentication unless
|
||||||
.Cm IdentitiesOnly
|
.Cm IdentitiesOnly
|
||||||
is set.
|
is set.
|
||||||
|
If no certificates have been explicitly specified by
|
||||||
|
.Cm CertificateFile ,
|
||||||
.Xr ssh 1
|
.Xr ssh 1
|
||||||
will try to load certificate information from the filename obtained by
|
will try to load certificate information from the filename obtained by
|
||||||
appending
|
appending
|
||||||
|
@ -934,6 +975,11 @@ differs from that of other configuration directives).
|
||||||
may be used in conjunction with
|
may be used in conjunction with
|
||||||
.Cm IdentitiesOnly
|
.Cm IdentitiesOnly
|
||||||
to select which identities in an agent are offered during authentication.
|
to select which identities in an agent are offered during authentication.
|
||||||
|
.Cm IdentityFile
|
||||||
|
may also be used in conjunction with
|
||||||
|
.Cm CertificateFile
|
||||||
|
in order to provide any certificate also needed for authentication with
|
||||||
|
the identity.
|
||||||
.It Cm IgnoreUnknown
|
.It Cm IgnoreUnknown
|
||||||
Specifies a pattern-list of unknown options to be ignored if they are
|
Specifies a pattern-list of unknown options to be ignored if they are
|
||||||
encountered in configuration parsing.
|
encountered in configuration parsing.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshconnect2.c,v 1.226 2015/07/30 00:01:34 djm Exp $ */
|
/* $OpenBSD: sshconnect2.c,v 1.227 2015/09/24 06:15:11 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
||||||
|
@ -1001,18 +1001,17 @@ static int
|
||||||
sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
|
sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
|
||||||
{
|
{
|
||||||
Buffer b;
|
Buffer b;
|
||||||
|
Identity *private_id;
|
||||||
u_char *blob, *signature;
|
u_char *blob, *signature;
|
||||||
u_int bloblen;
|
|
||||||
size_t slen;
|
size_t slen;
|
||||||
u_int skip = 0;
|
u_int bloblen, skip = 0;
|
||||||
int ret = -1;
|
int matched, ret = -1, have_sig = 1;
|
||||||
int have_sig = 1;
|
|
||||||
char *fp;
|
char *fp;
|
||||||
|
|
||||||
if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
|
if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
|
||||||
SSH_FP_DEFAULT)) == NULL)
|
SSH_FP_DEFAULT)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
|
debug3("%s: %s %s", __func__, key_type(id->key), fp);
|
||||||
free(fp);
|
free(fp);
|
||||||
|
|
||||||
if (key_to_blob(id->key, &blob, &bloblen) == 0) {
|
if (key_to_blob(id->key, &blob, &bloblen) == 0) {
|
||||||
|
@ -1044,6 +1043,36 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
|
||||||
}
|
}
|
||||||
buffer_put_string(&b, blob, bloblen);
|
buffer_put_string(&b, blob, bloblen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the key is an certificate, try to find a matching private key
|
||||||
|
* and use it to complete the signature.
|
||||||
|
* If no such private key exists, return failure and continue with
|
||||||
|
* other methods of authentication.
|
||||||
|
*/
|
||||||
|
if (key_is_cert(id->key)) {
|
||||||
|
matched = 0;
|
||||||
|
TAILQ_FOREACH(private_id, &authctxt->keys, next) {
|
||||||
|
if (sshkey_equal_public(id->key, private_id->key) &&
|
||||||
|
id->key->type != private_id->key->type) {
|
||||||
|
id = private_id;
|
||||||
|
matched = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matched) {
|
||||||
|
debug2("%s: using private key \"%s\"%s for "
|
||||||
|
"certificate", __func__, id->filename,
|
||||||
|
id->agent_fd != -1 ? " from agent" : "");
|
||||||
|
} else {
|
||||||
|
/* XXX maybe verbose/error? */
|
||||||
|
debug("%s: no private key for certificate "
|
||||||
|
"\"%s\"", __func__, id->filename);
|
||||||
|
free(blob);
|
||||||
|
buffer_free(&b);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* generate signature */
|
/* generate signature */
|
||||||
ret = identity_sign(id, &signature, &slen,
|
ret = identity_sign(id, &signature, &slen,
|
||||||
buffer_ptr(&b), buffer_len(&b), datafellows);
|
buffer_ptr(&b), buffer_len(&b), datafellows);
|
||||||
|
@ -1180,9 +1209,11 @@ load_identity_file(char *filename, int userprovided)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* try keys in the following order:
|
* try keys in the following order:
|
||||||
* 1. agent keys that are found in the config file
|
* 1. certificates listed in the config file
|
||||||
* 2. other agent keys
|
* 2. other input certificates
|
||||||
* 3. keys that are only listed in the config file
|
* 3. agent keys that are found in the config file
|
||||||
|
* 4. other agent keys
|
||||||
|
* 5. keys that are only listed in the config file
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
pubkey_prepare(Authctxt *authctxt)
|
pubkey_prepare(Authctxt *authctxt)
|
||||||
|
@ -1236,6 +1267,18 @@ pubkey_prepare(Authctxt *authctxt)
|
||||||
free(id);
|
free(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* list of certificates specified by user */
|
||||||
|
for (i = 0; i < options.num_certificate_files; i++) {
|
||||||
|
key = options.certificates[i];
|
||||||
|
if (!key_is_cert(key) || key->cert == NULL ||
|
||||||
|
key->cert->type != SSH2_CERT_TYPE_USER)
|
||||||
|
continue;
|
||||||
|
id = xcalloc(1, sizeof(*id));
|
||||||
|
id->key = key;
|
||||||
|
id->filename = xstrdup(options.certificate_files[i]);
|
||||||
|
id->userprovided = options.certificate_file_userprovided[i];
|
||||||
|
TAILQ_INSERT_TAIL(preferred, id, next);
|
||||||
|
}
|
||||||
/* list of keys supported by the agent */
|
/* list of keys supported by the agent */
|
||||||
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
|
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
|
||||||
if (r != SSH_ERR_AGENT_NOT_PRESENT)
|
if (r != SSH_ERR_AGENT_NOT_PRESENT)
|
||||||
|
|
Loading…
Reference in New Issue