mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-05 00:00:45 -04:00
Merge branch 'regex-ids'
Adds support for POSIX regular expressions in configured identities, which makes matching remote identities more flexible.
This commit is contained in:
commit
301887b865
@ -241,6 +241,7 @@ class GroffTagReplacer(TagReplacer):
|
||||
if not punct:
|
||||
punct = ''
|
||||
text = re.sub(r'[\r\n\t]', ' ', m.group('text'))
|
||||
text = re.sub(r'"', '""', text)
|
||||
return '{0}.R{1} "{2}" "{3}" "{4}"\n'.format(nl, format, brack, text, punct)
|
||||
return replacer
|
||||
|
||||
@ -305,7 +306,8 @@ class ManFormatter:
|
||||
def __groffize(self, text):
|
||||
"""Encode text as groff text"""
|
||||
text = self.__tags.replace(text)
|
||||
text = re.sub(r'(?<!\\)-', r'\\-', text)
|
||||
text = re.sub(r'\\(?!-)', '\\[rs]', text)
|
||||
text = re.sub(r'(?<!\\)-', '\\-', text)
|
||||
# remove any leading whitespace
|
||||
return re.sub(r'^\s+', '', text, flags = re.MULTILINE)
|
||||
|
||||
|
@ -604,6 +604,10 @@ AC_LINK_IFELSE(
|
||||
AC_SUBST(ATOMICLIB)
|
||||
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
# Some platforms require explicit linking to use POSIX regular expressions
|
||||
AC_SEARCH_LIBS([regcomp], [regex], [AC_DEFINE([HAVE_REGEX], [], [have regcomp() etc.])])
|
||||
|
||||
# ------------------------------------------------------
|
||||
|
||||
AC_MSG_CHECKING(for dladdr)
|
||||
|
@ -1486,13 +1486,15 @@ CALLBACK(parse_auth, bool,
|
||||
*/
|
||||
static bool parse_id(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
|
||||
{
|
||||
identification_t *id;
|
||||
char buf[BUF_LEN];
|
||||
|
||||
if (!vici_stringify(v, buf, sizeof(buf)))
|
||||
if (!vici_stringify(v, buf, sizeof(buf)) ||
|
||||
!(id = identification_create_from_string_with_regex(buf)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
cfg->add(cfg, rule, identification_create_from_string(buf));
|
||||
cfg->add(cfg, rule, id);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -395,13 +395,15 @@ CALLBACK(shared_owners, bool,
|
||||
{
|
||||
if (streq(name, "owners"))
|
||||
{
|
||||
identification_t *id;
|
||||
char buf[256];
|
||||
|
||||
if (!vici_stringify(value, buf, sizeof(buf)))
|
||||
if (!vici_stringify(value, buf, sizeof(buf)) ||
|
||||
!(id = identification_create_from_string_with_regex(buf)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
owners->insert_last(owners, identification_create_from_string(buf));
|
||||
owners->insert_last(owners, id);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -311,6 +311,45 @@ START_TEST(test_from_string)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_from_string_with_regex)
|
||||
{
|
||||
identification_t *id;
|
||||
|
||||
id = identification_create_from_string_with_regex("fqdn:^vpn.*\\.strongswan\\.org$");
|
||||
ck_assert(id);
|
||||
ck_assert_int_eq(ID_FQDN, id->get_type(id));
|
||||
ck_assert_chunk_eq(chunk_from_str("^vpn.*\\.strongswan\\.org$"), id->get_encoding(id));
|
||||
id->destroy(id);
|
||||
|
||||
id = identification_create_from_string_with_regex("email:^.+@strongswan\\.org$");
|
||||
ck_assert(id);
|
||||
ck_assert_int_eq(ID_RFC822_ADDR, id->get_type(id));
|
||||
ck_assert_chunk_eq(chunk_from_str("^.+@strongswan\\.org$"), id->get_encoding(id));
|
||||
id->destroy(id);
|
||||
|
||||
id = identification_create_from_string_with_regex("asn1dn:^.+CN=.+@strongswan\\.org$");
|
||||
ck_assert(id);
|
||||
ck_assert_int_eq(ID_DER_ASN1_DN, id->get_type(id));
|
||||
ck_assert_chunk_eq(chunk_from_str("^.+CN=.+@strongswan\\.org$"), id->get_encoding(id));
|
||||
id->destroy(id);
|
||||
|
||||
/* invalid regex */
|
||||
ck_assert(!identification_create_from_string_with_regex("fqdn:^[+\\.strongswan\\.org$"));
|
||||
|
||||
/* ignored if pre-/suffix is missing or the type is unsupported */
|
||||
id = identification_create_from_string_with_regex("fqdn:[+\\.strongswan\\.org$");
|
||||
ck_assert(id);
|
||||
id->destroy(id);
|
||||
id = identification_create_from_string_with_regex("fqdn:^[+\\.strongswan\\.org");
|
||||
ck_assert(id);
|
||||
id->destroy(id);
|
||||
id = identification_create_from_string_with_regex("keyid:^[+\\.strongswan\\.org$");
|
||||
ck_assert(id);
|
||||
ck_assert_int_eq(ID_KEY_ID, id->get_type(id));
|
||||
id->destroy(id);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*******************************************************************************
|
||||
* printf_hook
|
||||
*/
|
||||
@ -458,6 +497,22 @@ START_TEST(test_printf_hook_width)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_printf_hook_regex)
|
||||
{
|
||||
identification_t *a;
|
||||
char buf[128];
|
||||
|
||||
a = identification_create_from_string_with_regex("fqdn:^vpn.+\\.strongswan\\.org$");
|
||||
snprintf(buf, sizeof(buf), "%Y", a);
|
||||
ck_assert_str_eq("^vpn.+\\.strongswan\\.org$", buf);
|
||||
snprintf(buf, sizeof(buf), "%30Y", a);
|
||||
ck_assert_str_eq(" ^vpn.+\\.strongswan\\.org$", buf);
|
||||
snprintf(buf, sizeof(buf), "%-*Y", 30, a);
|
||||
ck_assert_str_eq("^vpn.+\\.strongswan\\.org$ ", buf);
|
||||
a->destroy(a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*******************************************************************************
|
||||
* equals
|
||||
*/
|
||||
@ -587,6 +642,30 @@ START_TEST(test_equals_fqdn)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_equals_regex)
|
||||
{
|
||||
identification_t *a, *b;
|
||||
|
||||
a = identification_create_from_string_with_regex("fqdn:^vpn.*\\.strongswan\\.org$");
|
||||
b = identification_create_from_string_with_regex("fqdn:^vpn.*\\.strongswan\\.org$");
|
||||
ck_assert(a->equals(a, b));
|
||||
ck_assert(b->equals(b, a));
|
||||
b->destroy(b);
|
||||
b = identification_create_from_string_with_regex("fqdn:^vpn.+\\.strongswan\\.org$");
|
||||
ck_assert(!a->equals(a, b));
|
||||
ck_assert(!b->equals(b, a));
|
||||
b->destroy(b);
|
||||
|
||||
b = identification_create_from_string("fqdn:^vpn.*\\.strongswan\\.org$");
|
||||
ck_assert_int_eq(a->get_type(a), b->get_type(b));
|
||||
ck_assert_chunk_eq(a->get_encoding(a), b->get_encoding(b));
|
||||
ck_assert(!a->equals(a, b));
|
||||
ck_assert(!b->equals(b, a));
|
||||
b->destroy(b);
|
||||
a->destroy(a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_equals_empty)
|
||||
{
|
||||
identification_t *a;
|
||||
@ -1140,6 +1219,78 @@ START_TEST(test_matches_string)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static bool regex_matches(identification_t *a, char *b_regex, id_match_t expected)
|
||||
{
|
||||
identification_t *b;
|
||||
id_match_t match;
|
||||
|
||||
b = identification_create_from_string_with_regex(b_regex);
|
||||
ck_assert_msg(b, "'%s' is invalid", b_regex);
|
||||
match = a->matches(a, b);
|
||||
b->destroy(b);
|
||||
return match == expected;
|
||||
}
|
||||
|
||||
START_TEST(test_matches_regex)
|
||||
{
|
||||
identification_t *a;
|
||||
|
||||
a = identification_create_from_string("moon@strongswan.org");
|
||||
|
||||
ck_assert(regex_matches(a, "email:^moon@strongswan.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "email:^moon@strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "email:^MOON@strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "email:^(moon|sun)@strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "email:^moon@strongswan\\.or$", ID_MATCH_NONE));
|
||||
ck_assert(regex_matches(a, "email:^.+@strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "email:^moon@.*.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "email:^.+$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "email:^$", ID_MATCH_NONE));
|
||||
a->destroy(a);
|
||||
|
||||
a = identification_create_from_string("vpn1.strongswan.org");
|
||||
|
||||
ck_assert(regex_matches(a, "fqdn:^vpn1\\.strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "fqdn:^VPN1\\.strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "fqdn:^strongswan\\.org$", ID_MATCH_NONE));
|
||||
ck_assert(regex_matches(a, "fqdn:^.*\\.strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "fqdn:^vpn[0-9]\\.strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "fqdn:^vpn[[:digit:]]\\.strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "fqdn:^[^0-9]+[0-9]+\\.strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
a->destroy(a);
|
||||
|
||||
a = identification_create_from_string("C=CH, O=strongSwan, CN=vpn1.strongswan.org");
|
||||
|
||||
ck_assert(regex_matches(a, "asn1dn:^.*CN=.*\\.strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
ck_assert(regex_matches(a, "asn1dn:^.*CN=vpn[0-9]\\.strongswan\\.org$", ID_MATCH_MAX_WILDCARDS));
|
||||
a->destroy(a);
|
||||
|
||||
a = identification_create_from_string("fqdn:^vpn1\\.strongswan\\.org$");
|
||||
|
||||
ck_assert(regex_matches(a, "fqdn:^vpn1\\.strongswan\\.org$", ID_MATCH_NONE));
|
||||
ck_assert(regex_matches(a, "vpn1.strongswan.org", ID_MATCH_NONE));
|
||||
ck_assert(regex_matches(a, "%any", ID_MATCH_ANY));
|
||||
a->destroy(a);
|
||||
|
||||
a = identification_create_from_string_with_regex("fqdn:^vpn1\\.strongswan\\.org$");
|
||||
|
||||
ck_assert(regex_matches(a, "fqdn:^vpn1\\.strongswan\\.org$", ID_MATCH_NONE));
|
||||
ck_assert(regex_matches(a, "vpn1.strongswan.org", ID_MATCH_NONE));
|
||||
ck_assert(regex_matches(a, "%any", ID_MATCH_ANY));
|
||||
a->destroy(a);
|
||||
|
||||
/* internal buffer for matched identities is BUF_LEN-1, do a suffix match
|
||||
* as it would fail if the buffer was too small anyway otherwise */
|
||||
a = identification_create_from_string("moon@strongswan.org ");
|
||||
ck_assert(regex_matches(a, "email:^moon@strongswan.org.*$", ID_MATCH_MAX_WILDCARDS));
|
||||
a->destroy(a);
|
||||
|
||||
a = identification_create_from_string("moon@strongswan.org ");
|
||||
ck_assert(regex_matches(a, "email:^moon@strongswan.org.*$", ID_MATCH_NONE));
|
||||
a->destroy(a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_matches_empty)
|
||||
{
|
||||
identification_t *a;
|
||||
@ -1305,6 +1456,23 @@ START_TEST(test_hash_dn)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_hash_regex)
|
||||
{
|
||||
identification_t *a, *b;
|
||||
|
||||
a = identification_create_from_string_with_regex("fqdn:^vpn1\\.strongswan\\.org$");
|
||||
b = identification_create_from_string_with_regex("fqdn:^vpn1\\.strongswan\\.org$");
|
||||
ck_assert_int_eq(a->hash(a, 0), b->hash(b, 0));
|
||||
b->destroy(b);
|
||||
b = identification_create_from_string("fqdn:^vpn1\\.strongswan\\.org$");
|
||||
ck_assert_int_eq(a->get_type(a), b->get_type(b));
|
||||
ck_assert_chunk_eq(a->get_encoding(a), b->get_encoding(b));
|
||||
ck_assert(a->hash(a, 0) != b->hash(b, 0));
|
||||
b->destroy(b);
|
||||
a->destroy(a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_hash_inc)
|
||||
{
|
||||
identification_t *a;
|
||||
@ -1364,25 +1532,38 @@ END_TEST
|
||||
* wildcards
|
||||
*/
|
||||
|
||||
static bool id_contains_wildcards(char *string)
|
||||
static bool check_id_contains_wildcards(identification_t *id)
|
||||
{
|
||||
identification_t *id;
|
||||
bool contains;
|
||||
|
||||
id = identification_create_from_string(string);
|
||||
contains = id->contains_wildcards(id);
|
||||
id->destroy(id);
|
||||
return contains;
|
||||
}
|
||||
|
||||
static bool id_contains_wildcards(char *str)
|
||||
{
|
||||
return check_id_contains_wildcards(identification_create_from_string(str));
|
||||
}
|
||||
|
||||
START_TEST(test_contains_wildcards)
|
||||
{
|
||||
identification_t *id;
|
||||
|
||||
ck_assert(id_contains_wildcards("%any"));
|
||||
ck_assert(id_contains_wildcards("C=*, O=strongSwan, CN=gw"));
|
||||
ck_assert(id_contains_wildcards("C=CH, O=strongSwan, CN=*"));
|
||||
ck_assert(id_contains_wildcards("*@strongswan.org"));
|
||||
ck_assert(id_contains_wildcards("*.strongswan.org"));
|
||||
ck_assert(!id_contains_wildcards("C=**, O=a*, CN=*a"));
|
||||
/* not actual regexes as the wrong constructor is used */
|
||||
ck_assert(!id_contains_wildcards("fqdn:^vpn1\\.strongswan\\.org$"));
|
||||
ck_assert(id_contains_wildcards("fqdn:^vpn.*\\.strongswan\\.org$"));
|
||||
/* no regex due to missing type prefix */
|
||||
id = identification_create_from_string_with_regex("^vpn1\\.strongswan\\.org$");
|
||||
ck_assert(!check_id_contains_wildcards(id));
|
||||
id = identification_create_from_string_with_regex("fqdn:^vpn1\\.strongswan\\.org$");
|
||||
ck_assert(check_id_contains_wildcards(id));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@ -1392,7 +1573,7 @@ END_TEST
|
||||
|
||||
START_TEST(test_clone)
|
||||
{
|
||||
identification_t *a, *b;
|
||||
identification_t *a, *b, *c;
|
||||
chunk_t a_enc, b_enc;
|
||||
|
||||
a = identification_create_from_string("moon@strongswan.org");
|
||||
@ -1400,11 +1581,30 @@ START_TEST(test_clone)
|
||||
b = a->clone(a);
|
||||
ck_assert(b != NULL);
|
||||
ck_assert(a != b);
|
||||
ck_assert_int_eq(a->get_type(a), b->get_type(b));
|
||||
b_enc = b->get_encoding(b);
|
||||
ck_assert(a_enc.ptr != b_enc.ptr);
|
||||
ck_assert(chunk_equals(a_enc, b_enc));
|
||||
a->destroy(a);
|
||||
b->destroy(b);
|
||||
|
||||
a = identification_create_from_string_with_regex("fqdn:^vpn.+\\.strongswan\\.org$");
|
||||
a_enc = a->get_encoding(a);
|
||||
b = a->clone(a);
|
||||
ck_assert(b != NULL);
|
||||
ck_assert(a != b);
|
||||
ck_assert_int_eq(a->get_type(a), b->get_type(b));
|
||||
b_enc = b->get_encoding(b);
|
||||
ck_assert(a_enc.ptr != b_enc.ptr);
|
||||
ck_assert(chunk_equals(a_enc, b_enc));
|
||||
ck_assert_int_eq(0, a_enc.ptr[a_enc.len]);
|
||||
ck_assert_int_eq(0, b_enc.ptr[b_enc.len]);
|
||||
c = identification_create_from_string("vpn1.strongswan.org");
|
||||
ck_assert_int_eq(ID_MATCH_MAX_WILDCARDS, c->matches(c, a));
|
||||
ck_assert_int_eq(ID_MATCH_MAX_WILDCARDS, c->matches(c, b));
|
||||
a->destroy(a);
|
||||
b->destroy(b);
|
||||
c->destroy(c);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@ -1420,11 +1620,13 @@ Suite *identification_suite_create()
|
||||
tcase_add_test(tc, test_from_data);
|
||||
tcase_add_test(tc, test_from_sockaddr);
|
||||
tcase_add_loop_test(tc, test_from_string, 0, countof(string_data));
|
||||
tcase_add_test(tc, test_from_string_with_regex);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("printf_hook");
|
||||
tcase_add_test(tc, test_printf_hook);
|
||||
tcase_add_test(tc, test_printf_hook_width);
|
||||
tcase_add_test(tc, test_printf_hook_regex);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("equals");
|
||||
@ -1432,6 +1634,7 @@ Suite *identification_suite_create()
|
||||
tcase_add_test(tc, test_equals_any);
|
||||
tcase_add_test(tc, test_equals_binary);
|
||||
tcase_add_test(tc, test_equals_fqdn);
|
||||
tcase_add_test(tc, test_equals_regex);
|
||||
tcase_add_loop_test(tc, test_equals_empty, ID_ANY, ID_KEY_ID + 1);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
@ -1444,6 +1647,7 @@ Suite *identification_suite_create()
|
||||
tcase_add_test(tc, test_matches_range_subnet);
|
||||
tcase_add_test(tc, test_matches_range_range);
|
||||
tcase_add_test(tc, test_matches_string);
|
||||
tcase_add_test(tc, test_matches_regex);
|
||||
tcase_add_loop_test(tc, test_matches_empty, ID_ANY, ID_KEY_ID + 1);
|
||||
tcase_add_loop_test(tc, test_matches_empty_reverse, ID_ANY, ID_KEY_ID + 1);
|
||||
suite_add_tcase(s, tc);
|
||||
@ -1452,6 +1656,7 @@ Suite *identification_suite_create()
|
||||
tcase_add_test(tc, test_hash);
|
||||
tcase_add_test(tc, test_hash_any);
|
||||
tcase_add_test(tc, test_hash_dn);
|
||||
tcase_add_test(tc, test_hash_regex);
|
||||
tcase_add_test(tc, test_hash_inc);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Andreas Steffen
|
||||
* Copyright (C) 2009-2019 Tobias Brunner
|
||||
* Copyright (C) 2009-2025 Tobias Brunner
|
||||
* Copyright (C) 2005-2009 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
*
|
||||
@ -21,6 +21,24 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_REGEX
|
||||
#include <regex.h>
|
||||
#else
|
||||
/* usually, POSIX regular expressions are supported. for the rare case they are
|
||||
* not, e.g. when cross-compiling for Windows, we define some stubs to simplify
|
||||
* the implementation below */
|
||||
typedef void regex_t;
|
||||
static int regexec(const regex_t *restrict preg, const char *restrict string,
|
||||
size_t nmatch, void *pmatch, int eflags)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void regfree(regex_t *preg)
|
||||
{
|
||||
}
|
||||
#endif /* HAVE_REGEX */
|
||||
|
||||
#include "identification.h"
|
||||
|
||||
#include <utils/utils.h>
|
||||
@ -104,7 +122,6 @@ static const x501rdn_t x501rdns[] = {
|
||||
*/
|
||||
#define RDN_MAX 20
|
||||
|
||||
|
||||
typedef struct private_identification_t private_identification_t;
|
||||
|
||||
/**
|
||||
@ -125,8 +142,23 @@ struct private_identification_t {
|
||||
* Type of this ID.
|
||||
*/
|
||||
id_type_t type;
|
||||
|
||||
/**
|
||||
* Pointer if we use regex comparison.
|
||||
*/
|
||||
regex_t *regex;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check that neither object uses a regex.
|
||||
*/
|
||||
static inline bool neither_is_regex(private_identification_t *this,
|
||||
identification_t *other)
|
||||
{
|
||||
private_identification_t *other_priv = (private_identification_t*)other;
|
||||
return !this->regex && !other_priv->regex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerator over RDNs
|
||||
*/
|
||||
@ -174,7 +206,7 @@ METHOD(enumerator_t, rdn_enumerate, bool,
|
||||
/**
|
||||
* Create an enumerator over all RDNs (oid, string type, data) of a DN
|
||||
*/
|
||||
static enumerator_t* create_rdn_enumerator(chunk_t dn)
|
||||
static enumerator_t *create_rdn_enumerator(chunk_t dn)
|
||||
{
|
||||
rdn_enumerator_t *e;
|
||||
|
||||
@ -613,19 +645,26 @@ METHOD(identification_t, hash_binary, u_int,
|
||||
{
|
||||
hash = chunk_hash_inc(this->encoded, hash);
|
||||
}
|
||||
if (this->regex)
|
||||
{ /* ensure regexes have different hashes even if type/encoding is equal */
|
||||
hash = chunk_hash_inc(chunk_from_chars(0x01), hash);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
METHOD(identification_t, equals_binary, bool,
|
||||
private_identification_t *this, identification_t *other)
|
||||
{
|
||||
if (this->type == other->get_type(other))
|
||||
private_identification_t *other_priv = (private_identification_t*)other;
|
||||
|
||||
if (this->type == other_priv->type &&
|
||||
(neither_is_regex(this, other) || (this->regex && other_priv->regex)))
|
||||
{
|
||||
if (this->type == ID_ANY)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return chunk_equals(this->encoded, other->get_encoding(other));
|
||||
return chunk_equals(this->encoded, other_priv->encoded);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@ -895,7 +934,8 @@ static bool is_valid_dn(chunk_t dn)
|
||||
METHOD(identification_t, equals_dn, bool,
|
||||
private_identification_t *this, identification_t *other)
|
||||
{
|
||||
return compare_dn(this->encoded, other->get_encoding(other), NULL);
|
||||
return neither_is_regex(this, other) &&
|
||||
compare_dn(this->encoded, other->get_encoding(other), NULL);
|
||||
}
|
||||
|
||||
METHOD(identification_t, hash_dn, u_int,
|
||||
@ -924,6 +964,7 @@ METHOD(identification_t, equals_strcasecmp, bool,
|
||||
/* we do some extra sanity checks to check for invalid IDs with a
|
||||
* terminating null in it. */
|
||||
if (this->type == other->get_type(other) &&
|
||||
neither_is_regex(this, other) &&
|
||||
this->encoded.len == encoded.len &&
|
||||
memchr(this->encoded.ptr, 0, this->encoded.len) == NULL &&
|
||||
memchr(encoded.ptr, 0, encoded.len) == NULL &&
|
||||
@ -949,9 +990,38 @@ METHOD(identification_t, matches_binary, id_match_t,
|
||||
return ID_MATCH_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the regex in other against our own encoding.
|
||||
*/
|
||||
static id_match_t matches_regex(private_identification_t *this,
|
||||
private_identification_t *other)
|
||||
{
|
||||
char buf[BUF_LEN-1];
|
||||
int rc;
|
||||
|
||||
if (this->regex)
|
||||
{ /* don't match two regex values */
|
||||
return ID_MATCH_NONE;
|
||||
}
|
||||
if (!this->encoded.len)
|
||||
{
|
||||
return ID_MATCH_NONE;
|
||||
}
|
||||
/* match against the string representation of the identity */
|
||||
if (snprintf(buf, sizeof(buf), "%Y", this) >= sizeof(buf))
|
||||
{
|
||||
/* fail if the buffer is too small. note that we use BUF_LEN-1 because
|
||||
* the printf hook uses BUF_LEN to print the identity internally */
|
||||
return ID_MATCH_NONE;
|
||||
}
|
||||
rc = regexec(other->regex, buf, 0, NULL, 0);
|
||||
return rc == 0 ? ID_MATCH_MAX_WILDCARDS : ID_MATCH_NONE;
|
||||
}
|
||||
|
||||
METHOD(identification_t, matches_string, id_match_t,
|
||||
private_identification_t *this, identification_t *other)
|
||||
{
|
||||
private_identification_t *other_priv = (private_identification_t*)other;
|
||||
chunk_t encoded = other->get_encoding(other);
|
||||
u_int len = encoded.len;
|
||||
|
||||
@ -963,6 +1033,10 @@ METHOD(identification_t, matches_string, id_match_t,
|
||||
{
|
||||
return ID_MATCH_NONE;
|
||||
}
|
||||
if (other_priv->regex)
|
||||
{
|
||||
return matches_regex(this, other_priv);
|
||||
}
|
||||
/* try a equals check first */
|
||||
if (equals_strcasecmp(this, other))
|
||||
{
|
||||
@ -1007,6 +1081,7 @@ static id_match_t matches_dn_internal(private_identification_t *this,
|
||||
identification_t *other,
|
||||
bool (*match)(chunk_t,chunk_t,int*))
|
||||
{
|
||||
private_identification_t *other_priv = (private_identification_t*)other;
|
||||
int wc;
|
||||
|
||||
if (other->get_type(other) == ID_ANY)
|
||||
@ -1016,7 +1091,11 @@ static id_match_t matches_dn_internal(private_identification_t *this,
|
||||
|
||||
if (this->type == other->get_type(other))
|
||||
{
|
||||
if (match(this->encoded, other->get_encoding(other), &wc))
|
||||
if (other_priv->regex)
|
||||
{
|
||||
return matches_regex(this, other_priv);
|
||||
}
|
||||
else if (match(this->encoded, other->get_encoding(other), &wc))
|
||||
{
|
||||
wc = min(wc, ID_MATCH_ONE_WILDCARD - ID_MATCH_MAX_WILDCARDS);
|
||||
return ID_MATCH_PERFECT - wc;
|
||||
@ -1442,21 +1521,20 @@ METHOD(identification_t, matches_range, id_match_t,
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
* Convert the given identity to a string depending on its type.
|
||||
*/
|
||||
int identification_printf_hook(printf_hook_data_t *data,
|
||||
printf_hook_spec_t *spec, const void *const *args)
|
||||
static void identity_to_string(private_identification_t *this, char buf[BUF_LEN])
|
||||
{
|
||||
private_identification_t *this = *((private_identification_t**)(args[0]));
|
||||
chunk_t proper;
|
||||
char buf[BUF_LEN], *pos;
|
||||
char *pos;
|
||||
uint8_t address_size;
|
||||
size_t len;
|
||||
int written;
|
||||
|
||||
if (this == NULL)
|
||||
if (this->regex)
|
||||
{
|
||||
return print_in_hook(data, "%*s", spec->width, "(null)");
|
||||
snprintf(buf, BUF_LEN, "%s", this->encoded.ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this->type)
|
||||
@ -1573,6 +1651,24 @@ int identification_printf_hook(printf_hook_data_t *data,
|
||||
snprintf(buf, BUF_LEN, "(unknown ID type: %d)", this->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
int identification_printf_hook(printf_hook_data_t *data,
|
||||
printf_hook_spec_t *spec, const void *const *args)
|
||||
{
|
||||
private_identification_t *this = *((private_identification_t**)(args[0]));
|
||||
char buf[BUF_LEN];
|
||||
|
||||
if (!this)
|
||||
{
|
||||
return print_in_hook(data, "%*s", spec->width, "(null)");
|
||||
}
|
||||
|
||||
identity_to_string(this, buf);
|
||||
|
||||
if (spec->minus)
|
||||
{
|
||||
return print_in_hook(data, "%-*s", spec->width, buf);
|
||||
@ -1580,13 +1676,52 @@ int identification_printf_hook(printf_hook_data_t *data,
|
||||
return print_in_hook(data, "%*s", spec->width, buf);
|
||||
}
|
||||
|
||||
#ifdef HAVE_REGEX
|
||||
|
||||
/**
|
||||
* Compile the encoded regular expression.
|
||||
*/
|
||||
static bool compile_regex(private_identification_t *this)
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
int err = 0;
|
||||
|
||||
this->regex = malloc(sizeof(*this->regex));
|
||||
err = regcomp(this->regex, this->encoded.ptr,
|
||||
REG_EXTENDED | REG_ICASE | REG_NOSUB);
|
||||
if (err != 0)
|
||||
{
|
||||
regerror(err, NULL, buf, sizeof(buf));
|
||||
DBG1(DBG_LIB, "invalid regular expression '%s': %s",
|
||||
this->encoded.ptr, buf);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#else /* HAVE_REGEX */
|
||||
|
||||
static bool compile_regex(private_identification_t *this)
|
||||
{
|
||||
DBG1(DBG_LIB, "regular expressions are not supported");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif /* HAVE_REGEX */
|
||||
|
||||
METHOD(identification_t, clone_, identification_t*,
|
||||
private_identification_t *this)
|
||||
{
|
||||
private_identification_t *clone = malloc_thing(private_identification_t);
|
||||
|
||||
memcpy(clone, this, sizeof(private_identification_t));
|
||||
if (this->encoded.len)
|
||||
if (this->regex)
|
||||
{
|
||||
/* make sure we have the full encoding cloned */
|
||||
clone->encoded = chunk_from_str(strdup(this->encoded.ptr));
|
||||
compile_regex(clone);
|
||||
}
|
||||
else if (this->encoded.len)
|
||||
{
|
||||
clone->encoded = chunk_clone(this->encoded);
|
||||
}
|
||||
@ -1597,6 +1732,11 @@ METHOD(identification_t, destroy, void,
|
||||
private_identification_t *this)
|
||||
{
|
||||
chunk_free(&this->encoded);
|
||||
if (this->regex)
|
||||
{
|
||||
regfree(this->regex);
|
||||
free(this->regex);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
@ -1672,32 +1812,37 @@ static private_identification_t *identification_create(id_type_t type)
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefixes used when parsing identities.
|
||||
*/
|
||||
static const struct {
|
||||
const char *str;
|
||||
id_type_t type;
|
||||
bool regex;
|
||||
} prefixes[] = {
|
||||
{ "ipv4:", ID_IPV4_ADDR, FALSE},
|
||||
{ "ipv6:", ID_IPV6_ADDR, FALSE},
|
||||
{ "ipv4net:", ID_IPV4_ADDR_SUBNET, FALSE},
|
||||
{ "ipv6net:", ID_IPV6_ADDR_SUBNET, FALSE},
|
||||
{ "ipv4range:", ID_IPV4_ADDR_RANGE, FALSE},
|
||||
{ "ipv6range:", ID_IPV6_ADDR_RANGE, FALSE},
|
||||
{ "rfc822:", ID_RFC822_ADDR, TRUE},
|
||||
{ "email:", ID_RFC822_ADDR, TRUE},
|
||||
{ "userfqdn:", ID_USER_FQDN, FALSE},
|
||||
{ "fqdn:", ID_FQDN, TRUE},
|
||||
{ "dns:", ID_FQDN, TRUE},
|
||||
{ "asn1dn:", ID_DER_ASN1_DN, TRUE},
|
||||
{ "asn1gn:", ID_DER_ASN1_GN, FALSE},
|
||||
{ "xmppaddr:", ID_DER_ASN1_GN, FALSE},
|
||||
{ "keyid:", ID_KEY_ID, FALSE},
|
||||
{ "uri:", ID_DER_ASN1_GN_URI, FALSE},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an identity for a specific type, determined by prefix
|
||||
*/
|
||||
static private_identification_t* create_from_string_with_prefix_type(char *str)
|
||||
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 },
|
||||
{ "ipv4net:", ID_IPV4_ADDR_SUBNET },
|
||||
{ "ipv6net:", ID_IPV6_ADDR_SUBNET },
|
||||
{ "ipv4range:", ID_IPV4_ADDR_RANGE },
|
||||
{ "ipv6range:", ID_IPV6_ADDR_RANGE },
|
||||
{ "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 },
|
||||
{ "xmppaddr:", ID_DER_ASN1_GN },
|
||||
{ "keyid:", ID_KEY_ID },
|
||||
{ "uri:", ID_DER_ASN1_GN_URI },
|
||||
};
|
||||
private_identification_t *this;
|
||||
int i;
|
||||
|
||||
@ -1726,7 +1871,6 @@ static private_identification_t* create_from_string_with_prefix_type(char *str)
|
||||
asn1_wrap(ASN1_UTF8STRING, "m",
|
||||
this->encoded)));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@ -1739,7 +1883,7 @@ static private_identification_t* create_from_string_with_prefix_type(char *str)
|
||||
* 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)
|
||||
static private_identification_t *create_from_string_with_num_type(char *str)
|
||||
{
|
||||
private_identification_t *this;
|
||||
u_long type;
|
||||
@ -1769,7 +1913,7 @@ static private_identification_t* create_from_string_with_num_type(char *str)
|
||||
/**
|
||||
* Convert to an IPv4/IPv6 host address, subnet or address range
|
||||
*/
|
||||
static private_identification_t* create_ip_address_from_string(char *string,
|
||||
static private_identification_t *create_ip_address_from_string(char *string,
|
||||
bool is_ipv4)
|
||||
{
|
||||
private_identification_t *this;
|
||||
@ -1910,7 +2054,7 @@ identification_t *identification_create_from_string(char *string)
|
||||
else
|
||||
{
|
||||
this = identification_create(ID_KEY_ID);
|
||||
this->encoded = chunk_from_str(strdup(string));
|
||||
this->encoded = chunk_clone(chunk_from_str(string));
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
@ -1937,7 +2081,7 @@ identification_t *identification_create_from_string(char *string)
|
||||
if (!this)
|
||||
{ /* not IPv4, mostly FQDN */
|
||||
this = identification_create(ID_FQDN);
|
||||
this->encoded = chunk_from_str(strdup(string));
|
||||
this->encoded = chunk_clone(chunk_from_str(string));
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
@ -1948,7 +2092,7 @@ identification_t *identification_create_from_string(char *string)
|
||||
if (!this)
|
||||
{ /* not IPv4/6 fallback to KEY_ID */
|
||||
this = identification_create(ID_KEY_ID);
|
||||
this->encoded = chunk_from_str(strdup(string));
|
||||
this->encoded = chunk_clone(chunk_from_str(string));
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
@ -1981,16 +2125,75 @@ identification_t *identification_create_from_string(char *string)
|
||||
else
|
||||
{
|
||||
this = identification_create(ID_RFC822_ADDR);
|
||||
this->encoded = chunk_from_str(strdup(string));
|
||||
this->encoded = chunk_clone(chunk_from_str(string));
|
||||
return &this->public;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given string should be parsed as regular expression identity.
|
||||
* If so, it modifies the string and returns the identity type, otherwise,
|
||||
* ID_ANY is returned.
|
||||
*/
|
||||
static id_type_t is_regex_identity(char **string)
|
||||
{
|
||||
char *regex;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < countof(prefixes); i++)
|
||||
{
|
||||
if (strcasepfx(*string, prefixes[i].str))
|
||||
{
|
||||
regex = *string + strlen(prefixes[i].str);
|
||||
|
||||
if (prefixes[i].regex &&
|
||||
*regex == '^' && *(regex + strlen(regex) - 1) == '$')
|
||||
{
|
||||
*string = regex;
|
||||
return prefixes[i].type;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ID_ANY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
identification_t * identification_create_from_data(chunk_t data)
|
||||
identification_t *identification_create_from_string_with_regex(char *string)
|
||||
{
|
||||
private_identification_t *this;
|
||||
id_type_t type;
|
||||
|
||||
type = is_regex_identity(&string);
|
||||
if (type != ID_ANY)
|
||||
{
|
||||
this = identification_create(type);
|
||||
|
||||
this->public.hash = _hash_binary;
|
||||
this->public.equals = _equals_binary;
|
||||
this->public.matches = _matches_any;
|
||||
this->public.contains_wildcards = (void*)return_true;
|
||||
|
||||
/* this encoding explicitly includes the null-terminator so we can
|
||||
* directly use it to compile the regex and printing */
|
||||
this->encoded = chunk_from_str(strdup(string));
|
||||
if (!compile_regex(this))
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
return identification_create_from_string(string);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
identification_t *identification_create_from_data(chunk_t data)
|
||||
{
|
||||
char buf[data.len + 1];
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015 Tobias Brunner
|
||||
* Copyright (C) 2009-2025 Tobias Brunner
|
||||
* Copyright (C) 2005-2009 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
*
|
||||
@ -325,7 +325,30 @@ struct identification_t {
|
||||
* @param string input string, which will be converted
|
||||
* @return identification_t
|
||||
*/
|
||||
identification_t * identification_create_from_string(char *string);
|
||||
identification_t *identification_create_from_string(char *string);
|
||||
|
||||
/**
|
||||
* Creates an identification_t object from a string that may contain a regular
|
||||
* expression.
|
||||
*
|
||||
* This function behaves like identification_create_from_string() but also
|
||||
* accepts regular expressions. So it must only be used to parse
|
||||
* trusted/configured values, never untrusted values received over the network.
|
||||
*
|
||||
* A regular expression must be prefixed by an identity type (supported are
|
||||
* rfc822:, email:, fqdn:, dns:, and asn1dn:), and it must start with a caret
|
||||
* ('^') and end with a dollar sign ('$') to indicate an anchored pattern.
|
||||
* If the regular expression is invalid, the function returns NULL.
|
||||
*
|
||||
* The regular expression is always matched against the string representation
|
||||
* of other identities and matching is performed case-insensitive.
|
||||
*
|
||||
* @param string string to parse, regex must begin with '^' and end with '$'
|
||||
* and must be prefixed with a valid identification type
|
||||
* @return pointer to newly allocated identification_t object, or NULL
|
||||
* if regular expression is invalid
|
||||
*/
|
||||
identification_t *identification_create_from_string_with_regex(char *string);
|
||||
|
||||
/**
|
||||
* Creates an identification from a chunk of data, guessing its type.
|
||||
@ -333,7 +356,7 @@ identification_t * identification_create_from_string(char *string);
|
||||
* @param data identification data
|
||||
* @return identification_t
|
||||
*/
|
||||
identification_t * identification_create_from_data(chunk_t data);
|
||||
identification_t *identification_create_from_data(chunk_t data);
|
||||
|
||||
/**
|
||||
* Creates an identification_t object from an encoded chunk.
|
||||
@ -342,7 +365,8 @@ identification_t * identification_create_from_data(chunk_t data);
|
||||
* @param encoded encoded bytes, such as from identification_t.get_encoding
|
||||
* @return identification_t
|
||||
*/
|
||||
identification_t * identification_create_from_encoding(id_type_t type, chunk_t encoded);
|
||||
identification_t *identification_create_from_encoding(id_type_t type,
|
||||
chunk_t encoded);
|
||||
|
||||
/**
|
||||
* Creates an identification_t object from a sockaddr struct
|
||||
@ -350,7 +374,7 @@ identification_t * identification_create_from_encoding(id_type_t type, chunk_t e
|
||||
* @param sockaddr sockaddr struct which contains family and address
|
||||
* @return identification_t
|
||||
*/
|
||||
identification_t * identification_create_from_sockaddr(sockaddr_t *sockaddr);
|
||||
identification_t *identification_create_from_sockaddr(sockaddr_t *sockaddr);
|
||||
|
||||
/**
|
||||
* printf hook function for identification_t.
|
||||
@ -359,6 +383,7 @@ identification_t * identification_create_from_sockaddr(sockaddr_t *sockaddr);
|
||||
* identification_t *identification
|
||||
*/
|
||||
int identification_printf_hook(printf_hook_data_t *data,
|
||||
printf_hook_spec_t *spec, const void *const *args);
|
||||
printf_hook_spec_t *spec,
|
||||
const void *const *args);
|
||||
|
||||
#endif /** IDENTIFICATION_H_ @}*/
|
||||
|
@ -162,8 +162,8 @@ connections.<conn>.fragmentation = yes
|
||||
Use IKE UDP datagram fragmentation (_yes_, _accept_, _no_ or _force_).
|
||||
|
||||
Use IKE fragmentation (proprietary IKEv1 extension or RFC 7383 IKEv2
|
||||
fragmentation). Acceptable values are _yes_ (the default), _accept_,
|
||||
_force_ and _no_. If set to _yes_, and the peer supports it, oversized IKE
|
||||
fragmentation). Acceptable values are _yes_ (the default), _accept_,
|
||||
_force_ and _no_. If set to _yes_, and the peer supports it, oversized IKE
|
||||
messages will be sent in fragments. If set to _accept_, support for
|
||||
fragmentation is announced to the peer but the daemon does not send its own
|
||||
messages in fragments. If set to _force_ (only supported for IKEv1) the
|
||||
@ -350,7 +350,7 @@ connections.<conn>.mediated_by =
|
||||
|
||||
The name of the connection to mediate this connection through. If given, the
|
||||
connection will be mediated through the named mediation connection.
|
||||
The mediation connection must have **mediation** enabled.
|
||||
The mediation connection must have **mediation** enabled.
|
||||
|
||||
connections.<conn>.mediation_peer =
|
||||
Identity under which the peer is registered at the mediation server.
|
||||
@ -426,7 +426,7 @@ connections.<conn>.local<suffix>.pubkeys =
|
||||
directory or an absolute path.
|
||||
|
||||
Even though multiple local public keys could be defined in principle, only
|
||||
the first public key in the list is used for authentication.
|
||||
the first public key in the list is used for authentication.
|
||||
|
||||
connections.<conn>.local<suffix>.auth = pubkey
|
||||
Authentication to perform locally (_pubkey_, _psk_, _xauth[-backend]_ or
|
||||
@ -534,13 +534,27 @@ connections.<conn>.remote<suffix>.id = %any
|
||||
with wildcards, the _charon.rdn_matching_ option in **strongswan.conf**(5)
|
||||
specifies how RDNs are matched.
|
||||
|
||||
Extended POSIX regular expressions are also supported for remote identity
|
||||
matching. They must start with an explicit type prefix, followed by a caret
|
||||
character ('^'), and end with a dollar sign ('$') to indicate an anchored
|
||||
pattern. Supported types are _rfc822_, _email_, _fqdn_, _dns_, and _asn1dn_.
|
||||
While regular expressions are always matched against the string
|
||||
representation of other identities, the type must match as well. The
|
||||
matching is performed case insensitive. Make sure to escape backslash
|
||||
characters when configuring identities in double quotes. Examples:
|
||||
_email:^(moon|sun)@strongswan\.org$_, _fqdn:^vpn[0-9]+\.strongswan\.org$_,
|
||||
_"asn1dn:^.*CN=.+\\.strongswan\\.org$"_.
|
||||
|
||||
connections.<conn>.remote<suffix>.eap_id = id
|
||||
Use EAP-Identity method to request an identity from the client to match
|
||||
against and use during EAP authentication.
|
||||
|
||||
Use EAP-Identity method to request an identity from the client to match
|
||||
against and use during EAP authentication. There is currently no "best"
|
||||
match, configs are matched in the order they are loaded.
|
||||
match, configs are matched in the order they are loaded.
|
||||
|
||||
Wildcards and regular expressions are supported, refer to the **id** keyword
|
||||
for details.
|
||||
|
||||
connections.<conn>.remote<suffix>.groups =
|
||||
Authorization group memberships to require.
|
||||
@ -699,7 +713,7 @@ connections.<conn>.children.<child>.ah_proposals =
|
||||
AH proposals to offer for the CHILD_SA. A proposal is a set of algorithms.
|
||||
For AH, this includes an integrity algorithm and an optional key exchange
|
||||
method. If a KE method is specified, CHILD_SA/Quick Mode rekeying and
|
||||
initial negotiation uses a separate key exchange using the negotiated method
|
||||
initial negotiation uses a separate key exchange using the negotiated method
|
||||
(refer to _esp_proposals_ for details).
|
||||
|
||||
With peers that support multiple IKEv2 key exchanges (RFC 9370), up to seven
|
||||
@ -737,7 +751,7 @@ connections.<conn>.children.<child>.esp_proposals = default
|
||||
mismatch might, therefore, not immediately be noticed when the SA is
|
||||
established, but may later cause rekeying to fail. If one or more key
|
||||
exchange methods are configured in a proposal, the key exchange can be made
|
||||
optional by also adding **none**.
|
||||
optional by also adding **none**.
|
||||
|
||||
With peers that support multiple IKEv2 key exchanges (RFC 9370), up to seven
|
||||
additional key exchanges may be negotiated. They can be configured by
|
||||
@ -999,7 +1013,7 @@ connections.<conn>.children.<child>.mark_in_sa = no
|
||||
only set on the inbound policy. The tuple destination address, protocol and
|
||||
SPI is unique and the mark is not required to find the correct SA, allowing
|
||||
to mark traffic after decryption instead (where more specific selectors may
|
||||
be used) to match different policies. Marking packets before decryption is
|
||||
be used) to match different policies. Marking packets before decryption is
|
||||
still possible, even if no mark is set on the SA.
|
||||
|
||||
connections.<conn>.children.<child>.mark_out = 0/0x00000000
|
||||
@ -1269,7 +1283,7 @@ secrets.ppk<suffix> { # }
|
||||
Postquantum Preshared Key (PPK) section for a specific secret.
|
||||
|
||||
Postquantum Preshared Key (PPK) section for a specific secret. Each PPK is
|
||||
defined in a unique section having the _ppk_ prefix.
|
||||
defined in a unique section having the _ppk_ prefix.
|
||||
|
||||
secrets.ppk<suffix>.secret =
|
||||
Value of the PPK.
|
||||
|
Loading…
x
Reference in New Issue
Block a user