diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | authfd.c | 37 | ||||
-rw-r--r-- | authfd.h | 7 | ||||
-rw-r--r-- | ssh-add.1 | 6 | ||||
-rw-r--r-- | ssh-add.c | 22 | ||||
-rw-r--r-- | ssh-agent.c | 89 |
6 files changed, 152 insertions, 15 deletions
@@ -117,6 +117,10 @@ | |||
117 | - markus@cvs.openbsd.org 2002/06/05 20:56:39 | 117 | - markus@cvs.openbsd.org 2002/06/05 20:56:39 |
118 | [ssh-add.c] | 118 | [ssh-add.c] |
119 | add -x/-X to usage | 119 | add -x/-X to usage |
120 | - markus@cvs.openbsd.org 2002/06/05 21:55:44 | ||
121 | [authfd.c authfd.h ssh-add.1 ssh-add.c ssh-agent.c] | ||
122 | ssh-add -t life, Set lifetime (in seconds) when adding identities; | ||
123 | ok provos@ | ||
120 | 124 | ||
121 | 20020604 | 125 | 20020604 |
122 | - (stevesk) [channels.c] bug #164 patch from YOSHIFUJI Hideaki (changed | 126 | - (stevesk) [channels.c] bug #164 patch from YOSHIFUJI Hideaki (changed |
@@ -801,4 +805,4 @@ | |||
801 | - (stevesk) entropy.c: typo in debug message | 805 | - (stevesk) entropy.c: typo in debug message |
802 | - (djm) ssh-keygen -i needs seeded RNG; report from markus@ | 806 | - (djm) ssh-keygen -i needs seeded RNG; report from markus@ |
803 | 807 | ||
804 | $Id: ChangeLog,v 1.2175 2002/06/06 21:53:11 mouring Exp $ | 808 | $Id: ChangeLog,v 1.2176 2002/06/06 21:54:57 mouring Exp $ |
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: authfd.c,v 1.50 2002/06/05 19:57:12 markus Exp $"); | 38 | RCSID("$OpenBSD: authfd.c,v 1.51 2002/06/05 21:55:44 markus Exp $"); |
39 | 39 | ||
40 | #include <openssl/evp.h> | 40 | #include <openssl/evp.h> |
41 | 41 | ||
@@ -552,6 +552,41 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key) | |||
552 | } | 552 | } |
553 | 553 | ||
554 | int | 554 | int |
555 | ssh_lifetime_identity(AuthenticationConnection *auth, Key *key, u_int life) | ||
556 | { | ||
557 | Buffer msg; | ||
558 | int type; | ||
559 | u_char *blob; | ||
560 | u_int blen; | ||
561 | |||
562 | buffer_init(&msg); | ||
563 | |||
564 | if (key->type == KEY_RSA1) { | ||
565 | buffer_put_char(&msg, SSH_AGENTC_LIFETIME_IDENTITY1); | ||
566 | buffer_put_int(&msg, life); | ||
567 | buffer_put_int(&msg, BN_num_bits(key->rsa->n)); | ||
568 | buffer_put_bignum(&msg, key->rsa->e); | ||
569 | buffer_put_bignum(&msg, key->rsa->n); | ||
570 | } else if (key->type == KEY_DSA || key->type == KEY_RSA) { | ||
571 | key_to_blob(key, &blob, &blen); | ||
572 | buffer_put_char(&msg, SSH_AGENTC_LIFETIME_IDENTITY); | ||
573 | buffer_put_int(&msg, life); | ||
574 | buffer_put_string(&msg, blob, blen); | ||
575 | xfree(blob); | ||
576 | } else { | ||
577 | buffer_free(&msg); | ||
578 | return 0; | ||
579 | } | ||
580 | if (ssh_request_reply(auth, &msg, &msg) == 0) { | ||
581 | buffer_free(&msg); | ||
582 | return 0; | ||
583 | } | ||
584 | type = buffer_get_char(&msg); | ||
585 | buffer_free(&msg); | ||
586 | return decode_reply(type); | ||
587 | } | ||
588 | |||
589 | int | ||
555 | ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id, const char *pin) | 590 | ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id, const char *pin) |
556 | { | 591 | { |
557 | Buffer msg; | 592 | Buffer msg; |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfd.h,v 1.25 2002/06/05 19:57:12 markus Exp $ */ | 1 | /* $OpenBSD: authfd.h,v 1.26 2002/06/05 21:55:44 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -46,6 +46,10 @@ | |||
46 | #define SSH_AGENTC_LOCK 22 | 46 | #define SSH_AGENTC_LOCK 22 |
47 | #define SSH_AGENTC_UNLOCK 23 | 47 | #define SSH_AGENTC_UNLOCK 23 |
48 | 48 | ||
49 | /* set key lifetime */ | ||
50 | #define SSH_AGENTC_LIFETIME_IDENTITY1 24 | ||
51 | #define SSH_AGENTC_LIFETIME_IDENTITY 25 | ||
52 | |||
49 | /* extended failure messages */ | 53 | /* extended failure messages */ |
50 | #define SSH2_AGENT_FAILURE 30 | 54 | #define SSH2_AGENT_FAILURE 30 |
51 | 55 | ||
@@ -69,6 +73,7 @@ int ssh_get_num_identities(AuthenticationConnection *, int); | |||
69 | Key *ssh_get_first_identity(AuthenticationConnection *, char **, int); | 73 | Key *ssh_get_first_identity(AuthenticationConnection *, char **, int); |
70 | Key *ssh_get_next_identity(AuthenticationConnection *, char **, int); | 74 | Key *ssh_get_next_identity(AuthenticationConnection *, char **, int); |
71 | int ssh_add_identity(AuthenticationConnection *, Key *, const char *); | 75 | int ssh_add_identity(AuthenticationConnection *, Key *, const char *); |
76 | int ssh_lifetime_identity(AuthenticationConnection *, Key *, u_int); | ||
72 | int ssh_remove_identity(AuthenticationConnection *, Key *); | 77 | int ssh_remove_identity(AuthenticationConnection *, Key *); |
73 | int ssh_remove_all_identities(AuthenticationConnection *, int); | 78 | int ssh_remove_all_identities(AuthenticationConnection *, int); |
74 | int ssh_lock_agent(AuthenticationConnection *, int, const char *); | 79 | int ssh_lock_agent(AuthenticationConnection *, int, const char *); |
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-add.1,v 1.32 2002/06/05 19:57:12 markus Exp $ | 1 | .\" $OpenBSD: ssh-add.1,v 1.33 2002/06/05 21:55:44 markus Exp $ |
2 | .\" | 2 | .\" |
3 | .\" -*- nroff -*- | 3 | .\" -*- nroff -*- |
4 | .\" | 4 | .\" |
@@ -46,6 +46,7 @@ | |||
46 | .Sh SYNOPSIS | 46 | .Sh SYNOPSIS |
47 | .Nm ssh-add | 47 | .Nm ssh-add |
48 | .Op Fl lLdDxX | 48 | .Op Fl lLdDxX |
49 | .Op Fl t Ar life | ||
49 | .Op Ar | 50 | .Op Ar |
50 | .Nm ssh-add | 51 | .Nm ssh-add |
51 | .Fl s Ar reader | 52 | .Fl s Ar reader |
@@ -87,6 +88,9 @@ Deletes all identities from the agent. | |||
87 | Lock the agent with a password. | 88 | Lock the agent with a password. |
88 | .It Fl X | 89 | .It Fl X |
89 | Unlock the agent. | 90 | Unlock the agent. |
91 | .It Fl t Ar life | ||
92 | Set a maximum lifetime when adding identities to an agent. | ||
93 | The lifetime is specified in seconds. | ||
90 | .It Fl s Ar reader | 94 | .It Fl s Ar reader |
91 | Add key in smartcard | 95 | Add key in smartcard |
92 | .Ar reader . | 96 | .Ar reader . |
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: ssh-add.c,v 1.55 2002/06/05 20:56:39 markus Exp $"); | 38 | RCSID("$OpenBSD: ssh-add.c,v 1.56 2002/06/05 21:55:44 markus Exp $"); |
39 | 39 | ||
40 | #include <openssl/evp.h> | 40 | #include <openssl/evp.h> |
41 | 41 | ||
@@ -66,6 +66,8 @@ static char *default_files[] = { | |||
66 | NULL | 66 | NULL |
67 | }; | 67 | }; |
68 | 68 | ||
69 | /* Default lifetime (0 == forever) */ | ||
70 | static u_int lifetime = 0; | ||
69 | 71 | ||
70 | /* we keep a cache of one passphrases */ | 72 | /* we keep a cache of one passphrases */ |
71 | static char *pass = NULL; | 73 | static char *pass = NULL; |
@@ -167,6 +169,18 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
167 | } else | 169 | } else |
168 | fprintf(stderr, "Could not add identity: %s\n", filename); | 170 | fprintf(stderr, "Could not add identity: %s\n", filename); |
169 | 171 | ||
172 | if (ret == 0 && lifetime != 0) { | ||
173 | if (ssh_lifetime_identity(ac, private, lifetime)) { | ||
174 | fprintf(stderr, | ||
175 | "Lifetime set to %d seconds for: %s (%s)\n", | ||
176 | lifetime, filename, comment); | ||
177 | } else { | ||
178 | fprintf(stderr, | ||
179 | "Could not set lifetime for identity: %s\n", | ||
180 | filename); | ||
181 | } | ||
182 | } | ||
183 | |||
170 | xfree(comment); | 184 | xfree(comment); |
171 | key_free(private); | 185 | key_free(private); |
172 | 186 | ||
@@ -280,6 +294,7 @@ usage(void) | |||
280 | fprintf(stderr, " -D Delete all identities.\n"); | 294 | fprintf(stderr, " -D Delete all identities.\n"); |
281 | fprintf(stderr, " -x Lock agent.\n"); | 295 | fprintf(stderr, " -x Lock agent.\n"); |
282 | fprintf(stderr, " -x Unlock agent.\n"); | 296 | fprintf(stderr, " -x Unlock agent.\n"); |
297 | fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n"); | ||
283 | #ifdef SMARTCARD | 298 | #ifdef SMARTCARD |
284 | fprintf(stderr, " -s reader Add key in smartcard reader.\n"); | 299 | fprintf(stderr, " -s reader Add key in smartcard reader.\n"); |
285 | fprintf(stderr, " -e reader Remove key in smartcard reader.\n"); | 300 | fprintf(stderr, " -e reader Remove key in smartcard reader.\n"); |
@@ -307,7 +322,7 @@ main(int argc, char **argv) | |||
307 | fprintf(stderr, "Could not open a connection to your authentication agent.\n"); | 322 | fprintf(stderr, "Could not open a connection to your authentication agent.\n"); |
308 | exit(2); | 323 | exit(2); |
309 | } | 324 | } |
310 | while ((ch = getopt(argc, argv, "lLdDxXe:s:")) != -1) { | 325 | while ((ch = getopt(argc, argv, "lLdDxXe:s:t:")) != -1) { |
311 | switch (ch) { | 326 | switch (ch) { |
312 | case 'l': | 327 | case 'l': |
313 | case 'L': | 328 | case 'L': |
@@ -336,6 +351,9 @@ main(int argc, char **argv) | |||
336 | deleting = 1; | 351 | deleting = 1; |
337 | sc_reader_id = optarg; | 352 | sc_reader_id = optarg; |
338 | break; | 353 | break; |
354 | case 't': | ||
355 | lifetime = atoi(optarg); | ||
356 | break; | ||
339 | default: | 357 | default: |
340 | usage(); | 358 | usage(); |
341 | ret = 1; | 359 | ret = 1; |
diff --git a/ssh-agent.c b/ssh-agent.c index d9567af5c..56db292ba 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | #include "includes.h" | 36 | #include "includes.h" |
37 | #include "openbsd-compat/fake-queue.h" | 37 | #include "openbsd-compat/fake-queue.h" |
38 | RCSID("$OpenBSD: ssh-agent.c,v 1.88 2002/06/05 19:57:12 markus Exp $"); | 38 | RCSID("$OpenBSD: ssh-agent.c,v 1.89 2002/06/05 21:55:44 markus Exp $"); |
39 | 39 | ||
40 | #include <openssl/evp.h> | 40 | #include <openssl/evp.h> |
41 | #include <openssl/md5.h> | 41 | #include <openssl/md5.h> |
@@ -76,6 +76,7 @@ typedef struct identity { | |||
76 | TAILQ_ENTRY(identity) next; | 76 | TAILQ_ENTRY(identity) next; |
77 | Key *key; | 77 | Key *key; |
78 | char *comment; | 78 | char *comment; |
79 | u_int death; | ||
79 | } Identity; | 80 | } Identity; |
80 | 81 | ||
81 | typedef struct { | 82 | typedef struct { |
@@ -124,6 +125,14 @@ idtab_lookup(int version) | |||
124 | return &idtable[version]; | 125 | return &idtable[version]; |
125 | } | 126 | } |
126 | 127 | ||
128 | static void | ||
129 | free_identity(Identity *id) | ||
130 | { | ||
131 | key_free(id->key); | ||
132 | xfree(id->comment); | ||
133 | xfree(id); | ||
134 | } | ||
135 | |||
127 | /* return matching private key for given public key */ | 136 | /* return matching private key for given public key */ |
128 | static Identity * | 137 | static Identity * |
129 | lookup_identity(Key *key, int version) | 138 | lookup_identity(Key *key, int version) |
@@ -138,14 +147,6 @@ lookup_identity(Key *key, int version) | |||
138 | return (NULL); | 147 | return (NULL); |
139 | } | 148 | } |
140 | 149 | ||
141 | static void | ||
142 | free_identity(Identity *id) | ||
143 | { | ||
144 | key_free(id->key); | ||
145 | xfree(id->comment); | ||
146 | xfree(id); | ||
147 | } | ||
148 | |||
149 | /* send list of supported public keys to 'client' */ | 150 | /* send list of supported public keys to 'client' */ |
150 | static void | 151 | static void |
151 | process_request_identities(SocketEntry *e, int version) | 152 | process_request_identities(SocketEntry *e, int version) |
@@ -368,6 +369,27 @@ process_remove_all_identities(SocketEntry *e, int version) | |||
368 | } | 369 | } |
369 | 370 | ||
370 | static void | 371 | static void |
372 | reaper(void) | ||
373 | { | ||
374 | Idtab *tab; | ||
375 | Identity *id, *nxt; | ||
376 | int version; | ||
377 | u_int now = time(NULL); | ||
378 | |||
379 | for (version = 1; version < 3; version++) { | ||
380 | tab = idtab_lookup(version); | ||
381 | for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { | ||
382 | nxt = TAILQ_NEXT(id, next); | ||
383 | if (id->death != 0 && now >= id->death) { | ||
384 | TAILQ_REMOVE(&tab->idlist, id, next); | ||
385 | free_identity(id); | ||
386 | tab->nentries--; | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | } | ||
391 | |||
392 | static void | ||
371 | process_add_identity(SocketEntry *e, int version) | 393 | process_add_identity(SocketEntry *e, int version) |
372 | { | 394 | { |
373 | Key *k = NULL; | 395 | Key *k = NULL; |
@@ -433,6 +455,7 @@ process_add_identity(SocketEntry *e, int version) | |||
433 | Identity *id = xmalloc(sizeof(Identity)); | 455 | Identity *id = xmalloc(sizeof(Identity)); |
434 | id->key = k; | 456 | id->key = k; |
435 | id->comment = comment; | 457 | id->comment = comment; |
458 | id->death = 0; | ||
436 | TAILQ_INSERT_TAIL(&tab->idlist, id, next); | 459 | TAILQ_INSERT_TAIL(&tab->idlist, id, next); |
437 | /* Increment the number of identities. */ | 460 | /* Increment the number of identities. */ |
438 | tab->nentries++; | 461 | tab->nentries++; |
@@ -446,6 +469,43 @@ send: | |||
446 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | 469 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); |
447 | } | 470 | } |
448 | 471 | ||
472 | static void | ||
473 | process_lifetime_identity(SocketEntry *e, int version) | ||
474 | { | ||
475 | Key *key = NULL; | ||
476 | u_char *blob; | ||
477 | u_int blen, bits, death; | ||
478 | int success = 0; | ||
479 | |||
480 | death = time(NULL) + buffer_get_int(&e->request); | ||
481 | |||
482 | switch (version) { | ||
483 | case 1: | ||
484 | key = key_new(KEY_RSA1); | ||
485 | bits = buffer_get_int(&e->request); | ||
486 | buffer_get_bignum(&e->request, key->rsa->e); | ||
487 | buffer_get_bignum(&e->request, key->rsa->n); | ||
488 | |||
489 | break; | ||
490 | case 2: | ||
491 | blob = buffer_get_string(&e->request, &blen); | ||
492 | key = key_from_blob(blob, blen); | ||
493 | xfree(blob); | ||
494 | break; | ||
495 | } | ||
496 | if (key != NULL) { | ||
497 | Identity *id = lookup_identity(key, version); | ||
498 | if (id != NULL && id->death == 0) { | ||
499 | id->death = death; | ||
500 | success = 1; | ||
501 | } | ||
502 | key_free(key); | ||
503 | } | ||
504 | buffer_put_int(&e->output, 1); | ||
505 | buffer_put_char(&e->output, | ||
506 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | ||
507 | } | ||
508 | |||
449 | /* XXX todo: encrypt sensitive data with passphrase */ | 509 | /* XXX todo: encrypt sensitive data with passphrase */ |
450 | static void | 510 | static void |
451 | process_lock_agent(SocketEntry *e, int lock) | 511 | process_lock_agent(SocketEntry *e, int lock) |
@@ -517,6 +577,7 @@ process_add_smartcard_key (SocketEntry *e) | |||
517 | id = xmalloc(sizeof(Identity)); | 577 | id = xmalloc(sizeof(Identity)); |
518 | id->key = k; | 578 | id->key = k; |
519 | id->comment = xstrdup("smartcard key"); | 579 | id->comment = xstrdup("smartcard key"); |
580 | id->death = 0; | ||
520 | TAILQ_INSERT_TAIL(&tab->idlist, id, next); | 581 | TAILQ_INSERT_TAIL(&tab->idlist, id, next); |
521 | tab->nentries++; | 582 | tab->nentries++; |
522 | success = 1; | 583 | success = 1; |
@@ -580,6 +641,10 @@ process_message(SocketEntry *e) | |||
580 | u_int msg_len; | 641 | u_int msg_len; |
581 | u_int type; | 642 | u_int type; |
582 | u_char *cp; | 643 | u_char *cp; |
644 | |||
645 | /* kill dead keys */ | ||
646 | reaper(); | ||
647 | |||
583 | if (buffer_len(&e->input) < 5) | 648 | if (buffer_len(&e->input) < 5) |
584 | return; /* Incomplete message. */ | 649 | return; /* Incomplete message. */ |
585 | cp = buffer_ptr(&e->input); | 650 | cp = buffer_ptr(&e->input); |
@@ -642,6 +707,9 @@ process_message(SocketEntry *e) | |||
642 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: | 707 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: |
643 | process_remove_all_identities(e, 1); | 708 | process_remove_all_identities(e, 1); |
644 | break; | 709 | break; |
710 | case SSH_AGENTC_LIFETIME_IDENTITY1: | ||
711 | process_lifetime_identity(e, 1); | ||
712 | break; | ||
645 | /* ssh2 */ | 713 | /* ssh2 */ |
646 | case SSH2_AGENTC_SIGN_REQUEST: | 714 | case SSH2_AGENTC_SIGN_REQUEST: |
647 | process_sign_request2(e); | 715 | process_sign_request2(e); |
@@ -658,6 +726,9 @@ process_message(SocketEntry *e) | |||
658 | case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: | 726 | case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: |
659 | process_remove_all_identities(e, 2); | 727 | process_remove_all_identities(e, 2); |
660 | break; | 728 | break; |
729 | case SSH_AGENTC_LIFETIME_IDENTITY: | ||
730 | process_lifetime_identity(e, 2); | ||
731 | break; | ||
661 | #ifdef SMARTCARD | 732 | #ifdef SMARTCARD |
662 | case SSH_AGENTC_ADD_SMARTCARD_KEY: | 733 | case SSH_AGENTC_ADD_SMARTCARD_KEY: |
663 | process_add_smartcard_key(e); | 734 | process_add_smartcard_key(e); |