From 8b29008bbe97f33381d9b4b93fcfa304168d0286 Mon Sep 17 00:00:00 2001 From: "jmc@openbsd.org" Date: Thu, 5 Nov 2015 09:48:05 +0000 Subject: upstream commit "commandline" -> "command line", since there are so few examples of the former in the pages, so many of the latter, and in some of these pages we had multiple spellings; prompted by tj Upstream-ID: 78459d59bff74223f8139d9001ccd56fc4310659 --- ssh-agent.1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'ssh-agent.1') diff --git a/ssh-agent.1 b/ssh-agent.1 index d0aa712f1..5a521cb56 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.59 2015/04/24 06:26:49 jmc Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.60 2015/11/05 09:48:05 jmc Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,7 +34,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: April 24 2015 $ +.Dd $Mdocdate: November 5 2015 $ .Dt SSH-AGENT 1 .Os .Sh NAME @@ -130,7 +130,7 @@ overrides this value. Without this option the default maximum lifetime is forever. .El .Pp -If a commandline is given, this is executed as a subprocess of the agent. +If a command line is given, this is executed as a subprocess of the agent. When the command dies, so does the agent. .Pp The idea is that the agent is run in the user's local PC, laptop, or -- cgit v1.2.3 From f361df474c49a097bfcf16d1b7b5c36fcd844b4b Mon Sep 17 00:00:00 2001 From: "jcs@openbsd.org" Date: Sun, 15 Nov 2015 22:26:49 +0000 Subject: upstream commit Add an AddKeysToAgent client option which can be set to 'yes', 'no', 'ask', or 'confirm', and defaults to 'no'. When enabled, a private key that is used during authentication will be added to ssh-agent if it is running (with confirmation enabled if set to 'confirm'). Initial version from Joachim Schipper many years ago. ok markus@ Upstream-ID: a680db2248e8064ec55f8be72d539458c987d5f4 --- readconf.c | 22 ++++++++++++++++++++-- readconf.h | 4 +++- ssh-agent.1 | 11 +++++++++-- ssh.1 | 9 +++++++-- ssh_config.5 | 37 +++++++++++++++++++++++++++++++++++-- sshconnect.c | 30 +++++++++++++++++++++++++++++- sshconnect.h | 4 +++- sshconnect1.c | 15 +++++++++++---- sshconnect2.c | 35 ++++++++++++++++++++--------------- 9 files changed, 137 insertions(+), 30 deletions(-) (limited to 'ssh-agent.1') diff --git a/readconf.c b/readconf.c index c062433ce..0a380913f 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.245 2015/10/27 08:54:52 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.246 2015/11/15 22:26:49 jcs Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -135,7 +135,7 @@ typedef enum { oPasswordAuthentication, oRSAAuthentication, oChallengeResponseAuthentication, oXAuthLocation, oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, - oCertificateFile, + oCertificateFile, oAddKeysToAgent, oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, @@ -204,6 +204,7 @@ static struct { { "identityfile2", oIdentityFile }, /* obsolete */ { "identitiesonly", oIdentitiesOnly }, { "certificatefile", oCertificateFile }, + { "addkeystoagent", oAddKeysToAgent }, { "hostname", oHostName }, { "hostkeyalias", oHostKeyAlias }, { "proxycommand", oProxyCommand }, @@ -712,6 +713,15 @@ static const struct multistate multistate_yesnoask[] = { { "ask", 2 }, { NULL, -1 } }; +static const struct multistate multistate_yesnoaskconfirm[] = { + { "true", 1 }, + { "false", 0 }, + { "yes", 1 }, + { "no", 0 }, + { "ask", 2 }, + { "confirm", 3 }, + { NULL, -1 } +}; static const struct multistate multistate_addressfamily[] = { { "inet", AF_INET }, { "inet6", AF_INET6 }, @@ -1533,6 +1543,11 @@ parse_keytypes: charptr = &options->pubkey_key_types; goto parse_keytypes; + case oAddKeysToAgent: + intptr = &options->add_keys_to_agent; + multistate_ptr = multistate_yesnoaskconfirm; + goto parse_multistate; + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); @@ -1699,6 +1714,7 @@ initialize_options(Options * options) options->local_command = NULL; options->permit_local_command = -1; options->use_roaming = -1; + options->add_keys_to_agent = -1; options->visual_host_key = -1; options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; @@ -1803,6 +1819,8 @@ fill_default_options(Options * options) /* options->hostkeyalgorithms, default set in myproposals.h */ if (options->protocol == SSH_PROTO_UNKNOWN) options->protocol = SSH_PROTO_2; + if (options->add_keys_to_agent == -1) + options->add_keys_to_agent = 0; if (options->num_identity_files == 0) { if (options->protocol & SSH_PROTO_1) { add_identity_file(options, "~/", diff --git a/readconf.h b/readconf.h index 6d6927f06..2034bfd9d 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.111 2015/09/24 06:15:11 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.112 2015/11/15 22:26:49 jcs Exp $ */ /* * Author: Tatu Ylonen @@ -100,6 +100,8 @@ typedef struct { int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; + int add_keys_to_agent; + /* Local TCP/IP forward requests. */ int num_local_forwards; struct Forward *local_forwards; diff --git a/ssh-agent.1 b/ssh-agent.1 index 5a521cb56..dabc5c46b 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.60 2015/11/05 09:48:05 jmc Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.61 2015/11/15 22:26:49 jcs Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,7 +34,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: November 5 2015 $ +.Dd $Mdocdate: November 15 2015 $ .Dt SSH-AGENT 1 .Os .Sh NAME @@ -66,6 +66,13 @@ machines using .Pp The agent initially does not have any private keys. Keys are added using +.Xr ssh 1 +(see +.Cm AddKeysToAgent +in +.Xr ssh_config 5 +for details) +or .Xr ssh-add 1 . Multiple identities may be stored in .Nm diff --git a/ssh.1 b/ssh.1 index c4b7250a5..5b35b6cc0 100644 --- a/ssh.1 +++ b/ssh.1 @@ -33,8 +33,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.365 2015/11/06 00:31:41 mmcc Exp $ -.Dd $Mdocdate: November 6 2015 $ +.\" $OpenBSD: ssh.1,v 1.366 2015/11/15 22:26:49 jcs Exp $ +.Dd $Mdocdate: November 15 2015 $ .Dt SSH 1 .Os .Sh NAME @@ -462,6 +462,7 @@ For full details of the options listed below, and their possible values, see .Xr ssh_config 5 . .Pp .Bl -tag -width Ds -offset indent -compact +.It AddKeysToAgent .It AddressFamily .It BatchMode .It BindAddress @@ -926,6 +927,10 @@ The most convenient way to use public key or certificate authentication may be with an authentication agent. See .Xr ssh-agent 1 +and (optionally) the +.Cm AddKeysToAgent +directive in +.Xr ssh_config 5 for more information. .Pp Challenge-response authentication works as follows: diff --git a/ssh_config.5 b/ssh_config.5 index 39cf932d3..e6673b103 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -33,8 +33,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.221 2015/09/24 06:15:11 djm Exp $ -.Dd $Mdocdate: September 24 2015 $ +.\" $OpenBSD: ssh_config.5,v 1.222 2015/11/15 22:26:49 jcs Exp $ +.Dd $Mdocdate: November 15 2015 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -221,6 +221,39 @@ keyword matches against the name of the local user running (this keyword may be useful in system-wide .Nm files). +.It Cm AddKeysToAgent +Specifies whether keys should be automatically added to a running +.Xr ssh-agent 5 . +If this option is set to +.Dq yes +and a key is loaded from a file, the key and its passphrase are added to +the agent with the default lifetime, as if by +.Xr ssh-add 1 . +If this option is set to +.Dq ask , +.Nm ssh +will require confirmation using the +.Ev SSH_ASKPASS +program before adding a key (see +.Xr ssh-add 1 +for details). +If this option is set to +.Dq confirm , +each use of the key must be confirmed, as if the +.Fl c +option was specified to +.Xr ssh-add 1 . +If this option is set to +.Dq no , +no keys are added to the agent. +The argument must be +.Dq yes , +.Dq confirm , +.Dq ask , +or +.Dq no . +The default is +.Dq no . .It Cm AddressFamily Specifies which address family to use when connecting. Valid arguments are diff --git a/sshconnect.c b/sshconnect.c index c9f88e035..19d393f7b 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.265 2015/09/04 04:55:24 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.266 2015/11/15 22:26:49 jcs Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -65,6 +65,7 @@ #include "version.h" #include "authfile.h" #include "ssherr.h" +#include "authfd.h" char *client_version_string = NULL; char *server_version_string = NULL; @@ -1487,3 +1488,30 @@ ssh_local_cmd(const char *args) return (WEXITSTATUS(status)); } + +void +maybe_add_key_to_agent(char *authfile, Key *private, char *comment, + char *passphrase) +{ + int auth_sock = -1, r; + + if (options.add_keys_to_agent == 0) + return; + + if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { + debug3("no authentication agent, not adding key"); + return; + } + + if (options.add_keys_to_agent == 2 && + !ask_permission("Add key %s (%s) to agent?", authfile, comment)) { + debug3("user denied adding this key"); + return; + } + + if ((r = ssh_add_identity_constrained(auth_sock, private, comment, 0, + (options.add_keys_to_agent == 3))) == 0) + debug("identity added to agent: %s", authfile); + else + debug("could not add identity to agent: %s (%d)", authfile, r); +} diff --git a/sshconnect.h b/sshconnect.h index 0ea6e99f6..cf1851a95 100644 --- a/sshconnect.h +++ b/sshconnect.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.h,v 1.28 2013/10/16 02:31:47 djm Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.29 2015/11/15 22:26:49 jcs Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -55,6 +55,8 @@ void ssh_userauth2(const char *, const char *, char *, Sensitive *); void ssh_put_password(char *); int ssh_local_cmd(const char *); +void maybe_add_key_to_agent(char *, Key *, char *, char *); + /* * Macros to raise/lower permissions. */ diff --git a/sshconnect1.c b/sshconnect1.c index 016abbce5..bfc523bde 100644 --- a/sshconnect1.c +++ b/sshconnect1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect1.c,v 1.77 2015/01/14 20:05:27 djm Exp $ */ +/* $OpenBSD: sshconnect1.c,v 1.78 2015/11/15 22:26:49 jcs Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -221,7 +221,7 @@ try_rsa_authentication(int idx) { BIGNUM *challenge; Key *public, *private; - char buf[300], *passphrase, *comment, *authfile; + char buf[300], *passphrase = NULL, *comment, *authfile; int i, perm_ok = 1, type, quit; public = options.identity_keys[idx]; @@ -283,13 +283,20 @@ try_rsa_authentication(int idx) debug2("no passphrase given, try next key"); quit = 1; } - explicit_bzero(passphrase, strlen(passphrase)); - free(passphrase); if (private != NULL || quit) break; debug2("bad passphrase given, try again..."); } } + + if (private != NULL) + maybe_add_key_to_agent(authfile, private, comment, passphrase); + + if (passphrase != NULL) { + explicit_bzero(passphrase, strlen(passphrase)); + free(passphrase); + } + /* We no longer need the comment. */ free(comment); diff --git a/sshconnect2.c b/sshconnect2.c index 3ab686e86..69d0bee4e 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.228 2015/10/13 16:15:21 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.229 2015/11/15 22:26:49 jcs Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -313,7 +313,7 @@ void userauth(Authctxt *, char *); static int sign_and_send_pubkey(Authctxt *, Identity *); static void pubkey_prepare(Authctxt *); static void pubkey_cleanup(Authctxt *); -static Key *load_identity_file(char *, int); +static Key *load_identity_file(Identity *); static Authmethod *authmethod_get(char *authlist); static Authmethod *authmethod_lookup(const char *name); @@ -990,7 +990,7 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, return (sshkey_sign(id->key, sigp, lenp, data, datalen, compat)); /* load the private key from the file */ - if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL) + if ((prv = load_identity_file(id)) == NULL) return (-1); /* XXX return decent error code */ ret = sshkey_sign(prv, sigp, lenp, data, datalen, compat); sshkey_free(prv); @@ -1147,20 +1147,20 @@ send_pubkey_test(Authctxt *authctxt, Identity *id) } static Key * -load_identity_file(char *filename, int userprovided) +load_identity_file(Identity *id) { Key *private; - char prompt[300], *passphrase; + char prompt[300], *passphrase, *comment; int r, perm_ok = 0, quit = 0, i; struct stat st; - if (stat(filename, &st) < 0) { - (userprovided ? logit : debug3)("no such identity: %s: %s", - filename, strerror(errno)); + if (stat(id->filename, &st) < 0) { + (id->userprovided ? logit : debug3)("no such identity: %s: %s", + id->filename, strerror(errno)); return NULL; } snprintf(prompt, sizeof prompt, - "Enter passphrase for key '%.100s': ", filename); + "Enter passphrase for key '%.100s': ", id->filename); for (i = 0; i <= options.number_of_password_prompts; i++) { if (i == 0) passphrase = ""; @@ -1172,8 +1172,8 @@ load_identity_file(char *filename, int userprovided) break; } } - switch ((r = sshkey_load_private_type(KEY_UNSPEC, filename, - passphrase, &private, NULL, &perm_ok))) { + switch ((r = sshkey_load_private_type(KEY_UNSPEC, id->filename, + passphrase, &private, &comment, &perm_ok))) { case 0: break; case SSH_ERR_KEY_WRONG_PASSPHRASE: @@ -1187,20 +1187,26 @@ load_identity_file(char *filename, int userprovided) case SSH_ERR_SYSTEM_ERROR: if (errno == ENOENT) { debug2("Load key \"%s\": %s", - filename, ssh_err(r)); + id->filename, ssh_err(r)); quit = 1; break; } /* FALLTHROUGH */ default: - error("Load key \"%s\": %s", filename, ssh_err(r)); + error("Load key \"%s\": %s", id->filename, ssh_err(r)); quit = 1; break; } + if (!quit && private != NULL && !id->agent_fd && + !(id->key && id->isprivate)) + maybe_add_key_to_agent(id->filename, private, comment, + passphrase); if (i > 0) { explicit_bzero(passphrase, strlen(passphrase)); free(passphrase); } + if (comment) + free(comment); if (private != NULL || quit) break; } @@ -1403,8 +1409,7 @@ userauth_pubkey(Authctxt *authctxt) } } else { debug("Trying private key: %s", id->filename); - id->key = load_identity_file(id->filename, - id->userprovided); + id->key = load_identity_file(id); if (id->key != NULL) { if (try_identity(id)) { id->isprivate = 1; -- cgit v1.2.3 From 1a11670286acddcc19f5eff0966c380831fc4638 Mon Sep 17 00:00:00 2001 From: "jmc@openbsd.org" Date: Sun, 15 Nov 2015 23:54:15 +0000 Subject: upstream commit do not confuse mandoc by presenting "Dd"; Upstream-ID: 1470fce171c47b60bbc7ecd0fc717a442c2cfe65 --- ssh-agent.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ssh-agent.1') diff --git a/ssh-agent.1 b/ssh-agent.1 index dabc5c46b..c4b50bbdf 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.61 2015/11/15 22:26:49 jcs Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.62 2015/11/15 23:54:15 jmc Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -43,7 +43,7 @@ .Sh SYNOPSIS .Nm ssh-agent .Op Fl c | s -.Op Fl Dd +.Op Fl \&Dd .Op Fl a Ar bind_address .Op Fl E Ar fingerprint_hash .Op Fl t Ar life -- cgit v1.2.3 From d7698edca3667ffacae051582028eb3971928edc Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 9 Feb 2014 16:10:13 +0000 Subject: Document consequences of ssh-agent being setgid in ssh-agent(1) Bug-Debian: http://bugs.debian.org/711623 Forwarded: no Last-Update: 2013-06-08 Patch-Name: ssh-agent-setgid.patch --- ssh-agent.1 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'ssh-agent.1') diff --git a/ssh-agent.1 b/ssh-agent.1 index c4b50bbdf..2fe22013a 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 @@ -193,6 +193,21 @@ environment variable holds the agent's process ID. .Pp The agent exits automatically when the command given on the command line terminates. +.Pp +In Debian, +.Nm +is installed with the set-group-id bit set, to prevent +.Xr ptrace 2 +attacks retrieving private key material. +This has the side-effect of causing the run-time linker to remove certain +environment variables which might have security implications for set-id +programs, including +.Ev LD_PRELOAD , +.Ev LD_LIBRARY_PATH , +and +.Ev TMPDIR . +If you need to set any of these environment variables, you will need to do +so in the program executed by ssh-agent. .Sh FILES .Bl -tag -width Ds .It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt -- cgit v1.2.3