aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstrongswan/credentials/builder.c1
-rw-r--r--src/libstrongswan/credentials/builder.h2
-rw-r--r--src/libstrongswan/plugins/x509/x509_cert.c136
-rw-r--r--src/pki/commands/issue.c17
-rw-r--r--src/pki/commands/self.c17
-rw-r--r--src/pki/man/pki---issue.1.in9
-rw-r--r--src/pki/man/pki---self.1.in9
-rw-r--r--src/pki/pki.c22
-rw-r--r--src/pki/pki.h9
9 files changed, 218 insertions, 4 deletions
diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c
index 243dfd7cf..baa17c47d 100644
--- a/src/libstrongswan/credentials/builder.c
+++ b/src/libstrongswan/credentials/builder.c
@@ -45,6 +45,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
"BUILD_CRL_DISTRIBUTION_POINTS",
"BUILD_OCSP_ACCESS_LOCATIONS",
"BUILD_PATHLEN",
+ "BUILD_ADDRBLOCKS",
"BUILD_PERMITTED_NAME_CONSTRAINTS",
"BUILD_EXCLUDED_NAME_CONSTRAINTS",
"BUILD_CERTIFICATE_POLICIES",
diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h
index 7d1139348..1c6f5001b 100644
--- a/src/libstrongswan/credentials/builder.h
+++ b/src/libstrongswan/credentials/builder.h
@@ -100,6 +100,8 @@ enum builder_part_t {
BUILD_OCSP_ACCESS_LOCATIONS,
/** certificate path length constraint */
BUILD_PATHLEN,
+ /** RFC3779 addressBlock, linked_list_t* of traffic_selector_t* */
+ BUILD_ADDRBLOCKS,
/** permitted X509 name constraints, linked_list_t* of identification_t* */
BUILD_PERMITTED_NAME_CONSTRAINTS,
/** excluded X509 name constraints, linked_list_t* of identification_t* */
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index 2b83f3328..b77c5db4d 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -1992,6 +1992,72 @@ chunk_t x509_build_crlDistributionPoints(linked_list_t *list, int extn)
asn1_wrap(ASN1_SEQUENCE, "m", crlDistributionPoints)));
}
+static chunk_t generate_ts(traffic_selector_t *ts)
+{
+ chunk_t from, to;
+ uint8_t minbits = 0, maxbits = 0, unused;
+ host_t *net;
+ int bit, byte;
+
+ if (ts->to_subnet(ts, &net, &minbits))
+ {
+ unused = round_up(minbits, BITS_PER_BYTE) - minbits;
+ from = asn1_wrap(ASN1_BIT_STRING, "m",
+ chunk_cat("cc", chunk_from_thing(unused),
+ chunk_create(net->get_address(net).ptr,
+ (minbits + unused) / BITS_PER_BYTE)));
+ net->destroy(net);
+ return from;
+ }
+ net->destroy(net);
+
+ from = ts->get_from_address(ts);
+ for (byte = from.len - 1; byte >= 0; byte--)
+ {
+ if (from.ptr[byte] != 0)
+ {
+ minbits = byte * BITS_PER_BYTE + BITS_PER_BYTE;
+ for (bit = 0; bit < BITS_PER_BYTE; bit++)
+ {
+ if (from.ptr[byte] & 1 << bit)
+ {
+ break;
+ }
+ minbits--;
+ }
+ break;
+ }
+ }
+ to = ts->get_to_address(ts);
+ for (byte = to.len - 1; byte >= 0; byte--)
+ {
+ if (to.ptr[byte] != 0xFF)
+ {
+ maxbits = byte * BITS_PER_BYTE + BITS_PER_BYTE;
+ for (bit = 0; bit < BITS_PER_BYTE; bit++)
+ {
+ if ((to.ptr[byte] & 1 << bit) == 0)
+ {
+ break;
+ }
+ maxbits--;
+ }
+ break;
+ }
+ }
+ unused = round_up(minbits, BITS_PER_BYTE) - minbits;
+ from = asn1_wrap(ASN1_BIT_STRING, "m",
+ chunk_cat("cc", chunk_from_thing(unused),
+ chunk_create(from.ptr,
+ (minbits + unused) / BITS_PER_BYTE)));
+ unused = round_up(maxbits, BITS_PER_BYTE) - maxbits;
+ to = asn1_wrap(ASN1_BIT_STRING, "m",
+ chunk_cat("cc", chunk_from_thing(unused),
+ chunk_create(to.ptr,
+ (maxbits + unused) / BITS_PER_BYTE)));
+ return asn1_wrap(ASN1_SEQUENCE, "mm", from, to);
+}
+
/**
* Generate and sign a new certificate
*/
@@ -2008,6 +2074,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty;
chunk_t policyConstraints = chunk_empty, inhibitAnyPolicy = chunk_empty;
chunk_t ikeIntermediate = chunk_empty, msSmartcardLogon = chunk_empty;
+ chunk_t ipAddrBlocks = chunk_empty;
identification_t *issuer, *subject;
chunk_t key_info;
signature_scheme_t scheme;
@@ -2184,6 +2251,52 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
}
}
+ if (cert->ipAddrBlocks->get_count(cert->ipAddrBlocks))
+ {
+ chunk_t v4blocks = chunk_empty, v6blocks = chunk_empty, block;
+ traffic_selector_t *ts;
+
+ enumerator = cert->ipAddrBlocks->create_enumerator(cert->ipAddrBlocks);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ switch (ts->get_type(ts))
+ {
+ case TS_IPV4_ADDR_RANGE:
+ block = generate_ts(ts);
+ v4blocks = chunk_cat("mm", v4blocks, block);
+ break;
+ case TS_IPV6_ADDR_RANGE:
+ block = generate_ts(ts);
+ v6blocks = chunk_cat("mm", v6blocks, block);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (v4blocks.ptr)
+ {
+ v4blocks = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_wrap(ASN1_OCTET_STRING, "c",
+ chunk_from_chars(0x00,0x01)),
+ asn1_wrap(ASN1_SEQUENCE, "m", v4blocks));
+ }
+ if (v6blocks.ptr)
+ {
+ v6blocks = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_wrap(ASN1_OCTET_STRING, "c",
+ chunk_from_chars(0x00,0x02)),
+ asn1_wrap(ASN1_SEQUENCE, "m", v6blocks));
+ }
+ ipAddrBlocks = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(OID_IP_ADDR_BLOCKS),
+ asn1_wrap(ASN1_OCTET_STRING, "m",
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ v4blocks, v6blocks)));
+ cert->flags |= X509_IP_ADDR_BLOCKS;
+ }
+
if (cert->permitted_names->get_count(cert->permitted_names) ||
cert->excluded_names->get_count(cert->excluded_names))
{
@@ -2321,15 +2434,16 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
}
if (basicConstraints.ptr || subjectAltNames.ptr || authKeyIdentifier.ptr ||
- crlDistributionPoints.ptr || nameConstraints.ptr)
+ crlDistributionPoints.ptr || nameConstraints.ptr || ipAddrBlocks.ptr)
{
extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m",
- asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmmmmm",
+ asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmmmmmm",
basicConstraints, keyUsage, subjectKeyIdentifier,
authKeyIdentifier, subjectAltNames,
extendedKeyUsage, crlDistributionPoints,
authorityInfoAccess, nameConstraints, certPolicies,
- policyMappings, policyConstraints, inhibitAnyPolicy));
+ policyMappings, policyConstraints, inhibitAnyPolicy,
+ ipAddrBlocks));
}
cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmmcmcmm",
@@ -2492,6 +2606,22 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args)
cert->pathLenConstraint = (constraint < 128) ?
constraint : X509_NO_CONSTRAINT;
continue;
+ case BUILD_ADDRBLOCKS:
+ {
+ enumerator_t *enumerator;
+ traffic_selector_t *ts;
+ linked_list_t *list;
+
+ list = va_arg(args, linked_list_t*);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ cert->ipAddrBlocks->insert_last(cert->ipAddrBlocks,
+ ts->clone(ts));
+ }
+ enumerator->destroy(enumerator);
+ continue;
+ }
case BUILD_PERMITTED_NAME_CONSTRAINTS:
{
enumerator_t *enumerator;
diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c
index d95f53c03..333c6ebb3 100644
--- a/src/pki/commands/issue.c
+++ b/src/pki/commands/issue.c
@@ -71,6 +71,7 @@ static int issue()
char *error = NULL, *keyid = NULL;
identification_t *id = NULL;
linked_list_t *san, *cdps, *ocsp, *permitted, *excluded, *policies, *mappings;
+ linked_list_t *addrblocks;
int pathlen = X509_NO_CONSTRAINT, inhibit_any = X509_NO_CONSTRAINT;
int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT;
chunk_t serial = chunk_empty;
@@ -81,6 +82,7 @@ static int issue()
x509_t *x509;
x509_cdp_t *cdp = NULL;
x509_cert_policy_t *policy = NULL;
+ traffic_selector_t *ts;
char *arg;
san = linked_list_create();
@@ -90,6 +92,7 @@ static int issue()
excluded = linked_list_create();
policies = linked_list_create();
mappings = linked_list_create();
+ addrblocks = linked_list_create();
while (TRUE)
{
@@ -184,6 +187,15 @@ static int issue()
case 'p':
pathlen = atoi(arg);
continue;
+ case 'B':
+ ts = parse_ts(arg);
+ if (!ts)
+ {
+ error = "invalid addressBlock";
+ goto usage;
+ }
+ addrblocks->insert_last(addrblocks, ts);
+ continue;
case 'n':
permitted->insert_last(permitted,
identification_create_from_string(arg));
@@ -519,7 +531,7 @@ static int issue()
BUILD_NOT_BEFORE_TIME, not_before, BUILD_DIGEST_ALG, digest,
BUILD_NOT_AFTER_TIME, not_after, BUILD_SERIAL, serial,
BUILD_SUBJECT_ALTNAMES, san, BUILD_X509_FLAG, flags,
- BUILD_PATHLEN, pathlen,
+ BUILD_PATHLEN, pathlen, BUILD_ADDRBLOCKS, addrblocks,
BUILD_CRL_DISTRIBUTION_POINTS, cdps,
BUILD_OCSP_ACCESS_LOCATIONS, ocsp,
BUILD_PERMITTED_NAME_CONSTRAINTS, permitted,
@@ -557,6 +569,7 @@ end:
san->destroy_offset(san, offsetof(identification_t, destroy));
permitted->destroy_offset(permitted, offsetof(identification_t, destroy));
excluded->destroy_offset(excluded, offsetof(identification_t, destroy));
+ addrblocks->destroy_offset(addrblocks, offsetof(traffic_selector_t, destroy));
policies->destroy_function(policies, (void*)destroy_cert_policy);
mappings->destroy_function(mappings, (void*)destroy_policy_mapping);
cdps->destroy_function(cdps, (void*)destroy_cdp);
@@ -575,6 +588,7 @@ usage:
san->destroy_offset(san, offsetof(identification_t, destroy));
permitted->destroy_offset(permitted, offsetof(identification_t, destroy));
excluded->destroy_offset(excluded, offsetof(identification_t, destroy));
+ addrblocks->destroy_offset(addrblocks, offsetof(traffic_selector_t, destroy));
policies->destroy_function(policies, (void*)destroy_cert_policy);
mappings->destroy_function(mappings, (void*)destroy_policy_mapping);
cdps->destroy_function(cdps, (void*)destroy_cdp);
@@ -616,6 +630,7 @@ static void __attribute__ ((constructor))reg()
{"serial", 's', 1, "serial number in hex, default: random"},
{"ca", 'b', 0, "include CA basicConstraint, default: no"},
{"pathlen", 'p', 1, "set path length constraint"},
+ {"addrblock", 'B', 1, "RFC 3779 addrBlock to include"},
{"nc-permitted", 'n', 1, "add permitted NameConstraint"},
{"nc-excluded", 'N', 1, "add excluded NameConstraint"},
{"cert-policy", 'P', 1, "certificatePolicy OID to include"},
diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c
index 1899daac9..b894ac190 100644
--- a/src/pki/commands/self.c
+++ b/src/pki/commands/self.c
@@ -22,6 +22,7 @@
#include <collections/linked_list.h>
#include <credentials/certificates/certificate.h>
#include <credentials/certificates/x509.h>
+#include <selectors/traffic_selector.h>
#include <asn1/asn1.h>
/**
@@ -57,6 +58,7 @@ static int self()
char *file = NULL, *dn = NULL, *hex = NULL, *error = NULL, *keyid = NULL;
identification_t *id = NULL;
linked_list_t *san, *ocsp, *permitted, *excluded, *policies, *mappings;
+ linked_list_t *addrblocks;
int pathlen = X509_NO_CONSTRAINT, inhibit_any = X509_NO_CONSTRAINT;
int inhibit_mapping = X509_NO_CONSTRAINT;
int require_explicit = X509_NO_CONSTRAINT;
@@ -66,6 +68,7 @@ static int self()
char *datenb = NULL, *datena = NULL, *dateform = NULL;
x509_flag_t flags = 0;
x509_cert_policy_t *policy = NULL;
+ traffic_selector_t *ts;
char *arg;
san = linked_list_create();
@@ -74,6 +77,7 @@ static int self()
excluded = linked_list_create();
policies = linked_list_create();
mappings = linked_list_create();
+ addrblocks = linked_list_create();
while (TRUE)
{
@@ -153,6 +157,15 @@ static int self()
case 'p':
pathlen = atoi(arg);
continue;
+ case 'B':
+ ts = parse_ts(arg);
+ if (!ts)
+ {
+ error = "invalid addressBlock";
+ goto usage;
+ }
+ addrblocks->insert_last(addrblocks, ts);
+ continue;
case 'n':
permitted->insert_last(permitted,
identification_create_from_string(arg));
@@ -360,6 +373,7 @@ static int self()
BUILD_NOT_AFTER_TIME, not_after, BUILD_SERIAL, serial,
BUILD_DIGEST_ALG, digest, BUILD_X509_FLAG, flags,
BUILD_PATHLEN, pathlen, BUILD_SUBJECT_ALTNAMES, san,
+ BUILD_ADDRBLOCKS, addrblocks,
BUILD_OCSP_ACCESS_LOCATIONS, ocsp,
BUILD_PERMITTED_NAME_CONSTRAINTS, permitted,
BUILD_EXCLUDED_NAME_CONSTRAINTS, excluded,
@@ -394,6 +408,7 @@ end:
san->destroy_offset(san, offsetof(identification_t, destroy));
permitted->destroy_offset(permitted, offsetof(identification_t, destroy));
excluded->destroy_offset(excluded, offsetof(identification_t, destroy));
+ addrblocks->destroy_offset(addrblocks, offsetof(traffic_selector_t, destroy));
policies->destroy_function(policies, (void*)destroy_cert_policy);
mappings->destroy_function(mappings, (void*)destroy_policy_mapping);
ocsp->destroy(ocsp);
@@ -411,6 +426,7 @@ usage:
san->destroy_offset(san, offsetof(identification_t, destroy));
permitted->destroy_offset(permitted, offsetof(identification_t, destroy));
excluded->destroy_offset(excluded, offsetof(identification_t, destroy));
+ addrblocks->destroy_offset(addrblocks, offsetof(traffic_selector_t, destroy));
policies->destroy_function(policies, (void*)destroy_cert_policy);
mappings->destroy_function(mappings, (void*)destroy_policy_mapping);
ocsp->destroy(ocsp);
@@ -449,6 +465,7 @@ static void __attribute__ ((constructor))reg()
{"serial", 's', 1, "serial number in hex, default: random"},
{"ca", 'b', 0, "include CA basicConstraint, default: no"},
{"pathlen", 'p', 1, "set path length constraint"},
+ {"addrblock", 'B', 1, "RFC 3779 addrBlock to include"},
{"nc-permitted", 'n', 1, "add permitted NameConstraint"},
{"nc-excluded", 'N', 1, "add excluded NameConstraint"},
{"cert-policy", 'P', 1, "certificatePolicy OID to include"},
diff --git a/src/pki/man/pki---issue.1.in b/src/pki/man/pki---issue.1.in
index ba5886f5f..d1fa3473f 100644
--- a/src/pki/man/pki---issue.1.in
+++ b/src/pki/man/pki---issue.1.in
@@ -24,6 +24,7 @@ pki \-\-issue \- Issue a certificate using a CA certificate and key
.OP \-\-ocsp uri
.OP \-\-pathlen len
.OP \-\-nc-permitted name
+.OP \-\-addrblock block
.OP \-\-nc-excluded name
.OP \-\-policy\-mapping mapping
.OP \-\-policy\-explicit len
@@ -148,6 +149,14 @@ times.
.BI "\-p, \-\-pathlen " len
Set path length constraint.
.TP
+.BI "\-B, \-\-addrblock " block
+RFC 3779 address block to include in certificate. \fIblock\fR is either a
+CIDR subnet (such as \fI10.0.0.0/8\fR) or an arbitrary address range
+(\fI192.168.1.7-192.168.1.13\fR). Can be repeated to include multiple blocks.
+Please note that the supplied blocks are included in the certificate as is,
+so for standards compliance, multiple blocks must be supplied in correct
+order and adjacent blocks must be combined. Refer to RFC 3779 for details.
+.TP
.BI "\-n, \-\-nc-permitted " name
Add permitted NameConstraint extension to certificate. For DNS or email
constraints, the identity type is not always detectable by the given name. Use
diff --git a/src/pki/man/pki---self.1.in b/src/pki/man/pki---self.1.in
index 81f59bbb2..4384fa72d 100644
--- a/src/pki/man/pki---self.1.in
+++ b/src/pki/man/pki---self.1.in
@@ -22,6 +22,7 @@ pki \-\-self \- Create a self-signed certificate
.OP \-\-ca
.OP \-\-ocsp uri
.OP \-\-pathlen len
+.OP \-\-addrblock block
.OP \-\-nc-permitted name
.OP \-\-nc-excluded name
.OP \-\-policy\-mapping mapping
@@ -127,6 +128,14 @@ times.
.BI "\-p, \-\-pathlen " len
Set path length constraint.
.TP
+.BI "\-B, \-\-addrblock " block
+RFC 3779 address block to include in certificate. \fIblock\fR is either a
+CIDR subnet (such as \fI10.0.0.0/8\fR) or an arbitrary address range
+(\fI192.168.1.7-192.168.1.13\fR). Can be repeated to include multiple blocks.
+Please note that the supplied blocks are included in the certificate as is,
+so for standards compliance, multiple blocks must be supplied in correct
+order and adjacent blocks must be combined. Refer to RFC 3779 for details.
+.TP
.BI "\-n, \-\-nc-permitted " name
Add permitted NameConstraint extension to certificate. For DNS or email
constraints, the identity type is not always detectable by the given name. Use
diff --git a/src/pki/pki.c b/src/pki/pki.c
index 472704945..00fffefa6 100644
--- a/src/pki/pki.c
+++ b/src/pki/pki.c
@@ -258,6 +258,28 @@ hash_algorithm_t get_default_digest(private_key_t *private)
return alg == HASH_UNKNOWN ? HASH_SHA256 : alg;
}
+/*
+ * Described in header
+ */
+traffic_selector_t* parse_ts(char *str)
+{
+ ts_type_t type = TS_IPV4_ADDR_RANGE;
+ char *to, from[64];
+
+ if (strchr(str, ':'))
+ {
+ type = TS_IPV6_ADDR_RANGE;
+ }
+ to = strchr(str, '-');
+ if (to)
+ {
+ snprintf(from, sizeof(from), "%.*s", to - str, str);
+ to++;
+ return traffic_selector_create_from_string(0, type, from, 0, to, 65535);
+ }
+ return traffic_selector_create_from_cidr(str, 0, 0, 65535);
+}
+
/**
* Callback credential set pki uses
*/
diff --git a/src/pki/pki.h b/src/pki/pki.h
index 017e61df6..54be59f8f 100644
--- a/src/pki/pki.h
+++ b/src/pki/pki.h
@@ -26,6 +26,7 @@
#include "command.h"
#include <library.h>
+#include <selectors/traffic_selector.h>
#include <credentials/keys/private_key.h>
/**
@@ -63,4 +64,12 @@ void set_file_mode(FILE *stream, cred_encoding_type_t enc);
*/
hash_algorithm_t get_default_digest(private_key_t *private);
+/**
+ * Create a traffic selector from a CIDR or range string.
+ *
+ * @param str input string, either a.b.c.d/e or a.b.c.d-e.f.g.h
+ * @return traffic selector, NULL on error
+ */
+traffic_selector_t* parse_ts(char *str);
+
#endif /** PKI_H_ @}*/