[openssh-commits] [openssh] 07/10: upstream commit

git+noreply at mindrot.org git+noreply at mindrot.org
Mon Nov 16 11:31:56 AEDT 2015


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit f361df474c49a097bfcf16d1b7b5c36fcd844b4b
Author: jcs at openbsd.org <jcs at openbsd.org>
Date:   Sun Nov 15 22:26:49 2015 +0000

    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(-)

diff --git a/readconf.c b/readconf.c
index c062433..0a38091 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 <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, 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 6d6927f..2034bfd 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 <ylo at cs.hut.fi>
@@ -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 5a521cb..dabc5c4 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 <ylo at cs.hut.fi>
 .\" Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, 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 c4b7250..5b35b6c 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 39cf932..e6673b1 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 c9f88e0..19d393f 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 <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, 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 0ea6e99..cf1851a 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 016abbc..bfc523b 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 <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, 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 3ab686e..69d0bee 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;

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list