=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh-agent.c,v retrieving revision 1.88 retrieving revision 1.89 diff -u -r1.88 -r1.89 --- src/usr.bin/ssh/ssh-agent.c 2002/06/05 19:57:12 1.88 +++ src/usr.bin/ssh/ssh-agent.c 2002/06/05 21:55:44 1.89 @@ -35,7 +35,7 @@ #include "includes.h" #include -RCSID("$OpenBSD: ssh-agent.c,v 1.88 2002/06/05 19:57:12 markus Exp $"); +RCSID("$OpenBSD: ssh-agent.c,v 1.89 2002/06/05 21:55:44 markus Exp $"); #include #include @@ -76,6 +76,7 @@ TAILQ_ENTRY(identity) next; Key *key; char *comment; + u_int death; } Identity; typedef struct { @@ -120,6 +121,14 @@ return &idtable[version]; } +static void +free_identity(Identity *id) +{ + key_free(id->key); + xfree(id->comment); + xfree(id); +} + /* return matching private key for given public key */ static Identity * lookup_identity(Key *key, int version) @@ -134,14 +143,6 @@ return (NULL); } -static void -free_identity(Identity *id) -{ - key_free(id->key); - xfree(id->comment); - xfree(id); -} - /* send list of supported public keys to 'client' */ static void process_request_identities(SocketEntry *e, int version) @@ -364,6 +365,27 @@ } static void +reaper(void) +{ + Idtab *tab; + Identity *id, *nxt; + int version; + u_int now = time(NULL); + + 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 && now >= id->death) { + TAILQ_REMOVE(&tab->idlist, id, next); + free_identity(id); + tab->nentries--; + } + } + } +} + +static void process_add_identity(SocketEntry *e, int version) { Key *k = NULL; @@ -429,6 +451,7 @@ Identity *id = xmalloc(sizeof(Identity)); id->key = k; id->comment = comment; + id->death = 0; TAILQ_INSERT_TAIL(&tab->idlist, id, next); /* Increment the number of identities. */ tab->nentries++; @@ -442,6 +465,43 @@ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); } +static void +process_lifetime_identity(SocketEntry *e, int version) +{ + Key *key = NULL; + u_char *blob; + u_int blen, bits, death; + int success = 0; + + death = time(NULL) + buffer_get_int(&e->request); + + switch (version) { + case 1: + key = key_new(KEY_RSA1); + bits = buffer_get_int(&e->request); + buffer_get_bignum(&e->request, key->rsa->e); + buffer_get_bignum(&e->request, key->rsa->n); + + break; + case 2: + blob = buffer_get_string(&e->request, &blen); + key = key_from_blob(blob, blen); + xfree(blob); + break; + } + if (key != NULL) { + Identity *id = lookup_identity(key, version); + if (id != NULL && id->death == 0) { + id->death = death; + success = 1; + } + key_free(key); + } + buffer_put_int(&e->output, 1); + buffer_put_char(&e->output, + success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); +} + /* XXX todo: encrypt sensitive data with passphrase */ static void process_lock_agent(SocketEntry *e, int lock) @@ -513,6 +573,7 @@ id = xmalloc(sizeof(Identity)); id->key = k; id->comment = xstrdup("smartcard key"); + id->death = 0; TAILQ_INSERT_TAIL(&tab->idlist, id, next); tab->nentries++; success = 1; @@ -576,6 +637,10 @@ u_int msg_len; u_int type; u_char *cp; + + /* kill dead keys */ + reaper(); + if (buffer_len(&e->input) < 5) return; /* Incomplete message. */ cp = buffer_ptr(&e->input); @@ -638,6 +703,9 @@ case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: process_remove_all_identities(e, 1); break; + case SSH_AGENTC_LIFETIME_IDENTITY1: + process_lifetime_identity(e, 1); + break; /* ssh2 */ case SSH2_AGENTC_SIGN_REQUEST: process_sign_request2(e); @@ -653,6 +721,9 @@ break; case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: process_remove_all_identities(e, 2); + break; + case SSH_AGENTC_LIFETIME_IDENTITY: + process_lifetime_identity(e, 2); break; #ifdef SMARTCARD case SSH_AGENTC_ADD_SMARTCARD_KEY: