diff options
author | Damien Miller <djm@mindrot.org> | 2010-02-12 09:21:02 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2010-02-12 09:21:02 +1100 |
commit | 7ea845e48df6d34a333ebbe79380cba0938d02a5 (patch) | |
tree | 44ab0d3fdfe0560b7ca92f5747e9dd5d012aea18 /ssh-agent.c | |
parent | 17751bcab25681d341442fdc2386a30a6bea345e (diff) |
- markus@cvs.openbsd.org 2010/02/08 10:50:20
[pathnames.h readconf.c readconf.h scp.1 sftp.1 ssh-add.1 ssh-add.c]
[ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config.5]
replace our obsolete smartcard code with PKCS#11.
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs-11v2-20.pdf
ssh(1) and ssh-keygen(1) use dlopen(3) directly to talk to a PKCS#11
provider (shared library) while ssh-agent(1) delegates PKCS#11 to
a forked a ssh-pkcs11-helper process.
PKCS#11 is currently a compile time option.
feedback and ok djm@; inspired by patches from Alon Bar-Lev
`
Diffstat (limited to 'ssh-agent.c')
-rw-r--r-- | ssh-agent.c | 101 |
1 files changed, 51 insertions, 50 deletions
diff --git a/ssh-agent.c b/ssh-agent.c index df3a87d9a..f745c2513 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.162 2009/09/01 14:43:17 djm Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.163 2010/02/08 10:50:20 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -76,8 +76,8 @@ | |||
76 | #include "log.h" | 76 | #include "log.h" |
77 | #include "misc.h" | 77 | #include "misc.h" |
78 | 78 | ||
79 | #ifdef SMARTCARD | 79 | #ifdef ENABLE_PKCS11 |
80 | #include "scard.h" | 80 | #include "ssh-pkcs11.h" |
81 | #endif | 81 | #endif |
82 | 82 | ||
83 | #if defined(HAVE_SYS_PRCTL_H) | 83 | #if defined(HAVE_SYS_PRCTL_H) |
@@ -105,6 +105,7 @@ typedef struct identity { | |||
105 | TAILQ_ENTRY(identity) next; | 105 | TAILQ_ENTRY(identity) next; |
106 | Key *key; | 106 | Key *key; |
107 | char *comment; | 107 | char *comment; |
108 | char *provider; | ||
108 | u_int death; | 109 | u_int death; |
109 | u_int confirm; | 110 | u_int confirm; |
110 | } Identity; | 111 | } Identity; |
@@ -171,6 +172,7 @@ static void | |||
171 | free_identity(Identity *id) | 172 | free_identity(Identity *id) |
172 | { | 173 | { |
173 | key_free(id->key); | 174 | key_free(id->key); |
175 | xfree(id->provider); | ||
174 | xfree(id->comment); | 176 | xfree(id->comment); |
175 | xfree(id); | 177 | xfree(id); |
176 | } | 178 | } |
@@ -549,7 +551,7 @@ process_add_identity(SocketEntry *e, int version) | |||
549 | if (lifetime && !death) | 551 | if (lifetime && !death) |
550 | death = time(NULL) + lifetime; | 552 | death = time(NULL) + lifetime; |
551 | if ((id = lookup_identity(k, version)) == NULL) { | 553 | if ((id = lookup_identity(k, version)) == NULL) { |
552 | id = xmalloc(sizeof(Identity)); | 554 | id = xcalloc(1, sizeof(Identity)); |
553 | id->key = k; | 555 | id->key = k; |
554 | TAILQ_INSERT_TAIL(&tab->idlist, id, next); | 556 | TAILQ_INSERT_TAIL(&tab->idlist, id, next); |
555 | /* Increment the number of identities. */ | 557 | /* Increment the number of identities. */ |
@@ -609,17 +611,17 @@ no_identities(SocketEntry *e, u_int type) | |||
609 | buffer_free(&msg); | 611 | buffer_free(&msg); |
610 | } | 612 | } |
611 | 613 | ||
612 | #ifdef SMARTCARD | 614 | #ifdef ENABLE_PKCS11 |
613 | static void | 615 | static void |
614 | process_add_smartcard_key(SocketEntry *e) | 616 | process_add_smartcard_key(SocketEntry *e) |
615 | { | 617 | { |
616 | char *sc_reader_id = NULL, *pin; | 618 | char *provider = NULL, *pin; |
617 | int i, type, version, success = 0, death = 0, confirm = 0; | 619 | int i, type, version, count = 0, success = 0, death = 0, confirm = 0; |
618 | Key **keys, *k; | 620 | Key **keys = NULL, *k; |
619 | Identity *id; | 621 | Identity *id; |
620 | Idtab *tab; | 622 | Idtab *tab; |
621 | 623 | ||
622 | sc_reader_id = buffer_get_string(&e->request, NULL); | 624 | provider = buffer_get_string(&e->request, NULL); |
623 | pin = buffer_get_string(&e->request, NULL); | 625 | pin = buffer_get_string(&e->request, NULL); |
624 | 626 | ||
625 | while (buffer_len(&e->request)) { | 627 | while (buffer_len(&e->request)) { |
@@ -633,30 +635,22 @@ process_add_smartcard_key(SocketEntry *e) | |||
633 | default: | 635 | default: |
634 | error("process_add_smartcard_key: " | 636 | error("process_add_smartcard_key: " |
635 | "Unknown constraint type %d", type); | 637 | "Unknown constraint type %d", type); |
636 | xfree(sc_reader_id); | ||
637 | xfree(pin); | ||
638 | goto send; | 638 | goto send; |
639 | } | 639 | } |
640 | } | 640 | } |
641 | if (lifetime && !death) | 641 | if (lifetime && !death) |
642 | death = time(NULL) + lifetime; | 642 | death = time(NULL) + lifetime; |
643 | 643 | ||
644 | keys = sc_get_keys(sc_reader_id, pin); | 644 | count = pkcs11_add_provider(provider, pin, &keys); |
645 | xfree(sc_reader_id); | 645 | for (i = 0; i < count; i++) { |
646 | xfree(pin); | ||
647 | |||
648 | if (keys == NULL || keys[0] == NULL) { | ||
649 | error("sc_get_keys failed"); | ||
650 | goto send; | ||
651 | } | ||
652 | for (i = 0; keys[i] != NULL; i++) { | ||
653 | k = keys[i]; | 646 | k = keys[i]; |
654 | version = k->type == KEY_RSA1 ? 1 : 2; | 647 | version = k->type == KEY_RSA1 ? 1 : 2; |
655 | tab = idtab_lookup(version); | 648 | tab = idtab_lookup(version); |
656 | if (lookup_identity(k, version) == NULL) { | 649 | if (lookup_identity(k, version) == NULL) { |
657 | id = xmalloc(sizeof(Identity)); | 650 | id = xcalloc(1, sizeof(Identity)); |
658 | id->key = k; | 651 | id->key = k; |
659 | id->comment = sc_get_key_label(k); | 652 | id->provider = xstrdup(provider); |
653 | id->comment = xstrdup(provider); /* XXX */ | ||
660 | id->death = death; | 654 | id->death = death; |
661 | id->confirm = confirm; | 655 | id->confirm = confirm; |
662 | TAILQ_INSERT_TAIL(&tab->idlist, id, next); | 656 | TAILQ_INSERT_TAIL(&tab->idlist, id, next); |
@@ -667,8 +661,13 @@ process_add_smartcard_key(SocketEntry *e) | |||
667 | } | 661 | } |
668 | keys[i] = NULL; | 662 | keys[i] = NULL; |
669 | } | 663 | } |
670 | xfree(keys); | ||
671 | send: | 664 | send: |
665 | if (pin) | ||
666 | xfree(pin); | ||
667 | if (provider) | ||
668 | xfree(provider); | ||
669 | if (keys) | ||
670 | xfree(keys); | ||
672 | buffer_put_int(&e->output, 1); | 671 | buffer_put_int(&e->output, 1); |
673 | buffer_put_char(&e->output, | 672 | buffer_put_char(&e->output, |
674 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | 673 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); |
@@ -677,42 +676,37 @@ send: | |||
677 | static void | 676 | static void |
678 | process_remove_smartcard_key(SocketEntry *e) | 677 | process_remove_smartcard_key(SocketEntry *e) |
679 | { | 678 | { |
680 | char *sc_reader_id = NULL, *pin; | 679 | char *provider = NULL, *pin = NULL; |
681 | int i, version, success = 0; | 680 | int version, success = 0; |
682 | Key **keys, *k = NULL; | 681 | Identity *id, *nxt; |
683 | Identity *id; | ||
684 | Idtab *tab; | 682 | Idtab *tab; |
685 | 683 | ||
686 | sc_reader_id = buffer_get_string(&e->request, NULL); | 684 | provider = buffer_get_string(&e->request, NULL); |
687 | pin = buffer_get_string(&e->request, NULL); | 685 | pin = buffer_get_string(&e->request, NULL); |
688 | keys = sc_get_keys(sc_reader_id, pin); | ||
689 | xfree(sc_reader_id); | ||
690 | xfree(pin); | 686 | xfree(pin); |
691 | 687 | ||
692 | if (keys == NULL || keys[0] == NULL) { | 688 | for (version = 1; version < 3; version++) { |
693 | error("sc_get_keys failed"); | 689 | tab = idtab_lookup(version); |
694 | goto send; | 690 | for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { |
695 | } | 691 | nxt = TAILQ_NEXT(id, next); |
696 | for (i = 0; keys[i] != NULL; i++) { | 692 | if (!strcmp(provider, id->provider)) { |
697 | k = keys[i]; | 693 | TAILQ_REMOVE(&tab->idlist, id, next); |
698 | version = k->type == KEY_RSA1 ? 1 : 2; | 694 | free_identity(id); |
699 | if ((id = lookup_identity(k, version)) != NULL) { | 695 | tab->nentries--; |
700 | tab = idtab_lookup(version); | 696 | } |
701 | TAILQ_REMOVE(&tab->idlist, id, next); | ||
702 | tab->nentries--; | ||
703 | free_identity(id); | ||
704 | success = 1; | ||
705 | } | 697 | } |
706 | key_free(k); | ||
707 | keys[i] = NULL; | ||
708 | } | 698 | } |
709 | xfree(keys); | 699 | if (pkcs11_del_provider(provider) == 0) |
710 | send: | 700 | success = 1; |
701 | else | ||
702 | error("process_remove_smartcard_key:" | ||
703 | " pkcs11_del_provider failed"); | ||
704 | xfree(provider); | ||
711 | buffer_put_int(&e->output, 1); | 705 | buffer_put_int(&e->output, 1); |
712 | buffer_put_char(&e->output, | 706 | buffer_put_char(&e->output, |
713 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | 707 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); |
714 | } | 708 | } |
715 | #endif /* SMARTCARD */ | 709 | #endif /* ENABLE_PKCS11 */ |
716 | 710 | ||
717 | /* dispatch incoming messages */ | 711 | /* dispatch incoming messages */ |
718 | 712 | ||
@@ -797,7 +791,7 @@ process_message(SocketEntry *e) | |||
797 | case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: | 791 | case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: |
798 | process_remove_all_identities(e, 2); | 792 | process_remove_all_identities(e, 2); |
799 | break; | 793 | break; |
800 | #ifdef SMARTCARD | 794 | #ifdef ENABLE_PKCS11 |
801 | case SSH_AGENTC_ADD_SMARTCARD_KEY: | 795 | case SSH_AGENTC_ADD_SMARTCARD_KEY: |
802 | case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED: | 796 | case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED: |
803 | process_add_smartcard_key(e); | 797 | process_add_smartcard_key(e); |
@@ -805,7 +799,7 @@ process_message(SocketEntry *e) | |||
805 | case SSH_AGENTC_REMOVE_SMARTCARD_KEY: | 799 | case SSH_AGENTC_REMOVE_SMARTCARD_KEY: |
806 | process_remove_smartcard_key(e); | 800 | process_remove_smartcard_key(e); |
807 | break; | 801 | break; |
808 | #endif /* SMARTCARD */ | 802 | #endif /* ENABLE_PKCS11 */ |
809 | default: | 803 | default: |
810 | /* Unknown message. Respond with failure. */ | 804 | /* Unknown message. Respond with failure. */ |
811 | error("Unknown message %d", type); | 805 | error("Unknown message %d", type); |
@@ -1009,6 +1003,9 @@ static void | |||
1009 | cleanup_handler(int sig) | 1003 | cleanup_handler(int sig) |
1010 | { | 1004 | { |
1011 | cleanup_socket(); | 1005 | cleanup_socket(); |
1006 | #ifdef ENABLE_PKCS11 | ||
1007 | pkcs11_terminate(); | ||
1008 | #endif | ||
1012 | _exit(2); | 1009 | _exit(2); |
1013 | } | 1010 | } |
1014 | 1011 | ||
@@ -1255,6 +1252,10 @@ main(int ac, char **av) | |||
1255 | #endif | 1252 | #endif |
1256 | 1253 | ||
1257 | skip: | 1254 | skip: |
1255 | |||
1256 | #ifdef ENABLE_PKCS11 | ||
1257 | pkcs11_init(0); | ||
1258 | #endif | ||
1258 | new_socket(AUTH_SOCKET, sock); | 1259 | new_socket(AUTH_SOCKET, sock); |
1259 | if (ac > 0) | 1260 | if (ac > 0) |
1260 | parent_alive_interval = 10; | 1261 | parent_alive_interval = 10; |