aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libstrongswan/credentials/builder.c1
-rw-r--r--src/libstrongswan/credentials/builder.h2
-rw-r--r--src/libstrongswan/credentials/certificates/x509.h4
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_x509.c83
-rw-r--r--src/libstrongswan/plugins/revocation/revocation_validator.c3
-rw-r--r--src/libstrongswan/plugins/x509/x509_cert.c231
-rw-r--r--src/pki/commands/print.c11
-rw-r--r--src/pluto/crl.c4
8 files changed, 269 insertions, 70 deletions
diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c
index c43e5fd5d..2323f6ce5 100644
--- a/src/libstrongswan/credentials/builder.c
+++ b/src/libstrongswan/credentials/builder.c
@@ -41,6 +41,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
"BUILD_CA_CERT",
"BUILD_CERT",
"BUILD_CRL_DISTRIBUTION_POINTS",
+ "BUILD_CRL_ISSUER",
"BUILD_OCSP_ACCESS_LOCATIONS",
"BUILD_PATHLEN",
"BUILD_X509_FLAG",
diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h
index dc87da2a4..390c314a6 100644
--- a/src/libstrongswan/credentials/builder.h
+++ b/src/libstrongswan/credentials/builder.h
@@ -89,6 +89,8 @@ enum builder_part_t {
BUILD_CERT,
/** CRL distribution point URIs, linked_list_t* containing char* */
BUILD_CRL_DISTRIBUTION_POINTS,
+ /** CRL issuer for all distribution points follow up, identification_t* */
+ BUILD_CRL_ISSUER,
/** OCSP AuthorityInfoAccess locations, linked_list_t* containing char* */
BUILD_OCSP_ACCESS_LOCATIONS,
/** certificate path length constraint */
diff --git a/src/libstrongswan/credentials/certificates/x509.h b/src/libstrongswan/credentials/certificates/x509.h
index 6e0a5002a..3f1c4b738 100644
--- a/src/libstrongswan/credentials/certificates/x509.h
+++ b/src/libstrongswan/credentials/certificates/x509.h
@@ -112,9 +112,9 @@ struct x509_t {
enumerator_t* (*create_subjectAltName_enumerator)(x509_t *this);
/**
- * Create an enumerator over all CRL URIs.
+ * Create an enumerator over all CRL URIs and CRL Issuers.
*
- * @return enumerator over URIs as char*
+ * @return enumerator over URIs (char*, identificiation_t*)
*/
enumerator_t* (*create_crl_uri_enumerator)(x509_t *this);
diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c
index aa39bc93d..1630d8faf 100644
--- a/src/libstrongswan/plugins/openssl/openssl_x509.c
+++ b/src/libstrongswan/plugins/openssl/openssl_x509.c
@@ -137,7 +137,7 @@ struct private_openssl_x509_t {
linked_list_t *issuerAltNames;
/**
- * List of CRL URIs
+ * List of CRL URIs, as crl_uri_t
*/
linked_list_t *crl_uris;
@@ -153,6 +153,37 @@ struct private_openssl_x509_t {
};
/**
+ * CRL URIs with associated issuer
+ */
+typedef struct {
+ identification_t *issuer;
+ linked_list_t *uris;
+} crl_uri_t;
+
+/**
+ * Create a new issuer entry
+ */
+static crl_uri_t *crl_uri_create()
+{
+ crl_uri_t *this;
+
+ INIT(this,
+ .uris = linked_list_create(),
+ );
+ return this;
+}
+
+/**
+ * Destroy a CRL URI struct
+ */
+static void crl_uri_destroy(crl_uri_t *this)
+{
+ this->uris->destroy_function(this->uris, free);
+ DESTROY_IF(this->issuer);
+ free(this);
+}
+
+/**
* Convert a GeneralName to an identification_t.
*/
static identification_t *general_name2id(GENERAL_NAME *name)
@@ -252,10 +283,36 @@ METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
return this->subjectAltNames->create_enumerator(this->subjectAltNames);
}
+/**
+ * Convert enumerator value from entry to (uri, issuer)
+ */
+static bool crl_enum_filter(identification_t *issuer_in,
+ char **uri_in, char **uri_out,
+ void *none_in, identification_t **issuer_out)
+{
+ *uri_out = *uri_in;
+ if (issuer_out)
+ {
+ *issuer_out = issuer_in;
+ }
+ return TRUE;
+}
+
+/**
+ * Create inner enumerator over URIs
+ */
+static enumerator_t *crl_enum_create(crl_uri_t *entry)
+{
+ return enumerator_create_filter(entry->uris->create_enumerator(entry->uris),
+ (void*)crl_enum_filter, entry->issuer, NULL);
+}
+
METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
private_openssl_x509_t *this)
{
- return this->crl_uris->create_enumerator(this->crl_uris);
+ return enumerator_create_nested(
+ this->crl_uris->create_enumerator(this->crl_uris),
+ (void*)crl_enum_create, NULL, NULL);
}
METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
@@ -483,7 +540,7 @@ METHOD(certificate_t, destroy, void,
offsetof(identification_t, destroy));
this->issuerAltNames->destroy_offset(this->issuerAltNames,
offsetof(identification_t, destroy));
- this->crl_uris->destroy_function(this->crl_uris, free);
+ this->crl_uris->destroy_function(this->crl_uris, (void*)crl_uri_destroy);
this->ocsp_uris->destroy_function(this->ocsp_uris, free);
free(this);
}
@@ -615,6 +672,11 @@ static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this,
cdp = sk_DIST_POINT_value(cdps, i);
if (cdp)
{
+ crl_uri_t *entry;
+
+ entry = crl_uri_create();
+ this->crl_uris->insert_last(this->crl_uris, entry);
+
if (cdp->distpoint && cdp->distpoint->type == 0 &&
cdp->distpoint->name.fullname)
{
@@ -627,12 +689,25 @@ static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this,
{
if (asprintf(&uri, "%Y", id) > 0)
{
- this->crl_uris->insert_first(this->crl_uris, uri);
+ entry->uris->insert_last(entry->uris, uri);
}
id->destroy(id);
}
}
}
+ if (cdp->CRLissuer)
+ {
+ name_num = sk_GENERAL_NAME_num(cdp->CRLissuer);
+ for (j = 0; j < name_num; j++)
+ {
+ id = general_name2id(sk_GENERAL_NAME_value(cdp->CRLissuer, j));
+ if (id)
+ { /* get only one */
+ entry->issuer = id;
+ break;
+ }
+ }
+ }
DIST_POINT_free(cdp);
}
}
diff --git a/src/libstrongswan/plugins/revocation/revocation_validator.c b/src/libstrongswan/plugins/revocation/revocation_validator.c
index 29d2bc128..511a04a3e 100644
--- a/src/libstrongswan/plugins/revocation/revocation_validator.c
+++ b/src/libstrongswan/plugins/revocation/revocation_validator.c
@@ -476,8 +476,7 @@ static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
{
enumerator = subject->create_crl_uri_enumerator(subject);
-
- while (enumerator->enumerate(enumerator, &uri))
+ while (enumerator->enumerate(enumerator, &uri, NULL))
{
current = fetch_crl(uri);
if (current)
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index 559090aa0..6fcd9f033 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -117,7 +117,7 @@ struct private_x509_cert_t {
linked_list_t *subjectAltNames;
/**
- * List of crlDistributionPoints as allocated char*
+ * List of crlDistributionPoints as crl_uri_t
*/
linked_list_t *crl_uris;
@@ -187,6 +187,38 @@ static const chunk_t ASN1_subjectAltName_oid = chunk_from_chars(
);
/**
+ * CRL URIs with associated issuer
+ */
+typedef struct {
+ identification_t *issuer;
+ linked_list_t *uris;
+} crl_uri_t;
+
+/**
+ * Create a new issuer entry
+ */
+static crl_uri_t *crl_uri_create(identification_t *issuer)
+{
+ crl_uri_t *this;
+
+ INIT(this,
+ .issuer = issuer ? issuer->clone(issuer) : NULL,
+ .uris = linked_list_create(),
+ );
+ return this;
+}
+
+/**
+ * Destroy a CRL URI struct
+ */
+static void crl_uri_destroy(crl_uri_t *this)
+{
+ this->uris->destroy_function(this->uris, free);
+ DESTROY_IF(this->issuer);
+ free(this);
+}
+
+/**
* ASN.1 definition of a basicConstraints extension
*/
static const asn1Object_t basicConstraintsObjects[] = {
@@ -649,12 +681,14 @@ static const asn1Object_t crlDistributionPointsObjects[] = {
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
{ 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 8 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
- { 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_BODY }, /* 10 */
+ { 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_OBJ }, /* 10 */
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
+#define CRL_DIST_POINTS 1
#define CRL_DIST_POINTS_FULLNAME 3
+#define CRL_DIST_POINTS_ISSUER 10
/**
* Extracts one or several crlDistributionPoints into a list
@@ -665,6 +699,9 @@ static void parse_crlDistributionPoints(chunk_t blob, int level0,
asn1_parser_t *parser;
chunk_t object;
int objectID;
+ crl_uri_t *entry = NULL;
+ identification_t *id;
+ char *uri;
linked_list_t *list = linked_list_create();
parser = asn1_parser_create(crlDistributionPointsObjects, blob);
@@ -672,24 +709,45 @@ static void parse_crlDistributionPoints(chunk_t blob, int level0,
while (parser->iterate(parser, &objectID, &object))
{
- if (objectID == CRL_DIST_POINTS_FULLNAME)
+ switch (objectID)
{
- identification_t *id;
-
- /* append extracted generalNames to existing chained list */
- x509_parse_generalNames(object, parser->get_level(parser)+1,
- TRUE, list);
-
- while (list->remove_last(list, (void**)&id) == SUCCESS)
- {
- char *uri;
-
- if (asprintf(&uri, "%Y", id) > 0)
+ case CRL_DIST_POINTS:
+ entry = crl_uri_create(NULL);
+ this->crl_uris->insert_last(this->crl_uris, entry);
+ break;
+ case CRL_DIST_POINTS_FULLNAME:
+ if (entry)
{
- this->crl_uris->insert_last(this->crl_uris, uri);
+ x509_parse_generalNames(object, parser->get_level(parser)+1,
+ TRUE, list);
+ while (list->remove_last(list, (void**)&id) == SUCCESS)
+ {
+ if (asprintf(&uri, "%Y", id) > 0)
+ {
+ entry->uris->insert_last(entry->uris, uri);
+ }
+ id->destroy(id);
+ }
}
- id->destroy(id);
- }
+ break;
+ case CRL_DIST_POINTS_ISSUER:
+ if (entry)
+ {
+ x509_parse_generalNames(object, parser->get_level(parser)+1,
+ TRUE, list);
+ while (list->remove_last(list, (void**)&id) == SUCCESS)
+ {
+ if (!entry->issuer)
+ {
+ entry->issuer = id;
+ }
+ else
+ {
+ id->destroy(id);
+ }
+ }
+ }
+ break;
}
}
parser->destroy(parser);
@@ -1356,11 +1414,37 @@ static enumerator_t* create_ocsp_uri_enumerator(private_x509_cert_t *this)
}
/**
+ * Convert enumerator value from entry to (uri, issuer)
+ */
+static bool crl_enum_filter(identification_t *issuer_in,
+ char **uri_in, char **uri_out,
+ void *none_in, identification_t **issuer_out)
+{
+ *uri_out = *uri_in;
+ if (issuer_out)
+ {
+ *issuer_out = issuer_in;
+ }
+ return TRUE;
+}
+
+/**
+ * Create inner enumerator over URIs
+ */
+static enumerator_t *crl_enum_create(crl_uri_t *entry)
+{
+ return enumerator_create_filter(entry->uris->create_enumerator(entry->uris),
+ (void*)crl_enum_filter, entry->issuer, NULL);
+}
+
+/**
* Implementation of x509_cert_t.create_crl_uri_enumerator.
*/
static enumerator_t* create_crl_uri_enumerator(private_x509_cert_t *this)
{
- return this->crl_uris->create_enumerator(this->crl_uris);
+ return enumerator_create_nested(
+ this->crl_uris->create_enumerator(this->crl_uris),
+ (void*)crl_enum_create, NULL, NULL);
}
/**
@@ -1380,7 +1464,7 @@ static void destroy(private_x509_cert_t *this)
{
this->subjectAltNames->destroy_offset(this->subjectAltNames,
offsetof(identification_t, destroy));
- this->crl_uris->destroy_function(this->crl_uris, free);
+ this->crl_uris->destroy_function(this->crl_uris, (void*)crl_uri_destroy);
this->ocsp_uris->destroy_function(this->ocsp_uris, free);
this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks, offsetof(traffic_selector_t, destroy));
DESTROY_IF(this->issuer);
@@ -1456,11 +1540,41 @@ static private_x509_cert_t* create_empty(void)
}
/**
+ * Build a generalName from an id
+ */
+chunk_t build_generalName(identification_t *id)
+{
+ int context;
+
+ switch (id->get_type(id))
+ {
+ case ID_RFC822_ADDR:
+ context = ASN1_CONTEXT_S_1;
+ break;
+ case ID_FQDN:
+ context = ASN1_CONTEXT_S_2;
+ break;
+ case ID_DER_ASN1_DN:
+ context = ASN1_CONTEXT_C_4;
+ break;
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ context = ASN1_CONTEXT_S_7;
+ break;
+ default:
+ DBG1(DBG_LIB, "encoding %N as generalName not supported",
+ id_type_names, id->get_type(id));
+ return chunk_empty;
+ }
+ return asn1_wrap(context, "c", id->get_encoding(id));
+}
+
+/**
* Encode a linked list of subjectAltNames
*/
chunk_t x509_build_subjectAltNames(linked_list_t *list)
{
- chunk_t subjectAltNames = chunk_empty;
+ chunk_t subjectAltNames = chunk_empty, name;
enumerator_t *enumerator;
identification_t *id;
@@ -1472,29 +1586,7 @@ chunk_t x509_build_subjectAltNames(linked_list_t *list)
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &id))
{
- int context;
- chunk_t name;
-
- switch (id->get_type(id))
- {
- case ID_RFC822_ADDR:
- context = ASN1_CONTEXT_S_1;
- break;
- case ID_FQDN:
- context = ASN1_CONTEXT_S_2;
- break;
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- context = ASN1_CONTEXT_S_7;
- break;
- default:
- DBG1(DBG_LIB, "encoding %N as subjectAltName not supported",
- id_type_names, id->get_type(id));
- enumerator->destroy(enumerator);
- free(subjectAltNames.ptr);
- return chunk_empty;
- }
- name = asn1_wrap(context, "c", id->get_encoding(id));
+ name = build_generalName(id);
subjectAltNames = chunk_cat("mm", subjectAltNames, name);
}
enumerator->destroy(enumerator);
@@ -1522,10 +1614,11 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty;
chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty;
identification_t *issuer, *subject;
+ crl_uri_t *entry;
chunk_t key_info;
signature_scheme_t scheme;
hasher_t *hasher;
- enumerator_t *enumerator;
+ enumerator_t *enumerator, *uris;
char *uri;
subject = cert->subject;
@@ -1576,16 +1669,28 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
/* encode CRL distribution points extension */
enumerator = cert->crl_uris->create_enumerator(cert->crl_uris);
- while (enumerator->enumerate(enumerator, &uri))
+ while (enumerator->enumerate(enumerator, &entry))
{
- chunk_t distributionPoint;
+ chunk_t distributionPoint, gn;
+ chunk_t crlIssuer = chunk_empty, gns = chunk_empty;
- distributionPoint = asn1_wrap(ASN1_SEQUENCE, "m",
- asn1_wrap(ASN1_CONTEXT_C_0, "m",
- asn1_wrap(ASN1_CONTEXT_C_0, "m",
- asn1_wrap(ASN1_CONTEXT_S_6, "c",
- chunk_create(uri, strlen(uri))))));
+ if (entry->issuer)
+ {
+ crlIssuer = asn1_wrap(ASN1_CONTEXT_C_2, "m",
+ build_generalName(entry->issuer));
+ }
+ uris = entry->uris->create_enumerator(entry->uris);
+ while (uris->enumerate(uris, &uri))
+ {
+ gn = asn1_wrap(ASN1_CONTEXT_S_6, "c", chunk_create(uri, strlen(uri)));
+ gns = chunk_cat("mm", gns, gn);
+ }
+ uris->destroy(uris);
+ distributionPoint = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_wrap(ASN1_CONTEXT_C_0, "m",
+ asn1_wrap(ASN1_CONTEXT_C_0, "m", gns)),
+ crlIssuer);
crlDistributionPoints = chunk_cat("mm", crlDistributionPoints,
distributionPoint);
}
@@ -1594,8 +1699,8 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
{
crlDistributionPoints = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_build_known_oid(OID_CRL_DISTRIBUTION_POINTS),
- asn1_wrap(ASN1_OCTET_STRING, "m",
- asn1_wrap(ASN1_SEQUENCE, "m", crlDistributionPoints)));
+ asn1_wrap(ASN1_OCTET_STRING, "m",
+ asn1_wrap(ASN1_SEQUENCE, "m", crlDistributionPoints)));
}
/* encode OCSP URIs in authorityInfoAccess extension */
@@ -1793,6 +1898,7 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args)
private_x509_cert_t *cert;
certificate_t *sign_cert = NULL;
private_key_t *sign_key = NULL;
+ identification_t *crl_issuer = NULL;
hash_algorithm_t digest_alg = HASH_SHA1;
cert = create_empty();
@@ -1837,15 +1943,26 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args)
{
enumerator_t *enumerator;
linked_list_t *list;
+ crl_uri_t *entry;
char *uri;
list = va_arg(args, linked_list_t*);
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &uri))
+ if (list->get_count(list))
{
- cert->crl_uris->insert_last(cert->crl_uris, strdup(uri));
+ entry = crl_uri_create(crl_issuer);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ entry->uris->insert_last(entry->uris, strdup(uri));
+ }
+ enumerator->destroy(enumerator);
+ cert->crl_uris->insert_last(cert->crl_uris, entry);
}
- enumerator->destroy(enumerator);
+ continue;
+ }
+ case BUILD_CRL_ISSUER:
+ {
+ crl_issuer = va_arg(args, identification_t*);
continue;
}
case BUILD_OCSP_ACCESS_LOCATIONS:
diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c
index 870dca920..4dcc4718e 100644
--- a/src/pki/commands/print.c
+++ b/src/pki/commands/print.c
@@ -133,17 +133,22 @@ static void print_x509(x509_t *x509)
first = TRUE;
enumerator = x509->create_crl_uri_enumerator(x509);
- while (enumerator->enumerate(enumerator, &uri))
+ while (enumerator->enumerate(enumerator, &uri, &id))
{
if (first)
{
- printf("CRL URIs: %s\n", uri);
+ printf("CRL URIs: %s", uri);
first = FALSE;
}
else
{
- printf(" %s\n", uri);
+ printf(" %s", uri);
}
+ if (id)
+ {
+ printf(" (CRL issuer: %Y)", id);
+ }
+ printf("\n");
}
enumerator->destroy(enumerator);
diff --git a/src/pluto/crl.c b/src/pluto/crl.c
index c8fb107d5..7b14e5ff1 100644
--- a/src/pluto/crl.c
+++ b/src/pluto/crl.c
@@ -376,7 +376,7 @@ cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate,
}
enumerator = x509->create_crl_uri_enumerator(x509);
- while (enumerator->enumerate(enumerator, &point))
+ while (enumerator->enumerate(enumerator, &point, NULL))
{
add_distribution_point(crluris, point);
}
@@ -416,7 +416,7 @@ cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate,
}
enumerator = x509->create_crl_uri_enumerator(x509);
- while (enumerator->enumerate(enumerator, &point))
+ while (enumerator->enumerate(enumerator, &point, NULL))
{
add_distribution_point(x509crl->distributionPoints, point);
}