зеркало из https://github.com/Azure/sonic-openssh.git
upstream commit
flense SSHv1 support from ssh-agent, considerably simplifying it ok markus Upstream-ID: 71d772cdcefcb29f76e01252e8361e6fc2dfc365
This commit is contained in:
Родитель
930e8d2827
Коммит
f4a6a88ddb
250
ssh-agent.c
250
ssh-agent.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-agent.c,v 1.220 2017/04/30 23:18:44 djm Exp $ */
|
||||
/* $OpenBSD: ssh-agent.c,v 1.221 2017/04/30 23:29:10 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -118,13 +118,13 @@ typedef struct identity {
|
|||
u_int confirm;
|
||||
} Identity;
|
||||
|
||||
typedef struct {
|
||||
struct idtable {
|
||||
int nentries;
|
||||
TAILQ_HEAD(idqueue, identity) idlist;
|
||||
} Idtab;
|
||||
};
|
||||
|
||||
/* private key table, one per protocol version */
|
||||
Idtab idtable[3];
|
||||
/* private key table */
|
||||
struct idtable *idtab;
|
||||
|
||||
int max_fd = 0;
|
||||
|
||||
|
@ -171,21 +171,9 @@ close_socket(SocketEntry *e)
|
|||
static void
|
||||
idtab_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i <=2; i++) {
|
||||
TAILQ_INIT(&idtable[i].idlist);
|
||||
idtable[i].nentries = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* return private key table for requested protocol version */
|
||||
static Idtab *
|
||||
idtab_lookup(int version)
|
||||
{
|
||||
if (version < 1 || version > 2)
|
||||
fatal("internal error, bad protocol version %d", version);
|
||||
return &idtable[version];
|
||||
idtab = xcalloc(1, sizeof(*idtab));
|
||||
TAILQ_INIT(&idtab->idlist);
|
||||
idtab->nentries = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -199,12 +187,11 @@ free_identity(Identity *id)
|
|||
|
||||
/* return matching private key for given public key */
|
||||
static Identity *
|
||||
lookup_identity(struct sshkey *key, int version)
|
||||
lookup_identity(struct sshkey *key)
|
||||
{
|
||||
Identity *id;
|
||||
|
||||
Idtab *tab = idtab_lookup(version);
|
||||
TAILQ_FOREACH(id, &tab->idlist, next) {
|
||||
TAILQ_FOREACH(id, &idtab->idlist, next) {
|
||||
if (sshkey_equal(key, id->key))
|
||||
return (id);
|
||||
}
|
||||
|
@ -241,34 +228,24 @@ send_status(SocketEntry *e, int success)
|
|||
|
||||
/* send list of supported public keys to 'client' */
|
||||
static void
|
||||
process_request_identities(SocketEntry *e, int version)
|
||||
process_request_identities(SocketEntry *e)
|
||||
{
|
||||
Idtab *tab = idtab_lookup(version);
|
||||
Identity *id;
|
||||
struct sshbuf *msg;
|
||||
int r;
|
||||
u_char *blob;
|
||||
size_t blen;
|
||||
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
if ((r = sshbuf_put_u8(msg, (version == 1) ?
|
||||
SSH_AGENT_RSA_IDENTITIES_ANSWER :
|
||||
SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
|
||||
(r = sshbuf_put_u32(msg, tab->nentries)) != 0)
|
||||
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
|
||||
(r = sshbuf_put_u32(msg, idtab->nentries)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
TAILQ_FOREACH(id, &tab->idlist, next) {
|
||||
if ((r = sshkey_to_blob(id->key, &blob, &blen)) != 0) {
|
||||
error("%s: sshkey_to_blob: %s", __func__,
|
||||
TAILQ_FOREACH(id, &idtab->idlist, next) {
|
||||
if ((r = sshkey_puts(id->key, msg)) != 0 ||
|
||||
(r = sshbuf_put_cstring(msg, id->comment)) != 0) {
|
||||
error("%s: put key/comment: %s", __func__,
|
||||
ssh_err(r));
|
||||
continue;
|
||||
}
|
||||
if ((r = sshbuf_put_string(msg, blob, blen)) != 0)
|
||||
fatal("%s: buffer error: %s",
|
||||
__func__, ssh_err(r));
|
||||
free(blob);
|
||||
if ((r = sshbuf_put_cstring(msg, id->comment)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
}
|
||||
if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
|
@ -292,27 +269,24 @@ agent_decode_alg(struct sshkey *key, u_int flags)
|
|||
static void
|
||||
process_sign_request2(SocketEntry *e)
|
||||
{
|
||||
u_char *blob, *data, *signature = NULL;
|
||||
size_t blen, dlen, slen = 0;
|
||||
const u_char *data;
|
||||
u_char *signature = NULL;
|
||||
size_t dlen, slen = 0;
|
||||
u_int compat = 0, flags;
|
||||
int r, ok = -1;
|
||||
struct sshbuf *msg;
|
||||
struct sshkey *key;
|
||||
struct sshkey *key = NULL;
|
||||
struct identity *id;
|
||||
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0 ||
|
||||
(r = sshbuf_get_string(e->request, &data, &dlen)) != 0 ||
|
||||
if ((r = sshkey_froms(e->request, &key)) != 0 ||
|
||||
(r = sshbuf_get_string_direct(e->request, &data, &dlen)) != 0 ||
|
||||
(r = sshbuf_get_u32(e->request, &flags)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
if (flags & SSH_AGENT_OLD_SIGNATURE)
|
||||
compat = SSH_BUG_SIGBLOB;
|
||||
if ((r = sshkey_from_blob(blob, blen, &key)) != 0) {
|
||||
error("%s: cannot parse key blob: %s", __func__, ssh_err(r));
|
||||
goto send;
|
||||
}
|
||||
if ((id = lookup_identity(key, 2)) == NULL) {
|
||||
if ((id = lookup_identity(key)) == NULL) {
|
||||
verbose("%s: %s key not found", __func__, sshkey_type(key));
|
||||
goto send;
|
||||
}
|
||||
|
@ -340,70 +314,52 @@ process_sign_request2(SocketEntry *e)
|
|||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
|
||||
sshbuf_free(msg);
|
||||
free(data);
|
||||
free(blob);
|
||||
free(signature);
|
||||
}
|
||||
|
||||
/* shared */
|
||||
static void
|
||||
process_remove_identity(SocketEntry *e, int version)
|
||||
process_remove_identity(SocketEntry *e)
|
||||
{
|
||||
size_t blen;
|
||||
int r, success = 0;
|
||||
struct sshkey *key = NULL;
|
||||
u_char *blob;
|
||||
Identity *id;
|
||||
|
||||
switch (version) {
|
||||
case 2:
|
||||
if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
|
||||
error("%s: sshkey_from_blob failed: %s",
|
||||
__func__, ssh_err(r));
|
||||
free(blob);
|
||||
break;
|
||||
if ((r = sshkey_froms(e->request, &key)) != 0) {
|
||||
error("%s: get key: %s", __func__, ssh_err(r));
|
||||
goto done;
|
||||
}
|
||||
if (key != NULL) {
|
||||
Identity *id = lookup_identity(key, version);
|
||||
if (id != NULL) {
|
||||
/*
|
||||
* We have this key. Free the old key. Since we
|
||||
* don't want to leave empty slots in the middle of
|
||||
* the array, we actually free the key there and move
|
||||
* all the entries between the empty slot and the end
|
||||
* of the array.
|
||||
*/
|
||||
Idtab *tab = idtab_lookup(version);
|
||||
if (tab->nentries < 1)
|
||||
fatal("process_remove_identity: "
|
||||
"internal error: tab->nentries %d",
|
||||
tab->nentries);
|
||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||
free_identity(id);
|
||||
tab->nentries--;
|
||||
success = 1;
|
||||
}
|
||||
sshkey_free(key);
|
||||
if ((id = lookup_identity(key)) == NULL) {
|
||||
debug("%s: key not found", __func__);
|
||||
goto done;
|
||||
}
|
||||
/* We have this key, free it. */
|
||||
if (idtab->nentries < 1)
|
||||
fatal("%s: internal error: nentries %d",
|
||||
__func__, idtab->nentries);
|
||||
TAILQ_REMOVE(&idtab->idlist, id, next);
|
||||
free_identity(id);
|
||||
idtab->nentries--;
|
||||
sshkey_free(key);
|
||||
success = 1;
|
||||
done:
|
||||
send_status(e, success);
|
||||
}
|
||||
|
||||
static void
|
||||
process_remove_all_identities(SocketEntry *e, int version)
|
||||
process_remove_all_identities(SocketEntry *e)
|
||||
{
|
||||
Idtab *tab = idtab_lookup(version);
|
||||
Identity *id;
|
||||
|
||||
/* Loop over all identities and clear the keys. */
|
||||
for (id = TAILQ_FIRST(&tab->idlist); id;
|
||||
id = TAILQ_FIRST(&tab->idlist)) {
|
||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||
for (id = TAILQ_FIRST(&idtab->idlist); id;
|
||||
id = TAILQ_FIRST(&idtab->idlist)) {
|
||||
TAILQ_REMOVE(&idtab->idlist, id, next);
|
||||
free_identity(id);
|
||||
}
|
||||
|
||||
/* Mark that there are no identities. */
|
||||
tab->nentries = 0;
|
||||
idtab->nentries = 0;
|
||||
|
||||
/* Send success. */
|
||||
send_status(e, 1);
|
||||
|
@ -415,24 +371,19 @@ reaper(void)
|
|||
{
|
||||
time_t deadline = 0, now = monotime();
|
||||
Identity *id, *nxt;
|
||||
int version;
|
||||
Idtab *tab;
|
||||
|
||||
for (version = 1; version < 3; version++) {
|
||||
tab = idtab_lookup(version);
|
||||
for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
|
||||
nxt = TAILQ_NEXT(id, next);
|
||||
if (id->death == 0)
|
||||
continue;
|
||||
if (now >= id->death) {
|
||||
debug("expiring key '%s'", id->comment);
|
||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||
free_identity(id);
|
||||
tab->nentries--;
|
||||
} else
|
||||
deadline = (deadline == 0) ? id->death :
|
||||
MINIMUM(deadline, id->death);
|
||||
}
|
||||
for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
|
||||
nxt = TAILQ_NEXT(id, next);
|
||||
if (id->death == 0)
|
||||
continue;
|
||||
if (now >= id->death) {
|
||||
debug("expiring key '%s'", id->comment);
|
||||
TAILQ_REMOVE(&idtab->idlist, id, next);
|
||||
free_identity(id);
|
||||
idtab->nentries--;
|
||||
} else
|
||||
deadline = (deadline == 0) ? id->death :
|
||||
MINIMUM(deadline, id->death);
|
||||
}
|
||||
if (deadline == 0 || deadline <= now)
|
||||
return 0;
|
||||
|
@ -440,15 +391,9 @@ reaper(void)
|
|||
return (deadline - now);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX this and the corresponding serialisation function probably belongs
|
||||
* in key.c
|
||||
*/
|
||||
|
||||
static void
|
||||
process_add_identity(SocketEntry *e, int version)
|
||||
process_add_identity(SocketEntry *e)
|
||||
{
|
||||
Idtab *tab = idtab_lookup(version);
|
||||
Identity *id;
|
||||
int success = 0, confirm = 0;
|
||||
u_int seconds;
|
||||
|
@ -458,12 +403,8 @@ process_add_identity(SocketEntry *e, int version)
|
|||
u_char ctype;
|
||||
int r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
switch (version) {
|
||||
case 2:
|
||||
r = sshkey_private_deserialize(e->request, &k);
|
||||
break;
|
||||
}
|
||||
if (r != 0 || k == NULL ||
|
||||
if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
|
||||
k == NULL ||
|
||||
(r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
|
||||
error("%s: decode private key: %s", __func__, ssh_err(r));
|
||||
goto err;
|
||||
|
@ -499,12 +440,12 @@ process_add_identity(SocketEntry *e, int version)
|
|||
success = 1;
|
||||
if (lifetime && !death)
|
||||
death = monotime() + lifetime;
|
||||
if ((id = lookup_identity(k, version)) == NULL) {
|
||||
if ((id = lookup_identity(k)) == NULL) {
|
||||
id = xcalloc(1, sizeof(Identity));
|
||||
id->key = k;
|
||||
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
||||
TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
|
||||
/* Increment the number of identities. */
|
||||
tab->nentries++;
|
||||
idtab->nentries++;
|
||||
} else {
|
||||
sshkey_free(k);
|
||||
free(id->comment);
|
||||
|
@ -565,17 +506,14 @@ process_lock_agent(SocketEntry *e, int lock)
|
|||
}
|
||||
|
||||
static void
|
||||
no_identities(SocketEntry *e, u_int type)
|
||||
no_identities(SocketEntry *e)
|
||||
{
|
||||
struct sshbuf *msg;
|
||||
int r;
|
||||
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
if ((r = sshbuf_put_u8(msg,
|
||||
(type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ?
|
||||
SSH_AGENT_RSA_IDENTITIES_ANSWER :
|
||||
SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
|
||||
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
|
||||
(r = sshbuf_put_u32(msg, 0)) != 0 ||
|
||||
(r = sshbuf_put_stringb(e->output, msg)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
|
@ -587,13 +525,12 @@ static void
|
|||
process_add_smartcard_key(SocketEntry *e)
|
||||
{
|
||||
char *provider = NULL, *pin, canonical_provider[PATH_MAX];
|
||||
int r, i, version, count = 0, success = 0, confirm = 0;
|
||||
int r, i, count = 0, success = 0, confirm = 0;
|
||||
u_int seconds;
|
||||
time_t death = 0;
|
||||
u_char type;
|
||||
struct sshkey **keys = NULL, *k;
|
||||
Identity *id;
|
||||
Idtab *tab;
|
||||
|
||||
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
|
||||
(r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0)
|
||||
|
@ -613,8 +550,7 @@ process_add_smartcard_key(SocketEntry *e)
|
|||
confirm = 1;
|
||||
break;
|
||||
default:
|
||||
error("process_add_smartcard_key: "
|
||||
"Unknown constraint type %d", type);
|
||||
error("%s: Unknown constraint type %d", __func__, type);
|
||||
goto send;
|
||||
}
|
||||
}
|
||||
|
@ -635,17 +571,15 @@ process_add_smartcard_key(SocketEntry *e)
|
|||
count = pkcs11_add_provider(canonical_provider, pin, &keys);
|
||||
for (i = 0; i < count; i++) {
|
||||
k = keys[i];
|
||||
version = 2;
|
||||
tab = idtab_lookup(version);
|
||||
if (lookup_identity(k, version) == NULL) {
|
||||
if (lookup_identity(k) == NULL) {
|
||||
id = xcalloc(1, sizeof(Identity));
|
||||
id->key = k;
|
||||
id->provider = xstrdup(canonical_provider);
|
||||
id->comment = xstrdup(canonical_provider); /* XXX */
|
||||
id->death = death;
|
||||
id->confirm = confirm;
|
||||
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
|
||||
tab->nentries++;
|
||||
TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
|
||||
idtab->nentries++;
|
||||
success = 1;
|
||||
} else {
|
||||
sshkey_free(k);
|
||||
|
@ -663,9 +597,8 @@ static void
|
|||
process_remove_smartcard_key(SocketEntry *e)
|
||||
{
|
||||
char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
|
||||
int r, version, success = 0;
|
||||
int r, success = 0;
|
||||
Identity *id, *nxt;
|
||||
Idtab *tab;
|
||||
|
||||
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
|
||||
(r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0)
|
||||
|
@ -679,25 +612,21 @@ process_remove_smartcard_key(SocketEntry *e)
|
|||
}
|
||||
|
||||
debug("%s: remove %.100s", __func__, canonical_provider);
|
||||
for (version = 1; version < 3; version++) {
|
||||
tab = idtab_lookup(version);
|
||||
for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
|
||||
nxt = TAILQ_NEXT(id, next);
|
||||
/* Skip file--based keys */
|
||||
if (id->provider == NULL)
|
||||
continue;
|
||||
if (!strcmp(canonical_provider, id->provider)) {
|
||||
TAILQ_REMOVE(&tab->idlist, id, next);
|
||||
free_identity(id);
|
||||
tab->nentries--;
|
||||
}
|
||||
for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
|
||||
nxt = TAILQ_NEXT(id, next);
|
||||
/* Skip file--based keys */
|
||||
if (id->provider == NULL)
|
||||
continue;
|
||||
if (!strcmp(canonical_provider, id->provider)) {
|
||||
TAILQ_REMOVE(&idtab->idlist, id, next);
|
||||
free_identity(id);
|
||||
idtab->nentries--;
|
||||
}
|
||||
}
|
||||
if (pkcs11_del_provider(canonical_provider) == 0)
|
||||
success = 1;
|
||||
else
|
||||
error("process_remove_smartcard_key:"
|
||||
" pkcs11_del_provider failed");
|
||||
error("%s: pkcs11_del_provider failed", __func__);
|
||||
send:
|
||||
free(provider);
|
||||
send_status(e, success);
|
||||
|
@ -735,10 +664,9 @@ process_message(SocketEntry *e)
|
|||
if (locked && type != SSH_AGENTC_UNLOCK) {
|
||||
sshbuf_reset(e->request);
|
||||
switch (type) {
|
||||
case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
|
||||
case SSH2_AGENTC_REQUEST_IDENTITIES:
|
||||
/* send empty lists */
|
||||
no_identities(e, type);
|
||||
no_identities(e);
|
||||
break;
|
||||
default:
|
||||
/* send a fail message for all other request types */
|
||||
|
@ -754,24 +682,24 @@ process_message(SocketEntry *e)
|
|||
process_lock_agent(e, type == SSH_AGENTC_LOCK);
|
||||
break;
|
||||
case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
|
||||
process_remove_all_identities(e, 1); /* safe for !WITH_SSH1 */
|
||||
process_remove_all_identities(e); /* safe for !WITH_SSH1 */
|
||||
break;
|
||||
/* ssh2 */
|
||||
case SSH2_AGENTC_SIGN_REQUEST:
|
||||
process_sign_request2(e);
|
||||
break;
|
||||
case SSH2_AGENTC_REQUEST_IDENTITIES:
|
||||
process_request_identities(e, 2);
|
||||
process_request_identities(e);
|
||||
break;
|
||||
case SSH2_AGENTC_ADD_IDENTITY:
|
||||
case SSH2_AGENTC_ADD_ID_CONSTRAINED:
|
||||
process_add_identity(e, 2);
|
||||
process_add_identity(e);
|
||||
break;
|
||||
case SSH2_AGENTC_REMOVE_IDENTITY:
|
||||
process_remove_identity(e, 2);
|
||||
process_remove_identity(e);
|
||||
break;
|
||||
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
||||
process_remove_all_identities(e, 2);
|
||||
process_remove_all_identities(e);
|
||||
break;
|
||||
#ifdef ENABLE_PKCS11
|
||||
case SSH_AGENTC_ADD_SMARTCARD_KEY:
|
||||
|
|
Загрузка…
Ссылка в новой задаче