From: Tobias Brunner Date: Mon, 30 Oct 2023 17:12:12 +0000 (+0100) Subject: pki: Add option to load certificate status information from index.txt X-Git-Tag: 5.9.12rc1~2^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=95c7d499544aee263f6c1f27b41f2cccbcb594f1;p=thirdparty%2Fstrongswan.git pki: Add option to load certificate status information from index.txt Each index.txt is associated with the most recently loaded CA certificate. --- diff --git a/src/pki/commands/ocsp.c b/src/pki/commands/ocsp.c index 0dd5b4a780..81e732cf49 100644 --- a/src/pki/commands/ocsp.c +++ b/src/pki/commands/ocsp.c @@ -18,7 +18,9 @@ #include #include "pki.h" +#include "ocsp/index_responder.h" +#include #include #include #include @@ -155,7 +157,7 @@ static bool find_issuer_cacert(hash_algorithm_t hashAlgorithm, /* * Find an OCSP signer certificate. Either the certificate of the CA itself that - * issued the end entitity certificate, the certificate of an OCSP signer + * issued the end-entity certificate, the certificate of an OCSP signer * delegated by the CA via the standard OCSPSigning Extended Key Usage (EKU) * flag or a self-signed OCSP signer certificate when multiple issuer OCSP * requests have to be supported. @@ -180,7 +182,7 @@ static void find_ocsp_signer(certificate_t *first_issuer, bool *self_signed, KEY_ANY, NULL, TRUE); while (certs->enumerate(certs, &candidate)) { - /* get the flags and key identfiers of the candidate certificate */ + /* get the flags and key identifiers of the candidate certificate */ x509 = (x509_t*)candidate; flags = x509->get_flags(x509); subKeyId = x509->get_subjectKeyIdentifier(x509); @@ -228,7 +230,9 @@ static int ocsp() certificate_t *cacert = NULL, *first_issuer = NULL; ocsp_request_t *ocsp_request; ocsp_status_t ocsp_status = OCSP_SUCCESSFUL; + ocsp_responder_t *index_responder = NULL; linked_list_t *responses = NULL; + array_t *index_responders = NULL; chunk_t encoding = chunk_empty, nonce = chunk_empty; chunk_t issuerNameHash, issuerKeyHash, serialNumber; hash_algorithm_t hashAlgorithm = HASH_SHA1, digest = HASH_UNKNOWN; @@ -284,6 +288,7 @@ static int ocsp() creds->add_cert(creds, TRUE, cert); continue; case 'C': + DESTROY_IF(cacert); cacert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, arg, BUILD_END); @@ -292,7 +297,7 @@ static int ocsp() error = "parsing CA certificate failed"; goto usage; } - creds->add_cert(creds, TRUE, cacert); + cacert = creds->add_cert_ref(creds, TRUE, cacert); continue; case 'l': lifetime = atoi(arg) * 60; @@ -316,6 +321,21 @@ static int ocsp() goto usage; } continue; + case 'x': + if (!cacert) + { + error = "--index must follow --cacert of corresponding CA"; + goto usage; + } + index_responder = index_responder_create(cacert, arg); + if (!index_responder) + { + error = "invalid ---index value"; + goto usage; + } + array_insert_create(&index_responders, ARRAY_TAIL, + index_responder); + continue; case EOF: break; default: @@ -331,7 +351,7 @@ static int ocsp() if (op == OP_RESPOND && !cacert) { - error = "respond mode requires a ca certificate"; + error = "respond mode requires a CA certificate"; goto end; } @@ -542,6 +562,8 @@ gen: res = 0; end: + array_destroy_offset(index_responders, offsetof(ocsp_responder_t, destroy)); + DESTROY_IF(cacert); DESTROY_IF(key); lib->credmgr->remove_local_set(lib->credmgr, &creds->set); creds->destroy(creds); @@ -558,6 +580,8 @@ end: return res; usage: + array_destroy_offset(index_responders, offsetof(ocsp_responder_t, destroy)); + DESTROY_IF(cacert); creds->destroy(creds); return command_usage(error); } @@ -569,7 +593,8 @@ static void __attribute__ ((constructor))reg() { command_register((command_t) { ocsp, 'o', "ocsp", "OCSP responder", - {"[--in file] [--respond] [--cert file]+ [--key file]+ [--cacert file]+ ", + {"[--in file] [--respond] [--cert file]+ [--key file]+ ", + "[--cacert file [--index file]]+", "[--digest md5|sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]", "[--rsa-padding pkcs1|pss] [--lifetime minutes]"}, { @@ -579,6 +604,7 @@ static void __attribute__ ((constructor))reg() {"key", 'k', 1, "path to OCSP signing private key (can be used multiple times)"}, {"cert", 'c', 1, "path to OCSP signing certificate (can be used multiple times"}, {"cacert", 'C', 1, "CA certificate (can be used multiple times"}, + {"index", 'x', 1, "OpenSSL-style index.txt to check status of certificates"}, {"digest", 'g', 1, "digest for signature creation, default: key-specific"}, {"rsa-padding", 'R', 1, "padding for RSA signatures, default: pkcs1"}, {"lifetime", 'l', 1, "validity in minutes of the OCSP response (if missing, nextUpdate is omitted)"}, diff --git a/src/pki/man/pki---ocsp.1.in b/src/pki/man/pki---ocsp.1.in index 23d4c7de4f..54ae002249 100644 --- a/src/pki/man/pki---ocsp.1.in +++ b/src/pki/man/pki---ocsp.1.in @@ -18,6 +18,7 @@ pki \-\-ocsp \- OCSP request parser and OCSP responder. .BI \-\-cacert\~ file .BI \-\-key\~ file .OP \-\-cert file +.OP \-\-index file .OP \-\-lifetime minutes .OP \-\-digest digest .OP \-\-rsa\-padding padding @@ -87,6 +88,14 @@ OCSP signer key. Can be used multiple times. OCSP signer certificate (if it is not a CA certificate). Can be used multiple times. .TP +.BI "\-x, \-\-index " file +OpenSSL-style index.txt providing information about the status of certificates +issued by the CA certificate loaded immediately before. Can be used multiple +times if the status for multiple CAs should be provided, just make sure to +pass each index.txt file right after the corresponding CA certificate. + +See below for a description of the structure of these files. +.TP .BI "\-l, \-\-lifetime " minutes Validity in minutes of the OCSP response (if missing, nextUpdate is omitted). .TP @@ -94,12 +103,52 @@ Validity in minutes of the OCSP response (if missing, nextUpdate is omitted). Digest to use for signature creation. One of \fImd5\fR, \fIsha1\fR, \fIsha224\fR, \fIsha256\fR, \fIsha384\fR, or \fIsha512\fR, \fIsha3_224\fR, \fIsha3_256\fR, \fIsha3_384\fR, \fIsha3_512\fR. The default is -determined based on the type and size of the ocsp signing key. +determined based on the type and size of the OCSP signing key. .TP .BI "\-R, \-\-rsa\-padding " padding Padding to use for RSA signatures. Either \fIpkcs1\fR or \fIpss\fR, defaults to \fIpkcs1\fR. . +.SH "INDEX.TXT DESCRIPTION" +. +Each line in an index.txt file consists of six columns that are separated by +tab characters: + +The first column denotes the certificate status, which can be either "V" (for +valid), "E" (for expired, treated like valid), or "R" (for revoked). + +The second column contains the certificate's expiration date and time in UTC in +the format YYMMDDHHMMSSZ. This field is ignored by the command but must not be +empty. + +The third column is the revocation date and time in UTC in the format +YYMMDDHHMMSSZ and an optional revocation reason that immediately follows it, +separated by a comma. Valid reasons are "keyCompromise", "CACompromise", +"affiliationChanged", "superseded", "cessationOfOperation", "certificateHold", +and "removeFromCRL", any other value or omitting a reason results in +"unspecified". + +The fourth column contains the certificate's serial number in +hexadecimal encoding. + +The fifth and sixth columns are both ignored by the command, so they may be +omitted completely. They can contain a path to the certificate (usually set to +"unknown") and the certificate's subject DN with slashes separating the RDNs. + +Example index.txt: +.PP +.EX +V 310930122422Z 03 unknown /C=CH/O=strongSwan/CN=moon... +V 310930122422Z 04 unknown /C=CH/O=strongSwan/CN=sun... +R 310930122422Z 231002122422Z,keyCompromise 88 +V Z 05 +.EE +.PP +Note that the fields are separated by tabs. So if a certificate is valid, two +tabs follow after the expiration date. The third line in this example only +specifies the relevant first four columns, the fourth even uses a dummy +expiration date. +. .SH "EXAMPLES" . Show the raw content of an OCSP request: