Merge
This commit is contained in:
23
src/acl.c
23
src/acl.c
@@ -27,18 +27,18 @@ static int is_included_in_acl(int list_length, struct ip_and_mask (*list)[], uni
|
|||||||
NULLCHECK( test );
|
NULLCHECK( test );
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i < list_length; i++) {
|
for (i=0; i < list_length; i++) {
|
||||||
struct ip_and_mask *entry = &(*list)[i];
|
struct ip_and_mask *entry = &(*list)[i];
|
||||||
int testbits;
|
int testbits;
|
||||||
unsigned char *raw_address1, *raw_address2;
|
unsigned char *raw_address1, *raw_address2;
|
||||||
|
|
||||||
debug("checking acl entry %d (%d/%d)", i, test->generic.sa_family, entry->ip.family);
|
debug("checking acl entry %d (%d/%d)", i, test->generic.sa_family, entry->ip.family);
|
||||||
|
|
||||||
if (test->generic.sa_family != entry->ip.family) {
|
if (test->generic.sa_family != entry->ip.family) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test->generic.sa_family == AF_INET) {
|
if (test->generic.sa_family == AF_INET) {
|
||||||
debug("it's an AF_INET");
|
debug("it's an AF_INET");
|
||||||
raw_address1 = (unsigned char*) &test->v4.sin_addr;
|
raw_address1 = (unsigned char*) &test->v4.sin_addr;
|
||||||
@@ -49,9 +49,9 @@ static int is_included_in_acl(int list_length, struct ip_and_mask (*list)[], uni
|
|||||||
raw_address1 = (unsigned char*) &test->v6.sin6_addr;
|
raw_address1 = (unsigned char*) &test->v6.sin6_addr;
|
||||||
raw_address2 = (unsigned char*) &entry->ip.v6.sin6_addr;
|
raw_address2 = (unsigned char*) &entry->ip.v6.sin6_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("testbits=%d", entry->mask);
|
debug("testbits=%d", entry->mask);
|
||||||
|
|
||||||
for (testbits = entry->mask; testbits > 0; testbits -= 8) {
|
for (testbits = entry->mask; testbits > 0; testbits -= 8) {
|
||||||
debug("testbits=%d, c1=%02x, c2=%02x", testbits, raw_address1[0], raw_address2[0]);
|
debug("testbits=%d, c1=%02x, c2=%02x", testbits, raw_address1[0], raw_address2[0]);
|
||||||
if (testbits >= 8) {
|
if (testbits >= 8) {
|
||||||
@@ -63,17 +63,17 @@ static int is_included_in_acl(int list_length, struct ip_and_mask (*list)[], uni
|
|||||||
(raw_address2[0] & testmasks[testbits%8]) )
|
(raw_address2[0] & testmasks[testbits%8]) )
|
||||||
goto no_match;
|
goto no_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_address1++;
|
raw_address1++;
|
||||||
raw_address2++;
|
raw_address2++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
no_match: ;
|
no_match: ;
|
||||||
debug("no match");
|
debug("no match");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ int acl_includes( struct acl * acl, union mysockaddr * addr )
|
|||||||
|
|
||||||
if ( 0 == acl->len ) {
|
if ( 0 == acl->len ) {
|
||||||
return !( acl->default_deny );
|
return !( acl->default_deny );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return is_included_in_acl( acl->len, acl->entries, addr );
|
return is_included_in_acl( acl->len, acl->entries, addr );
|
||||||
}
|
}
|
||||||
@@ -97,3 +97,4 @@ void acl_destroy( struct acl * acl )
|
|||||||
acl->entries = NULL;
|
acl->entries = NULL;
|
||||||
free( acl );
|
free( acl );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
44
src/parse.c
44
src/parse.c
@@ -12,9 +12,9 @@ int atoi(const char *nptr);
|
|||||||
int parse_ip_to_sockaddr(struct sockaddr* out, char* src)
|
int parse_ip_to_sockaddr(struct sockaddr* out, char* src)
|
||||||
{
|
{
|
||||||
char temp[64];
|
char temp[64];
|
||||||
struct sockaddr_in *v4 = (struct sockaddr_in *) out;
|
struct sockaddr_in *v4 = (struct sockaddr_in *) out;
|
||||||
struct sockaddr_in6 *v6 = (struct sockaddr_in6 *) out;
|
struct sockaddr_in6 *v6 = (struct sockaddr_in6 *) out;
|
||||||
|
|
||||||
/* allow user to start with [ and end with any other invalid char */
|
/* allow user to start with [ and end with any other invalid char */
|
||||||
{
|
{
|
||||||
int i=0, j=0;
|
int i=0, j=0;
|
||||||
@@ -24,7 +24,7 @@ int parse_ip_to_sockaddr(struct sockaddr* out, char* src)
|
|||||||
temp[j++] = src[i];
|
temp[j++] = src[i];
|
||||||
temp[j] = 0;
|
temp[j] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (temp[0] == '0' && temp[1] == '\0') {
|
if (temp[0] == '0' && temp[1] == '\0') {
|
||||||
v4->sin_family = AF_INET;
|
v4->sin_family = AF_INET;
|
||||||
v4->sin_addr.s_addr = INADDR_ANY;
|
v4->sin_addr.s_addr = INADDR_ANY;
|
||||||
@@ -35,56 +35,58 @@ int parse_ip_to_sockaddr(struct sockaddr* out, char* src)
|
|||||||
out->sa_family = AF_INET;
|
out->sa_family = AF_INET;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inet_pton(AF_INET6, temp, &v6->sin6_addr) == 1) {
|
if (inet_pton(AF_INET6, temp, &v6->sin6_addr) == 1) {
|
||||||
out->sa_family = AF_INET6;
|
out->sa_family = AF_INET6;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_acl(struct ip_and_mask (**out)[], int max, char **entries)
|
int parse_acl(struct ip_and_mask (**out)[], int max, char **entries)
|
||||||
{
|
{
|
||||||
struct ip_and_mask (*list)[0];
|
struct ip_and_mask* list;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (max == 0) {
|
if (max == 0) {
|
||||||
*out = NULL;
|
*out = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*out = xmalloc(max * sizeof(struct ip_and_mask));
|
list = xmalloc(max * sizeof(struct ip_and_mask));
|
||||||
|
*out = (struct ip_and_mask (*)[])list;
|
||||||
debug("acl alloc: %p", *out);
|
debug("acl alloc: %p", *out);
|
||||||
}
|
}
|
||||||
|
|
||||||
list = *out;
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++) {
|
for (i = 0; i < max; i++) {
|
||||||
# define MAX_MASK_BITS (outentry->ip.family == AF_INET ? 32 : 128)
|
|
||||||
int j;
|
int j;
|
||||||
struct ip_and_mask* outentry = list[i];
|
struct ip_and_mask* outentry = &list[i];
|
||||||
|
# define MAX_MASK_BITS (outentry->ip.family == AF_INET ? 32 : 128)
|
||||||
if (parse_ip_to_sockaddr(&outentry->ip.generic, entries[i]) == 0)
|
if (parse_ip_to_sockaddr(&outentry->ip.generic, entries[i]) == 0) {
|
||||||
return i;
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
for (j=0; entries[i][j] && entries[i][j] != '/'; j++)
|
for (j=0; entries[i][j] && entries[i][j] != '/'; j++)
|
||||||
;
|
; // increment j!
|
||||||
|
|
||||||
if (entries[i][j] == '/') {
|
if (entries[i][j] == '/') {
|
||||||
outentry->mask = atoi(entries[i]+j+1);
|
outentry->mask = atoi(entries[i]+j+1);
|
||||||
if (outentry->mask < 1 || outentry->mask > MAX_MASK_BITS)
|
if (outentry->mask < 1 || outentry->mask > MAX_MASK_BITS)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
outentry->mask = MAX_MASK_BITS;
|
outentry->mask = MAX_MASK_BITS;
|
||||||
|
}
|
||||||
# undef MAX_MASK_BITS
|
# undef MAX_MASK_BITS
|
||||||
debug("acl ptr[%d]: %p %d",i, outentry, outentry->mask);
|
debug("acl ptr[%d]: %p %d",i, outentry, outentry->mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i < max; i++) {
|
for (i=0; i < max; i++) {
|
||||||
debug("acl entry %d @ %p has mask %d", i, list[i], list[i]->mask);
|
debug("acl entry %d @ %p has mask %d", i, list[i], list[i].mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,24 @@ START_TEST( test_parses_single_line )
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST( test_parses_multiple_lines )
|
||||||
|
{
|
||||||
|
char *lines[] = {"127.0.0.1", "::1"};
|
||||||
|
struct acl * acl = acl_create( 2, lines, 0 );
|
||||||
|
union mysockaddr e0, e1;
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &e0.generic, lines[0] );
|
||||||
|
parse_ip_to_sockaddr( &e1.generic, lines[1] );
|
||||||
|
|
||||||
|
fail_unless( acl->len == 2, "Multiple lines not parsed" );
|
||||||
|
|
||||||
|
struct ip_and_mask *entry;
|
||||||
|
entry = &(*acl->entries)[0];
|
||||||
|
fail_unless(entry->ip.family == e0.family, "entry 0 has wrong family!");
|
||||||
|
entry = &(*acl->entries)[1];
|
||||||
|
fail_unless(entry->ip.family == e1.family, "entry 1 has wrong family!");
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST( test_destroy_doesnt_crash )
|
START_TEST( test_destroy_doesnt_crash )
|
||||||
{
|
{
|
||||||
@@ -40,13 +58,62 @@ START_TEST( test_includes_single_address )
|
|||||||
char *lines[] = {"127.0.0.1"};
|
char *lines[] = {"127.0.0.1"};
|
||||||
struct acl * acl = acl_create( 1, lines, 0 );
|
struct acl * acl = acl_create( 1, lines, 0 );
|
||||||
union mysockaddr x;
|
union mysockaddr x;
|
||||||
|
|
||||||
parse_ip_to_sockaddr( &x.generic, "127.0.0.1" );
|
parse_ip_to_sockaddr( &x.generic, "127.0.0.1" );
|
||||||
|
|
||||||
fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" );
|
fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" );
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST( test_includes_single_address_when_netmask_specified_ipv4 )
|
||||||
|
{
|
||||||
|
char *lines[] = {"127.0.0.1/24"};
|
||||||
|
struct acl * acl = acl_create( 1, lines, 0 );
|
||||||
|
union mysockaddr x;
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &x.generic, "127.0.0.0" );
|
||||||
|
fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" );
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &x.generic, "127.0.0.1" );
|
||||||
|
fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" );
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &x.generic, "127.0.0.255" );
|
||||||
|
fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" );
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST( test_includes_single_address_when_netmask_specified_ipv6 )
|
||||||
|
{
|
||||||
|
char *lines[] = {"fe80::/10"};
|
||||||
|
struct acl * acl = acl_create( 1, lines, 0 );
|
||||||
|
union mysockaddr x;
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &x.generic, "fe80::1" );
|
||||||
|
fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" );
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &x.generic, "fe80::2" );
|
||||||
|
fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" );
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &x.generic, "fe80:ffff:ffff::ffff" );
|
||||||
|
fail_unless( acl_includes( acl, &x ), "Included address wasn't covered" );
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST( test_includes_single_address_when_multiple_entries_exist )
|
||||||
|
{
|
||||||
|
char *lines[] = {"127.0.0.1", "::1"};
|
||||||
|
struct acl * acl = acl_create( 2, lines, 0 );
|
||||||
|
union mysockaddr e0;
|
||||||
|
union mysockaddr e1;
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &e0.generic, "127.0.0.1" );
|
||||||
|
parse_ip_to_sockaddr( &e1.generic, "::1" );
|
||||||
|
|
||||||
|
fail_unless( acl_includes( acl, &e0 ), "Included address 0 wasn't covered" );
|
||||||
|
fail_unless( acl_includes( acl, &e1 ), "Included address 1 wasn't covered" );
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST( test_doesnt_include_other_address )
|
START_TEST( test_doesnt_include_other_address )
|
||||||
{
|
{
|
||||||
@@ -59,6 +126,31 @@ START_TEST( test_doesnt_include_other_address )
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST( test_doesnt_include_other_address_when_netmask_specified )
|
||||||
|
{
|
||||||
|
char *lines[] = {"127.0.0.1/32"};
|
||||||
|
struct acl * acl = acl_create( 1, lines, 0 );
|
||||||
|
union mysockaddr x;
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &x.generic, "127.0.0.2" );
|
||||||
|
fail_if( acl_includes( acl, &x ), "Excluded address was covered." );
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST( test_doesnt_include_other_address_when_multiple_entries_exist )
|
||||||
|
{
|
||||||
|
char *lines[] = {"127.0.0.1", "::1"};
|
||||||
|
struct acl * acl = acl_create( 2, lines, 0 );
|
||||||
|
union mysockaddr e0;
|
||||||
|
union mysockaddr e1;
|
||||||
|
|
||||||
|
parse_ip_to_sockaddr( &e0.generic, "127.0.0.2" );
|
||||||
|
parse_ip_to_sockaddr( &e1.generic, "::2" );
|
||||||
|
|
||||||
|
fail_if( acl_includes( acl, &e0 ), "Excluded address 0 was covered." );
|
||||||
|
fail_if( acl_includes( acl, &e1 ), "Excluded address 1 was covered." );
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST( test_default_deny_rejects )
|
START_TEST( test_default_deny_rejects )
|
||||||
{
|
{
|
||||||
@@ -90,12 +182,22 @@ Suite* acl_suite()
|
|||||||
TCase *tc_create = tcase_create("create");
|
TCase *tc_create = tcase_create("create");
|
||||||
TCase *tc_includes = tcase_create("includes");
|
TCase *tc_includes = tcase_create("includes");
|
||||||
TCase *tc_destroy = tcase_create("destroy");
|
TCase *tc_destroy = tcase_create("destroy");
|
||||||
|
|
||||||
|
|
||||||
tcase_add_test(tc_create, test_null_acl);
|
tcase_add_test(tc_create, test_null_acl);
|
||||||
tcase_add_test(tc_create, test_parses_single_line);
|
tcase_add_test(tc_create, test_parses_single_line);
|
||||||
|
tcase_add_test(tc_includes, test_parses_multiple_lines);
|
||||||
|
|
||||||
tcase_add_test(tc_includes, test_includes_single_address);
|
tcase_add_test(tc_includes, test_includes_single_address);
|
||||||
|
tcase_add_test(tc_includes, test_includes_single_address_when_netmask_specified_ipv4);
|
||||||
|
tcase_add_test(tc_includes, test_includes_single_address_when_netmask_specified_ipv6);
|
||||||
|
|
||||||
|
tcase_add_test(tc_includes, test_includes_single_address_when_multiple_entries_exist);
|
||||||
|
|
||||||
tcase_add_test(tc_includes, test_doesnt_include_other_address);
|
tcase_add_test(tc_includes, test_doesnt_include_other_address);
|
||||||
|
tcase_add_test(tc_includes, test_doesnt_include_other_address_when_netmask_specified);
|
||||||
|
tcase_add_test(tc_includes, test_doesnt_include_other_address_when_multiple_entries_exist);
|
||||||
|
|
||||||
tcase_add_test(tc_includes, test_default_deny_rejects);
|
tcase_add_test(tc_includes, test_default_deny_rejects);
|
||||||
tcase_add_test(tc_includes, test_default_accept_rejects);
|
tcase_add_test(tc_includes, test_default_accept_rejects);
|
||||||
|
|
||||||
@@ -105,12 +207,12 @@ Suite* acl_suite()
|
|||||||
suite_add_tcase(s, tc_includes);
|
suite_add_tcase(s, tc_includes);
|
||||||
suite_add_tcase(s, tc_destroy);
|
suite_add_tcase(s, tc_destroy);
|
||||||
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
log_level = 0;
|
||||||
int number_failed;
|
int number_failed;
|
||||||
Suite *s = acl_suite();
|
Suite *s = acl_suite();
|
||||||
SRunner *sr = srunner_create(s);
|
SRunner *sr = srunner_create(s);
|
||||||
|
@@ -156,12 +156,10 @@ END_TEST
|
|||||||
START_TEST( test_acl_update_leaves_good_client )
|
START_TEST( test_acl_update_leaves_good_client )
|
||||||
{
|
{
|
||||||
struct server * s = server_create( "127.0.0.7", "0", dummy_file, NULL, 0, 0, NULL );
|
struct server * s = server_create( "127.0.0.7", "0", dummy_file, NULL, 0, 0, NULL );
|
||||||
/* There's an assumption here that the localhost *is* 127.0.0.1.
|
|
||||||
* If it's not, this test will fail and we'll have to explicitly
|
// Client source address may be IPv4 or IPv6 localhost. Should be explicit
|
||||||
* pick a source address.
|
char *lines[] = {"127.0.0.1", "::1"};
|
||||||
*/
|
struct acl * new_acl = acl_create( 2, lines, 1 );
|
||||||
char *lines[] = {"127.0.0.1"};
|
|
||||||
struct acl * new_acl = acl_create( 1, lines, 0);
|
|
||||||
struct client * c;
|
struct client * c;
|
||||||
struct client_tbl_entry * entry;
|
struct client_tbl_entry * entry;
|
||||||
|
|
||||||
@@ -169,6 +167,7 @@ START_TEST( test_acl_update_leaves_good_client )
|
|||||||
int client_fd;
|
int client_fd;
|
||||||
int server_fd;
|
int server_fd;
|
||||||
|
|
||||||
|
myfail_if(new_acl->len != 2, "sanity: new_acl length is not 2");
|
||||||
|
|
||||||
serve_open_server_socket( s );
|
serve_open_server_socket( s );
|
||||||
actual_port = server_port( s );
|
actual_port = server_port( s );
|
||||||
|
Reference in New Issue
Block a user