#include "includes.h"
#include "openbsd-compat/fake-queue.h"
-RCSID("$OpenBSD: ssh-agent.c,v 1.88 2002/06/05 19:57:12 markus Exp $");
+RCSID("$OpenBSD: ssh-agent.c,v 1.95 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
#include <openssl/md5.h>
TAILQ_ENTRY(identity) next;
Key *key;
char *comment;
+ u_int death;
} Identity;
typedef struct {
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)
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)
/* Send success. */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
- return;
+}
+
+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
Key *k = NULL;
char *type_name;
char *comment;
- int type, success = 0;
+ int type, success = 0, death = 0;
Idtab *tab = idtab_lookup(version);
switch (version) {
goto send;
}
success = 1;
+ while (buffer_len(&e->request)) {
+ switch (buffer_get_char(&e->request)) {
+ case SSH_AGENT_CONSTRAIN_LIFETIME:
+ death = time(NULL) + buffer_get_int(&e->request);
+ break;
+ default:
+ break;
+ }
+ }
if (lookup_identity(k, version) == NULL) {
Identity *id = xmalloc(sizeof(Identity));
id->key = k;
id->comment = comment;
+ id->death = death;
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
/* Increment the number of identities. */
tab->nentries++;
}
memset(passwd, 0, strlen(passwd));
xfree(passwd);
-
+
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
- return;
}
static void
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;
version = k->type == KEY_RSA1 ? 1 : 2;
if ((id = lookup_identity(k, version)) != NULL) {
tab = idtab_lookup(version);
- TAILQ_REMOVE(&tab->idlist, id, next);
+ TAILQ_REMOVE(&tab->idlist, id, next);
tab->nentries--;
free_identity(id);
success = 1;
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);
process_request_identities(e, 1);
break;
case SSH_AGENTC_ADD_RSA_IDENTITY:
+ case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
process_add_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
process_request_identities(e, 2);
break;
case SSH2_AGENTC_ADD_IDENTITY:
+ case SSH2_AGENTC_ADD_ID_CONSTRAINED:
process_add_identity(e, 2);
break;
case SSH2_AGENTC_REMOVE_IDENTITY:
init_rng();
seed_rng();
-#ifdef __GNU_LIBRARY__
- while ((ch = getopt(ac, av, "+cdksa:")) != -1) {
-#else /* __GNU_LIBRARY__ */
while ((ch = getopt(ac, av, "cdksa:")) != -1) {
-#endif /* __GNU_LIBRARY__ */
switch (ch) {
case 'c':
if (s_flag)
format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME);
- printf("echo Agent pid %d killed;\n", pid);
+ printf("echo Agent pid %ld killed;\n", (long)pid);
exit(0);
}
parent_pid = getpid();
perror("mkdtemp: private socket dir");
exit(1);
}
- snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
- parent_pid);
+ snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
+ (long)parent_pid);
} else {
/* Try to use specified agent socket */
socket_dir[0] = '\0';
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
- printf("echo Agent pid %d;\n", parent_pid);
+ printf("echo Agent pid %ld;\n", (long)parent_pid);
goto skip;
}
pid = fork();
}
if (pid != 0) { /* Parent - execute the given command. */
close(sock);
- snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
+ snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
if (ac == 0) {
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
SSH_AGENTPID_ENV_NAME);
- printf("echo Agent pid %d;\n", pid);
+ printf("echo Agent pid %ld;\n", (long)pid);
exit(0);
}
if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||