refactor agent client code

removed fatal()
buffer_ => sshbuf_
changed lookup of identies to return a fully-deserialised list of keys
removed AuthenticationConnection abstration; all operations now use plain socket
This commit is contained in:
Damien Miller
2012-03-26 23:10:27 +11:00
parent 67ce107972
commit 2c25fb2ede
9 changed files with 671 additions and 578 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -16,6 +16,33 @@
#ifndef AUTHFD_H
#define AUTHFD_H
/* List of identities returned by ssh_fetch_identitylist() */
struct ssh_identitylist {
size_t nkeys;
struct sshkey **keys;
char **comments;
};
int ssh_get_authentication_socket(int *fdp);
void ssh_close_authentication_socket(int sock);
int ssh_lock_agent(int sock, int lock, const char *password);
int ssh_fetch_identitylist(int sock, int version,
struct ssh_identitylist **idlp);
void ssh_free_identitylist(struct ssh_identitylist *idl);
int ssh_add_identity_constrained(int sock, struct sshkey *key,
const char *comment, u_int life, u_int confirm);
int ssh_remove_identity(int sock, struct sshkey *key);
int ssh_update_card(int sock, int add, const char *reader_id,
const char *pin, u_int life, u_int confirm);
int ssh_remove_all_identities(int sock, int version);
int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
u_char session_id[16], u_char response[16]);
int ssh_agent_sign(int sock, struct sshkey *key,
u_char **sigp, u_int *lenp,
u_char *data, u_int datalen, u_int compat);
/* Messages for the authentication agent connection. */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
@@ -60,34 +87,4 @@
#define SSH_AGENT_OLD_SIGNATURE 0x01
typedef struct {
int fd;
Buffer identities;
int howmany;
} AuthenticationConnection;
int ssh_agent_present(void);
int ssh_get_authentication_socket(void);
void ssh_close_authentication_socket(int);
AuthenticationConnection *ssh_get_authentication_connection(void);
void ssh_close_authentication_connection(AuthenticationConnection *);
int ssh_get_num_identities(AuthenticationConnection *, int);
struct sshkey *ssh_get_first_identity(AuthenticationConnection *, char **, int);
struct sshkey *ssh_get_next_identity(AuthenticationConnection *, char **, int);
int ssh_add_identity_constrained(AuthenticationConnection *,
struct sshkey *, const char *, u_int, u_int);
int ssh_remove_identity(AuthenticationConnection *, struct sshkey *);
int ssh_remove_all_identities(AuthenticationConnection *, int);
int ssh_lock_agent(AuthenticationConnection *, int, const char *);
int ssh_update_card(AuthenticationConnection *, int, const char *,
const char *, u_int, u_int);
int ssh_decrypt_challenge(AuthenticationConnection *, struct sshkey *,
BIGNUM *, u_char[16], u_int, u_char[16]);
int
ssh_agent_sign(AuthenticationConnection *, struct sshkey *,
u_char **, u_int *, u_char *, u_int, u_int);
#endif /* AUTHFD_H */

View File

@@ -1705,7 +1705,7 @@ static int
client_input_agent_open(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = NULL;
int remote_id, sock;
int remote_id, sock, r;
/* Read the remote channel number from the message. */
remote_id = ssh_packet_get_int(ssh);
@@ -1715,7 +1715,10 @@ client_input_agent_open(int type, u_int32_t seq, struct ssh *ssh)
* Get a connection to the local authentication agent (this may again
* get forwarded).
*/
sock = ssh_get_authentication_socket();
if ((r = ssh_get_authentication_socket(&sock)) != 0 &&
r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
/*
* If we could not connect the agent, send an error message back to
@@ -1723,7 +1726,7 @@ client_input_agent_open(int type, u_int32_t seq, struct ssh *ssh)
* because authentication forwarding is only enabled if we have an
* agent.
*/
if (sock >= 0) {
if (r == 0) {
c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
-1, 0, 0, 0, "authentication agent connection", 1);
c->remote_id = remote_id;
@@ -1814,7 +1817,7 @@ static Channel *
client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
{
Channel *c = NULL;
int sock;
int r, sock;
if (!options.forward_agent) {
error("Warning: ssh server tried agent forwarding.");
@@ -1822,9 +1825,12 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
"malicious server.");
return NULL;
}
sock = ssh_get_authentication_socket();
if (sock < 0)
if ((r = ssh_get_authentication_socket(&sock)) != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
return NULL;
}
c = channel_new("authentication agent connection",
SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,

View File

@@ -115,6 +115,10 @@ ssh_err(int n)
return "certificate does not match key";
case SSH_ERR_KEY_NOT_FOUND:
return "key not found";
case SSH_ERR_AGENT_NOT_PRESENT:
return "agent not present";
case SSH_ERR_AGENT_NO_IDENTITIES:
return "agent contains no identities";
default:
return "unknown error";
}

View File

@@ -67,6 +67,8 @@
#define SSH_ERR_KEY_BAD_PERMISSIONS -43
#define SSH_ERR_KEY_CERT_MISMATCH -44
#define SSH_ERR_KEY_NOT_FOUND -45
#define SSH_ERR_AGENT_NOT_PRESENT -46
#define SSH_ERR_AGENT_NO_IDENTITIES -47
/* Translate a numeric error code to a human-readable error string */

View File

@@ -91,7 +91,7 @@ clear_pass(void)
}
static int
delete_file(AuthenticationConnection *ac, const char *filename)
delete_file(int agent_fd, const char *filename)
{
struct sshkey *public;
char *comment = NULL;
@@ -101,11 +101,12 @@ delete_file(AuthenticationConnection *ac, const char *filename)
printf("Bad key file %s: %s\n", filename, ssh_err(r));
return -1;
}
if (ssh_remove_identity(ac, public)) {
if ((r = ssh_remove_identity(agent_fd, public)) == 0) {
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
ret = 0;
} else
fprintf(stderr, "Could not remove identity: %s\n", filename);
fprintf(stderr, "Could not remove identity \"%s\": %s\n",
filename, ssh_err(r));
sshkey_free(public);
xfree(comment);
@@ -115,14 +116,15 @@ delete_file(AuthenticationConnection *ac, const char *filename)
/* Send a request to remove all identities. */
static int
delete_all(AuthenticationConnection *ac)
delete_all(int agent_fd)
{
int ret = -1;
if (ssh_remove_all_identities(ac, 1))
if (ssh_remove_all_identities(agent_fd, 1) == 0)
ret = 0;
/* ignore error-code for ssh2 */
ssh_remove_all_identities(ac, 2);
/* XXX revisit */
ssh_remove_all_identities(agent_fd, 2);
if (ret == 0)
fprintf(stderr, "All identities removed.\n");
@@ -133,7 +135,7 @@ delete_all(AuthenticationConnection *ac)
}
static int
add_file(AuthenticationConnection *ac, const char *filename, int key_only)
add_file(int agent_fd, const char *filename, int key_only)
{
struct sshkey *private, *cert;
char *comment = NULL;
@@ -219,8 +221,8 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
}
buffer_free(&keyblob);
if (ssh_add_identity_constrained(ac, private, comment, lifetime,
confirm)) {
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
lifetime, confirm)) == 0) {
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
ret = 0;
if (lifetime != 0)
@@ -230,7 +232,8 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
fprintf(stderr,
"The user must confirm each use of the key\n");
} else {
fprintf(stderr, "Could not add identity: %s\n", filename);
fprintf(stderr, "Could not add identity \"%s\": %s\n",
filename, ssh_err(r));
}
/* Skip trying to load the cert if requested */
@@ -266,10 +269,11 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
}
sshkey_free(cert);
if (!ssh_add_identity_constrained(ac, private, comment,
lifetime, confirm)) {
error("Certificate %s (%s) add failed", certpath,
private->cert->key_id);
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
lifetime, confirm)) != 0) {
error("Certificate %s (%s) add failed: %s", certpath,
private->cert->key_id, ssh_err(r));
goto out;
}
fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
private->cert->key_id);
@@ -287,22 +291,23 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
}
static int
update_card(AuthenticationConnection *ac, int add, const char *id)
update_card(int agent_fd, int add, const char *id)
{
char *pin;
int ret = -1;
int r, ret = -1;
pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN);
if (pin == NULL)
return -1;
if (ssh_update_card(ac, add, id, pin, lifetime, confirm)) {
if ((r = ssh_update_card(agent_fd, add, id, pin, lifetime,
confirm)) == 0) {
fprintf(stderr, "Card %s: %s\n",
add ? "added" : "removed", id);
ret = 0;
} else {
fprintf(stderr, "Could not %s card: %s\n",
add ? "add" : "remove", id);
fprintf(stderr, "Could not %s card \"%s\": %s\n",
add ? "add" : "remove", id, ssh_err(r));
ret = -1;
}
xfree(pin);
@@ -310,33 +315,42 @@ update_card(AuthenticationConnection *ac, int add, const char *id)
}
static int
list_identities(AuthenticationConnection *ac, int do_fp)
list_identities(int agent_fd, int do_fp)
{
struct sshkey *key;
char *comment, *fp;
char *fp;
int version, r, had_identities = 0;
struct ssh_identitylist *idlist;
size_t i;
for (version = 1; version <= 2; version++) {
for (key = ssh_get_first_identity(ac, &comment, version);
key != NULL;
key = ssh_get_next_identity(ac, &comment, version)) {
if ((r = ssh_fetch_identitylist(agent_fd, version,
&idlist)) != 0) {
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
fprintf(stderr, "error fetching identities for "
"protocol %d: %s\n", version, ssh_err(r));
continue;
}
for (i = 0; i < idlist->nkeys; i++) {
had_identities = 1;
if (do_fp) {
fp = sshkey_fingerprint(key, SSH_FP_MD5,
SSH_FP_HEX);
fp = sshkey_fingerprint(idlist->keys[i],
SSH_FP_MD5, SSH_FP_HEX);
printf("%d %s %s (%s)\n",
sshkey_size(key), fp, comment,
sshkey_type(key));
sshkey_size(idlist->keys[i]), fp,
idlist->comments[i],
sshkey_type(idlist->keys[i]));
xfree(fp);
} else {
if ((r = sshkey_write(key, stdout)) != 0)
fprintf(stderr, "sshkey_write: %s",
if ((r = sshkey_write(idlist->keys[i],
stdout)) != 0) {
fprintf(stderr, "sshkey_write: %s\n",
ssh_err(r));
fprintf(stdout, " %s\n", comment);
continue;
}
fprintf(stdout, " %s\n", idlist->comments[i]);
}
sshkey_free(key);
xfree(comment);
}
ssh_free_identitylist(idlist);
}
if (!had_identities) {
printf("The agent has no identities.\n");
@@ -346,10 +360,10 @@ list_identities(AuthenticationConnection *ac, int do_fp)
}
static int
lock_agent(AuthenticationConnection *ac, int lock)
lock_agent(int agent_fd, int lock)
{
char prompt[100], *p1, *p2;
int passok = 1, ret = -1;
int r, passok = 1, ret = -1;
strlcpy(prompt, "Enter lock password: ", sizeof(prompt));
p1 = read_passphrase(prompt, RP_ALLOW_STDIN);
@@ -363,24 +377,28 @@ lock_agent(AuthenticationConnection *ac, int lock)
memset(p2, 0, strlen(p2));
xfree(p2);
}
if (passok && ssh_lock_agent(ac, lock, p1)) {
fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un");
ret = 0;
} else
fprintf(stderr, "Failed to %slock agent.\n", lock ? "" : "un");
if (passok) {
if ((r = ssh_lock_agent(agent_fd, lock, p1)) == 0) {
fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un");
ret = 0;
} else {
fprintf(stderr, "Failed to %slock agent: %sn",
lock ? "" : "un", ssh_err(r));
}
}
memset(p1, 0, strlen(p1));
xfree(p1);
return (ret);
}
static int
do_file(AuthenticationConnection *ac, int deleting, int key_only, char *file)
do_file(int agent_fd, int deleting, int key_only, char *file)
{
if (deleting) {
if (delete_file(ac, file) == -1)
if (delete_file(agent_fd, file) == -1)
return -1;
} else {
if (add_file(ac, file, key_only) == -1)
if (add_file(agent_fd, file, key_only) == -1)
return -1;
}
return 0;
@@ -409,22 +427,28 @@ main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
AuthenticationConnection *ac = NULL;
int agent_fd;
char *pkcs11provider = NULL;
int i, ch, deleting = 0, ret = 0, key_only = 0;
int r, i, ch, deleting = 0, ret = 0, key_only = 0;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
OpenSSL_add_all_algorithms();
/* At first, get a connection to the authentication agent. */
ac = ssh_get_authentication_connection();
if (ac == NULL) {
fprintf(stderr,
"Could not open a connection to your authentication agent.\n");
/* First, get a connection to the authentication agent. */
switch (r = ssh_get_authentication_socket(&agent_fd)) {
case 0:
break;
case SSH_ERR_AGENT_NOT_PRESENT:
fprintf(stderr, "Could not open a connection to your "
"authentication agent.\n");
exit(2);
default:
fprintf(stderr, "Error connecting to agent: %s\n", ssh_err(r));
exit(2);
}
while ((ch = getopt(argc, argv, "klLcdDxXe:s:t:")) != -1) {
switch (ch) {
case 'k':
@@ -432,12 +456,12 @@ main(int argc, char **argv)
break;
case 'l':
case 'L':
if (list_identities(ac, ch == 'l' ? 1 : 0) == -1)
if (list_identities(agent_fd, ch == 'l' ? 1 : 0) == -1)
ret = 1;
goto done;
case 'x':
case 'X':
if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1)
if (lock_agent(agent_fd, ch == 'x' ? 1 : 0) == -1)
ret = 1;
goto done;
case 'c':
@@ -447,7 +471,7 @@ main(int argc, char **argv)
deleting = 1;
break;
case 'D':
if (delete_all(ac) == -1)
if (delete_all(agent_fd) == -1)
ret = 1;
goto done;
case 's':
@@ -473,7 +497,7 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
if (pkcs11provider != NULL) {
if (update_card(ac, !deleting, pkcs11provider) == -1)
if (update_card(agent_fd, !deleting, pkcs11provider) == -1)
ret = 1;
goto done;
}
@@ -495,7 +519,7 @@ main(int argc, char **argv)
default_files[i]);
if (stat(buf, &st) < 0)
continue;
if (do_file(ac, deleting, key_only, buf) == -1)
if (do_file(agent_fd, deleting, key_only, buf) == -1)
ret = 1;
else
count++;
@@ -504,13 +528,14 @@ main(int argc, char **argv)
ret = 1;
} else {
for (i = 0; i < argc; i++) {
if (do_file(ac, deleting, key_only, argv[i]) == -1)
if (do_file(agent_fd, deleting, key_only,
argv[i]) == -1)
ret = 1;
}
}
clear_pass();
done:
ssh_close_authentication_connection(ac);
ssh_close_authentication_socket(agent_fd);
return ret;
}

View File

@@ -1129,10 +1129,16 @@ ssh_init_forwarding(struct ssh *ssh)
static void
check_agent_present(void)
{
int r;
if (options.forward_agent) {
/* Clear agent forwarding if we don't have an agent. */
if (!ssh_agent_present())
if ((r = ssh_get_authentication_socket(NULL)) != 0) {
options.forward_agent = 0;
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("ssh_get_authentication_socket: %s",
ssh_err(r));
}
}
}

View File

@@ -61,33 +61,41 @@ extern char *__progname;
static int
try_agent_authentication(void)
{
int type;
char *comment;
AuthenticationConnection *auth;
int r, type, agent_fd, ret = 0;
u_char response[16];
u_int i;
struct sshkey *key;
size_t i;
BIGNUM *challenge;
struct ssh_identitylist *idlist = NULL;
/* Get connection to the agent. */
auth = ssh_get_authentication_connection();
if (!auth)
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
return 0;
}
if ((challenge = BN_new()) == NULL)
fatal("try_agent_authentication: BN_new failed");
/* Loop through identities served by the agent. */
for (key = ssh_get_first_identity(auth, &comment, 1);
key != NULL;
key = ssh_get_next_identity(auth, &comment, 1)) {
if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) {
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
debug("%s: ssh_fetch_identitylist: %s",
__func__, ssh_err(r));
goto out;
}
for (i = 0; i < idlist->nkeys; i++) {
/* Try this identity. */
debug("Trying RSA authentication via agent with '%.100s'", comment);
xfree(comment);
debug("Trying RSA authentication via agent with '%.100s'",
idlist->comments[i]);
/* Tell the server that we are willing to authenticate using this key. */
/*
* Tell the server that we are willing to authenticate
* using this key.
*/
packet_start(SSH_CMSG_AUTH_RSA);
packet_put_bignum(key->rsa->n);
packet_put_bignum(idlist->keys[i]->rsa->n);
packet_send();
packet_write_wait();
@@ -98,7 +106,6 @@ try_agent_authentication(void)
does not support RSA authentication. */
if (type == SSH_SMSG_FAILURE) {
debug("Server refused our key.");
sshkey_free(key);
continue;
}
/* Otherwise it should have sent a challenge. */
@@ -112,16 +119,17 @@ try_agent_authentication(void)
debug("Received RSA challenge from server.");
/* Ask the agent to decrypt the challenge. */
if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {
if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i],
challenge, session_id, response)) != 0) {
/*
* The agent failed to authenticate this identifier
* although it advertised it supports this. Just
* return a wrong value.
*/
logit("Authentication agent failed to decrypt challenge.");
logit("Authentication agent failed to decrypt i"
"challenge.");
memset(response, 0, sizeof(response));
}
sshkey_free(key);
debug("Sending response to RSA challenge.");
/* Send the decrypted challenge back to the server. */
@@ -134,22 +142,26 @@ try_agent_authentication(void)
/* Wait for response from the server. */
type = packet_read();
/* The server returns success if it accepted the authentication. */
/*
* 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;
ret = 1;
goto out;
}
/* Otherwise it should return failure. */
if (type != SSH_SMSG_FAILURE)
packet_disconnect("Protocol error waiting RSA auth response: %d",
type);
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;
out:
ssh_free_identitylist(idlist);
ssh_close_authentication_socket(agent_fd);
BN_clear_free(challenge);
return ret;
}
/*

View File

@@ -236,7 +236,7 @@ typedef struct idlist Idlist;
struct identity {
TAILQ_ENTRY(identity) next;
AuthenticationConnection *ac; /* set if agent supports key */
int agent_fd; /* >=0 if agent supports key */
struct sshkey *key; /* public/private key */
char *filename; /* comment for agent-only keys */
int tried;
@@ -255,7 +255,7 @@ struct Authctxt {
int attempt;
/* pubkey */
Idlist keys;
AuthenticationConnection *agent;
int agent_fd;
/* hostbased */
Sensitive *sensitive;
/* kbd-interactive */
@@ -1200,9 +1200,9 @@ identity_sign(Identity *id, u_char **sigp, u_int *lenp,
int ret;
/* the agent supports this key */
if (id->ac)
return (ssh_agent_sign(id->ac, id->key, sigp, lenp,
data, datalen, compat));
if (id->agent_fd)
return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
data, datalen, compat);
/*
* we have already loaded the private key or
* the private key is stored in external hardware
@@ -1414,9 +1414,9 @@ pubkey_prepare(struct ssh *ssh)
Identity *id;
Idlist agent, files, *preferred;
struct sshkey *key;
AuthenticationConnection *ac;
char *comment;
int i, found;
int agent_fd, i, r, found;
size_t j;
struct ssh_identitylist *idlist;
TAILQ_INIT(&agent); /* keys from the agent */
TAILQ_INIT(&files); /* keys from the config file */
@@ -1437,37 +1437,48 @@ pubkey_prepare(struct ssh *ssh)
TAILQ_INSERT_TAIL(&files, id, next);
}
/* 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)) {
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
} else if ((r = ssh_fetch_identitylist(agent_fd, 2, &idlist)) != 0) {
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
debug("%s: ssh_fetch_identitylist: %s",
__func__, ssh_err(r));
} else {
for (j = 0; j < idlist->nkeys; j++) {
found = 0;
TAILQ_FOREACH(id, &files, next) {
/* agent keys from the config file are preferred */
if (sshkey_equal(key, id->key)) {
sshkey_free(key);
xfree(comment);
/*
* agent keys from the config file are
* preferred
*/
if (sshkey_equal(idlist->keys[j], id->key)) {
TAILQ_REMOVE(&files, id, next);
TAILQ_INSERT_TAIL(preferred, id, next);
id->ac = ac;
id->agent_fd = agent_fd;
found = 1;
break;
}
}
if (!found && !options.identities_only) {
id = xcalloc(1, sizeof(*id));
id->key = key;
id->filename = comment;
id->ac = ac;
/* XXX "steals" key/comment from idlist */
id->key = idlist->keys[j];
id->filename = idlist->comments[j];
idlist->keys[j] = NULL;
idlist->comments[j] = NULL;
id->agent_fd = agent_fd;
TAILQ_INSERT_TAIL(&agent, id, next);
}
}
ssh_free_identitylist(idlist);
/* append remaining agent keys */
for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
TAILQ_REMOVE(&agent, id, next);
TAILQ_INSERT_TAIL(preferred, id, next);
}
authctxt->agent = ac;
authctxt->agent_fd = agent_fd;
}
/* append remaining keys from the config file */
for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
@@ -1485,8 +1496,8 @@ pubkey_cleanup(struct ssh *ssh)
Authctxt *authctxt = ssh->authctxt;
Identity *id;
if (authctxt->agent != NULL)
ssh_close_authentication_connection(authctxt->agent);
if (authctxt->agent_fd != -1)
ssh_close_authentication_socket(authctxt->agent_fd);
for (id = TAILQ_FIRST(&authctxt->keys); id;
id = TAILQ_FIRST(&authctxt->keys)) {
TAILQ_REMOVE(&authctxt->keys, id, next);