diff options
author | jcs@openbsd.org <jcs@openbsd.org> | 2015-11-15 22:26:49 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2015-11-16 11:31:39 +1100 |
commit | f361df474c49a097bfcf16d1b7b5c36fcd844b4b (patch) | |
tree | 493beb15e73f9b57f42244e8c927bdf75480188f | |
parent | d87063d9baf5479b6e813d47dfb694a97df6f6f5 (diff) |
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
-rw-r--r-- | readconf.c | 22 | ||||
-rw-r--r-- | readconf.h | 4 | ||||
-rw-r--r-- | ssh-agent.1 | 11 | ||||
-rw-r--r-- | ssh.1 | 9 | ||||
-rw-r--r-- | ssh_config.5 | 37 | ||||
-rw-r--r-- | sshconnect.c | 30 | ||||
-rw-r--r-- | sshconnect.h | 4 | ||||
-rw-r--r-- | sshconnect1.c | 15 | ||||
-rw-r--r-- | sshconnect2.c | 35 |
9 files changed, 137 insertions, 30 deletions
diff --git a/readconf.c b/readconf.c index c062433ce..0a380913f 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.245 2015/10/27 08:54:52 djm Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.246 2015/11/15 22:26:49 jcs Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -135,7 +135,7 @@ typedef enum { | |||
135 | oPasswordAuthentication, oRSAAuthentication, | 135 | oPasswordAuthentication, oRSAAuthentication, |
136 | oChallengeResponseAuthentication, oXAuthLocation, | 136 | oChallengeResponseAuthentication, oXAuthLocation, |
137 | oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, | 137 | oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, |
138 | oCertificateFile, | 138 | oCertificateFile, oAddKeysToAgent, |
139 | oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, | 139 | oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, |
140 | oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, | 140 | oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, |
141 | oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, | 141 | oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, |
@@ -204,6 +204,7 @@ static struct { | |||
204 | { "identityfile2", oIdentityFile }, /* obsolete */ | 204 | { "identityfile2", oIdentityFile }, /* obsolete */ |
205 | { "identitiesonly", oIdentitiesOnly }, | 205 | { "identitiesonly", oIdentitiesOnly }, |
206 | { "certificatefile", oCertificateFile }, | 206 | { "certificatefile", oCertificateFile }, |
207 | { "addkeystoagent", oAddKeysToAgent }, | ||
207 | { "hostname", oHostName }, | 208 | { "hostname", oHostName }, |
208 | { "hostkeyalias", oHostKeyAlias }, | 209 | { "hostkeyalias", oHostKeyAlias }, |
209 | { "proxycommand", oProxyCommand }, | 210 | { "proxycommand", oProxyCommand }, |
@@ -712,6 +713,15 @@ static const struct multistate multistate_yesnoask[] = { | |||
712 | { "ask", 2 }, | 713 | { "ask", 2 }, |
713 | { NULL, -1 } | 714 | { NULL, -1 } |
714 | }; | 715 | }; |
716 | static const struct multistate multistate_yesnoaskconfirm[] = { | ||
717 | { "true", 1 }, | ||
718 | { "false", 0 }, | ||
719 | { "yes", 1 }, | ||
720 | { "no", 0 }, | ||
721 | { "ask", 2 }, | ||
722 | { "confirm", 3 }, | ||
723 | { NULL, -1 } | ||
724 | }; | ||
715 | static const struct multistate multistate_addressfamily[] = { | 725 | static const struct multistate multistate_addressfamily[] = { |
716 | { "inet", AF_INET }, | 726 | { "inet", AF_INET }, |
717 | { "inet6", AF_INET6 }, | 727 | { "inet6", AF_INET6 }, |
@@ -1533,6 +1543,11 @@ parse_keytypes: | |||
1533 | charptr = &options->pubkey_key_types; | 1543 | charptr = &options->pubkey_key_types; |
1534 | goto parse_keytypes; | 1544 | goto parse_keytypes; |
1535 | 1545 | ||
1546 | case oAddKeysToAgent: | ||
1547 | intptr = &options->add_keys_to_agent; | ||
1548 | multistate_ptr = multistate_yesnoaskconfirm; | ||
1549 | goto parse_multistate; | ||
1550 | |||
1536 | case oDeprecated: | 1551 | case oDeprecated: |
1537 | debug("%s line %d: Deprecated option \"%s\"", | 1552 | debug("%s line %d: Deprecated option \"%s\"", |
1538 | filename, linenum, keyword); | 1553 | filename, linenum, keyword); |
@@ -1699,6 +1714,7 @@ initialize_options(Options * options) | |||
1699 | options->local_command = NULL; | 1714 | options->local_command = NULL; |
1700 | options->permit_local_command = -1; | 1715 | options->permit_local_command = -1; |
1701 | options->use_roaming = -1; | 1716 | options->use_roaming = -1; |
1717 | options->add_keys_to_agent = -1; | ||
1702 | options->visual_host_key = -1; | 1718 | options->visual_host_key = -1; |
1703 | options->ip_qos_interactive = -1; | 1719 | options->ip_qos_interactive = -1; |
1704 | options->ip_qos_bulk = -1; | 1720 | options->ip_qos_bulk = -1; |
@@ -1803,6 +1819,8 @@ fill_default_options(Options * options) | |||
1803 | /* options->hostkeyalgorithms, default set in myproposals.h */ | 1819 | /* options->hostkeyalgorithms, default set in myproposals.h */ |
1804 | if (options->protocol == SSH_PROTO_UNKNOWN) | 1820 | if (options->protocol == SSH_PROTO_UNKNOWN) |
1805 | options->protocol = SSH_PROTO_2; | 1821 | options->protocol = SSH_PROTO_2; |
1822 | if (options->add_keys_to_agent == -1) | ||
1823 | options->add_keys_to_agent = 0; | ||
1806 | if (options->num_identity_files == 0) { | 1824 | if (options->num_identity_files == 0) { |
1807 | if (options->protocol & SSH_PROTO_1) { | 1825 | if (options->protocol & SSH_PROTO_1) { |
1808 | add_identity_file(options, "~/", | 1826 | 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 @@ | |||
1 | /* $OpenBSD: readconf.h,v 1.111 2015/09/24 06:15:11 djm Exp $ */ | 1 | /* $OpenBSD: readconf.h,v 1.112 2015/11/15 22:26:49 jcs Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -100,6 +100,8 @@ typedef struct { | |||
100 | int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; | 100 | int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; |
101 | struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; | 101 | struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; |
102 | 102 | ||
103 | int add_keys_to_agent; | ||
104 | |||
103 | /* Local TCP/IP forward requests. */ | 105 | /* Local TCP/IP forward requests. */ |
104 | int num_local_forwards; | 106 | int num_local_forwards; |
105 | struct Forward *local_forwards; | 107 | 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 @@ | |||
1 | .\" $OpenBSD: ssh-agent.1,v 1.60 2015/11/05 09:48:05 jmc Exp $ | 1 | .\" $OpenBSD: ssh-agent.1,v 1.61 2015/11/15 22:26:49 jcs Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -34,7 +34,7 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .Dd $Mdocdate: November 5 2015 $ | 37 | .Dd $Mdocdate: November 15 2015 $ |
38 | .Dt SSH-AGENT 1 | 38 | .Dt SSH-AGENT 1 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -66,6 +66,13 @@ machines using | |||
66 | .Pp | 66 | .Pp |
67 | The agent initially does not have any private keys. | 67 | The agent initially does not have any private keys. |
68 | Keys are added using | 68 | Keys are added using |
69 | .Xr ssh 1 | ||
70 | (see | ||
71 | .Cm AddKeysToAgent | ||
72 | in | ||
73 | .Xr ssh_config 5 | ||
74 | for details) | ||
75 | or | ||
69 | .Xr ssh-add 1 . | 76 | .Xr ssh-add 1 . |
70 | Multiple identities may be stored in | 77 | Multiple identities may be stored in |
71 | .Nm | 78 | .Nm |
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: ssh.1,v 1.365 2015/11/06 00:31:41 mmcc Exp $ | 36 | .\" $OpenBSD: ssh.1,v 1.366 2015/11/15 22:26:49 jcs Exp $ |
37 | .Dd $Mdocdate: November 6 2015 $ | 37 | .Dd $Mdocdate: November 15 2015 $ |
38 | .Dt SSH 1 | 38 | .Dt SSH 1 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -462,6 +462,7 @@ For full details of the options listed below, and their possible values, see | |||
462 | .Xr ssh_config 5 . | 462 | .Xr ssh_config 5 . |
463 | .Pp | 463 | .Pp |
464 | .Bl -tag -width Ds -offset indent -compact | 464 | .Bl -tag -width Ds -offset indent -compact |
465 | .It AddKeysToAgent | ||
465 | .It AddressFamily | 466 | .It AddressFamily |
466 | .It BatchMode | 467 | .It BatchMode |
467 | .It BindAddress | 468 | .It BindAddress |
@@ -926,6 +927,10 @@ The most convenient way to use public key or certificate authentication | |||
926 | may be with an authentication agent. | 927 | may be with an authentication agent. |
927 | See | 928 | See |
928 | .Xr ssh-agent 1 | 929 | .Xr ssh-agent 1 |
930 | and (optionally) the | ||
931 | .Cm AddKeysToAgent | ||
932 | directive in | ||
933 | .Xr ssh_config 5 | ||
929 | for more information. | 934 | for more information. |
930 | .Pp | 935 | .Pp |
931 | Challenge-response authentication works as follows: | 936 | 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 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: ssh_config.5,v 1.221 2015/09/24 06:15:11 djm Exp $ | 36 | .\" $OpenBSD: ssh_config.5,v 1.222 2015/11/15 22:26:49 jcs Exp $ |
37 | .Dd $Mdocdate: September 24 2015 $ | 37 | .Dd $Mdocdate: November 15 2015 $ |
38 | .Dt SSH_CONFIG 5 | 38 | .Dt SSH_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -221,6 +221,39 @@ keyword matches against the name of the local user running | |||
221 | (this keyword may be useful in system-wide | 221 | (this keyword may be useful in system-wide |
222 | .Nm | 222 | .Nm |
223 | files). | 223 | files). |
224 | .It Cm AddKeysToAgent | ||
225 | Specifies whether keys should be automatically added to a running | ||
226 | .Xr ssh-agent 5 . | ||
227 | If this option is set to | ||
228 | .Dq yes | ||
229 | and a key is loaded from a file, the key and its passphrase are added to | ||
230 | the agent with the default lifetime, as if by | ||
231 | .Xr ssh-add 1 . | ||
232 | If this option is set to | ||
233 | .Dq ask , | ||
234 | .Nm ssh | ||
235 | will require confirmation using the | ||
236 | .Ev SSH_ASKPASS | ||
237 | program before adding a key (see | ||
238 | .Xr ssh-add 1 | ||
239 | for details). | ||
240 | If this option is set to | ||
241 | .Dq confirm , | ||
242 | each use of the key must be confirmed, as if the | ||
243 | .Fl c | ||
244 | option was specified to | ||
245 | .Xr ssh-add 1 . | ||
246 | If this option is set to | ||
247 | .Dq no , | ||
248 | no keys are added to the agent. | ||
249 | The argument must be | ||
250 | .Dq yes , | ||
251 | .Dq confirm , | ||
252 | .Dq ask , | ||
253 | or | ||
254 | .Dq no . | ||
255 | The default is | ||
256 | .Dq no . | ||
224 | .It Cm AddressFamily | 257 | .It Cm AddressFamily |
225 | Specifies which address family to use when connecting. | 258 | Specifies which address family to use when connecting. |
226 | Valid arguments are | 259 | 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 @@ | |||
1 | /* $OpenBSD: sshconnect.c,v 1.265 2015/09/04 04:55:24 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect.c,v 1.266 2015/11/15 22:26:49 jcs Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -65,6 +65,7 @@ | |||
65 | #include "version.h" | 65 | #include "version.h" |
66 | #include "authfile.h" | 66 | #include "authfile.h" |
67 | #include "ssherr.h" | 67 | #include "ssherr.h" |
68 | #include "authfd.h" | ||
68 | 69 | ||
69 | char *client_version_string = NULL; | 70 | char *client_version_string = NULL; |
70 | char *server_version_string = NULL; | 71 | char *server_version_string = NULL; |
@@ -1487,3 +1488,30 @@ ssh_local_cmd(const char *args) | |||
1487 | 1488 | ||
1488 | return (WEXITSTATUS(status)); | 1489 | return (WEXITSTATUS(status)); |
1489 | } | 1490 | } |
1491 | |||
1492 | void | ||
1493 | maybe_add_key_to_agent(char *authfile, Key *private, char *comment, | ||
1494 | char *passphrase) | ||
1495 | { | ||
1496 | int auth_sock = -1, r; | ||
1497 | |||
1498 | if (options.add_keys_to_agent == 0) | ||
1499 | return; | ||
1500 | |||
1501 | if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { | ||
1502 | debug3("no authentication agent, not adding key"); | ||
1503 | return; | ||
1504 | } | ||
1505 | |||
1506 | if (options.add_keys_to_agent == 2 && | ||
1507 | !ask_permission("Add key %s (%s) to agent?", authfile, comment)) { | ||
1508 | debug3("user denied adding this key"); | ||
1509 | return; | ||
1510 | } | ||
1511 | |||
1512 | if ((r = ssh_add_identity_constrained(auth_sock, private, comment, 0, | ||
1513 | (options.add_keys_to_agent == 3))) == 0) | ||
1514 | debug("identity added to agent: %s", authfile); | ||
1515 | else | ||
1516 | debug("could not add identity to agent: %s (%d)", authfile, r); | ||
1517 | } | ||
diff --git a/sshconnect.h b/sshconnect.h index 0ea6e99f6..cf1851a95 100644 --- a/sshconnect.h +++ b/sshconnect.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect.h,v 1.28 2013/10/16 02:31:47 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect.h,v 1.29 2015/11/15 22:26:49 jcs Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -55,6 +55,8 @@ void ssh_userauth2(const char *, const char *, char *, Sensitive *); | |||
55 | void ssh_put_password(char *); | 55 | void ssh_put_password(char *); |
56 | int ssh_local_cmd(const char *); | 56 | int ssh_local_cmd(const char *); |
57 | 57 | ||
58 | void maybe_add_key_to_agent(char *, Key *, char *, char *); | ||
59 | |||
58 | /* | 60 | /* |
59 | * Macros to raise/lower permissions. | 61 | * Macros to raise/lower permissions. |
60 | */ | 62 | */ |
diff --git a/sshconnect1.c b/sshconnect1.c index 016abbce5..bfc523bde 100644 --- a/sshconnect1.c +++ b/sshconnect1.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect1.c,v 1.77 2015/01/14 20:05:27 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect1.c,v 1.78 2015/11/15 22:26:49 jcs Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -221,7 +221,7 @@ try_rsa_authentication(int idx) | |||
221 | { | 221 | { |
222 | BIGNUM *challenge; | 222 | BIGNUM *challenge; |
223 | Key *public, *private; | 223 | Key *public, *private; |
224 | char buf[300], *passphrase, *comment, *authfile; | 224 | char buf[300], *passphrase = NULL, *comment, *authfile; |
225 | int i, perm_ok = 1, type, quit; | 225 | int i, perm_ok = 1, type, quit; |
226 | 226 | ||
227 | public = options.identity_keys[idx]; | 227 | public = options.identity_keys[idx]; |
@@ -283,13 +283,20 @@ try_rsa_authentication(int idx) | |||
283 | debug2("no passphrase given, try next key"); | 283 | debug2("no passphrase given, try next key"); |
284 | quit = 1; | 284 | quit = 1; |
285 | } | 285 | } |
286 | explicit_bzero(passphrase, strlen(passphrase)); | ||
287 | free(passphrase); | ||
288 | if (private != NULL || quit) | 286 | if (private != NULL || quit) |
289 | break; | 287 | break; |
290 | debug2("bad passphrase given, try again..."); | 288 | debug2("bad passphrase given, try again..."); |
291 | } | 289 | } |
292 | } | 290 | } |
291 | |||
292 | if (private != NULL) | ||
293 | maybe_add_key_to_agent(authfile, private, comment, passphrase); | ||
294 | |||
295 | if (passphrase != NULL) { | ||
296 | explicit_bzero(passphrase, strlen(passphrase)); | ||
297 | free(passphrase); | ||
298 | } | ||
299 | |||
293 | /* We no longer need the comment. */ | 300 | /* We no longer need the comment. */ |
294 | free(comment); | 301 | free(comment); |
295 | 302 | ||
diff --git a/sshconnect2.c b/sshconnect2.c index 3ab686e86..69d0bee4e 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.228 2015/10/13 16:15:21 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.229 2015/11/15 22:26:49 jcs Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
@@ -313,7 +313,7 @@ void userauth(Authctxt *, char *); | |||
313 | static int sign_and_send_pubkey(Authctxt *, Identity *); | 313 | static int sign_and_send_pubkey(Authctxt *, Identity *); |
314 | static void pubkey_prepare(Authctxt *); | 314 | static void pubkey_prepare(Authctxt *); |
315 | static void pubkey_cleanup(Authctxt *); | 315 | static void pubkey_cleanup(Authctxt *); |
316 | static Key *load_identity_file(char *, int); | 316 | static Key *load_identity_file(Identity *); |
317 | 317 | ||
318 | static Authmethod *authmethod_get(char *authlist); | 318 | static Authmethod *authmethod_get(char *authlist); |
319 | static Authmethod *authmethod_lookup(const char *name); | 319 | static Authmethod *authmethod_lookup(const char *name); |
@@ -990,7 +990,7 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, | |||
990 | return (sshkey_sign(id->key, sigp, lenp, data, datalen, | 990 | return (sshkey_sign(id->key, sigp, lenp, data, datalen, |
991 | compat)); | 991 | compat)); |
992 | /* load the private key from the file */ | 992 | /* load the private key from the file */ |
993 | if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL) | 993 | if ((prv = load_identity_file(id)) == NULL) |
994 | return (-1); /* XXX return decent error code */ | 994 | return (-1); /* XXX return decent error code */ |
995 | ret = sshkey_sign(prv, sigp, lenp, data, datalen, compat); | 995 | ret = sshkey_sign(prv, sigp, lenp, data, datalen, compat); |
996 | sshkey_free(prv); | 996 | sshkey_free(prv); |
@@ -1147,20 +1147,20 @@ send_pubkey_test(Authctxt *authctxt, Identity *id) | |||
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | static Key * | 1149 | static Key * |
1150 | load_identity_file(char *filename, int userprovided) | 1150 | load_identity_file(Identity *id) |
1151 | { | 1151 | { |
1152 | Key *private; | 1152 | Key *private; |
1153 | char prompt[300], *passphrase; | 1153 | char prompt[300], *passphrase, *comment; |
1154 | int r, perm_ok = 0, quit = 0, i; | 1154 | int r, perm_ok = 0, quit = 0, i; |
1155 | struct stat st; | 1155 | struct stat st; |
1156 | 1156 | ||
1157 | if (stat(filename, &st) < 0) { | 1157 | if (stat(id->filename, &st) < 0) { |
1158 | (userprovided ? logit : debug3)("no such identity: %s: %s", | 1158 | (id->userprovided ? logit : debug3)("no such identity: %s: %s", |
1159 | filename, strerror(errno)); | 1159 | id->filename, strerror(errno)); |
1160 | return NULL; | 1160 | return NULL; |
1161 | } | 1161 | } |
1162 | snprintf(prompt, sizeof prompt, | 1162 | snprintf(prompt, sizeof prompt, |
1163 | "Enter passphrase for key '%.100s': ", filename); | 1163 | "Enter passphrase for key '%.100s': ", id->filename); |
1164 | for (i = 0; i <= options.number_of_password_prompts; i++) { | 1164 | for (i = 0; i <= options.number_of_password_prompts; i++) { |
1165 | if (i == 0) | 1165 | if (i == 0) |
1166 | passphrase = ""; | 1166 | passphrase = ""; |
@@ -1172,8 +1172,8 @@ load_identity_file(char *filename, int userprovided) | |||
1172 | break; | 1172 | break; |
1173 | } | 1173 | } |
1174 | } | 1174 | } |
1175 | switch ((r = sshkey_load_private_type(KEY_UNSPEC, filename, | 1175 | switch ((r = sshkey_load_private_type(KEY_UNSPEC, id->filename, |
1176 | passphrase, &private, NULL, &perm_ok))) { | 1176 | passphrase, &private, &comment, &perm_ok))) { |
1177 | case 0: | 1177 | case 0: |
1178 | break; | 1178 | break; |
1179 | case SSH_ERR_KEY_WRONG_PASSPHRASE: | 1179 | case SSH_ERR_KEY_WRONG_PASSPHRASE: |
@@ -1187,20 +1187,26 @@ load_identity_file(char *filename, int userprovided) | |||
1187 | case SSH_ERR_SYSTEM_ERROR: | 1187 | case SSH_ERR_SYSTEM_ERROR: |
1188 | if (errno == ENOENT) { | 1188 | if (errno == ENOENT) { |
1189 | debug2("Load key \"%s\": %s", | 1189 | debug2("Load key \"%s\": %s", |
1190 | filename, ssh_err(r)); | 1190 | id->filename, ssh_err(r)); |
1191 | quit = 1; | 1191 | quit = 1; |
1192 | break; | 1192 | break; |
1193 | } | 1193 | } |
1194 | /* FALLTHROUGH */ | 1194 | /* FALLTHROUGH */ |
1195 | default: | 1195 | default: |
1196 | error("Load key \"%s\": %s", filename, ssh_err(r)); | 1196 | error("Load key \"%s\": %s", id->filename, ssh_err(r)); |
1197 | quit = 1; | 1197 | quit = 1; |
1198 | break; | 1198 | break; |
1199 | } | 1199 | } |
1200 | if (!quit && private != NULL && !id->agent_fd && | ||
1201 | !(id->key && id->isprivate)) | ||
1202 | maybe_add_key_to_agent(id->filename, private, comment, | ||
1203 | passphrase); | ||
1200 | if (i > 0) { | 1204 | if (i > 0) { |
1201 | explicit_bzero(passphrase, strlen(passphrase)); | 1205 | explicit_bzero(passphrase, strlen(passphrase)); |
1202 | free(passphrase); | 1206 | free(passphrase); |
1203 | } | 1207 | } |
1208 | if (comment) | ||
1209 | free(comment); | ||
1204 | if (private != NULL || quit) | 1210 | if (private != NULL || quit) |
1205 | break; | 1211 | break; |
1206 | } | 1212 | } |
@@ -1403,8 +1409,7 @@ userauth_pubkey(Authctxt *authctxt) | |||
1403 | } | 1409 | } |
1404 | } else { | 1410 | } else { |
1405 | debug("Trying private key: %s", id->filename); | 1411 | debug("Trying private key: %s", id->filename); |
1406 | id->key = load_identity_file(id->filename, | 1412 | id->key = load_identity_file(id); |
1407 | id->userprovided); | ||
1408 | if (id->key != NULL) { | 1413 | if (id->key != NULL) { |
1409 | if (try_identity(id)) { | 1414 | if (try_identity(id)) { |
1410 | id->isprivate = 1; | 1415 | id->isprivate = 1; |