diff options
Diffstat (limited to 'src/pki')
-rw-r--r-- | src/pki/Makefile.am | 2 | ||||
-rw-r--r-- | src/pki/Makefile.in | 22 | ||||
-rw-r--r-- | src/pki/commands/issue.c | 34 | ||||
-rw-r--r-- | src/pki/commands/print.c | 61 | ||||
-rw-r--r-- | src/pki/commands/pub.c | 18 | ||||
-rw-r--r-- | src/pki/commands/req.c | 2 | ||||
-rw-r--r-- | src/pki/commands/self.c | 19 | ||||
-rw-r--r-- | src/pki/commands/signcrl.c | 32 | ||||
-rw-r--r-- | src/pki/pki.c | 67 |
9 files changed, 222 insertions, 35 deletions
diff --git a/src/pki/Makefile.am b/src/pki/Makefile.am index 99e9bc581..482f83834 100644 --- a/src/pki/Makefile.am +++ b/src/pki/Makefile.am @@ -16,4 +16,4 @@ pki.o : $(top_builddir)/config.status INCLUDES = -I$(top_srcdir)/src/libstrongswan AM_CFLAGS = \ - -DPLUGINS=\""${libstrongswan_plugins}\"" + -DPLUGINS=\""${pki_plugins}\"" diff --git a/src/pki/Makefile.in b/src/pki/Makefile.in index 8f08777bb..0ec6f9c0b 100644 --- a/src/pki/Makefile.in +++ b/src/pki/Makefile.in @@ -45,6 +45,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/config/lt~obsolete.m4 \ $(top_srcdir)/m4/macros/with.m4 \ $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) @@ -142,6 +143,8 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PTHREADLIB = @PTHREADLIB@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ @@ -173,14 +176,17 @@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +c_plugins = @c_plugins@ datadir = @datadir@ datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ default_pkcs11 = @default_pkcs11@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gtk_CFLAGS = @gtk_CFLAGS@ gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -195,24 +201,31 @@ ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ -libhydra_plugins = @libhydra_plugins@ -libstrongswan_plugins = @libstrongswan_plugins@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ pdfdir = @pdfdir@ piddir = @piddir@ +pki_plugins = @pki_plugins@ plugindir = @plugindir@ pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ @@ -220,7 +233,10 @@ random_device = @random_device@ resolv_conf = @resolv_conf@ routing_table = @routing_table@ routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ @@ -246,7 +262,7 @@ pki_SOURCES = pki.c pki.h command.c command.h \ pki_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la INCLUDES = -I$(top_srcdir)/src/libstrongswan AM_CFLAGS = \ - -DPLUGINS=\""${libstrongswan_plugins}\"" + -DPLUGINS=\""${pki_plugins}\"" all: all-am diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index 2002cd555..8ea852e31 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -35,7 +35,7 @@ static int issue() public_key_t *public = NULL; bool pkcs10 = FALSE; char *file = NULL, *dn = NULL, *hex = NULL, *cacert = NULL, *cakey = NULL; - char *error = NULL; + char *error = NULL, *keyid = NULL; identification_t *id = NULL; linked_list_t *san, *cdps, *ocsp; int lifetime = 1095; @@ -85,6 +85,9 @@ static int issue() case 'k': cakey = arg; continue; + case 'x': + keyid = arg; + continue; case 'd': dn = arg; continue; @@ -153,9 +156,9 @@ static int issue() error = "--cacert is required"; goto usage; } - if (!cakey) + if (!cakey && !keyid) { - error = "--cakey is required"; + error = "--cakey or --keyid is required"; goto usage; } if (dn) @@ -190,12 +193,24 @@ static int issue() } DBG2(DBG_LIB, "Reading ca private key:"); - private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, - public->get_type(public), - BUILD_FROM_FILE, cakey, BUILD_END); + if (cakey) + { + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + public->get_type(public), + BUILD_FROM_FILE, cakey, BUILD_END); + } + else + { + chunk_t chunk; + + chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, chunk, BUILD_END); + free(chunk.ptr); + } if (!private) { - error = "parsing CA private key failed"; + error = "loading CA private key failed"; goto end; } if (!private->belongs_to(private, public)) @@ -354,8 +369,8 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { issue, 'i', "issue", "issue a certificate using a CA certificate and key", - {"[--in file] [--type pub|pkcs10]", - " --cacert file --cakey file --dn subject-dn [--san subjectAltName]+", + {"[--in file] [--type pub|pkcs10] --cakey file | --cakeyid hex", + " --cacert file --dn subject-dn [--san subjectAltName]+", "[--lifetime days] [--serial hex] [--crl uri]+ [--ocsp uri]+", "[--ca] [--pathlen len] [--flag serverAuth|clientAuth|ocspSigning]+", "[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"}, @@ -365,6 +380,7 @@ static void __attribute__ ((constructor))reg() {"type", 't', 1, "type of input, default: pub"}, {"cacert", 'c', 1, "CA certificate file"}, {"cakey", 'k', 1, "CA private key file"}, + {"cakeyid", 'x', 1, "keyid on smartcard of CA private key"}, {"dn", 'd', 1, "distinguished name to include as subject"}, {"san", 'a', 1, "subjectAltName to include in certificate"}, {"lifetime",'l', 1, "days the certificate is valid, default: 1095"}, diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c index 6d5462783..870dca920 100644 --- a/src/pki/commands/print.c +++ b/src/pki/commands/print.c @@ -17,6 +17,7 @@ #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> +#include <credentials/certificates/crl.h> #include <selectors/traffic_selector.h> #include <time.h> @@ -29,7 +30,7 @@ static void print_pubkey(public_key_t *key) chunk_t chunk; printf("pubkey: %N %d bits\n", key_type_names, key->get_type(key), - key->get_keysize(key) * 8); + key->get_keysize(key)); if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk)) { printf("keyid: %#B\n", &chunk); @@ -202,6 +203,44 @@ static void print_x509(x509_t *x509) } /** + * Print CRL specific information + */ +static void print_crl(crl_t *crl) +{ + enumerator_t *enumerator; + time_t ts; + crl_reason_t reason; + chunk_t chunk; + int count = 0; + char buf[64]; + struct tm tm; + + chunk = crl->get_serial(crl); + printf("serial: %#B\n", &chunk); + chunk = crl->get_authKeyIdentifier(crl); + printf("authKeyId: %#B\n", &chunk); + + enumerator = crl->create_enumerator(crl); + while (enumerator->enumerate(enumerator, &chunk, &ts, &reason)) + { + count++; + } + enumerator->destroy(enumerator); + + printf("%d revoked certificate%s%s\n", count, + count == 1 ? "" : "s", count ? ":" : ""); + enumerator = crl->create_enumerator(crl); + while (enumerator->enumerate(enumerator, &chunk, &ts, &reason)) + { + localtime_r(&ts, &tm); + strftime(buf, sizeof(buf), "%F %T", &tm); + printf(" %#B %N %s\n", &chunk, crl_reason_names, reason, buf); + count++; + } + enumerator->destroy(enumerator); +} + +/** * Print certificate information */ static void print_cert(certificate_t *cert) @@ -212,7 +251,10 @@ static void print_cert(certificate_t *cert) now = time(NULL); printf("cert: %N\n", certificate_type_names, cert->get_type(cert)); - printf("subject: \"%Y\"\n", cert->get_subject(cert)); + if (cert->get_type(cert) != CERT_X509_CRL) + { + printf("subject: \"%Y\"\n", cert->get_subject(cert)); + } printf("issuer: \"%Y\"\n", cert->get_issuer(cert)); cert->get_validity(cert, &now, ¬Before, ¬After); @@ -240,22 +282,20 @@ static void print_cert(certificate_t *cert) case CERT_X509: print_x509((x509_t*)cert); break; + case CERT_X509_CRL: + print_crl((crl_t*)cert); + break; default: printf("parsing certificate subtype %N not implemented\n", certificate_type_names, cert->get_type(cert)); break; } - key = cert->get_public_key(cert); if (key) { print_pubkey(key); key->destroy(key); } - else - { - printf("unable to extract public key\n"); - } } /** @@ -280,6 +320,11 @@ static int print() type = CRED_CERTIFICATE; subtype = CERT_X509; } + else if (streq(arg, "crl")) + { + type = CRED_CERTIFICATE; + subtype = CERT_X509_CRL; + } else if (streq(arg, "pub")) { type = CRED_PUBLIC_KEY; @@ -358,7 +403,7 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { print, 'a', "print", "print a credential in a human readable form", - {"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509]"}, + {"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509|crl]"}, { {"help", 'h', 0, "show usage information"}, {"in", 'i', 1, "input file, default: stdin"}, diff --git a/src/pki/commands/pub.c b/src/pki/commands/pub.c index fc2614c7d..30078a8fa 100644 --- a/src/pki/commands/pub.c +++ b/src/pki/commands/pub.c @@ -30,7 +30,7 @@ static int pub() private_key_t *private; public_key_t *public; chunk_t encoding; - char *file = NULL; + char *file = NULL, *keyid = NULL; void *cred; char *arg; @@ -75,6 +75,9 @@ static int pub() case 'i': file = arg; continue; + case 'x': + keyid = arg; + continue; case EOF: break; default: @@ -87,6 +90,15 @@ static int pub() cred = lib->creds->create(lib->creds, type, subtype, BUILD_FROM_FILE, file, BUILD_END); } + else if (keyid) + { + chunk_t chunk; + + chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); + cred = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, chunk, BUILD_END); + free(chunk.ptr); + } else { cred = lib->creds->create(lib->creds, type, subtype, @@ -145,10 +157,12 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { pub, 'p', "pub", "extract the public key from a private key/certificate", - {"[--in file] [--type rsa|ecdsa|pkcs10|x509] [--outform der|pem|pgp]"}, + {"[--in file|--keyid hex] [--type rsa|ecdsa|pkcs10|x509]", + "[--outform der|pem|pgp]"}, { {"help", 'h', 0, "show usage information"}, {"in", 'i', 1, "input file, default: stdin"}, + {"keyid", 'x', 1, "keyid on smartcard of private key"}, {"type", 't', 1, "type of credential, default: rsa"}, {"outform", 'f', 1, "encoding of extracted public key"}, } diff --git a/src/pki/commands/req.c b/src/pki/commands/req.c index a1ae2f515..d1ca45e1a 100644 --- a/src/pki/commands/req.c +++ b/src/pki/commands/req.c @@ -127,7 +127,7 @@ static int req() BUILD_SIGNING_KEY, private, BUILD_SUBJECT, id, BUILD_SUBJECT_ALTNAMES, san, - BUILD_PASSPHRASE, challenge_password, + BUILD_CHALLENGE_PWD, challenge_password, BUILD_DIGEST_ALG, digest, BUILD_END); if (!cert) diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c index 71776c745..5e6f0bd14 100644 --- a/src/pki/commands/self.c +++ b/src/pki/commands/self.c @@ -32,7 +32,7 @@ static int self() certificate_t *cert = NULL; private_key_t *private = NULL; public_key_t *public = NULL; - char *file = NULL, *dn = NULL, *hex = NULL, *error = NULL; + char *file = NULL, *dn = NULL, *hex = NULL, *error = NULL, *keyid = NULL; identification_t *id = NULL; linked_list_t *san, *ocsp; int lifetime = 1095; @@ -78,6 +78,9 @@ static int self() case 'i': file = arg; continue; + case 'x': + keyid = arg; + continue; case 'd': dn = arg; continue; @@ -149,6 +152,15 @@ static int self() private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, BUILD_FROM_FILE, file, BUILD_END); } + else if (keyid) + { + chunk_t chunk; + + chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, chunk, BUILD_END); + free(chunk.ptr); + } else { private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, @@ -156,7 +168,7 @@ static int self() } if (!private) { - error = "parsing private key failed"; + error = "loading private key failed"; goto end; } public = private->get_public_key(private); @@ -242,7 +254,7 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { self, 's', "self", "create a self signed certificate", - {"[--in file] [--type rsa|ecdsa]", + {"[--in file | --keyid hex] [--type rsa|ecdsa]", " --dn distinguished-name [--san subjectAltName]+", "[--lifetime days] [--serial hex] [--ca] [--ocsp uri]+", "[--flag serverAuth|clientAuth|ocspSigning]+", @@ -250,6 +262,7 @@ static void __attribute__ ((constructor))reg() { {"help", 'h', 0, "show usage information"}, {"in", 'i', 1, "private key input file, default: stdin"}, + {"keyid", 'x', 1, "keyid on smartcard of private key"}, {"type", 't', 1, "type of input key, default: rsa"}, {"dn", 'd', 1, "subject and issuer distinguished name"}, {"san", 'a', 1, "subjectAltName to include in certificate"}, diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c index b7163a153..24bf9123f 100644 --- a/src/pki/commands/signcrl.c +++ b/src/pki/commands/signcrl.c @@ -110,7 +110,7 @@ static int sign_crl() x509_t *x509; hash_algorithm_t digest = HASH_SHA1; char *arg, *cacert = NULL, *cakey = NULL, *lastupdate = NULL, *error = NULL; - char serial[512], crl_serial[8]; + char serial[512], crl_serial[8], *keyid = NULL; int serial_len = 0; crl_reason_t reason = CRL_REASON_UNSPECIFIED; time_t thisUpdate, nextUpdate, date = time(NULL); @@ -143,6 +143,9 @@ static int sign_crl() case 'k': cakey = arg; continue; + case 'x': + keyid = arg; + continue; case 'a': lastupdate = arg; continue; @@ -245,9 +248,9 @@ static int sign_crl() error = "--cacert is required"; goto usage; } - if (!cakey) + if (!cakey && !keyid) { - error = "--cakey is required"; + error = "--cakey or --keyid is required"; goto usage; } @@ -270,12 +273,24 @@ static int sign_crl() error = "extracting CA certificate public key failed"; goto error; } - private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, - public->get_type(public), - BUILD_FROM_FILE, cakey, BUILD_END); + if (cakey) + { + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + public->get_type(public), + BUILD_FROM_FILE, cakey, BUILD_END); + } + else + { + chunk_t chunk; + + chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, chunk, BUILD_END); + free(chunk.ptr); + } if (!private) { - error = "parsing CA private key failed"; + error = "loading CA private key failed"; goto error; } if (!private->belongs_to(private, public)) @@ -359,7 +374,7 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { sign_crl, 'c', "signcrl", "issue a CRL using a CA certificate and key", - {"--cacert file --cakey file --lifetime days", + {"--cacert file --cakey file | --cakeyid hex --lifetime days", "[ [--reason key-compromise|ca-compromise|affiliation-changed|", " superseded|cessation-of-operation|certificate-hold]", " [--date timestamp]", @@ -369,6 +384,7 @@ static void __attribute__ ((constructor))reg() {"help", 'h', 0, "show usage information"}, {"cacert", 'c', 1, "CA certificate file"}, {"cakey", 'k', 1, "CA private key file"}, + {"cakeyid", 'x', 1, "keyid on smartcard of CA private key"}, {"lifetime",'l', 1, "days the CRL gets a nextUpdate, default: 15"}, {"lastcrl", 'a', 1, "CRL of lastUpdate to copy revocations from"}, {"cert", 'z', 1, "certificate file to revoke"}, diff --git a/src/pki/pki.c b/src/pki/pki.c index d5dd03fa0..3005d2fcd 100644 --- a/src/pki/pki.c +++ b/src/pki/pki.c @@ -16,7 +16,10 @@ #include "command.h" #include "pki.h" +#include <unistd.h> + #include <debug.h> +#include <credentials/sets/callback_cred.h> /** * Convert a form string to a encoding type @@ -109,6 +112,67 @@ hash_algorithm_t get_digest(char *name) } /** + * Callback credential set pki uses + */ +static callback_cred_t *cb_set; + +/** + * Callback function to receive credentials + */ +static shared_key_t* cb(void *data, shared_key_type_t type, + identification_t *me, identification_t *other, + id_match_t *match_me, id_match_t *match_other) +{ + char buf[64], *label, *secret; + + switch (type) + { + case SHARED_PIN: + label = "Smartcard PIN"; + break; + case SHARED_PRIVATE_KEY_PASS: + label = "Private key passphrase"; + break; + default: + return NULL; + } + snprintf(buf, sizeof(buf), "%s: ", label); + secret = getpass(buf); + if (secret) + { + if (match_me) + { + *match_me = ID_MATCH_PERFECT; + } + if (match_other) + { + *match_other = ID_MATCH_NONE; + } + return shared_key_create(type, + chunk_clone(chunk_create(secret, strlen(secret)))); + } + return NULL; +} + +/** + * Register PIN/Passphrase callback function + */ +static void add_callback() +{ + cb_set = callback_cred_create_shared(cb, NULL); + lib->credmgr->add_set(lib->credmgr, &cb_set->set); +} + +/** + * Unregister PIN/Passphrase callback function + */ +static void remove_callback() +{ + lib->credmgr->remove_set(lib->credmgr, &cb_set->set); + cb_set->destroy(cb_set); +} + +/** * Library initialization and operation parsing */ int main(int argc, char *argv[]) @@ -129,6 +193,9 @@ int main(int argc, char *argv[]) { exit(SS_RC_INITIALIZATION_FAILED); } + + add_callback(); + atexit(remove_callback); return command_dispatch(argc, argv); } |