identification: Add hash() method
Compared to hashing the encoding we can ignore string types of RDNs when hashing DNs, making hash() compatible to equals() that does the same. Fixes #991.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Tobias Brunner
|
* Copyright (C) 2013-2015 Tobias Brunner
|
||||||
* Copyright (C) 2009 Martin Willi
|
* Copyright (C) 2009 Martin Willi
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
@@ -726,6 +726,88 @@ START_TEST(test_matches_empty_reverse)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* identification hashing
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool id_hash_equals(char *str, char *b_str)
|
||||||
|
{
|
||||||
|
identification_t *a, *b;
|
||||||
|
bool success = FALSE;
|
||||||
|
|
||||||
|
a = identification_create_from_string(str);
|
||||||
|
b = identification_create_from_string(b_str ?: str);
|
||||||
|
success = a->hash(a, 0) == b->hash(b, 0);
|
||||||
|
a->destroy(a);
|
||||||
|
b->destroy(b);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(test_hash)
|
||||||
|
{
|
||||||
|
ck_assert(id_hash_equals("[email protected]", NULL));
|
||||||
|
ck_assert(id_hash_equals("vpn.strongswan.org", NULL));
|
||||||
|
ck_assert(id_hash_equals("192.168.1.1", NULL));
|
||||||
|
ck_assert(id_hash_equals("C=CH", NULL));
|
||||||
|
|
||||||
|
ck_assert(!id_hash_equals("[email protected]", "[email protected]"));
|
||||||
|
ck_assert(!id_hash_equals("vpn.strongswan.org", "*.strongswan.org"));
|
||||||
|
ck_assert(!id_hash_equals("192.168.1.1", "192.168.1.2"));
|
||||||
|
ck_assert(!id_hash_equals("C=CH", "C=DE"));
|
||||||
|
ck_assert(!id_hash_equals("fqdn:strongswan.org", "keyid:strongswan.org"));
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_hash_any)
|
||||||
|
{
|
||||||
|
ck_assert(id_hash_equals("%any", NULL));
|
||||||
|
ck_assert(id_hash_equals("%any", "0.0.0.0"));
|
||||||
|
ck_assert(id_hash_equals("%any", "*"));
|
||||||
|
ck_assert(id_hash_equals("%any", ""));
|
||||||
|
|
||||||
|
ck_assert(!id_hash_equals("%any", "any"));
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_hash_dn)
|
||||||
|
{
|
||||||
|
identification_t *a, *b;
|
||||||
|
|
||||||
|
/* same DN (C=CH, O=strongSwan), different RDN type (PRINTABLESTRING vs.
|
||||||
|
* UTF8STRING) */
|
||||||
|
a = identification_create_from_data(chunk_from_chars(
|
||||||
|
0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
|
||||||
|
0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x31,
|
||||||
|
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a,
|
||||||
|
0x13, 0x0a, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67,
|
||||||
|
0x53, 0x77, 0x61, 0x6e));
|
||||||
|
b = identification_create_from_data(chunk_from_chars(
|
||||||
|
0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
|
||||||
|
0x55, 0x04, 0x06, 0x0c, 0x02, 0x43, 0x48, 0x31,
|
||||||
|
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a,
|
||||||
|
0x0c, 0x0a, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67,
|
||||||
|
0x53, 0x77, 0x61, 0x6e));
|
||||||
|
ck_assert_int_eq(a->hash(a, 0), b->hash(b, 0));
|
||||||
|
ck_assert(a->equals(a, b));
|
||||||
|
a->destroy(a);
|
||||||
|
b->destroy(b);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_hash_inc)
|
||||||
|
{
|
||||||
|
identification_t *a;
|
||||||
|
|
||||||
|
a = identification_create_from_string("vpn.strongswan.org");
|
||||||
|
ck_assert(a->hash(a, 0) != a->hash(a, 1));
|
||||||
|
a->destroy(a);
|
||||||
|
|
||||||
|
a = identification_create_from_string("C=CH, O=strongSwan");
|
||||||
|
ck_assert(a->hash(a, 0) != a->hash(a, 1));
|
||||||
|
a->destroy(a);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* identification part enumeration
|
* identification part enumeration
|
||||||
*/
|
*/
|
||||||
@@ -851,6 +933,13 @@ Suite *identification_suite_create()
|
|||||||
tcase_add_loop_test(tc, test_matches_empty_reverse, 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);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("hash");
|
||||||
|
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_inc);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("part enumeration");
|
tc = tcase_create("part enumeration");
|
||||||
tcase_add_test(tc, test_parts);
|
tcase_add_test(tc, test_parts);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2012 Tobias Brunner
|
* Copyright (C) 2009-2015 Tobias Brunner
|
||||||
* Copyright (C) 2005-2009 Martin Willi
|
* Copyright (C) 2005-2009 Martin Willi
|
||||||
* Copyright (C) 2005 Jan Hutter
|
* Copyright (C) 2005 Jan Hutter
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
@@ -579,6 +579,19 @@ METHOD(identification_t, contains_wildcards_memchr, bool,
|
|||||||
return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
|
return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(identification_t, hash_binary, u_int,
|
||||||
|
private_identification_t *this, u_int inc)
|
||||||
|
{
|
||||||
|
u_int hash;
|
||||||
|
|
||||||
|
hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
|
||||||
|
if (this->type != ID_ANY)
|
||||||
|
{
|
||||||
|
hash = chunk_hash_inc(this->encoded, hash);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(identification_t, equals_binary, bool,
|
METHOD(identification_t, equals_binary, bool,
|
||||||
private_identification_t *this, identification_t *other)
|
private_identification_t *this, identification_t *other)
|
||||||
{
|
{
|
||||||
@@ -687,6 +700,24 @@ METHOD(identification_t, equals_dn, bool,
|
|||||||
return compare_dn(this->encoded, other->get_encoding(other), NULL);
|
return compare_dn(this->encoded, other->get_encoding(other), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(identification_t, hash_dn, u_int,
|
||||||
|
private_identification_t *this, u_int inc)
|
||||||
|
{
|
||||||
|
enumerator_t *rdns;
|
||||||
|
chunk_t oid, data;
|
||||||
|
u_char type;
|
||||||
|
u_int hash;
|
||||||
|
|
||||||
|
hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
|
||||||
|
rdns = create_rdn_enumerator(this->encoded);
|
||||||
|
while (rdns->enumerate(rdns, &oid, &type, &data))
|
||||||
|
{
|
||||||
|
hash = chunk_hash_inc(data, chunk_hash_inc(oid, hash));
|
||||||
|
}
|
||||||
|
rdns->destroy(rdns);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(identification_t, equals_strcasecmp, bool,
|
METHOD(identification_t, equals_strcasecmp, bool,
|
||||||
private_identification_t *this, identification_t *other)
|
private_identification_t *this, identification_t *other)
|
||||||
{
|
{
|
||||||
@@ -903,6 +934,7 @@ static private_identification_t *identification_create(id_type_t type)
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ID_ANY:
|
case ID_ANY:
|
||||||
|
this->public.hash = _hash_binary;
|
||||||
this->public.matches = _matches_any;
|
this->public.matches = _matches_any;
|
||||||
this->public.equals = _equals_binary;
|
this->public.equals = _equals_binary;
|
||||||
this->public.contains_wildcards = return_true;
|
this->public.contains_wildcards = return_true;
|
||||||
@@ -910,16 +942,19 @@ static private_identification_t *identification_create(id_type_t type)
|
|||||||
case ID_FQDN:
|
case ID_FQDN:
|
||||||
case ID_RFC822_ADDR:
|
case ID_RFC822_ADDR:
|
||||||
case ID_USER_ID:
|
case ID_USER_ID:
|
||||||
|
this->public.hash = _hash_binary;
|
||||||
this->public.matches = _matches_string;
|
this->public.matches = _matches_string;
|
||||||
this->public.equals = _equals_strcasecmp;
|
this->public.equals = _equals_strcasecmp;
|
||||||
this->public.contains_wildcards = _contains_wildcards_memchr;
|
this->public.contains_wildcards = _contains_wildcards_memchr;
|
||||||
break;
|
break;
|
||||||
case ID_DER_ASN1_DN:
|
case ID_DER_ASN1_DN:
|
||||||
|
this->public.hash = _hash_dn;
|
||||||
this->public.equals = _equals_dn;
|
this->public.equals = _equals_dn;
|
||||||
this->public.matches = _matches_dn;
|
this->public.matches = _matches_dn;
|
||||||
this->public.contains_wildcards = _contains_wildcards_dn;
|
this->public.contains_wildcards = _contains_wildcards_dn;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
this->public.hash = _hash_binary;
|
||||||
this->public.equals = _equals_binary;
|
this->public.equals = _equals_binary;
|
||||||
this->public.matches = _matches_binary;
|
this->public.matches = _matches_binary;
|
||||||
this->public.contains_wildcards = return_false;
|
this->public.contains_wildcards = return_false;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 Tobias Brunner
|
* Copyright (C) 2009-2015 Tobias Brunner
|
||||||
* Copyright (C) 2005-2009 Martin Willi
|
* Copyright (C) 2005-2009 Martin Willi
|
||||||
* Copyright (C) 2005 Jan Hutter
|
* Copyright (C) 2005 Jan Hutter
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
@@ -218,6 +218,14 @@ struct identification_t {
|
|||||||
*/
|
*/
|
||||||
id_type_t (*get_type) (identification_t *this);
|
id_type_t (*get_type) (identification_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a hash value for this identification_t object.
|
||||||
|
*
|
||||||
|
* @param inc optional value for incremental hashing
|
||||||
|
* @return hash value
|
||||||
|
*/
|
||||||
|
u_int (*hash) (identification_t *this, u_int inc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if two identification_t objects are equal.
|
* Check if two identification_t objects are equal.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user