Merge branch 'id-type-prefix'
Introduce generic identity prefixes to enforce a specific type.
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
strongswan-5.2.2
|
||||||
|
----------------
|
||||||
|
|
||||||
|
- The left/rightid options in ipsec.conf, or any other identity in strongSwan,
|
||||||
|
now accept prefixes to enforce an explicit type, such as email: or fqdn:.
|
||||||
|
Note that no conversion is done for the remaining string, refer to
|
||||||
|
ipsec.conf(5) for details.
|
||||||
|
|
||||||
|
|
||||||
strongswan-5.2.1
|
strongswan-5.2.1
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|||||||
+27
-2
@@ -750,11 +750,36 @@ defaults to
|
|||||||
.B left
|
.B left
|
||||||
or the subject of the certificate configured with
|
or the subject of the certificate configured with
|
||||||
.BR leftcert .
|
.BR leftcert .
|
||||||
Can be an IP address, a fully-qualified domain name, an email address, or
|
If
|
||||||
a keyid. If
|
|
||||||
.B leftcert
|
.B leftcert
|
||||||
is configured the identity has to be confirmed by the certificate.
|
is configured the identity has to be confirmed by the certificate.
|
||||||
|
|
||||||
|
Can be an IP address, a fully-qualified domain name, an email address or a
|
||||||
|
Distinguished Name for which the ID type is determined automatically and the
|
||||||
|
string is converted to the appropriate encoding. To enforce a specific identity
|
||||||
|
type, a prefix may be used, followed by a colon (:). If the number sign (#)
|
||||||
|
follows the colon, the remaining data is interpreted as hex encoding, otherwise
|
||||||
|
the string is used as-is as the identification data. Note that this implies
|
||||||
|
that no conversion is performed for non-string identities. For example,
|
||||||
|
\fIipv4:10.0.0.1\fP does not create a valid ID_IPV4_ADDR IKE identity, as it
|
||||||
|
does not get converted to binary 0x0a000001. Instead, one could use
|
||||||
|
\fIipv4:#0a000001\fP to get a valid identity, but just using the implicit type
|
||||||
|
with automatic conversion is usually simpler. The same applies to the ASN1
|
||||||
|
encoded types. The following prefixes are known:
|
||||||
|
.BR ipv4 ,
|
||||||
|
.BR ipv6 ,
|
||||||
|
.BR rfc822 ,
|
||||||
|
.BR email ,
|
||||||
|
.BR userfqdn ,
|
||||||
|
.BR fqdn ,
|
||||||
|
.BR dns ,
|
||||||
|
.BR asn1dn ,
|
||||||
|
.B asn1gn
|
||||||
|
and
|
||||||
|
.BR keyid .
|
||||||
|
Custom type prefixes may be specified by surrounding the numerical type value by
|
||||||
|
curly brackets.
|
||||||
|
|
||||||
For IKEv2 and
|
For IKEv2 and
|
||||||
.B rightid
|
.B rightid
|
||||||
the prefix
|
the prefix
|
||||||
|
|||||||
@@ -122,58 +122,68 @@ static struct {
|
|||||||
} data;
|
} data;
|
||||||
} result;
|
} result;
|
||||||
} string_data[] = {
|
} string_data[] = {
|
||||||
{NULL, ID_ANY, { .type = ENC_CHUNK }},
|
{NULL, ID_ANY, { .type = ENC_CHUNK }},
|
||||||
{"", ID_ANY, { .type = ENC_CHUNK }},
|
{"", ID_ANY, { .type = ENC_CHUNK }},
|
||||||
{"%any", ID_ANY, { .type = ENC_CHUNK }},
|
{"%any", ID_ANY, { .type = ENC_CHUNK }},
|
||||||
{"%any6", ID_ANY, { .type = ENC_CHUNK }},
|
{"%any6", ID_ANY, { .type = ENC_CHUNK }},
|
||||||
{"0.0.0.0", ID_ANY, { .type = ENC_CHUNK }},
|
{"0.0.0.0", ID_ANY, { .type = ENC_CHUNK }},
|
||||||
{"0::0", ID_ANY, { .type = ENC_CHUNK }},
|
{"0::0", ID_ANY, { .type = ENC_CHUNK }},
|
||||||
{"::", ID_ANY, { .type = ENC_CHUNK }},
|
{"::", ID_ANY, { .type = ENC_CHUNK }},
|
||||||
{"*", ID_ANY, { .type = ENC_CHUNK }},
|
{"*", ID_ANY, { .type = ENC_CHUNK }},
|
||||||
{"any", ID_FQDN, { .type = ENC_SIMPLE }},
|
{"any", ID_FQDN, { .type = ENC_SIMPLE }},
|
||||||
{"any6", ID_FQDN, { .type = ENC_SIMPLE }},
|
{"any6", ID_FQDN, { .type = ENC_SIMPLE }},
|
||||||
{"0", ID_FQDN, { .type = ENC_SIMPLE }},
|
{"0", ID_FQDN, { .type = ENC_SIMPLE }},
|
||||||
{"**", ID_FQDN, { .type = ENC_SIMPLE }},
|
{"**", ID_FQDN, { .type = ENC_SIMPLE }},
|
||||||
{"192.168.1.1", ID_IPV4_ADDR, { .type = ENC_CHUNK,
|
{"192.168.1.1", ID_IPV4_ADDR, { .type = ENC_CHUNK,
|
||||||
.data.c = chunk_from_chars(0xc0, 0xa8, 0x01, 0x01) }},
|
.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01) }},
|
||||||
{"192.168.",ID_FQDN, { .type = ENC_SIMPLE }},
|
{"192.168.", ID_FQDN, { .type = ENC_SIMPLE }},
|
||||||
{".", ID_FQDN, { .type = ENC_SIMPLE }},
|
{".", ID_FQDN, { .type = ENC_SIMPLE }},
|
||||||
{"fec0::1", ID_IPV6_ADDR, { .type = ENC_CHUNK,
|
{"fec0::1", ID_IPV6_ADDR, { .type = ENC_CHUNK,
|
||||||
.data.c = chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
.data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01) }},
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01) }},
|
||||||
{"fec0::", ID_IPV6_ADDR, { .type = ENC_CHUNK,
|
{"fec0::", ID_IPV6_ADDR, { .type = ENC_CHUNK,
|
||||||
.data.c = chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
.data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) }},
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00) }},
|
||||||
{"fec0:", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
{"fec0:", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
||||||
{":", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
{":", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
||||||
{"[email protected]", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
{"[email protected]", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
||||||
{"alice@strongswan", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
{"alice@strongswan", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
||||||
{"alice@", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
{"alice@", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
||||||
{"alice", ID_FQDN, { .type = ENC_SIMPLE }},
|
{"alice", ID_FQDN, { .type = ENC_SIMPLE }},
|
||||||
{"@", ID_FQDN, { .type = ENC_CHUNK }},
|
{"@", ID_FQDN, { .type = ENC_CHUNK }},
|
||||||
{" @", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
{" @", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
|
||||||
{"@strongswan.org", ID_FQDN, { .type = ENC_STRING,
|
{"@strongswan.org", ID_FQDN, { .type = ENC_STRING,
|
||||||
.data.s = "strongswan.org" }},
|
.data.s = "strongswan.org" }},
|
||||||
{"@#deadbeef", ID_KEY_ID, { .type = ENC_CHUNK,
|
{"@#deadbeef", ID_KEY_ID, { .type = ENC_CHUNK,
|
||||||
.data.c = chunk_from_chars(0xde, 0xad, 0xbe, 0xef) }},
|
.data.c = chunk_from_chars(0xde,0xad,0xbe,0xef) }},
|
||||||
{"@#deadbee", ID_KEY_ID, { .type = ENC_CHUNK,
|
{"@#deadbee", ID_KEY_ID, { .type = ENC_CHUNK,
|
||||||
.data.c = chunk_from_chars(0x0d, 0xea, 0xdb, 0xee) }},
|
.data.c = chunk_from_chars(0x0d,0xea,0xdb,0xee) }},
|
||||||
{"foo=bar", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
{"foo=bar", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
||||||
{"foo=", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
{"foo=", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
||||||
{"=bar", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
{"=bar", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
||||||
{"C=", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
{"C=", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
||||||
.data.c = chunk_from_chars(0x30, 0x0b, 0x31, 0x09, 0x30, 0x07, 0x06,
|
.data.c = chunk_from_chars(0x30,0x0b,0x31,0x09,0x30,0x07,0x06,
|
||||||
0x03, 0x55, 0x04, 0x06, 0x13, 0x00)}},
|
0x03,0x55,0x04,0x06,0x13,0x00) }},
|
||||||
{"C=CH", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
{"C=CH", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
||||||
.data.c = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
|
.data.c = chunk_from_chars(0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,
|
||||||
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48)}},
|
0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48) }},
|
||||||
{"C=CH,", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
{"C=CH,", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
||||||
.data.c = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
|
.data.c = chunk_from_chars(0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,
|
||||||
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48)}},
|
0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48) }},
|
||||||
{"C=CH, ", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
{"C=CH, ", ID_DER_ASN1_DN, { .type = ENC_CHUNK,
|
||||||
.data.c = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
|
.data.c = chunk_from_chars(0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,
|
||||||
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48)}},
|
0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48) }},
|
||||||
{"C=CH, O", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
{"C=CH, O", ID_KEY_ID, { .type = ENC_SIMPLE }},
|
||||||
|
{"IPv4:#c0a80101", ID_IPV4_ADDR, { .type = ENC_CHUNK,
|
||||||
|
.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01) }},
|
||||||
|
{ "email:tester", ID_RFC822_ADDR, { .type = ENC_STRING,
|
||||||
|
.data.s = "tester" }},
|
||||||
|
{ "{1}:#c0a80101", ID_IPV4_ADDR, { .type = ENC_CHUNK,
|
||||||
|
.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01) }},
|
||||||
|
{ "{0x02}:tester", ID_FQDN, { .type = ENC_STRING,
|
||||||
|
.data.s = "tester" }},
|
||||||
|
{ "{99}:somedata", 99, { .type = ENC_STRING,
|
||||||
|
.data.s = "somedata" }},
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_from_string)
|
START_TEST(test_from_string)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "identification.h"
|
#include "identification.h"
|
||||||
|
|
||||||
@@ -927,6 +928,82 @@ static private_identification_t *identification_create(id_type_t type)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an identity for a specific type, determined by prefix
|
||||||
|
*/
|
||||||
|
static private_identification_t* create_from_string_with_prefix_type(char *str)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
const char *str;
|
||||||
|
id_type_t type;
|
||||||
|
} prefixes[] = {
|
||||||
|
{ "ipv4:", ID_IPV4_ADDR },
|
||||||
|
{ "ipv6:", ID_IPV6_ADDR },
|
||||||
|
{ "rfc822:", ID_RFC822_ADDR },
|
||||||
|
{ "email:", ID_RFC822_ADDR },
|
||||||
|
{ "userfqdn:", ID_USER_FQDN },
|
||||||
|
{ "fqdn:", ID_FQDN },
|
||||||
|
{ "dns:", ID_FQDN },
|
||||||
|
{ "asn1dn:", ID_DER_ASN1_DN },
|
||||||
|
{ "asn1gn:", ID_DER_ASN1_GN },
|
||||||
|
{ "keyid:", ID_KEY_ID },
|
||||||
|
};
|
||||||
|
private_identification_t *this;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < countof(prefixes); i++)
|
||||||
|
{
|
||||||
|
if (strcasepfx(str, prefixes[i].str))
|
||||||
|
{
|
||||||
|
this = identification_create(prefixes[i].type);
|
||||||
|
str += strlen(prefixes[i].str);
|
||||||
|
if (*str == '#')
|
||||||
|
{
|
||||||
|
this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->encoded = chunk_clone(chunk_from_str(str));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an identity for a specific type, determined by a numerical prefix
|
||||||
|
*
|
||||||
|
* The prefix is of the form "{x}:", where x denotes the numerical identity
|
||||||
|
* type.
|
||||||
|
*/
|
||||||
|
static private_identification_t* create_from_string_with_num_type(char *str)
|
||||||
|
{
|
||||||
|
private_identification_t *this;
|
||||||
|
u_long type;
|
||||||
|
|
||||||
|
if (*str++ != '{')
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
type = strtoul(str, &str, 0);
|
||||||
|
if (errno || *str++ != '}' || *str++ != ':')
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
this = identification_create(type);
|
||||||
|
if (*str == '#')
|
||||||
|
{
|
||||||
|
this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->encoded = chunk_clone(chunk_from_str(str));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Described in header.
|
* Described in header.
|
||||||
*/
|
*/
|
||||||
@@ -939,6 +1016,16 @@ identification_t *identification_create_from_string(char *string)
|
|||||||
{
|
{
|
||||||
string = "%any";
|
string = "%any";
|
||||||
}
|
}
|
||||||
|
this = create_from_string_with_prefix_type(string);
|
||||||
|
if (this)
|
||||||
|
{
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
this = create_from_string_with_num_type(string);
|
||||||
|
if (this)
|
||||||
|
{
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
if (strchr(string, '=') != NULL)
|
if (strchr(string, '=') != NULL)
|
||||||
{
|
{
|
||||||
/* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
|
/* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
|
||||||
|
|||||||
@@ -302,6 +302,15 @@ struct identification_t {
|
|||||||
* N, G, I, dnQualifier, ID, EN, EmployeeNumber, E, Email, emailAddress, UN,
|
* N, G, I, dnQualifier, ID, EN, EmployeeNumber, E, Email, emailAddress, UN,
|
||||||
* unstructuredName, TCGID.
|
* unstructuredName, TCGID.
|
||||||
*
|
*
|
||||||
|
* To skip automatic type detection the following prefixes may be used to
|
||||||
|
* enforce a specific type: ipv4:, ipv6:, rfc822:, email:, userfqdn:, fqdn:,
|
||||||
|
* dns:, asn1dn:, asn1gn: and keyid:. If a # follows the :, the remaining data
|
||||||
|
* is interpreted as hex encoded binary data for that ID, otherwise the raw
|
||||||
|
* string following the prefix is used as identity data, without conversion.
|
||||||
|
* To specify a non-standard ID type, the numerical type may be prefixed
|
||||||
|
* between curly backets, building a prefix. For instance the "{1}:" prefix
|
||||||
|
* defines an ID_IPV4_ADDR type.
|
||||||
|
*
|
||||||
* This constructor never returns NULL. If it does not find a suitable
|
* This constructor never returns NULL. If it does not find a suitable
|
||||||
* conversion function, it will copy the string to an ID_KEY_ID.
|
* conversion function, it will copy the string to an ID_KEY_ID.
|
||||||
*
|
*
|
||||||
|
|||||||
+18
-3
@@ -303,6 +303,22 @@ connections.<conn>.local<suffix>.id =
|
|||||||
authentication, the IKE identity must be contained in the certificate,
|
authentication, the IKE identity must be contained in the certificate,
|
||||||
either as subject or as subjectAltName.
|
either as subject or as subjectAltName.
|
||||||
|
|
||||||
|
The identity can be an IP address, a fully-qualified domain name, an email
|
||||||
|
address or a Distinguished Name for which the ID type is determined
|
||||||
|
automatically and the string is converted to the appropriate encoding. To
|
||||||
|
enforce a specific identity type, a prefix may be used, followed by a colon
|
||||||
|
(:). If the number sign (#) follows the colon, the remaining data is
|
||||||
|
interpreted as hex encoding, otherwise the string is used as-is as the
|
||||||
|
identification data. Note that this implies that no conversion is performed
|
||||||
|
for non-string identities. For example, _ipv4:10.0.0.1_ does not create a
|
||||||
|
valid ID_IPV4_ADDR IKE identity, as it does not get converted to binary
|
||||||
|
0x0a000001. Instead, one could use _ipv4:#0a000001_ to get a valid identity,
|
||||||
|
but just using the implicit type with automatic conversion is usually
|
||||||
|
simpler. The same applies to the ASN1 encoded types. The following prefixes
|
||||||
|
are known: _ipv4_, _ipv6_, _rfc822_, _email_, _userfqdn_, _fqdn_, _dns_,
|
||||||
|
_asn1dn_, _asn1gn_ and _keyid_. Custom type prefixes may be specified by
|
||||||
|
surrounding the numerical type value by curly brackets.
|
||||||
|
|
||||||
connections.<conn>.local<suffix>.eap_id = id
|
connections.<conn>.local<suffix>.eap_id = id
|
||||||
Client EAP-Identity to use in EAP-Identity exchange and the EAP method.
|
Client EAP-Identity to use in EAP-Identity exchange and the EAP method.
|
||||||
|
|
||||||
@@ -335,9 +351,8 @@ connections.<conn>.remote<suffix> {}
|
|||||||
connections.<conn>.remote<suffix>.id = %any
|
connections.<conn>.remote<suffix>.id = %any
|
||||||
IKE identity to expect for authentication round.
|
IKE identity to expect for authentication round.
|
||||||
|
|
||||||
IKE identity to expect for authentication round. When using certificate
|
IKE identity to expect for authentication round. Refer to the _local_ _id_
|
||||||
authentication, the IKE identity must be contained in the certificate,
|
section for details.
|
||||||
either as subject or as subjectAltName.
|
|
||||||
|
|
||||||
connections.<conn>.remote<suffix>.groups =
|
connections.<conn>.remote<suffix>.groups =
|
||||||
Authorization group memberships to require.
|
Authorization group memberships to require.
|
||||||
|
|||||||
Reference in New Issue
Block a user