Bugzilla – Attachment 1780 Details for
Bug 1699
[patch] Enhance SSH to automatically add keys to ssh-agent
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
[patch] Automatically add keys to ssh-agent(1)
addkeystoagent.patch (text/plain), 22.03 KB, created by
Joachim Schipper
on 2010-01-19 11:25:43 AEDT
(
hide
)
Description:
[patch] Automatically add keys to ssh-agent(1)
Filename:
MIME Type:
Creator:
Joachim Schipper
Created:
2010-01-19 11:25:43 AEDT
Size:
22.03 KB
patch
obsolete
>A quick overview of the patch: > >readconf.c: implement option; we want to load SSH1 files even if we are only >using SSH2 (and vice versa), or AddKeysToAgent behaves oddly (i.e. doesn't add >some keys). > >readconf.h: trivial > >sshconnect2.c: merge identity_sign() into sign_and_send_pubkey(), and call >add_keys_to_agent() from there and from userauth_pubkey() (i.e. from all >callers of load_identity_file()). Make load_identity_file() return the >passphrase used and set the comment. Make pubkey_prepare() iterate over SSH1 >agent keys (otherwise, we'd ask whether the user wants to add keys already in >the agent). > >sshconnect1.c: try_agent_authentication() does not open/close the connection >anymore, since we need it immediately thereafter. The other changes are >straightforward adaptions of the changes to sshconnect2.c. > >ssh-agent.1: reference new option in ssh_config(5) > >ssh.1: reference new option in ssh_config(5) > >ssh_config.5: add the above quote. > >Index: readconf.c >=================================================================== >RCS file: /usr/obsd-repos//src/usr.bin/ssh/readconf.c,v >retrieving revision 1.182 >diff -u -p -r1.182 readconf.c >--- readconf.c 9 Jan 2010 23:04:13 -0000 1.182 >+++ readconf.c 18 Jan 2010 23:50:40 -0000 >@@ -128,7 +128,7 @@ typedef enum { > oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, > oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, > oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, >- oDeprecated, oUnsupported >+ oAddKeysToAgent, oDeprecated, oUnsupported > } OpCodes; > > /* Textual representations of the tokens. */ >@@ -232,6 +232,7 @@ static struct { > #else > { "zeroknowledgepasswordauthentication", oUnsupported }, > #endif >+ { "addkeystoagent", oAddKeysToAgent }, > > { NULL, oBadOption } > }; >@@ -914,6 +915,28 @@ parse_int: > intptr = &options->use_roaming; > goto parse_flag; > >+ case oAddKeysToAgent: >+ intptr = &options->add_keys_to_agent; >+ arg = strdelim(&s); >+ if (!arg || *arg == '\0') >+ fatal("%.200s line %d: Missing yes/no/confirm/ask " >+ "argument.", filename, linenum); >+ value = 0; /* To avoid compiler warning... */ >+ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) >+ value = 1; >+ else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) >+ value = 0; >+ else if (strcmp(arg, "ask") == 0) >+ value = 2; >+ else if (strcmp(arg, "confirm") == 0) >+ value = 3; >+ else >+ fatal("%.200s line %d: Bad yes/no/confirm/ask " >+ "argument.", filename, linenum); >+ if (*activep && *intptr == -1) >+ *intptr = value; >+ break; >+ > case oDeprecated: > debug("%s line %d: Deprecated option \"%s\"", > filename, linenum, keyword); >@@ -1064,6 +1087,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->zero_knowledge_password_authentication = -1; > } >@@ -1138,15 +1162,19 @@ 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) { >+ if (options->protocol & SSH_PROTO_1 || >+ options->add_keys_to_agent != 0) { > len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; > options->identity_files[options->num_identity_files] = > xmalloc(len); > snprintf(options->identity_files[options->num_identity_files++], > len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); > } >- if (options->protocol & SSH_PROTO_2) { >+ if (options->protocol & SSH_PROTO_2 || >+ options->add_keys_to_agent != 0) { > len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; > options->identity_files[options->num_identity_files] = > xmalloc(len); >Index: readconf.h >=================================================================== >RCS file: /usr/obsd-repos//src/usr.bin/ssh/readconf.h,v >retrieving revision 1.81 >diff -u -p -r1.81 readconf.h >--- readconf.h 9 Jan 2010 23:04:13 -0000 1.81 >+++ readconf.h 18 Jan 2010 18:53:28 -0000 >@@ -125,6 +125,8 @@ typedef struct { > > int use_roaming; > >+ int add_keys_to_agent; >+ > } Options; > > #define SSHCTL_MASTER_NO 0 >Index: sshconnect2.c >=================================================================== >RCS file: /usr/obsd-repos//src/usr.bin/ssh/sshconnect2.c,v >retrieving revision 1.179 >diff -u -p -r1.179 sshconnect2.c >--- sshconnect2.c 13 Jan 2010 01:20:20 -0000 1.179 >+++ sshconnect2.c 18 Jan 2010 23:44:02 -0000 >@@ -178,6 +178,7 @@ struct identity { > AuthenticationConnection *ac; /* set if agent supports key */ > Key *key; /* public/private key */ > char *filename; /* comment for agent-only keys */ >+ char *comment; /* comment for other keys */ > int tried; > int isprivate; /* key points to the private key */ > }; >@@ -244,7 +245,8 @@ 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 *); >+static Key *load_identity_file(Identity *, char **); >+static void add_keys_to_agent(Authctxt *, char *); > > static Authmethod *authmethod_get(char *authlist); > static Authmethod *authmethod_lookup(const char *name); >@@ -1101,39 +1103,15 @@ input_userauth_jpake_server_confirm(int > #endif /* JPAKE */ > > static int >-identity_sign(Identity *id, u_char **sigp, u_int *lenp, >- u_char *data, u_int datalen) >-{ >- Key *prv; >- int ret; >- >- /* the agent supports this key */ >- if (id->ac) >- return (ssh_agent_sign(id->ac, id->key, sigp, lenp, >- data, datalen)); >- /* >- * we have already loaded the private key or >- * the private key is stored in external hardware >- */ >- if (id->isprivate || (id->key->flags & KEY_FLAG_EXT)) >- return (key_sign(id->key, sigp, lenp, data, datalen)); >- /* load the private key from the file */ >- if ((prv = load_identity_file(id->filename)) == NULL) >- return (-1); >- ret = key_sign(prv, sigp, lenp, data, datalen); >- key_free(prv); >- return (ret); >-} >- >-static int > sign_and_send_pubkey(Authctxt *authctxt, Identity *id) > { > Buffer b; > u_char *blob, *signature; > u_int bloblen, slen; > u_int skip = 0; >- int ret = -1; >- int have_sig = 1; >+ int sign_ok = -1, have_sig = 1; >+ Key *private; >+ char *passphrase; > > debug3("sign_and_send_pubkey"); > >@@ -1167,9 +1145,33 @@ sign_and_send_pubkey(Authctxt *authctxt, > buffer_put_string(&b, blob, bloblen); > > /* generate signature */ >- ret = identity_sign(id, &signature, &slen, >- buffer_ptr(&b), buffer_len(&b)); >- if (ret == -1) { >+ if (id->ac) { >+ /* the agent supports this key */ >+ sign_ok = ssh_agent_sign(id->ac, id->key, &signature, &slen, >+ buffer_ptr(&b), buffer_len(&b)); >+ } else if (id->isprivate || (id->key->flags & KEY_FLAG_EXT)) { >+ /* >+ * we have already loaded the private key or the private key is >+ * stored in external hardware >+ */ >+ sign_ok = key_sign(id->key, &signature, &slen, buffer_ptr(&b), >+ buffer_len(&b)); >+ } else { >+ /* load the private key from the file */ >+ private = load_identity_file(id, &passphrase); >+ if (private == NULL) >+ sign_ok = -1; >+ else { >+ sign_ok = key_sign(private, &signature, &slen, >+ buffer_ptr(&b), buffer_len(&b)); >+ >+ key_free(private); >+ >+ add_keys_to_agent(authctxt, passphrase); >+ } >+ } >+ >+ if (sign_ok == -1) { > xfree(blob); > buffer_free(&b); > return 0; >@@ -1240,38 +1242,44 @@ send_pubkey_test(Authctxt *authctxt, Ide > } > > static Key * >-load_identity_file(char *filename) >+load_identity_file(Identity *id, char **passphrase) > { > Key *private; >- char prompt[300], *passphrase; >+ char prompt[300]; > int perm_ok = 0, quit, i; > struct stat st; > >- if (stat(filename, &st) < 0) { >- debug3("no such identity: %s", filename); >+ if (stat(id->filename, &st) < 0) { >+ debug3("no such identity: %s", id->filename); > return NULL; > } >- private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok); >+ *passphrase = NULL; >+ private = key_load_private_type(KEY_UNSPEC, id->filename, "", >+ &id->comment, &perm_ok); > if (!perm_ok) > return NULL; > if (private == NULL) { > if (options.batch_mode) > 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++) { >- passphrase = read_passphrase(prompt, 0); >- if (strcmp(passphrase, "") != 0) { >+ *passphrase = read_passphrase(prompt, 0); >+ if (strcmp(*passphrase, "") != 0) { > private = key_load_private_type(KEY_UNSPEC, >- filename, passphrase, NULL, NULL); >+ id->filename, *passphrase, &id->comment, >+ NULL); > quit = 0; > } else { > debug2("no passphrase given, try next key"); > quit = 1; > } >- memset(passphrase, 0, strlen(passphrase)); >- xfree(passphrase); >- if (private != NULL || quit) >+ if (private != NULL) >+ break; >+ memset(*passphrase, 0, strlen(*passphrase)); >+ xfree(*passphrase); >+ *passphrase = NULL; >+ if (quit) > break; > debug2("bad passphrase given, try again..."); > } >@@ -1293,7 +1301,7 @@ pubkey_prepare(Authctxt *authctxt) > Key *key; > AuthenticationConnection *ac; > char *comment; >- int i, found; >+ int i, found, protocol; > > TAILQ_INIT(&agent); /* keys from the agent */ > TAILQ_INIT(&files); /* keys from the config file */ >@@ -1303,8 +1311,6 @@ pubkey_prepare(Authctxt *authctxt) > /* list of keys stored in the filesystem */ > for (i = 0; i < options.num_identity_files; i++) { > key = options.identity_keys[i]; >- if (key && key->type == KEY_RSA1) >- continue; > options.identity_keys[i] = NULL; > id = xcalloc(1, sizeof(*id)); > id->key = key; >@@ -1313,9 +1319,15 @@ pubkey_prepare(Authctxt *authctxt) > } > /* list of keys supported by the agent */ > if ((ac = ssh_get_authentication_connection())) { >- for (key = ssh_get_first_identity(ac, &comment, 2); >- key != NULL; >- key = ssh_get_next_identity(ac, &comment, 2)) { >+ for (key = ssh_get_first_identity(ac, &comment, protocol = 2); >+ key != NULL || protocol == 2; >+ key = ssh_get_next_identity(ac, &comment, protocol)) { >+ if (key == NULL && options.add_keys_to_agent != 0) { >+ protocol = 1; >+ key = ssh_get_first_identity(ac, &comment, protocol); >+ } >+ if (key == NULL) >+ break; > found = 0; > TAILQ_FOREACH(id, &files, next) { > /* agent keys from the config file are preferred */ >@@ -1368,15 +1380,87 @@ pubkey_cleanup(Authctxt *authctxt) > key_free(id->key); > if (id->filename) > xfree(id->filename); >+ if (id->comment) >+ xfree(id->comment); > xfree(id); > } > } > >+static void >+add_keys_to_agent(Authctxt *authctxt, char *passphrase) >+{ >+ Identity *id; >+ Key *private; >+ int perm_ok; >+ struct stat st; >+ >+ if (options.add_keys_to_agent == 0) >+ goto done; >+ >+ if (authctxt->agent == NULL) { >+ debug3("no connection to agent, not adding keys"); >+ goto done; >+ } >+ >+ TAILQ_FOREACH(id, &authctxt->keys, next) { >+ if (id->ac) { >+ debug3("key already in agent: %s", id->filename); >+ continue; >+ } >+ >+ if (id->key && id->isprivate) { >+ debug3("using private key loaded previously"); >+ private = id->key; >+ } else { >+ /* Try loading key */ >+ if (stat(id->filename, &st) < 0) { >+ debug3("no such identity to add to agent: %s", >+ id->filename); >+ continue; >+ } >+ private = key_load_private(id->filename, "", >+ &id->comment); >+ if (private == NULL && passphrase != NULL) >+ private = key_load_private(id->filename, >+ passphrase, &id->comment); >+ if (private == NULL) { >+ debug3("bad passphrase for identity: %s", id->filename); >+ continue; >+ } >+ } >+ >+ if (options.add_keys_to_agent == 2 && >+ !ask_permission("Add key %s (%s) to agent?", id->filename, >+ id->comment)) { >+ debug3("user did not confirm adding this key"); >+ key_free(private); >+ continue; >+ } >+ >+ if (ssh_add_identity_constrained(authctxt->agent, private, >+ id->comment, 0, options.add_keys_to_agent == 3)) >+ debug("Identity added to agent: %s (%s)", >+ id->filename, id->comment); >+ else >+ debug("Could not add identity: %s", id->filename); >+ >+ if (!id->isprivate || private != id->key) >+ key_free(private); >+ } >+ >+done: >+ if (passphrase != NULL) { >+ memset(passphrase, 0, strlen(passphrase)); >+ xfree(passphrase); >+ } >+} >+ > int > userauth_pubkey(Authctxt *authctxt) > { > Identity *id; > int sent = 0; >+ char *passphrase; > > while ((id = TAILQ_FIRST(&authctxt->keys))) { > if (id->tried++) >@@ -1394,9 +1478,10 @@ userauth_pubkey(Authctxt *authctxt) > sent = send_pubkey_test(authctxt, id); > } else if (id->key == NULL) { > debug("Trying private key: %s", id->filename); >- id->key = load_identity_file(id->filename); >+ id->key = load_identity_file(id, &passphrase); > if (id->key != NULL) { > id->isprivate = 1; >+ add_keys_to_agent(authctxt, passphrase); > sent = sign_and_send_pubkey(authctxt, id); > key_free(id->key); > id->key = NULL; >Index: sshconnect1.c >=================================================================== >RCS file: /usr/obsd-repos//src/usr.bin/ssh/sshconnect1.c,v >retrieving revision 1.70 >diff -u -p -r1.70 sshconnect1.c >--- sshconnect1.c 6 Nov 2006 21:25:28 -0000 1.70 >+++ sshconnect1.c 18 Jan 2010 23:27:01 -0000 >@@ -15,6 +15,7 @@ > > #include <sys/types.h> > #include <sys/socket.h> >+#include <sys/stat.h> > > #include <openssl/bn.h> > #include <openssl/md5.h> >@@ -57,21 +58,15 @@ extern char *__progname; > * authenticate using the agent. > */ > static int >-try_agent_authentication(void) >+try_agent_authentication(AuthenticationConnection *auth) > { > int type; > char *comment; >- AuthenticationConnection *auth; > u_char response[16]; > u_int i; > Key *key; > BIGNUM *challenge; > >- /* Get connection to the agent. */ >- auth = ssh_get_authentication_connection(); >- if (!auth) >- return 0; >- > if ((challenge = BN_new()) == NULL) > fatal("try_agent_authentication: BN_new failed"); > /* Loop through identities served by the agent. */ >@@ -134,7 +129,6 @@ try_agent_authentication(void) > > /* The server returns success if it accepted the authentication. */ > if (type == SSH_SMSG_SUCCESS) { >- ssh_close_authentication_connection(auth); > BN_clear_free(challenge); > debug("RSA authentication accepted by server."); > return 1; >@@ -144,7 +138,6 @@ try_agent_authentication(void) > packet_disconnect("Protocol error waiting RSA auth response: %d", > type); > } >- ssh_close_authentication_connection(auth); > BN_clear_free(challenge); > debug("RSA authentication using agent refused."); > return 0; >@@ -200,11 +193,11 @@ respond_to_rsa_challenge(BIGNUM * challe > * the user using it. > */ > static int >-try_rsa_authentication(int idx) >+try_rsa_authentication(int idx, char **passphrase) > { > BIGNUM *challenge; > Key *public, *private; >- char buf[300], *passphrase, *comment, *authfile; >+ char buf[300], *comment, *authfile; > int i, perm_ok = 1, type, quit; > > public = options.identity_keys[idx]; >@@ -248,6 +241,7 @@ try_rsa_authentication(int idx) > * load the private key. Try first with empty passphrase; if it > * fails, ask for a passphrase. > */ >+ *passphrase = NULL; > if (public->flags & KEY_FLAG_EXT) > private = public; > else >@@ -257,18 +251,20 @@ try_rsa_authentication(int idx) > snprintf(buf, sizeof(buf), > "Enter passphrase for RSA key '%.100s': ", comment); > for (i = 0; i < options.number_of_password_prompts; i++) { >- passphrase = read_passphrase(buf, 0); >- if (strcmp(passphrase, "") != 0) { >+ *passphrase = read_passphrase(buf, 0); >+ if (strcmp(*passphrase, "") != 0) { > private = key_load_private_type(KEY_RSA1, >- authfile, passphrase, NULL, NULL); >+ authfile, *passphrase, NULL, NULL); > quit = 0; > } else { > debug2("no passphrase given, try next key"); > quit = 1; > } >- memset(passphrase, 0, strlen(passphrase)); >- xfree(passphrase); >- if (private != NULL || quit) >+ if (private != NULL) >+ break; >+ memset(*passphrase, 0, strlen(*passphrase)); >+ xfree(*passphrase); >+ if (quit) > break; > debug2("bad passphrase given, try again..."); > } >@@ -669,7 +665,11 @@ void > ssh_userauth1(const char *local_user, const char *server_user, char *host, > Sensitive *sensitive) > { >- int i, type; >+ int i, type, protocol; >+ AuthenticationConnection *auth = NULL; >+ char *passphrase, *comment; >+ struct stat st; >+ Key *private, *key; > > if (supported_authentications == 0) > fatal("ssh_userauth1: server supports no auth methods"); >@@ -715,16 +715,99 @@ ssh_userauth1(const char *local_user, co > * agent is tried first because no passphrase is needed for > * it, whereas identity files may require passphrases. > */ >- if (try_agent_authentication()) >+ auth = ssh_get_authentication_connection(); >+ if (auth != NULL && try_agent_authentication(auth)) > goto success; > > /* Try RSA authentication for each identity. */ > for (i = 0; i < options.num_identity_files; i++) > if (options.identity_keys[i] != NULL && > options.identity_keys[i]->type == KEY_RSA1 && >- try_rsa_authentication(i)) >- goto success; >+ try_rsa_authentication(i, &passphrase)) >+ break; >+ >+ if (i == options.num_identity_files) >+ goto try_next_method; >+ >+ if (options.add_keys_to_agent == 0) >+ goto clear_passphrase; >+ >+ if (auth == NULL) { >+ debug3("no connection to agent, not adding keys"); >+ goto clear_passphrase; >+ } >+ >+ for (i = 0; >+ i < options.num_identity_files; >+ i++) { >+ /* Try loading key */ >+ if (stat(options.identity_files[i], &st) < 0) { >+ debug3("no such identity to add to agent: %s", >+ options.identity_files[i]); >+ continue; >+ } >+ private = key_load_private(options.identity_files[i], >+ "", &comment); >+ if (private == NULL && passphrase != NULL) >+ private = key_load_private( >+ options.identity_files[i], passphrase, >+ &comment); >+ if (private == NULL) { >+ debug3("bad passphrase for identity: %s", >+ options.identity_files[i]); >+ continue; >+ } >+ >+ /* Check whether key is already in agent */ >+ for (key = ssh_get_first_identity(auth, &comment, >+ protocol = 2); >+ key != NULL || protocol == 2; >+ key = ssh_get_next_identity(auth, &comment, >+ protocol)) { >+ if (key == NULL) { >+ protocol = 1; >+ key = ssh_get_first_identity(auth, >+ &comment, protocol); >+ if (key == NULL) >+ break; >+ } >+ if (key_equal(private, key)) >+ break; >+ } >+ if (key != NULL) { >+ debug3("key already in agent: %s", >+ options.identity_files[i]); >+ continue; >+ } >+ >+ if (options.add_keys_to_agent == 2 && >+ !ask_permission("Add key %s (%s) to agent?", >+ options.identity_files[i], comment)) { >+ debug3("user did not confirm adding this key"); >+ key_free(private); >+ continue; >+ } >+ >+ if (ssh_add_identity_constrained(auth, private, comment, >+ 0, options.add_keys_to_agent == 3)) >+ debug("Identity now in agent: %s (%s)", >+ options.identity_files[i], comment); >+ else >+ debug("Could not add identity: %s", >+ options.identity_files[i]); >+ >+ key_free(private); >+ } >+ >+clear_passphrase: >+ if (passphrase != NULL) { >+ memset(passphrase, 0, strlen(passphrase)); >+ xfree(passphrase); >+ } >+ >+ goto success; > } >+try_next_method: > /* Try challenge response authentication if the server supports it. */ > if ((supported_authentications & (1 << SSH_AUTH_TIS)) && > options.challenge_response_authentication && !options.batch_mode) { >@@ -746,5 +829,6 @@ ssh_userauth1(const char *local_user, co > /* NOTREACHED */ > > success: >- return; /* need statement after label */ >+ if (auth) >+ ssh_close_authentication_connection(auth); > } >Index: ssh-agent.1 >=================================================================== >RCS file: /usr/obsd-repos//src/usr.bin/ssh/ssh-agent.1,v >retrieving revision 1.50 >diff -u -p -r1.50 ssh-agent.1 >--- ssh-agent.1 17 Jan 2010 21:49:09 -0000 1.50 >+++ ssh-agent.1 18 Jan 2010 23:29:25 -0000 >@@ -109,6 +109,13 @@ When the command dies, so does the agent > .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 . > When executed without arguments, > .Xr ssh-add 1 >Index: ssh.1 >=================================================================== >RCS file: /usr/obsd-repos//src/usr.bin/ssh/ssh.1,v >retrieving revision 1.290 >diff -u -p -r1.290 ssh.1 >--- ssh.1 11 Jan 2010 01:39:46 -0000 1.290 >+++ ssh.1 18 Jan 2010 23:29:33 -0000 >@@ -428,6 +428,7 @@ For full details of the options listed b > .Xr ssh_config 5 . > .Pp > .Bl -tag -width Ds -offset indent -compact >+.It AddKeysToAgent > .It AddressFamily > .It BatchMode > .It BindAddress >@@ -803,6 +804,10 @@ The most convenient way to use public ke > 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: >Index: ssh_config.5 >=================================================================== >RCS file: /usr/obsd-repos//src/usr.bin/ssh/ssh_config.5,v >retrieving revision 1.126 >diff -u -p -r1.126 ssh_config.5 >--- ssh_config.5 9 Jan 2010 23:04:13 -0000 1.126 >+++ ssh_config.5 19 Jan 2010 00:04:14 -0000 >@@ -116,6 +116,40 @@ a canonicalized host name before matchin > See > .Sx PATTERNS > for more information on patterns. >+.It Cm AddKeysToAgent >+Specifies whether keys should be automatically added to >+.Xr ssh-agent 5 >+(if running). >+If this option is set to >+.Dq yes >+and a key is loaded from a file, this key and all keys with either the same or >+an empty 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, exactly 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
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1699
: 1780