5 |
* |
* |
6 |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
7 |
* |
* |
8 |
* Version: 1.6.0-rc 2008/03/26 |
* Version: 1.6.0-rc 2008/03/28 |
9 |
* |
* |
10 |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
11 |
* See README.ccs for ChangeLog. |
* See README.ccs for ChangeLog. |
25 |
* @address: An IPv4 or IPv6 address. |
* @address: An IPv4 or IPv6 address. |
26 |
* @port: Port number. |
* @port: Port number. |
27 |
* @is_granted: True if this is a granted log. |
* @is_granted: True if this is a granted log. |
28 |
* @profile: Profile number. |
* @profile: Profile number used. |
29 |
* @mode: Access control mode. |
* @mode: Access control mode used. |
30 |
* |
* |
31 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
32 |
*/ |
*/ |
33 |
static int audit_network_log(const bool is_ipv6, const char *operation, |
static int audit_network_log(const bool is_ipv6, const char *operation, |
34 |
const u32 *address, const u16 port, |
const char *address, const u16 port, |
35 |
const bool is_granted, const u8 profile, |
const bool is_granted, |
36 |
const u8 mode) |
const u8 profile, const u8 mode) |
37 |
{ |
{ |
38 |
char *buf; |
char *buf; |
39 |
int len = 256, len2; |
int len = 256; |
40 |
|
int len2; |
41 |
if (ccs_can_save_audit_log(is_granted) < 0) |
if (ccs_can_save_audit_log(is_granted) < 0) |
42 |
return -ENOMEM; |
return -ENOMEM; |
43 |
buf = ccs_init_audit_log(&len, profile, mode, NULL); |
buf = ccs_init_audit_log(&len, profile, mode, NULL); |
44 |
if (!buf) |
if (!buf) |
45 |
return -ENOMEM; |
return -ENOMEM; |
46 |
len2 = strlen(buf); |
len2 = strlen(buf); |
47 |
snprintf(buf + len2, len - len2 - 1, KEYWORD_ALLOW_NETWORK "%s ", |
snprintf(buf + len2, len - len2 - 1, KEYWORD_ALLOW_NETWORK "%s %s %u\n", |
48 |
operation); |
operation, address, port); |
|
len2 = strlen(buf); |
|
|
if (is_ipv6) { |
|
|
ccs_print_ipv6(buf + len2, len - len2, |
|
|
(const struct in6_addr *) address); |
|
|
} else { |
|
|
u32 ip = *address; |
|
|
snprintf(buf + len2, len - len2 - 1, "%u.%u.%u.%u", |
|
|
NIPQUAD(ip)); |
|
|
} |
|
|
len2 = strlen(buf); |
|
|
snprintf(buf + len2, len - len2 - 1, " %u\n", port); |
|
49 |
return ccs_write_audit_log(buf, is_granted); |
return ccs_write_audit_log(buf, is_granted); |
50 |
} |
} |
51 |
|
|
75 |
mutex_lock(&lock); |
mutex_lock(&lock); |
76 |
list1_for_each_entry(ptr, &address_list, list) { |
list1_for_each_entry(ptr, &address_list, list) { |
77 |
for (i = 0; i < ptr->in_use_count; i++) { |
for (i = 0; i < ptr->in_use_count; i++) { |
78 |
if (memcmp(&ptr->addr[i], addr, sizeof(*addr)) == 0) |
if (!memcmp(&ptr->addr[i], addr, sizeof(*addr))) |
79 |
goto ok; |
goto ok; |
80 |
} |
} |
81 |
if (i < block_size) |
if (i < block_size) |
100 |
/** |
/** |
101 |
* update_address_group_entry - Update "struct address_group_entry" list. |
* update_address_group_entry - Update "struct address_group_entry" list. |
102 |
* |
* |
103 |
* @group_name: The name of group. |
* @group_name: The name of address group. |
104 |
* @is_ipv6: True if @address is an IPv6 address. |
* @is_ipv6: True if @min_address and @max_address are IPv6 addresses. |
105 |
* @min_address: Start of IPv4 or IPv6 address range. |
* @min_address: Start of IPv4 or IPv6 address range. |
106 |
* @max_address: End of IPv4 or IPv6 address range. |
* @max_address: End of IPv4 or IPv6 address range. |
107 |
* @is_delete: True if it is a delete request. |
* @is_delete: True if it is a delete request. |
115 |
const bool is_delete) |
const bool is_delete) |
116 |
{ |
{ |
117 |
static DEFINE_MUTEX(lock); |
static DEFINE_MUTEX(lock); |
118 |
struct address_group_entry *new_group, *group; |
struct address_group_entry *new_group; |
119 |
struct address_group_member *new_member, *member; |
struct address_group_entry *group; |
120 |
|
struct address_group_member *new_member; |
121 |
|
struct address_group_member *member; |
122 |
const struct path_info *saved_group_name; |
const struct path_info *saved_group_name; |
123 |
const struct in6_addr *saved_min_address = NULL; |
const struct in6_addr *saved_min_address = NULL; |
124 |
const struct in6_addr *saved_max_address = NULL; |
const struct in6_addr *saved_max_address = NULL; |
191 |
error = 0; |
error = 0; |
192 |
out: |
out: |
193 |
mutex_unlock(&lock); |
mutex_unlock(&lock); |
194 |
|
ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY); |
195 |
return error; |
return error; |
196 |
} |
} |
197 |
|
|
207 |
{ |
{ |
208 |
u8 count; |
u8 count; |
209 |
bool is_ipv6; |
bool is_ipv6; |
210 |
u16 min_address[8], max_address[8]; |
u16 min_address[8]; |
211 |
|
u16 max_address[8]; |
212 |
char *cp = strchr(data, ' '); |
char *cp = strchr(data, ' '); |
213 |
if (!cp) |
if (!cp) |
214 |
return -EINVAL; |
return -EINVAL; |
252 |
+ (u8) max_address[3]); |
+ (u8) max_address[3]); |
253 |
*(u32 *) max_address = ip; |
*(u32 *) max_address = ip; |
254 |
is_ipv6 = false; |
is_ipv6 = false; |
255 |
} else { |
goto ok; |
|
return -EINVAL; |
|
256 |
} |
} |
257 |
|
return -EINVAL; |
258 |
ok: |
ok: |
259 |
return update_address_group_entry(data, is_ipv6, |
return update_address_group_entry(data, is_ipv6, |
260 |
min_address, max_address, is_delete); |
min_address, max_address, is_delete); |
263 |
/** |
/** |
264 |
* find_or_assign_new_address_group - Create address group. |
* find_or_assign_new_address_group - Create address group. |
265 |
* |
* |
266 |
* @group_name: The name of group. |
* @group_name: The name of address group. |
267 |
* |
* |
268 |
* Returns pointer to "struct address_group_entry" on success, NULL otherwise. |
* Returns pointer to "struct address_group_entry" on success, NULL otherwise. |
269 |
*/ |
*/ |
274 |
struct address_group_entry *group; |
struct address_group_entry *group; |
275 |
for (i = 0; i <= 1; i++) { |
for (i = 0; i <= 1; i++) { |
276 |
list1_for_each_entry(group, &address_group_list, list) { |
list1_for_each_entry(group, &address_group_list, list) { |
277 |
if (strcmp(group_name, group->group_name->name) == 0) |
if (!strcmp(group_name, group->group_name->name)) |
278 |
return group; |
return group; |
279 |
} |
} |
280 |
if (i == 0) { |
if (!i) { |
281 |
const u16 dummy[2] = { 0, 0 }; |
const u16 dummy[2] = { 0, 0 }; |
282 |
update_address_group_entry(group_name, false, |
update_address_group_entry(group_name, false, |
283 |
dummy, dummy, false); |
dummy, dummy, false); |
341 |
list); |
list); |
342 |
if (member->is_deleted) |
if (member->is_deleted) |
343 |
continue; |
continue; |
344 |
if (!member->is_ipv6) { |
if (member->is_ipv6) { |
345 |
const struct in6_addr *min_address |
const struct in6_addr *min_address |
346 |
= member->min.ipv6; |
= member->min.ipv6; |
347 |
const struct in6_addr *max_address |
const struct in6_addr *max_address |
392 |
* ccs_print_ipv6 - Print an IPv6 address. |
* ccs_print_ipv6 - Print an IPv6 address. |
393 |
* |
* |
394 |
* @buffer: Buffer to write to. |
* @buffer: Buffer to write to. |
395 |
* @buffer_len: Size of @buffer . |
* @buffer_len: Size of @buffer. |
396 |
* @ip: Pointer to "struct in6_addr". |
* @ip: Pointer to "struct in6_addr". |
397 |
* |
* |
398 |
* Returns @buffer. |
* Returns nothing. |
399 |
*/ |
*/ |
400 |
char *ccs_print_ipv6(char *buffer, const int buffer_len, |
void ccs_print_ipv6(char *buffer, const int buffer_len, |
401 |
const struct in6_addr *ip) |
const struct in6_addr *ip) |
402 |
{ |
{ |
403 |
memset(buffer, 0, buffer_len); |
memset(buffer, 0, buffer_len); |
404 |
snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip)); |
snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip)); |
|
return buffer; |
|
405 |
} |
} |
406 |
|
|
407 |
/** |
/** |
488 |
if (is_delete) |
if (is_delete) |
489 |
goto delete; |
goto delete; |
490 |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
491 |
if ((ptr->type & ~(ACL_DELETED | ACL_WITH_CONDITION)) |
if (ccs_acl_type1(ptr) != TYPE_IP_NETWORK_ACL) |
|
!= TYPE_IP_NETWORK_ACL) |
|
492 |
continue; |
continue; |
493 |
if (ccs_get_condition_part(ptr) != condition) |
if (ccs_get_condition_part(ptr) != condition) |
494 |
continue; |
continue; |
534 |
delete: |
delete: |
535 |
error = -ENOENT; |
error = -ENOENT; |
536 |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
537 |
if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_IP_NETWORK_ACL) |
if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL) |
538 |
continue; |
continue; |
539 |
if (ccs_get_condition_part(ptr) != condition) |
if (ccs_get_condition_part(ptr) != condition) |
540 |
continue; |
continue; |
585 |
/* using host byte order to allow u32 comparison than memcmp().*/ |
/* using host byte order to allow u32 comparison than memcmp().*/ |
586 |
const u32 ip = ntohl(*address); |
const u32 ip = ntohl(*address); |
587 |
bool found = false; |
bool found = false; |
588 |
|
char buf[64]; |
589 |
if (!mode) |
if (!mode) |
590 |
return 0; |
return 0; |
591 |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
list1_for_each_entry(ptr, &domain->acl_info_list, list) { |
592 |
struct ip_network_acl_record *acl; |
struct ip_network_acl_record *acl; |
593 |
if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_IP_NETWORK_ACL) |
if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL) |
594 |
continue; |
continue; |
595 |
acl = container_of(ptr, struct ip_network_acl_record, head); |
acl = container_of(ptr, struct ip_network_acl_record, head); |
596 |
if (acl->operation_type != operation || port < acl->min_port || |
if (acl->operation_type != operation || port < acl->min_port || |
614 |
found = true; |
found = true; |
615 |
break; |
break; |
616 |
} |
} |
617 |
audit_network_log(is_ipv6, keyword, address, port, found, profile, |
memset(buf, 0, sizeof(buf)); |
618 |
mode); |
if (is_ipv6) |
619 |
|
ccs_print_ipv6(buf, sizeof(buf), |
620 |
|
(const struct in6_addr *) address); |
621 |
|
else |
622 |
|
snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip)); |
623 |
|
audit_network_log(is_ipv6, keyword, buf, port, found, profile, mode); |
624 |
if (found) |
if (found) |
625 |
return 0; |
return 0; |
626 |
if (ccs_verbose_mode()) { |
if (ccs_verbose_mode()) |
627 |
if (is_ipv6) { |
printk(KERN_WARNING "TOMOYO-%s: %s to %s %u denied for %s\n", |
628 |
char buf[64]; |
ccs_get_msg(is_enforce), keyword, buf, port, |
629 |
ccs_print_ipv6(buf, sizeof(buf), |
ccs_get_last_name(domain)); |
630 |
(const struct in6_addr *) address); |
if (is_enforce) |
|
printk(KERN_WARNING "TOMOYO-%s: %s to %s %u " |
|
|
"denied for %s\n", ccs_get_msg(is_enforce), |
|
|
keyword, buf, port, ccs_get_last_name(domain)); |
|
|
} else { |
|
|
printk(KERN_WARNING "TOMOYO-%s: %s to %u.%u.%u.%u %u " |
|
|
"denied for %s\n", ccs_get_msg(is_enforce), |
|
|
keyword, HIPQUAD(ip), port, |
|
|
ccs_get_last_name(domain)); |
|
|
} |
|
|
} |
|
|
if (is_enforce) { |
|
|
if (is_ipv6) { |
|
|
char buf[64]; |
|
|
ccs_print_ipv6(buf, sizeof(buf), |
|
|
(const struct in6_addr *) address); |
|
|
return ccs_check_supervisor("%s\n" |
|
|
KEYWORD_ALLOW_NETWORK "%s " |
|
|
"%s %u\n", |
|
|
domain->domainname->name, |
|
|
keyword, buf, port); |
|
|
} |
|
631 |
return ccs_check_supervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s " |
return ccs_check_supervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s " |
632 |
"%u.%u.%u.%u %u\n", |
"%s %u\n", domain->domainname->name, |
633 |
domain->domainname->name, keyword, |
keyword, buf, port); |
634 |
HIPQUAD(ip), port); |
if (mode == 1 && ccs_check_domain_quota(domain)) |
|
} else if (mode == 1 && ccs_check_domain_quota(domain)) |
|
635 |
update_network_entry(operation, is_ipv6 ? |
update_network_entry(operation, is_ipv6 ? |
636 |
IP_RECORD_TYPE_IPv6 : IP_RECORD_TYPE_IPv4, |
IP_RECORD_TYPE_IPv6 : IP_RECORD_TYPE_IPv4, |
637 |
NULL, address, address, port, port, domain, |
NULL, address, address, port, port, domain, |
653 |
const struct condition_list *condition, |
const struct condition_list *condition, |
654 |
const bool is_delete) |
const bool is_delete) |
655 |
{ |
{ |
656 |
u8 sock_type, operation, record_type; |
u8 sock_type; |
657 |
u16 min_address[8], max_address[8]; |
u8 operation; |
658 |
|
u8 record_type; |
659 |
|
u16 min_address[8]; |
660 |
|
u16 max_address[8]; |
661 |
struct address_group_entry *group = NULL; |
struct address_group_entry *group = NULL; |
662 |
u16 min_port, max_port; |
u16 min_port; |
663 |
|
u16 max_port; |
664 |
u8 count; |
u8 count; |
665 |
char *cp1 = NULL, *cp2 = NULL; |
char *cp1 = strchr(data, ' '); |
666 |
cp1 = strchr(data, ' '); |
char *cp2; |
667 |
if (!cp1) |
if (!cp1) |
668 |
goto out; |
goto out; |
669 |
cp1++; |
cp1++; |
750 |
+ (u8) max_address[3]); |
+ (u8) max_address[3]); |
751 |
*(u32 *) max_address = ip; |
*(u32 *) max_address = ip; |
752 |
record_type = IP_RECORD_TYPE_IPv4; |
record_type = IP_RECORD_TYPE_IPv4; |
753 |
} else if (*cp2 == '@') { |
goto ok; |
754 |
|
} |
755 |
|
if (*cp2 == '@') { |
756 |
group = find_or_assign_new_address_group(cp2 + 1); |
group = find_or_assign_new_address_group(cp2 + 1); |
757 |
if (!group) |
if (!group) |
758 |
return -ENOMEM; |
return -ENOMEM; |
759 |
record_type = IP_RECORD_TYPE_ADDRESS_GROUP; |
record_type = IP_RECORD_TYPE_ADDRESS_GROUP; |
760 |
} else { |
goto ok; |
|
goto out; |
|
761 |
} |
} |
762 |
|
out: |
763 |
|
return -EINVAL; |
764 |
ok: |
ok: |
765 |
if (strchr(cp1, ' ')) |
if (strchr(cp1, ' ')) |
766 |
goto out; |
goto out; |
773 |
(u32 *) min_address, (u32 *) max_address, |
(u32 *) min_address, (u32 *) max_address, |
774 |
min_port, max_port, domain, condition, |
min_port, max_port, domain, condition, |
775 |
is_delete); |
is_delete); |
|
out: |
|
|
return -EINVAL; |
|
776 |
} |
} |
777 |
|
|
778 |
/** |
/** |
904 |
{ |
{ |
905 |
int retval; |
int retval; |
906 |
const u8 operation |
const u8 operation |
907 |
= sock_type == SOCK_DGRAM ? |
= (sock_type == SOCK_DGRAM) ? |
908 |
NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT; |
NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT; |
909 |
current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
910 |
retval = check_network_entry(is_ipv6, operation, (const u32 *) address, |
retval = check_network_entry(is_ipv6, operation, (const u32 *) address, |