diff options
author | Romain Francoise <rfrancoise@debian.org> | 2014-04-15 19:34:32 +0200 |
---|---|---|
committer | Romain Francoise <rfrancoise@debian.org> | 2014-04-15 19:34:32 +0200 |
commit | c5ebfc7b9c16551fe825dc1d79c3f7e2f096f6c9 (patch) | |
tree | d4e2118cbd411caa1a0528eac831030109bc6e65 /src/pki/commands | |
parent | 15fb7904f4431a6e7c305fd08732458f7f885e7e (diff) | |
download | vyos-strongswan-c5ebfc7b9c16551fe825dc1d79c3f7e2f096f6c9.tar.gz vyos-strongswan-c5ebfc7b9c16551fe825dc1d79c3f7e2f096f6c9.zip |
Import upstream version 5.1.3
Diffstat (limited to 'src/pki/commands')
-rw-r--r-- | src/pki/commands/acert.c | 292 | ||||
-rw-r--r-- | src/pki/commands/issue.c | 34 | ||||
-rw-r--r-- | src/pki/commands/print.c | 95 | ||||
-rw-r--r-- | src/pki/commands/self.c | 33 | ||||
-rw-r--r-- | src/pki/commands/signcrl.c | 28 |
5 files changed, 462 insertions, 20 deletions
diff --git a/src/pki/commands/acert.c b/src/pki/commands/acert.c new file mode 100644 index 000000000..d49365db5 --- /dev/null +++ b/src/pki/commands/acert.c @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <time.h> +#include <errno.h> + +#include "pki.h" + +#include <utils/debug.h> +#include <asn1/asn1.h> +#include <collections/linked_list.h> +#include <credentials/certificates/certificate.h> +#include <credentials/certificates/x509.h> +#include <credentials/certificates/ac.h> + +/** + * Issue an attribute certificate + */ +static int acert() +{ + cred_encoding_type_t form = CERT_ASN1_DER; + hash_algorithm_t digest = HASH_SHA1; + certificate_t *ac = NULL, *cert = NULL, *issuer =NULL; + private_key_t *private = NULL; + public_key_t *public = NULL; + char *file = NULL, *hex = NULL, *issuercert = NULL, *issuerkey = NULL; + char *error = NULL, *keyid = NULL; + linked_list_t *groups; + chunk_t serial = chunk_empty, encoding = chunk_empty; + time_t not_before, not_after, lifetime = 24 * 60 * 60; + char *datenb = NULL, *datena = NULL, *dateform = NULL; + rng_t *rng; + char *arg; + + groups = linked_list_create(); + + while (TRUE) + { + switch (command_getopt(&arg)) + { + case 'h': + goto usage; + case 'g': + digest = enum_from_name(hash_algorithm_short_names, arg); + if (digest == -1) + { + error = "invalid --digest type"; + goto usage; + } + continue; + case 'i': + file = arg; + continue; + case 'm': + groups->insert_last(groups, arg); + continue; + case 'c': + issuercert = arg; + continue; + case 'k': + issuerkey = arg; + continue; + case 'x': + keyid = arg; + continue; + case 'l': + lifetime = atoi(arg) * 60 * 60; + if (!lifetime) + { + error = "invalid --lifetime value"; + goto usage; + } + continue; + case 'D': + dateform = arg; + continue; + case 'F': + datenb = arg; + continue; + case 'T': + datena = arg; + continue; + case 's': + hex = arg; + continue; + case 'f': + if (!get_form(arg, &form, CRED_CERTIFICATE)) + { + error = "invalid output format"; + goto usage; + } + continue; + case EOF: + break; + default: + error = "invalid --acert option"; + goto usage; + } + break; + } + + if (!calculate_lifetime(dateform, datenb, datena, lifetime, + ¬_before, ¬_after)) + { + error = "invalid --not-before/after datetime"; + goto usage; + } + + if (!issuercert) + { + error = "--issuercert is required"; + goto usage; + } + if (!issuerkey && !keyid) + { + error = "--issuerkey or --issuerkeyid is required"; + goto usage; + } + + issuer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, issuercert, BUILD_END); + if (!issuer) + { + error = "parsing issuer certificate failed"; + goto end; + } + public = issuer->get_public_key(issuer); + if (!public) + { + error = "extracting issuer certificate public key failed"; + goto end; + } + if (issuerkey) + { + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + public->get_type(public), + BUILD_FROM_FILE, issuerkey, 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 = "loading issuer private key failed"; + goto end; + } + if (!private->belongs_to(private, public)) + { + error = "issuer private key does not match issuer certificate"; + goto end; + } + + if (hex) + { + serial = chunk_from_hex(chunk_create(hex, strlen(hex)), NULL); + } + else + { + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) + { + error = "no random number generator found"; + goto end; + } + if (!rng_allocate_bytes_not_zero(rng, 8, &serial, FALSE)) + { + error = "failed to generate serial number"; + rng->destroy(rng); + goto end; + } + serial.ptr[0] &= 0x7F; + rng->destroy(rng); + } + + if (file) + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, BUILD_END); + } + else + { + if (!chunk_from_fd(0, &encoding)) + { + fprintf(stderr, "%s: ", strerror(errno)); + error = "reading public key failed"; + goto end; + } + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB, encoding, BUILD_END); + chunk_free(&encoding); + } + if (!cert) + { + error = "parsing user certificate failed"; + goto end; + } + + ac = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509_AC, + BUILD_CERT, cert, + BUILD_NOT_BEFORE_TIME, not_before, + BUILD_NOT_AFTER_TIME, not_after, + BUILD_SERIAL, serial, + BUILD_AC_GROUP_STRINGS, groups, + BUILD_SIGNING_CERT, issuer, + BUILD_SIGNING_KEY, private, + BUILD_END); + if (!ac) + { + error = "generating attribute certificate failed"; + goto end; + } + if (!ac->get_encoding(ac, form, &encoding)) + { + error = "encoding attribute certificate failed"; + goto end; + } + if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1) + { + error = "writing attribute certificate key failed"; + goto end; + } + +end: + DESTROY_IF(ac); + DESTROY_IF(cert); + DESTROY_IF(issuer); + DESTROY_IF(public); + DESTROY_IF(private); + groups->destroy(groups); + free(encoding.ptr); + free(serial.ptr); + + if (error) + { + fprintf(stderr, "%s\n", error); + return 1; + } + return 0; + +usage: + groups->destroy(groups); + return command_usage(error); +} + +/** + * Register the command. + */ +static void __attribute__ ((constructor))reg() +{ + command_register((command_t) { + acert, 'z', "acert", + "issue an attribute certificate", + {"[--in file] [--group name]* --issuerkey file|--issuerkeyid hex", + " --issuercert file [--serial hex] [--lifetime hours]", + " [--not-before datetime] [--not-after datetime] [--dateform form]", + "[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"}, + { + {"help", 'h', 0, "show usage information"}, + {"in", 'i', 1, "holder certificate, default: stdin"}, + {"group", 'm', 1, "group membership string to include"}, + {"issuercert", 'c', 1, "issuer certificate file"}, + {"issuerkey", 'k', 1, "issuer private key file"}, + {"issuerkeyid", 'x', 1, "keyid on smartcard of issuer private key"}, + {"serial", 's', 1, "serial number in hex, default: random"}, + {"lifetime", 'l', 1, "hours the acert is valid, default: 24"}, + {"not-before", 'F', 1, "date/time the validity of the AC starts"}, + {"not-after", 'T', 1, "date/time the validity of the AC ends"}, + {"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"}, + {"digest", 'g', 1, "digest for signature creation, default: sha1"}, + {"outform", 'f', 1, "encoding of generated cert, default: der"}, + } + }); +} diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index d5c33b89f..d03326e3d 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -72,8 +72,8 @@ static int issue() int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT; chunk_t serial = chunk_empty; chunk_t encoding = chunk_empty; - time_t lifetime = 1095; - time_t not_before, not_after; + time_t not_before, not_after, lifetime = 1095 * 24 * 60 * 60; + char *datenb = NULL, *datena = NULL, *dateform = NULL; x509_flag_t flags = 0; x509_t *x509; x509_cdp_t *cdp = NULL; @@ -132,13 +132,22 @@ static int issue() san->insert_last(san, identification_create_from_string(arg)); continue; case 'l': - lifetime = atoi(arg); + lifetime = atoi(arg) * 24 * 60 * 60; if (!lifetime) { error = "invalid --lifetime value"; goto usage; } continue; + case 'D': + dateform = arg; + continue; + case 'F': + datenb = arg; + continue; + case 'T': + datena = arg; + continue; case 's': hex = arg; continue; @@ -242,6 +251,10 @@ static int issue() { flags |= X509_OCSP_SIGNER; } + else if (streq(arg, "msSmartcardLogon")) + { + flags |= X509_MS_SMARTCARD_LOGON; + } continue; case 'f': if (!get_form(arg, &form, CRED_CERTIFICATE)) @@ -285,6 +298,12 @@ static int issue() error = "--cakey or --keyid is required"; goto usage; } + if (!calculate_lifetime(dateform, datenb, datena, lifetime, + ¬_before, ¬_after)) + { + error = "invalid --not-before/after datetime"; + goto usage; + } if (dn && *dn) { id = identification_create_from_string(dn); @@ -363,6 +382,7 @@ static int issue() rng->destroy(rng); goto end; } + serial.ptr[0] &= 0x7F; rng->destroy(rng); } @@ -454,9 +474,6 @@ static int issue() chunk_from_chars(ASN1_SEQUENCE, 0)); } - not_before = time(NULL); - not_after = not_before + lifetime * 24 * 60 * 60; - cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_SIGNING_KEY, private, BUILD_SIGNING_CERT, ca, BUILD_PUBLIC_KEY, public, BUILD_SUBJECT, id, @@ -536,7 +553,7 @@ static void __attribute__ ((constructor))reg() {"[--in file] [--type pub|pkcs10] --cakey file|--cakeyid hex", " --cacert file [--dn subject-dn] [--san subjectAltName]+", "[--lifetime days] [--serial hex] [--ca] [--pathlen len]", - "[--flag serverAuth|clientAuth|crlSign|ocspSigning]+", + "[--flag serverAuth|clientAuth|crlSign|ocspSigning|msSmartcardLogon]+", "[--crl uri [--crlissuer i]]+ [--ocsp uri]+ [--nc-permitted name]", "[--nc-excluded name] [--policy-mapping issuer-oid:subject-oid]", "[--policy-explicit len] [--policy-inhibit len] [--policy-any len]", @@ -552,6 +569,9 @@ static void __attribute__ ((constructor))reg() {"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"}, + {"not-before", 'F', 1, "date/time the validity of the cert starts"}, + {"not-after", 'T', 1, "date/time the validity of the cert ends"}, + {"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"}, {"serial", 's', 1, "serial number in hex, default: random"}, {"ca", 'b', 0, "include CA basicConstraint, default: no"}, {"pathlen", 'p', 1, "set path length constraint"}, diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c index 077c1ef3e..15ace035d 100644 --- a/src/pki/commands/print.c +++ b/src/pki/commands/print.c @@ -16,9 +16,11 @@ #include "pki.h" #include <asn1/asn1.h> +#include <asn1/oid.h> #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> #include <credentials/certificates/crl.h> +#include <credentials/certificates/ac.h> #include <selectors/traffic_selector.h> #include <time.h> @@ -138,6 +140,10 @@ static void print_x509(x509_t *x509) { printf("iKEIntermediate "); } + if (flags & X509_MS_SMARTCARD_LOGON) + { + printf("msSmartcardLogon "); + } if (flags & X509_SELF_SIGNED) { printf("self-signed "); @@ -388,6 +394,85 @@ static void print_crl(crl_t *crl) } /** + * Print AC specific information + */ +static void print_ac(ac_t *ac) +{ + ac_group_type_t type; + identification_t *id; + enumerator_t *groups; + chunk_t chunk; + bool first = TRUE; + + chunk = chunk_skip_zero(ac->get_serial(ac)); + printf("serial: %#B\n", &chunk); + + id = ac->get_holderIssuer(ac); + if (id) + { + printf("hissuer: \"%Y\"\n", id); + } + chunk = chunk_skip_zero(ac->get_holderSerial(ac)); + if (chunk.ptr) + { + printf("hserial: %#B\n", &chunk); + } + groups = ac->create_group_enumerator(ac); + while (groups->enumerate(groups, &type, &chunk)) + { + int oid; + char *str; + + if (first) + { + printf("groups: "); + first = FALSE; + } + else + { + printf(" "); + } + switch (type) + { + case AC_GROUP_TYPE_STRING: + printf("%.*s", (int)chunk.len, chunk.ptr); + break; + case AC_GROUP_TYPE_OID: + oid = asn1_known_oid(chunk); + if (oid == OID_UNKNOWN) + { + str = asn1_oid_to_string(chunk); + if (str) + { + printf("%s", str); + free(str); + } + else + { + printf("OID:%#B", &chunk); + } + } + else + { + printf("%s", oid_names[oid].name); + } + break; + case AC_GROUP_TYPE_OCTETS: + printf("%#B", &chunk); + break; + } + printf("\n"); + } + groups->destroy(groups); + + chunk = ac->get_authKeyIdentifier(ac); + if (chunk.ptr) + { + printf("authkey: %#B\n", &chunk); + } +} + +/** * Print certificate information */ static void print_cert(certificate_t *cert) @@ -432,6 +517,9 @@ static void print_cert(certificate_t *cert) case CERT_X509_CRL: print_crl((crl_t*)cert); break; + case CERT_X509_AC: + print_ac((ac_t*)cert); + break; default: printf("parsing certificate subtype %N not implemented\n", certificate_type_names, cert->get_type(cert)); @@ -472,6 +560,11 @@ static int print() type = CRED_CERTIFICATE; subtype = CERT_X509_CRL; } + else if (streq(arg, "ac")) + { + type = CRED_CERTIFICATE; + subtype = CERT_X509_AC; + } else if (streq(arg, "pub")) { type = CRED_PUBLIC_KEY; @@ -558,7 +651,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|crl]"}, + {"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509|crl|ac]"}, { {"help", 'h', 0, "show usage information"}, {"in", 'i', 1, "input file, default: stdin"}, diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c index c28c9c291..a35a42b89 100644 --- a/src/pki/commands/self.c +++ b/src/pki/commands/self.c @@ -60,8 +60,8 @@ static int self() int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT; chunk_t serial = chunk_empty; chunk_t encoding = chunk_empty; - time_t lifetime = 1095; - time_t not_before, not_after; + time_t not_before, not_after, lifetime = 1095 * 24 * 60 * 60; + char *datenb = NULL, *datena = NULL, *dateform = NULL; x509_flag_t flags = 0; x509_cert_policy_t *policy = NULL; char *arg; @@ -115,13 +115,22 @@ static int self() san->insert_last(san, identification_create_from_string(arg)); continue; case 'l': - lifetime = atoi(arg); + lifetime = atoi(arg) * 24 * 60 * 60; if (!lifetime) { error = "invalid --lifetime value"; goto usage; } continue; + case 'D': + dateform = arg; + continue; + case 'F': + datenb = arg; + continue; + case 'T': + datena = arg; + continue; case 's': hex = arg; continue; @@ -225,6 +234,10 @@ static int self() { flags |= X509_OCSP_SIGNER; } + else if (streq(arg, "msSmartcardLogon")) + { + flags |= X509_MS_SMARTCARD_LOGON; + } continue; case 'f': if (!get_form(arg, &form, CRED_CERTIFICATE)) @@ -250,6 +263,12 @@ static int self() error = "--dn is required"; goto usage; } + if (!calculate_lifetime(dateform, datenb, datena, lifetime, + ¬_before, ¬_after)) + { + error = "invalid --not-before/after datetime"; + goto usage; + } id = identification_create_from_string(dn); if (id->get_type(id) != ID_DER_ASN1_DN) { @@ -314,10 +333,9 @@ static int self() rng->destroy(rng); goto end; } + serial.ptr[0] &= 0x7F; rng->destroy(rng); } - not_before = time(NULL); - not_after = not_before + lifetime * 24 * 60 * 60; cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_SIGNING_KEY, private, BUILD_PUBLIC_KEY, public, BUILD_SUBJECT, id, BUILD_NOT_BEFORE_TIME, not_before, @@ -391,7 +409,7 @@ static void __attribute__ ((constructor))reg() {" [--in file|--keyid hex] [--type rsa|ecdsa]", " --dn distinguished-name [--san subjectAltName]+", "[--lifetime days] [--serial hex] [--ca] [--ocsp uri]+", - "[--flag serverAuth|clientAuth|crlSign|ocspSigning]+", + "[--flag serverAuth|clientAuth|crlSign|ocspSigning|msSmartcardLogon]+", "[--nc-permitted name] [--nc-excluded name]", "[--policy-map issuer-oid:subject-oid]", "[--policy-explicit len] [--policy-inhibit len] [--policy-any len]", @@ -405,6 +423,9 @@ static void __attribute__ ((constructor))reg() {"dn", 'd', 1, "subject and issuer distinguished name"}, {"san", 'a', 1, "subjectAltName to include in certificate"}, {"lifetime", 'l', 1, "days the certificate is valid, default: 1095"}, + {"not-before", 'F', 1, "date/time the validity of the cert starts"}, + {"not-after", 'T', 1, "date/time the validity of the cert ends"}, + {"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"}, {"serial", 's', 1, "serial number in hex, default: random"}, {"ca", 'b', 0, "include CA basicConstraint, default: no"}, {"pathlen", 'p', 1, "set path length constraint"}, diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c index 4f9dd291d..c9eebbf59 100644 --- a/src/pki/commands/signcrl.c +++ b/src/pki/commands/signcrl.c @@ -124,7 +124,8 @@ static int sign_crl() int serial_len = 0; crl_reason_t reason = CRL_REASON_UNSPECIFIED; time_t thisUpdate, nextUpdate, date = time(NULL); - time_t lifetime = 15; + time_t lifetime = 15 * 24 * 60 * 60; + char *datetu = NULL, *datenu = NULL, *dateform = NULL; linked_list_t *list, *cdps; enumerator_t *enumerator, *lastenum = NULL; x509_cdp_t *cdp; @@ -161,13 +162,22 @@ static int sign_crl() lastupdate = arg; continue; case 'l': - lifetime = atoi(arg); + lifetime = atoi(arg) * 24 * 60 * 60; if (!lifetime) { - error = "invalid lifetime"; + error = "invalid --lifetime value"; goto usage; } continue; + case 'D': + dateform = arg; + continue; + case 'F': + datetu = arg; + continue; + case 'T': + datenu = arg; + continue; case 'z': serial_len = read_serial(arg, serial, sizeof(serial)); if (serial_len < 0) @@ -275,6 +285,12 @@ static int sign_crl() error = "--cakey or --keyid is required"; goto usage; } + if (!calculate_lifetime(dateform, datetu, datenu, lifetime, + &thisUpdate, &nextUpdate)) + { + error = "invalid --this/next-update datetime"; + goto usage; + } ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, cacert, BUILD_END); @@ -321,9 +337,6 @@ static int sign_crl() goto error; } - thisUpdate = time(NULL); - nextUpdate = thisUpdate + lifetime * 24 * 60 * 60; - if (basecrl) { lastcrl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, @@ -442,6 +455,9 @@ static void __attribute__ ((constructor))reg() {"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"}, + {"this-update", 'F', 1, "date/time the validity of the CRL starts"}, + {"next-update", 'T', 1, "date/time the validity of the CRL ends"}, + {"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"}, {"lastcrl", 'a', 1, "CRL of lastUpdate to copy revocations from"}, {"basecrl", 'b', 1, "base CRL to create a delta CRL for"}, {"crluri", 'u', 1, "freshest delta CRL URI to include"}, |