mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-01-03 16:22:05 +00:00
upstream commit
Add a ssh_config HostbasedKeyType option to control which host public key types are tried during hostbased authentication. This may be used to prevent too many keys being sent to the server, and blowing past its MaxAuthTries limit. bz#2211 based on patch by Iain Morgan; ok markus@
This commit is contained in:
parent
802660cb70
commit
46347ed596
25
readconf.c
25
readconf.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.c,v 1.229 2015/01/26 03:04:45 djm Exp $ */
|
/* $OpenBSD: readconf.c,v 1.230 2015/01/30 11:43:14 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
|
||||||
@ -156,7 +156,7 @@ typedef enum {
|
|||||||
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
|
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
|
||||||
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
|
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
|
||||||
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
|
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
|
||||||
oFingerprintHash, oUpdateHostkeys,
|
oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
|
||||||
oIgnoredUnknownOption, oDeprecated, oUnsupported
|
oIgnoredUnknownOption, oDeprecated, oUnsupported
|
||||||
} OpCodes;
|
} OpCodes;
|
||||||
|
|
||||||
@ -274,6 +274,7 @@ static struct {
|
|||||||
{ "revokedhostkeys", oRevokedHostKeys },
|
{ "revokedhostkeys", oRevokedHostKeys },
|
||||||
{ "fingerprinthash", oFingerprintHash },
|
{ "fingerprinthash", oFingerprintHash },
|
||||||
{ "updatehostkeys", oUpdateHostkeys },
|
{ "updatehostkeys", oUpdateHostkeys },
|
||||||
|
{ "hostbasedkeytypes", oHostbasedKeyTypes },
|
||||||
{ "ignoreunknown", oIgnoreUnknown },
|
{ "ignoreunknown", oIgnoreUnknown },
|
||||||
|
|
||||||
{ NULL, oBadOption }
|
{ NULL, oBadOption }
|
||||||
@ -1481,6 +1482,19 @@ parse_int:
|
|||||||
intptr = &options->update_hostkeys;
|
intptr = &options->update_hostkeys;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
|
case oHostbasedKeyTypes:
|
||||||
|
charptr = &options->hostbased_key_types;
|
||||||
|
arg = strdelim(&s);
|
||||||
|
if (!arg || *arg == '\0')
|
||||||
|
fatal("%.200s line %d: Missing argument.",
|
||||||
|
filename, linenum);
|
||||||
|
if (!sshkey_names_valid2(arg, 1))
|
||||||
|
fatal("%s line %d: Bad key types '%s'.",
|
||||||
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
|
if (*activep && *charptr == NULL)
|
||||||
|
*charptr = xstrdup(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
case oDeprecated:
|
case oDeprecated:
|
||||||
debug("%s line %d: Deprecated option \"%s\"",
|
debug("%s line %d: Deprecated option \"%s\"",
|
||||||
filename, linenum, keyword);
|
filename, linenum, keyword);
|
||||||
@ -1660,6 +1674,7 @@ initialize_options(Options * options)
|
|||||||
options->revoked_host_keys = NULL;
|
options->revoked_host_keys = NULL;
|
||||||
options->fingerprint_hash = -1;
|
options->fingerprint_hash = -1;
|
||||||
options->update_hostkeys = -1;
|
options->update_hostkeys = -1;
|
||||||
|
options->hostbased_key_types = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1841,6 +1856,8 @@ fill_default_options(Options * options)
|
|||||||
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
|
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
|
||||||
if (options->update_hostkeys == -1)
|
if (options->update_hostkeys == -1)
|
||||||
options->update_hostkeys = 1;
|
options->update_hostkeys = 1;
|
||||||
|
if (options->hostbased_key_types == NULL)
|
||||||
|
options->hostbased_key_types = xstrdup("*");
|
||||||
|
|
||||||
#define CLEAR_ON_NONE(v) \
|
#define CLEAR_ON_NONE(v) \
|
||||||
do { \
|
do { \
|
||||||
@ -2281,6 +2298,7 @@ dump_client_config(Options *o, const char *host)
|
|||||||
dump_cfg_string(oControlPath, o->control_path);
|
dump_cfg_string(oControlPath, o->control_path);
|
||||||
dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
|
dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
|
||||||
dump_cfg_string(oHostKeyAlias, o->host_key_alias);
|
dump_cfg_string(oHostKeyAlias, o->host_key_alias);
|
||||||
|
dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
|
||||||
dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
|
dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
|
||||||
dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
|
dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
|
||||||
dump_cfg_string(oLocalCommand, o->local_command);
|
dump_cfg_string(oLocalCommand, o->local_command);
|
||||||
@ -2289,9 +2307,10 @@ dump_client_config(Options *o, const char *host)
|
|||||||
dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
|
dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
|
||||||
dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
|
dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
|
||||||
dump_cfg_string(oProxyCommand, o->proxy_command);
|
dump_cfg_string(oProxyCommand, o->proxy_command);
|
||||||
dump_cfg_string(oXAuthLocation, o->xauth_location);
|
|
||||||
dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
|
dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
|
||||||
|
dump_cfg_string(oXAuthLocation, o->xauth_location);
|
||||||
|
|
||||||
|
/* Forwards */
|
||||||
dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
|
dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
|
||||||
dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
|
dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
|
||||||
dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
|
dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.h,v 1.107 2015/01/26 03:04:45 djm Exp $ */
|
/* $OpenBSD: readconf.h,v 1.108 2015/01/30 11:43:14 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -150,6 +150,8 @@ typedef struct {
|
|||||||
|
|
||||||
int update_hostkeys;
|
int update_hostkeys;
|
||||||
|
|
||||||
|
char *hostbased_key_types;
|
||||||
|
|
||||||
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
|
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
|
||||||
} Options;
|
} Options;
|
||||||
|
|
||||||
|
5
scp.1
5
scp.1
@ -8,9 +8,9 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" Created: Sun May 7 00:14:37 1995 ylo
|
.\" Created: Sun May 7 00:14:37 1995 ylo
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: scp.1,v 1.65 2015/01/26 13:55:29 jmc Exp $
|
.\" $OpenBSD: scp.1,v 1.66 2015/01/30 11:43:14 djm Exp $
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: January 26 2015 $
|
.Dd $Mdocdate: January 30 2015 $
|
||||||
.Dt SCP 1
|
.Dt SCP 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -150,6 +150,7 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It HashKnownHosts
|
.It HashKnownHosts
|
||||||
.It Host
|
.It Host
|
||||||
.It HostbasedAuthentication
|
.It HostbasedAuthentication
|
||||||
|
.It HostbasedKeyTypes
|
||||||
.It HostKeyAlgorithms
|
.It HostKeyAlgorithms
|
||||||
.It HostKeyAlias
|
.It HostKeyAlias
|
||||||
.It HostName
|
.It HostName
|
||||||
|
5
sftp.1
5
sftp.1
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: sftp.1,v 1.100 2015/01/26 12:16:36 djm Exp $
|
.\" $OpenBSD: sftp.1,v 1.101 2015/01/30 11:43:14 djm Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
|
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -22,7 +22,7 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: January 26 2015 $
|
.Dd $Mdocdate: January 30 2015 $
|
||||||
.Dt SFTP 1
|
.Dt SFTP 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -215,6 +215,7 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It HashKnownHosts
|
.It HashKnownHosts
|
||||||
.It Host
|
.It Host
|
||||||
.It HostbasedAuthentication
|
.It HostbasedAuthentication
|
||||||
|
.It HostbasedKeyTypes
|
||||||
.It HostKeyAlgorithms
|
.It HostKeyAlgorithms
|
||||||
.It HostKeyAlias
|
.It HostKeyAlias
|
||||||
.It HostName
|
.It HostName
|
||||||
|
5
ssh.1
5
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.354 2015/01/26 12:16:36 djm Exp $
|
.\" $OpenBSD: ssh.1,v 1.355 2015/01/30 11:43:14 djm Exp $
|
||||||
.Dd $Mdocdate: January 26 2015 $
|
.Dd $Mdocdate: January 30 2015 $
|
||||||
.Dt SSH 1
|
.Dt SSH 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -445,6 +445,7 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It HashKnownHosts
|
.It HashKnownHosts
|
||||||
.It Host
|
.It Host
|
||||||
.It HostbasedAuthentication
|
.It HostbasedAuthentication
|
||||||
|
.It HostbasedKeyTypes
|
||||||
.It HostKeyAlgorithms
|
.It HostKeyAlgorithms
|
||||||
.It HostKeyAlias
|
.It HostKeyAlias
|
||||||
.It HostName
|
.It HostName
|
||||||
|
15
ssh_config.5
15
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.201 2015/01/26 12:16:36 djm Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.202 2015/01/30 11:43:14 djm Exp $
|
||||||
.Dd $Mdocdate: January 26 2015 $
|
.Dd $Mdocdate: January 30 2015 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -777,6 +777,17 @@ The default is
|
|||||||
This option applies to protocol version 2 only and
|
This option applies to protocol version 2 only and
|
||||||
is similar to
|
is similar to
|
||||||
.Cm RhostsRSAAuthentication .
|
.Cm RhostsRSAAuthentication .
|
||||||
|
.It Cm HostbasedKeyTypes
|
||||||
|
Specifies the key types that will be used for hostbased authentication
|
||||||
|
as a comma-separated pattern list.
|
||||||
|
The default
|
||||||
|
.Dq *
|
||||||
|
will allow all key types.
|
||||||
|
The
|
||||||
|
.Fl Q
|
||||||
|
option of
|
||||||
|
.Xr ssh 1
|
||||||
|
may be used to list supported key types.
|
||||||
.It Cm HostKeyAlgorithms
|
.It Cm HostKeyAlgorithms
|
||||||
Specifies the protocol version 2 host key algorithms
|
Specifies the protocol version 2 host key algorithms
|
||||||
that the client wants to use in order of preference.
|
that the client wants to use in order of preference.
|
||||||
|
314
sshconnect2.c
314
sshconnect2.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshconnect2.c,v 1.222 2015/01/28 22:36:00 djm Exp $ */
|
/* $OpenBSD: sshconnect2.c,v 1.223 2015/01/30 11:43:14 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.
|
||||||
@ -273,6 +273,8 @@ struct cauthctxt {
|
|||||||
int agent_fd;
|
int agent_fd;
|
||||||
/* hostbased */
|
/* hostbased */
|
||||||
Sensitive *sensitive;
|
Sensitive *sensitive;
|
||||||
|
char *oktypes, *ktypes;
|
||||||
|
const char *active_ktype;
|
||||||
/* kbd-interactive */
|
/* kbd-interactive */
|
||||||
int info_req_seen;
|
int info_req_seen;
|
||||||
/* generic */
|
/* generic */
|
||||||
@ -401,6 +403,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
|
|||||||
authctxt.authlist = NULL;
|
authctxt.authlist = NULL;
|
||||||
authctxt.methoddata = NULL;
|
authctxt.methoddata = NULL;
|
||||||
authctxt.sensitive = sensitive;
|
authctxt.sensitive = sensitive;
|
||||||
|
authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL;
|
||||||
authctxt.info_req_seen = 0;
|
authctxt.info_req_seen = 0;
|
||||||
authctxt.agent_fd = -1;
|
authctxt.agent_fd = -1;
|
||||||
if (authctxt.method == NULL)
|
if (authctxt.method == NULL)
|
||||||
@ -1452,78 +1455,116 @@ input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
|
ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||||
u_char *data, u_int datalen)
|
const u_char *data, size_t datalen)
|
||||||
{
|
{
|
||||||
Buffer b;
|
struct sshbuf *b;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int to[2], from[2], status, version = 2;
|
int i, r, to[2], from[2], status, sock = packet_get_connection_in();
|
||||||
|
u_char rversion = 0, version = 2;
|
||||||
|
void (*osigchld)(int);
|
||||||
|
|
||||||
debug2("ssh_keysign called");
|
*sigp = NULL;
|
||||||
|
*lenp = 0;
|
||||||
|
|
||||||
if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
|
if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
|
||||||
error("ssh_keysign: not installed: %s", strerror(errno));
|
error("%s: not installed: %s", __func__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fflush(stdout) != 0) {
|
||||||
|
error("%s: fflush: %s", __func__, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (fflush(stdout) != 0)
|
|
||||||
error("ssh_keysign: fflush: %s", strerror(errno));
|
|
||||||
if (pipe(to) < 0) {
|
if (pipe(to) < 0) {
|
||||||
error("ssh_keysign: pipe: %s", strerror(errno));
|
error("%s: pipe: %s", __func__, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (pipe(from) < 0) {
|
if (pipe(from) < 0) {
|
||||||
error("ssh_keysign: pipe: %s", strerror(errno));
|
error("%s: pipe: %s", __func__, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((pid = fork()) < 0) {
|
if ((pid = fork()) < 0) {
|
||||||
error("ssh_keysign: fork: %s", strerror(errno));
|
error("%s: fork: %s", __func__, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
osigchld = signal(SIGCHLD, SIG_DFL);
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
/* keep the socket on exec */
|
/* keep the socket on exec */
|
||||||
fcntl(packet_get_connection_in(), F_SETFD, 0);
|
fcntl(sock, F_SETFD, 0);
|
||||||
permanently_drop_suid(getuid());
|
permanently_drop_suid(getuid());
|
||||||
close(from[0]);
|
close(from[0]);
|
||||||
if (dup2(from[1], STDOUT_FILENO) < 0)
|
if (dup2(from[1], STDOUT_FILENO) < 0)
|
||||||
fatal("ssh_keysign: dup2: %s", strerror(errno));
|
fatal("%s: dup2: %s", __func__, strerror(errno));
|
||||||
close(to[1]);
|
close(to[1]);
|
||||||
if (dup2(to[0], STDIN_FILENO) < 0)
|
if (dup2(to[0], STDIN_FILENO) < 0)
|
||||||
fatal("ssh_keysign: dup2: %s", strerror(errno));
|
fatal("%s: dup2: %s", __func__, strerror(errno));
|
||||||
close(from[1]);
|
close(from[1]);
|
||||||
close(to[0]);
|
close(to[0]);
|
||||||
|
/* Close everything but stdio and the socket */
|
||||||
|
for (i = STDERR_FILENO + 1; i < sock; i++)
|
||||||
|
close(i);
|
||||||
|
closefrom(sock + 1);
|
||||||
|
debug3("%s: [child] pid=%ld, exec %s",
|
||||||
|
__func__, (long)getpid(), _PATH_SSH_KEY_SIGN);
|
||||||
execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
|
execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
|
||||||
fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN,
|
fatal("%s: exec(%s): %s", __func__, _PATH_SSH_KEY_SIGN,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
close(from[1]);
|
close(from[1]);
|
||||||
close(to[0]);
|
close(to[0]);
|
||||||
|
|
||||||
buffer_init(&b);
|
if ((b = sshbuf_new()) == NULL)
|
||||||
buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */
|
fatal("%s: sshbuf_new failed", __func__);
|
||||||
buffer_put_string(&b, data, datalen);
|
/* send # of sock, data to be signed */
|
||||||
if (ssh_msg_send(to[1], version, &b) == -1)
|
if ((r = sshbuf_put_u32(b, sock) != 0) ||
|
||||||
fatal("ssh_keysign: couldn't send request");
|
(r = sshbuf_put_string(b, data, datalen)) != 0)
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
if (ssh_msg_recv(from[0], &b) < 0) {
|
if (ssh_msg_send(to[1], version, b) == -1)
|
||||||
error("ssh_keysign: no reply");
|
fatal("%s: couldn't send request", __func__);
|
||||||
buffer_free(&b);
|
sshbuf_reset(b);
|
||||||
return -1;
|
r = ssh_msg_recv(from[0], b);
|
||||||
}
|
|
||||||
close(from[0]);
|
close(from[0]);
|
||||||
close(to[1]);
|
close(to[1]);
|
||||||
|
if (r < 0) {
|
||||||
|
error("%s: no reply", __func__);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
while (waitpid(pid, &status, 0) < 0)
|
errno = 0;
|
||||||
if (errno != EINTR)
|
while (waitpid(pid, &status, 0) < 0) {
|
||||||
break;
|
if (errno != EINTR) {
|
||||||
|
error("%s: waitpid %ld: %s",
|
||||||
if (buffer_get_char(&b) != version) {
|
__func__, (long)pid, strerror(errno));
|
||||||
error("ssh_keysign: bad version");
|
goto fail;
|
||||||
buffer_free(&b);
|
}
|
||||||
|
}
|
||||||
|
if (!WIFEXITED(status)) {
|
||||||
|
error("%s: exited abnormally", __func__);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (WEXITSTATUS(status) != 0) {
|
||||||
|
error("%s: exited with status %d",
|
||||||
|
__func__, WEXITSTATUS(status));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_get_u8(b, &rversion)) != 0) {
|
||||||
|
error("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (rversion != version) {
|
||||||
|
error("%s: bad version", __func__);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) {
|
||||||
|
error("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
fail:
|
||||||
|
signal(SIGCHLD, osigchld);
|
||||||
|
sshbuf_free(b);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*sigp = buffer_get_string(&b, lenp);
|
signal(SIGCHLD, osigchld);
|
||||||
buffer_free(&b);
|
sshbuf_free(b);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1531,100 +1572,149 @@ ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
|
|||||||
int
|
int
|
||||||
userauth_hostbased(Authctxt *authctxt)
|
userauth_hostbased(Authctxt *authctxt)
|
||||||
{
|
{
|
||||||
Key *private = NULL;
|
struct ssh *ssh = active_state;
|
||||||
Sensitive *sensitive = authctxt->sensitive;
|
struct sshkey *private = NULL;
|
||||||
Buffer b;
|
struct sshbuf *b = NULL;
|
||||||
u_char *signature, *blob;
|
|
||||||
char *chost, *pkalg, *p;
|
|
||||||
const char *service;
|
const char *service;
|
||||||
u_int blen, slen;
|
u_char *sig = NULL, *keyblob = NULL;
|
||||||
int ok, i, found = 0;
|
char *fp = NULL, *chost = NULL, *lname = NULL;
|
||||||
|
size_t siglen = 0, keylen = 0;
|
||||||
|
int i, r, success = 0;
|
||||||
|
|
||||||
/* XXX provide some way to allow user to specify key types attempted */
|
if (authctxt->ktypes == NULL) {
|
||||||
|
authctxt->oktypes = xstrdup(options.hostbased_key_types);
|
||||||
|
authctxt->ktypes = authctxt->oktypes;
|
||||||
|
}
|
||||||
|
|
||||||
/* check for a useful key */
|
/*
|
||||||
for (i = 0; i < sensitive->nkeys; i++) {
|
* Work through each listed type pattern in HostbasedKeyTypes,
|
||||||
private = sensitive->keys[i];
|
* trying each hostkey that matches the type in turn.
|
||||||
if (private && private->type != KEY_RSA1) {
|
*/
|
||||||
found = 1;
|
for (;;) {
|
||||||
|
if (authctxt->active_ktype == NULL)
|
||||||
|
authctxt->active_ktype = strsep(&authctxt->ktypes, ",");
|
||||||
|
if (authctxt->active_ktype == NULL ||
|
||||||
|
*authctxt->active_ktype == '\0')
|
||||||
|
break;
|
||||||
|
debug3("%s: trying key type %s", __func__,
|
||||||
|
authctxt->active_ktype);
|
||||||
|
|
||||||
|
/* check for a useful key */
|
||||||
|
private = NULL;
|
||||||
|
for (i = 0; i < authctxt->sensitive->nkeys; i++) {
|
||||||
|
if (authctxt->sensitive->keys[i] == NULL ||
|
||||||
|
authctxt->sensitive->keys[i]->type == KEY_RSA1 ||
|
||||||
|
authctxt->sensitive->keys[i]->type == KEY_UNSPEC)
|
||||||
|
continue;
|
||||||
|
if (match_pattern_list(
|
||||||
|
sshkey_ssh_name(authctxt->sensitive->keys[i]),
|
||||||
|
authctxt->active_ktype,
|
||||||
|
strlen(authctxt->active_ktype), 0) != 1)
|
||||||
|
continue;
|
||||||
/* we take and free the key */
|
/* we take and free the key */
|
||||||
sensitive->keys[i] = NULL;
|
private = authctxt->sensitive->keys[i];
|
||||||
|
authctxt->sensitive->keys[i] = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* Found one */
|
||||||
|
if (private != NULL)
|
||||||
|
break;
|
||||||
|
/* No more keys of this type; advance */
|
||||||
|
authctxt->active_ktype = NULL;
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (private == NULL) {
|
||||||
|
free(authctxt->oktypes);
|
||||||
|
authctxt->oktypes = authctxt->ktypes = NULL;
|
||||||
|
authctxt->active_ktype = NULL;
|
||||||
debug("No more client hostkeys for hostbased authentication.");
|
debug("No more client hostkeys for hostbased authentication.");
|
||||||
return 0;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("%s: trying hostkey type %s", __func__, key_type(private));
|
if ((fp = sshkey_fingerprint(private, options.fingerprint_hash,
|
||||||
|
SSH_FP_DEFAULT)) == NULL) {
|
||||||
if (key_to_blob(private, &blob, &blen) == 0) {
|
error("%s: sshkey_fingerprint failed", __func__);
|
||||||
key_free(private);
|
goto out;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
debug("%s: trying hostkey %s %s",
|
||||||
|
__func__, sshkey_ssh_name(private), fp);
|
||||||
|
|
||||||
/* figure out a name for the client host */
|
/* figure out a name for the client host */
|
||||||
p = get_local_name(packet_get_connection_in());
|
if ((lname = get_local_name(packet_get_connection_in())) == NULL) {
|
||||||
if (p == NULL) {
|
error("%s: cannot get local ipaddr/name", __func__);
|
||||||
error("userauth_hostbased: cannot get local ipaddr/name");
|
goto out;
|
||||||
key_free(private);
|
|
||||||
free(blob);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
xasprintf(&chost, "%s.", p);
|
|
||||||
debug2("userauth_hostbased: chost %s", chost);
|
/* XXX sshbuf_put_stringf? */
|
||||||
free(p);
|
xasprintf(&chost, "%s.", lname);
|
||||||
|
debug2("%s: chost %s", __func__, chost);
|
||||||
|
|
||||||
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
|
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
|
||||||
authctxt->service;
|
authctxt->service;
|
||||||
pkalg = xstrdup(key_ssh_name(private));
|
|
||||||
buffer_init(&b);
|
|
||||||
/* construct data */
|
|
||||||
buffer_put_string(&b, session_id2, session_id2_len);
|
|
||||||
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
|
|
||||||
buffer_put_cstring(&b, authctxt->server_user);
|
|
||||||
buffer_put_cstring(&b, service);
|
|
||||||
buffer_put_cstring(&b, authctxt->method->name);
|
|
||||||
buffer_put_cstring(&b, pkalg);
|
|
||||||
buffer_put_string(&b, blob, blen);
|
|
||||||
buffer_put_cstring(&b, chost);
|
|
||||||
buffer_put_cstring(&b, authctxt->local_user);
|
|
||||||
#ifdef DEBUG_PK
|
|
||||||
buffer_dump(&b);
|
|
||||||
#endif
|
|
||||||
if (sensitive->external_keysign)
|
|
||||||
ok = ssh_keysign(private, &signature, &slen,
|
|
||||||
buffer_ptr(&b), buffer_len(&b));
|
|
||||||
else
|
|
||||||
ok = key_sign(private, &signature, &slen,
|
|
||||||
buffer_ptr(&b), buffer_len(&b));
|
|
||||||
key_free(private);
|
|
||||||
buffer_free(&b);
|
|
||||||
if (ok != 0) {
|
|
||||||
error("key_sign failed");
|
|
||||||
free(chost);
|
|
||||||
free(pkalg);
|
|
||||||
free(blob);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
packet_start(SSH2_MSG_USERAUTH_REQUEST);
|
|
||||||
packet_put_cstring(authctxt->server_user);
|
|
||||||
packet_put_cstring(authctxt->service);
|
|
||||||
packet_put_cstring(authctxt->method->name);
|
|
||||||
packet_put_cstring(pkalg);
|
|
||||||
packet_put_string(blob, blen);
|
|
||||||
packet_put_cstring(chost);
|
|
||||||
packet_put_cstring(authctxt->local_user);
|
|
||||||
packet_put_string(signature, slen);
|
|
||||||
explicit_bzero(signature, slen);
|
|
||||||
free(signature);
|
|
||||||
free(chost);
|
|
||||||
free(pkalg);
|
|
||||||
free(blob);
|
|
||||||
|
|
||||||
packet_send();
|
/* construct data */
|
||||||
return 1;
|
if ((b = sshbuf_new()) == NULL) {
|
||||||
|
error("%s: sshbuf_new failed", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) {
|
||||||
|
error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
|
||||||
|
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(b, service)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(b, key_ssh_name(private))) != 0 ||
|
||||||
|
(r = sshbuf_put_string(b, keyblob, keylen)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(b, chost)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) {
|
||||||
|
error("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_PK
|
||||||
|
sshbuf_dump(b, stderr);
|
||||||
|
#endif
|
||||||
|
if (authctxt->sensitive->external_keysign)
|
||||||
|
r = ssh_keysign(private, &sig, &siglen,
|
||||||
|
sshbuf_ptr(b), sshbuf_len(b));
|
||||||
|
else if ((r = sshkey_sign(private, &sig, &siglen,
|
||||||
|
sshbuf_ptr(b), sshbuf_len(b), datafellows)) != 0)
|
||||||
|
debug("%s: sshkey_sign: %s", __func__, ssh_err(r));
|
||||||
|
if (r != 0) {
|
||||||
|
error("sign using hostkey %s %s failed",
|
||||||
|
sshkey_ssh_name(private), fp);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
|
||||||
|
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
|
||||||
|
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
|
||||||
|
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
|
||||||
|
(r = sshpkt_put_cstring(ssh, key_ssh_name(private))) != 0 ||
|
||||||
|
(r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 ||
|
||||||
|
(r = sshpkt_put_cstring(ssh, chost)) != 0 ||
|
||||||
|
(r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 ||
|
||||||
|
(r = sshpkt_put_string(ssh, sig, siglen)) != 0 ||
|
||||||
|
(r = sshpkt_send(ssh)) != 0) {
|
||||||
|
error("%s: packet error: %s", __func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
success = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (sig != NULL) {
|
||||||
|
explicit_bzero(sig, siglen);
|
||||||
|
free(sig);
|
||||||
|
}
|
||||||
|
free(keyblob);
|
||||||
|
free(lname);
|
||||||
|
free(fp);
|
||||||
|
free(chost);
|
||||||
|
sshkey_free(private);
|
||||||
|
sshbuf_free(b);
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find auth method */
|
/* find auth method */
|
||||||
|
Loading…
Reference in New Issue
Block a user