オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Annotation of /branches/ccs-patch/security/ccsecurity/network.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1054 - (hide annotations) (download) (as text)
Mon Mar 24 09:38:11 2008 UTC (16 years, 2 months ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/tomoyo_network.c
File MIME type: text/x-csrc
File size: 27192 byte(s)


1 kumaneko 111 /*
2     * fs/tomoyo_network.c
3     *
4     * Implementation of the Domain-Based Mandatory Access Control.
5     *
6 kumaneko 851 * Copyright (C) 2005-2008 NTT DATA CORPORATION
7 kumaneko 111 *
8 kumaneko 1052 * Version: 1.6.0-pre 2008/03/24
9 kumaneko 111 *
10     * This file is applicable to both 2.4.30 and 2.6.11 and later.
11     * See README.ccs for ChangeLog.
12     *
13     */
14    
15     #include <linux/ccs_common.h>
16     #include <linux/tomoyo.h>
17     #include <linux/realpath.h>
18     #include <net/ip.h>
19    
20 kumaneko 1052 /**
21     * audit_network_log - Audit network log.
22     *
23     * @is_ipv6: True if @address is an IPv6 address.
24     * @operation: The name of operation.
25     * @address: An IPv4 or IPv6 address.
26     * @port: Port number.
27     * @is_granted: True if this is a granted log.
28     * @profile: Profile number.
29     * @mode: Access control mode.
30     *
31     * Returns 0 on success, negative value otherwise.
32     */
33     static int audit_network_log(const bool is_ipv6, const char *operation,
34     const u32 *address, const u16 port,
35     const bool is_granted, const u8 profile,
36     const u8 mode)
37 kumaneko 111 {
38     char *buf;
39 kumaneko 1052 int len = 256, len2;
40     if (ccs_can_save_audit_log(is_granted) < 0)
41     return -ENOMEM;
42     buf = ccs_init_audit_log(&len, profile, mode, NULL);
43     if (!buf)
44     return -ENOMEM;
45     len2 = strlen(buf);
46     snprintf(buf + len2, len - len2 - 1, KEYWORD_ALLOW_NETWORK "%s ",
47     operation);
48     len2 = strlen(buf);
49 kumaneko 111 if (is_ipv6) {
50 kumaneko 1052 ccs_print_ipv6(buf + len2, len - len2,
51     (const struct in6_addr *) address);
52 kumaneko 111 } else {
53     u32 ip = *address;
54 kumaneko 1052 snprintf(buf + len2, len - len2 - 1, "%u.%u.%u.%u",
55     NIPQUAD(ip));
56 kumaneko 111 }
57 kumaneko 1052 len2 = strlen(buf);
58     snprintf(buf + len2, len - len2 - 1, " %u\n", port);
59     return ccs_write_audit_log(buf, is_granted);
60 kumaneko 111 }
61    
62 kumaneko 1052 /**
63     * save_ipv6_address - Keep the given IPv6 address on the RAM.
64     *
65     * @addr: Pointer to "struct in6_addr".
66     *
67     * Returns pointer to "struct in6_addr" on success, NULL otherwise.
68     *
69     * The RAM is shared, so NEVER try to modify or kfree() the returned address.
70     */
71     static const struct in6_addr *save_ipv6_address(const struct in6_addr *addr)
72 kumaneko 719 {
73 kumaneko 853 static const u8 block_size = 16;
74 kumaneko 719 struct addr_list {
75     struct in6_addr addr[block_size];
76 kumaneko 731 struct list1_head list;
77 kumaneko 719 u32 in_use_count;
78     };
79 kumaneko 731 static LIST1_HEAD(address_list);
80 kumaneko 719 struct addr_list *ptr;
81     static DEFINE_MUTEX(lock);
82 kumaneko 853 u8 i = block_size;
83 kumaneko 1052 if (!addr)
84     return NULL;
85 kumaneko 719 mutex_lock(&lock);
86 kumaneko 731 list1_for_each_entry(ptr, &address_list, list) {
87 kumaneko 719 for (i = 0; i < ptr->in_use_count; i++) {
88 kumaneko 1052 if (memcmp(&ptr->addr[i], addr, sizeof(*addr)) == 0)
89     goto ok;
90 kumaneko 719 }
91 kumaneko 1052 if (i < block_size)
92     break;
93 kumaneko 719 }
94 kumaneko 731 if (i == block_size) {
95 kumaneko 1052 ptr = ccs_alloc_element(sizeof(*ptr));
96     if (!ptr)
97     goto ok;
98 kumaneko 731 list1_add_tail_mb(&ptr->list, &address_list);
99 kumaneko 719 i = 0;
100     }
101 kumaneko 731 ptr->addr[ptr->in_use_count++] = *addr;
102 kumaneko 1052 ok:
103 kumaneko 719 mutex_unlock(&lock);
104     return ptr ? &ptr->addr[i] : NULL;
105     }
106    
107 kumaneko 1052 /* The list for "struct address_group_entry". */
108 kumaneko 722 static LIST1_HEAD(address_group_list);
109 kumaneko 111
110 kumaneko 1052 /**
111     * update_address_group_entry - Update "struct address_group_entry" list.
112     *
113     * @group_name: The name of group.
114     * @is_ipv6: True if @address is an IPv6 address.
115     * @min_address: Start of IPv4 or IPv6 address range.
116     * @max_address: End of IPv4 or IPv6 address range.
117     * @is_delete: True if it is a delete request.
118     *
119     * Returns 0 on success, negative value otherwise.
120     */
121     static int update_address_group_entry(const char *group_name,
122     const bool is_ipv6,
123     const u16 *min_address,
124     const u16 *max_address,
125     const bool is_delete)
126 kumaneko 111 {
127 kumaneko 652 static DEFINE_MUTEX(lock);
128 kumaneko 214 struct address_group_entry *new_group, *group;
129     struct address_group_member *new_member, *member;
130 kumaneko 111 const struct path_info *saved_group_name;
131 kumaneko 1052 const struct in6_addr *saved_min_address = NULL;
132     const struct in6_addr *saved_max_address = NULL;
133 kumaneko 111 int error = -ENOMEM;
134 kumaneko 1016 bool found = false;
135 kumaneko 1052 if (!ccs_is_correct_path(group_name, 0, 0, 0, __func__) ||
136     !group_name[0])
137     return -EINVAL;
138     saved_group_name = ccs_save_name(group_name);
139     if (!saved_group_name)
140     return -ENOMEM;
141     if (!is_ipv6)
142     goto not_ipv6;
143     saved_min_address
144     = save_ipv6_address((struct in6_addr *) min_address);
145     saved_max_address
146     = save_ipv6_address((struct in6_addr *) max_address);
147     if (!saved_min_address || !saved_max_address)
148     return -ENOMEM;
149     not_ipv6:
150 kumaneko 652 mutex_lock(&lock);
151 kumaneko 722 list1_for_each_entry(group, &address_group_list, list) {
152 kumaneko 1052 if (saved_group_name != group->group_name)
153     continue;
154     list1_for_each_entry(member, &group->address_group_member_list,
155     list) {
156     if (member->is_ipv6 != is_ipv6)
157     continue;
158 kumaneko 111 if (is_ipv6) {
159 kumaneko 1052 if (member->min.ipv6 != saved_min_address ||
160     member->max.ipv6 != saved_max_address)
161     continue;
162 kumaneko 111 } else {
163 kumaneko 1052 if (member->min.ipv4 != *(u32 *) min_address ||
164     member->max.ipv4 != *(u32 *) max_address)
165     continue;
166 kumaneko 111 }
167     member->is_deleted = is_delete;
168     error = 0;
169     goto out;
170     }
171 kumaneko 1016 found = true;
172 kumaneko 111 break;
173     }
174     if (is_delete) {
175     error = -ENOENT;
176     goto out;
177     }
178 kumaneko 708 if (!found) {
179 kumaneko 1052 new_group = ccs_alloc_element(sizeof(*new_group));
180     if (!new_group)
181     goto out;
182 kumaneko 722 INIT_LIST1_HEAD(&new_group->address_group_member_list);
183 kumaneko 111 new_group->group_name = saved_group_name;
184 kumaneko 722 list1_add_tail_mb(&new_group->list, &address_group_list);
185 kumaneko 111 group = new_group;
186     }
187 kumaneko 1052 new_member = ccs_alloc_element(sizeof(*new_member));
188     if (!new_member)
189     goto out;
190 kumaneko 111 new_member->is_ipv6 = is_ipv6;
191     if (is_ipv6) {
192 kumaneko 719 new_member->min.ipv6 = saved_min_address;
193     new_member->max.ipv6 = saved_max_address;
194 kumaneko 111 } else {
195 kumaneko 1052 new_member->min.ipv4 = *(u32 *) min_address;
196     new_member->max.ipv4 = *(u32 *) max_address;
197 kumaneko 111 }
198 kumaneko 722 list1_add_tail_mb(&new_member->list, &group->address_group_member_list);
199 kumaneko 111 error = 0;
200     out:
201 kumaneko 652 mutex_unlock(&lock);
202 kumaneko 111 return error;
203     }
204    
205 kumaneko 1052 /**
206     * ccs_write_address_group_policy - Write "struct address_group_entry" list.
207     *
208     * @data: String to parse.
209     * @is_delete: True if it is a delete request.
210     *
211     * Returns 0 on success, negative value otherwise.
212     */
213     int ccs_write_address_group_policy(char *data, const bool is_delete)
214 kumaneko 111 {
215 kumaneko 853 u8 count;
216     bool is_ipv6;
217 kumaneko 111 u16 min_address[8], max_address[8];
218     char *cp = strchr(data, ' ');
219 kumaneko 1052 if (!cp)
220     return -EINVAL;
221 kumaneko 111 *cp++ = '\0';
222 kumaneko 1052 count = sscanf(cp, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
223     "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
224     &min_address[0], &min_address[1],
225     &min_address[2], &min_address[3],
226     &min_address[4], &min_address[5],
227     &min_address[6], &min_address[7],
228     &max_address[0], &max_address[1],
229     &max_address[2], &max_address[3],
230     &max_address[4], &max_address[5],
231     &max_address[6], &max_address[7]);
232     if (count == 8 || count == 16) {
233 kumaneko 853 u8 i;
234 kumaneko 111 for (i = 0; i < 8; i++) {
235     min_address[i] = htons(min_address[i]);
236     max_address[i] = htons(max_address[i]);
237     }
238 kumaneko 1052 if (count == 8)
239     memmove(max_address, min_address, sizeof(min_address));
240 kumaneko 1016 is_ipv6 = true;
241 kumaneko 1052 goto ok;
242     }
243     count = sscanf(cp, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
244     &min_address[0], &min_address[1],
245     &min_address[2], &min_address[3],
246     &max_address[0], &max_address[1],
247     &max_address[2], &max_address[3]);
248     if (count == 4 || count == 8) {
249     u32 ip = ((((u8) min_address[0]) << 24)
250     + (((u8) min_address[1]) << 16)
251     + (((u8) min_address[2]) << 8)
252     + (u8) min_address[3]);
253     *(u32 *) min_address = ip;
254     if (count == 8)
255     ip = ((((u8) max_address[0]) << 24)
256     + (((u8) max_address[1]) << 16)
257     + (((u8) max_address[2]) << 8)
258     + (u8) max_address[3]);
259     *(u32 *) max_address = ip;
260 kumaneko 1016 is_ipv6 = false;
261 kumaneko 111 } else {
262     return -EINVAL;
263     }
264 kumaneko 1052 ok:
265     return update_address_group_entry(data, is_ipv6,
266     min_address, max_address, is_delete);
267 kumaneko 111 }
268    
269 kumaneko 1052 /**
270     * find_or_assign_new_address_group - Create address group.
271     *
272     * @group_name: The name of group.
273     *
274     * Returns pointer to "struct address_group_entry" on success, NULL otherwise.
275     */
276     static struct address_group_entry *
277     find_or_assign_new_address_group(const char *group_name)
278 kumaneko 111 {
279 kumaneko 853 u8 i;
280 kumaneko 214 struct address_group_entry *group;
281 kumaneko 111 for (i = 0; i <= 1; i++) {
282 kumaneko 722 list1_for_each_entry(group, &address_group_list, list) {
283 kumaneko 1052 if (strcmp(group_name, group->group_name->name) == 0)
284     return group;
285 kumaneko 111 }
286     if (i == 0) {
287     const u16 dummy[2] = { 0, 0 };
288 kumaneko 1052 update_address_group_entry(group_name, false,
289     dummy, dummy, false);
290     update_address_group_entry(group_name, false,
291     dummy, dummy, true);
292 kumaneko 111 }
293     }
294     return NULL;
295     }
296    
297 kumaneko 1052 /**
298 kumaneko 1054 * address_matches_to_group - Check whether the given address matches members of the given address group.
299 kumaneko 1052 *
300     * @is_ipv6: True if @address is an IPv6 address.
301     * @address: An IPv4 or IPv6 address.
302     * @group: Pointer to "struct address_group_entry".
303     *
304     * Returns true if @address matches addresses in @group group, false otherwise.
305     */
306     static bool address_matches_to_group(const bool is_ipv6, const u32 *address,
307     const struct address_group_entry *group)
308 kumaneko 111 {
309 kumaneko 214 struct address_group_member *member;
310 kumaneko 111 const u32 ip = ntohl(*address);
311 kumaneko 722 list1_for_each_entry(member, &group->address_group_member_list, list) {
312 kumaneko 1052 if (member->is_deleted)
313     continue;
314 kumaneko 111 if (member->is_ipv6) {
315 kumaneko 1052 if (is_ipv6 &&
316     memcmp(member->min.ipv6, address, 16) <= 0 &&
317     memcmp(address, member->max.ipv6, 16) <= 0)
318     return true;
319 kumaneko 111 } else {
320 kumaneko 1052 if (!is_ipv6 &&
321     member->min.ipv4 <= ip && ip <= member->max.ipv4)
322     return true;
323 kumaneko 111 }
324     }
325 kumaneko 1016 return false;
326 kumaneko 111 }
327    
328 kumaneko 1052 /**
329 kumaneko 1054 * ccs_read_address_group_policy - Read "struct address_group_entry" list.
330 kumaneko 1052 *
331     * @head: Pointer to "struct ccs_io_buffer".
332     *
333     * Returns true on success, false otherwise.
334     */
335     bool ccs_read_address_group_policy(struct ccs_io_buffer *head)
336 kumaneko 111 {
337 kumaneko 722 struct list1_head *gpos;
338     struct list1_head *mpos;
339     list1_for_each_cookie(gpos, head->read_var1, &address_group_list) {
340 kumaneko 708 struct address_group_entry *group;
341 kumaneko 722 group = list1_entry(gpos, struct address_group_entry, list);
342 kumaneko 1052 list1_for_each_cookie(mpos, head->read_var2,
343     &group->address_group_member_list) {
344 kumaneko 708 char buf[128];
345     struct address_group_member *member;
346 kumaneko 1052 member = list1_entry(mpos, struct address_group_member,
347     list);
348     if (member->is_deleted)
349     continue;
350     if (!member->is_ipv6) {
351     const struct in6_addr *min_address
352     = member->min.ipv6;
353     const struct in6_addr *max_address
354     = member->max.ipv6;
355     ccs_print_ipv6(buf, sizeof(buf), min_address);
356 kumaneko 719 if (min_address != max_address) {
357 kumaneko 1052 int len;
358 kumaneko 708 char *cp = strchr(buf, '\0');
359     *cp++ = '-';
360 kumaneko 1052 len = strlen(buf);
361     ccs_print_ipv6(cp, sizeof(buf) - len,
362     max_address);
363 kumaneko 111 }
364 kumaneko 708 } else {
365 kumaneko 1052 const u32 min_address = member->min.ipv4;
366     const u32 max_address = member->max.ipv4;
367 kumaneko 708 memset(buf, 0, sizeof(buf));
368 kumaneko 1052 snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u",
369     HIPQUAD(min_address));
370 kumaneko 708 if (min_address != max_address) {
371     const int len = strlen(buf);
372 kumaneko 1052 snprintf(buf + len,
373     sizeof(buf) - 1 - len,
374     "-%u.%u.%u.%u",
375     HIPQUAD(max_address));
376 kumaneko 708 }
377 kumaneko 111 }
378 kumaneko 1052 if (!ccs_io_printf(head, KEYWORD_ADDRESS_GROUP
379     "%s %s\n", group->group_name->name,
380     buf))
381     goto out;
382 kumaneko 111 }
383     }
384 kumaneko 1052 return true;
385     out:
386     return false;
387 kumaneko 111 }
388    
389 kumaneko 719 #if !defined(NIP6)
390 kumaneko 1052 #define NIP6(addr) \
391     ntohs((addr).s6_addr16[0]),ntohs((addr).s6_addr16[1]),\
392     ntohs((addr).s6_addr16[2]),ntohs((addr).s6_addr16[3]),\
393     ntohs((addr).s6_addr16[4]),ntohs((addr).s6_addr16[5]),\
394     ntohs((addr).s6_addr16[6]),ntohs((addr).s6_addr16[7])
395 kumaneko 719 #endif
396    
397 kumaneko 1052 /**
398 kumaneko 1054 * ccs_print_ipv6 - Print an IPv6 address.
399 kumaneko 1052 *
400     * @buffer: Buffer to write to.
401     * @buffer_len: Size of @buffer .
402     * @ip: Pointer to "struct in6_addr".
403     *
404     * Returns @buffer.
405     */
406     char *ccs_print_ipv6(char *buffer, const int buffer_len,
407     const struct in6_addr *ip)
408 kumaneko 111 {
409     memset(buffer, 0, buffer_len);
410 kumaneko 719 snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip));
411 kumaneko 111 return buffer;
412     }
413    
414 kumaneko 1052 /**
415     * ccs_net2keyword - Convert network operation index to network operation name.
416     *
417     * @operation: Type of operation.
418     *
419     * Returns the name of operation.
420     */
421     const char *ccs_net2keyword(const u8 operation)
422 kumaneko 111 {
423     const char *keyword = "unknown";
424     switch (operation) {
425     case NETWORK_ACL_UDP_BIND:
426     keyword = "UDP bind";
427     break;
428     case NETWORK_ACL_UDP_CONNECT:
429     keyword = "UDP connect";
430     break;
431     case NETWORK_ACL_TCP_BIND:
432     keyword = "TCP bind";
433     break;
434     case NETWORK_ACL_TCP_LISTEN:
435     keyword = "TCP listen";
436     break;
437     case NETWORK_ACL_TCP_CONNECT:
438     keyword = "TCP connect";
439     break;
440     case NETWORK_ACL_TCP_ACCEPT:
441     keyword = "TCP accept";
442     break;
443     case NETWORK_ACL_RAW_BIND:
444     keyword = "RAW bind";
445     break;
446     case NETWORK_ACL_RAW_CONNECT:
447     keyword = "RAW connect";
448     break;
449     }
450     return keyword;
451     }
452    
453 kumaneko 1052 /**
454     * update_network_entry - Update "struct ip_network_acl_record" list.
455     *
456     * @operation: Type of operation.
457     * @record_type: Type of address.
458     * @group: Pointer to "struct address_group_entry". May be NULL.
459     * @min_address: Start of IPv4 or IPv6 address range.
460     * @max_address: End of IPv4 or IPv6 address range.
461     * @min_port: Start of port number range.
462     * @max_port: End of port number range.
463     * @domain: Pointer to "struct domain_info".
464     * @condition: Pointer to "struct condition_list". May be NULL.
465     * @is_delete: True if it is a delete request.
466     *
467     * Returns 0 on success, negative value otherwise.
468     */
469     static int update_network_entry(const u8 operation, const u8 record_type,
470     const struct address_group_entry *group,
471     const u32 *min_address, const u32 *max_address,
472     const u16 min_port, const u16 max_port,
473     struct domain_info *domain,
474     const struct condition_list *condition,
475     const bool is_delete)
476 kumaneko 111 {
477     struct acl_info *ptr;
478 kumaneko 708 struct ip_network_acl_record *acl;
479 kumaneko 111 int error = -ENOMEM;
480 kumaneko 1052 /* using host byte order to allow u32 comparison than memcmp().*/
481     const u32 min_ip = ntohl(*min_address);
482     const u32 max_ip = ntohl(*max_address);
483     const struct in6_addr *saved_min_address = NULL;
484     const struct in6_addr *saved_max_address = NULL;
485     if (!domain)
486     return -EINVAL;
487     if (record_type != IP_RECORD_TYPE_IPv6)
488     goto not_ipv6;
489     saved_min_address = save_ipv6_address((struct in6_addr *) min_address);
490     saved_max_address = save_ipv6_address((struct in6_addr *) max_address);
491     if (!saved_min_address || !saved_max_address)
492     return -ENOMEM;
493     not_ipv6:
494 kumaneko 652 mutex_lock(&domain_acl_lock);
495 kumaneko 1052 if (is_delete)
496     goto delete;
497     list1_for_each_entry(ptr, &domain->acl_info_list, list) {
498     if ((ptr->type & ~(ACL_DELETED | ACL_WITH_CONDITION))
499     != TYPE_IP_NETWORK_ACL)
500     continue;
501     if (ccs_get_condition_part(ptr) != condition)
502     continue;
503     acl = container_of(ptr, struct ip_network_acl_record, head);
504     if (acl->operation_type != operation ||
505     acl->record_type != record_type ||
506     acl->min_port != min_port || max_port != acl->max_port)
507     continue;
508 kumaneko 708 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
509 kumaneko 1052 if (acl->u.group != group)
510     continue;
511 kumaneko 708 } else if (record_type == IP_RECORD_TYPE_IPv4) {
512 kumaneko 1052 if (acl->u.ipv4.min != min_ip ||
513     max_ip != acl->u.ipv4.max)
514     continue;
515     } else if (record_type == IP_RECORD_TYPE_IPv6) {
516     if (acl->u.ipv6.min != saved_min_address ||
517     saved_max_address != acl->u.ipv6.max)
518     continue;
519 kumaneko 708 }
520 kumaneko 1052 error = ccs_add_domain_acl(NULL, ptr);
521     goto out;
522     }
523     /* Not found. Append it to the tail. */
524     acl = ccs_alloc_acl_element(TYPE_IP_NETWORK_ACL, condition);
525     if (!acl)
526     goto out;
527     acl->operation_type = operation;
528     acl->record_type = record_type;
529     if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
530     acl->u.group = group;
531     } else if (record_type == IP_RECORD_TYPE_IPv4) {
532     acl->u.ipv4.min = min_ip;
533     acl->u.ipv4.max = max_ip;
534 kumaneko 111 } else {
535 kumaneko 1052 acl->u.ipv6.min = saved_min_address;
536     acl->u.ipv6.max = saved_max_address;
537     }
538     acl->min_port = min_port;
539     acl->max_port = max_port;
540     error = ccs_add_domain_acl(domain, &acl->head);
541     goto out;
542     delete:
543     error = -ENOENT;
544     list1_for_each_entry(ptr, &domain->acl_info_list, list) {
545     if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_IP_NETWORK_ACL)
546     continue;
547     if (ccs_get_condition_part(ptr) != condition)
548     continue;
549     acl = container_of(ptr, struct ip_network_acl_record, head);
550     if (acl->operation_type != operation ||
551     acl->record_type != record_type ||
552     acl->min_port != min_port || max_port != acl->max_port)
553     continue;
554     if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
555     if (acl->u.group != group)
556     continue;
557     } else if (record_type == IP_RECORD_TYPE_IPv4) {
558     if (acl->u.ipv4.min != min_ip ||
559     max_ip != acl->u.ipv4.max)
560     continue;
561     } else if (record_type == IP_RECORD_TYPE_IPv6) {
562     if (acl->u.ipv6.min != saved_min_address ||
563     saved_max_address != acl->u.ipv6.max)
564     continue;
565 kumaneko 111 }
566 kumaneko 1052 error = ccs_del_domain_acl(ptr);
567     break;
568 kumaneko 111 }
569 kumaneko 1052 out:
570 kumaneko 652 mutex_unlock(&domain_acl_lock);
571 kumaneko 111 return error;
572     }
573    
574 kumaneko 1052 /**
575     * check_network_entry - Check permission for network operation.
576     *
577     * @is_ipv6: True if @address is an IPv6 address.
578     * @operation: Type of operation.
579     * @address: An IPv4 or IPv6 address.
580     * @port: Port number.
581     *
582     * Returns 0 on success, negative value otherwise.
583     */
584     static int check_network_entry(const bool is_ipv6, const u8 operation,
585     const u32 *address, const u16 port)
586 kumaneko 111 {
587     struct domain_info * const domain = current->domain_info;
588     struct acl_info *ptr;
589 kumaneko 1052 const char *keyword = ccs_net2keyword(operation);
590 kumaneko 815 const u8 profile = current->domain_info->profile;
591 kumaneko 1052 const u8 mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_NETWORK);
592 kumaneko 815 const bool is_enforce = (mode == 3);
593 kumaneko 1052 /* using host byte order to allow u32 comparison than memcmp().*/
594     const u32 ip = ntohl(*address);
595 kumaneko 1016 bool found = false;
596 kumaneko 1052 if (!mode)
597     return 0;
598 kumaneko 722 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
599 kumaneko 708 struct ip_network_acl_record *acl;
600 kumaneko 1052 if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_IP_NETWORK_ACL)
601     continue;
602 kumaneko 912 acl = container_of(ptr, struct ip_network_acl_record, head);
603 kumaneko 1052 if (acl->operation_type != operation || port < acl->min_port ||
604     acl->max_port < port || !ccs_check_condition(ptr, NULL))
605     continue;
606 kumaneko 708 if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
607 kumaneko 1052 if (!address_matches_to_group(is_ipv6, address,
608     acl->u.group))
609     continue;
610 kumaneko 708 } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {
611 kumaneko 1052 if (is_ipv6 ||
612     ip < acl->u.ipv4.min || acl->u.ipv4.max < ip)
613     continue;
614 kumaneko 111 } else {
615 kumaneko 1052 if (!is_ipv6 ||
616     memcmp(acl->u.ipv6.min, address, 16) > 0 ||
617     memcmp(address, acl->u.ipv6.max, 16) > 0)
618     continue;
619 kumaneko 111 }
620 kumaneko 1052 ccs_update_condition(ptr);
621 kumaneko 1016 found = true;
622 kumaneko 708 break;
623 kumaneko 111 }
624 kumaneko 1052 audit_network_log(is_ipv6, keyword, address, port, found, profile,
625     mode);
626     if (found)
627     return 0;
628     if (ccs_verbose_mode()) {
629 kumaneko 111 if (is_ipv6) {
630     char buf[64];
631 kumaneko 1052 ccs_print_ipv6(buf, sizeof(buf),
632     (const struct in6_addr *) address);
633     printk(KERN_WARNING "TOMOYO-%s: %s to %s %u "
634     "denied for %s\n", ccs_get_msg(is_enforce),
635     keyword, buf, port, ccs_get_last_name(domain));
636 kumaneko 111 } else {
637 kumaneko 1052 printk(KERN_WARNING "TOMOYO-%s: %s to %u.%u.%u.%u %u "
638     "denied for %s\n", ccs_get_msg(is_enforce),
639     keyword, HIPQUAD(ip), port,
640     ccs_get_last_name(domain));
641 kumaneko 111 }
642     }
643     if (is_enforce) {
644     if (is_ipv6) {
645     char buf[64];
646 kumaneko 1052 ccs_print_ipv6(buf, sizeof(buf),
647     (const struct in6_addr *) address);
648     return ccs_check_supervisor("%s\n"
649     KEYWORD_ALLOW_NETWORK "%s "
650     "%s %u\n",
651     domain->domainname->name,
652     keyword, buf, port);
653 kumaneko 111 }
654 kumaneko 1052 return ccs_check_supervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s "
655     "%u.%u.%u.%u %u\n",
656     domain->domainname->name, keyword,
657     HIPQUAD(ip), port);
658     } else if (mode == 1 && ccs_check_domain_quota(domain))
659     update_network_entry(operation, is_ipv6 ?
660     IP_RECORD_TYPE_IPv6 : IP_RECORD_TYPE_IPv4,
661     NULL, address, address, port, port, domain,
662     NULL, 0);
663 kumaneko 111 return 0;
664     }
665    
666 kumaneko 1052 /**
667     * ccs_write_network_policy - Write "struct ip_network_acl_record" list.
668     *
669     * @data: String to parse.
670     * @domain: Pointer to "struct domain_info".
671     * @condition: Pointer to "struct condition_list". May be NULL.
672     * @is_delete: True if it is a delete request.
673     *
674     * Returns 0 on success, negative value otherwise.
675     */
676     int ccs_write_network_policy(char *data, struct domain_info *domain,
677     const struct condition_list *condition,
678     const bool is_delete)
679 kumaneko 111 {
680     u8 sock_type, operation, record_type;
681     u16 min_address[8], max_address[8];
682     struct address_group_entry *group = NULL;
683     u16 min_port, max_port;
684 kumaneko 853 u8 count;
685 kumaneko 111 char *cp1 = NULL, *cp2 = NULL;
686 kumaneko 1052 cp1 = strchr(data, ' ');
687     if (!cp1)
688     goto out;
689     cp1++;
690     if (!strncmp(data, "TCP ", 4))
691     sock_type = SOCK_STREAM;
692     else if (!strncmp(data, "UDP ", 4))
693     sock_type = SOCK_DGRAM;
694     else if (!strncmp(data, "RAW ", 4))
695     sock_type = SOCK_RAW;
696     else
697     goto out;
698     cp2 = strchr(cp1, ' ');
699     if (!cp2)
700     goto out;
701     cp2++;
702     if (!strncmp(cp1, "bind ", 5))
703     switch (sock_type) {
704     case SOCK_STREAM:
705     operation = NETWORK_ACL_TCP_BIND;
706     break;
707     case SOCK_DGRAM:
708     operation = NETWORK_ACL_UDP_BIND;
709     break;
710     default:
711     operation = NETWORK_ACL_RAW_BIND;
712     }
713     else if (!strncmp(cp1, "connect ", 8))
714     switch (sock_type) {
715     case SOCK_STREAM:
716     operation = NETWORK_ACL_TCP_CONNECT;
717     break;
718     case SOCK_DGRAM:
719     operation = NETWORK_ACL_UDP_CONNECT;
720     break;
721     default:
722     operation = NETWORK_ACL_RAW_CONNECT;
723     }
724     else if (sock_type == SOCK_STREAM && !strncmp(cp1, "listen ", 7))
725 kumaneko 111 operation = NETWORK_ACL_TCP_LISTEN;
726 kumaneko 1052 else if (sock_type == SOCK_STREAM && !strncmp(cp1, "accept ", 7))
727 kumaneko 111 operation = NETWORK_ACL_TCP_ACCEPT;
728 kumaneko 1052 else
729 kumaneko 111 goto out;
730 kumaneko 1052 cp1 = strchr(cp2, ' ');
731     if (!cp1)
732     goto out;
733     *cp1++ = '\0';
734     count = sscanf(cp2, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
735     "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
736     &min_address[0], &min_address[1],
737     &min_address[2], &min_address[3],
738     &min_address[4], &min_address[5],
739     &min_address[6], &min_address[7],
740     &max_address[0], &max_address[1],
741     &max_address[2], &max_address[3],
742     &max_address[4], &max_address[5],
743     &max_address[6], &max_address[7]);
744     if (count == 8 || count == 16) {
745 kumaneko 853 u8 i;
746 kumaneko 111 for (i = 0; i < 8; i++) {
747     min_address[i] = htons(min_address[i]);
748     max_address[i] = htons(max_address[i]);
749     }
750 kumaneko 1052 if (count == 8)
751     memmove(max_address, min_address, sizeof(min_address));
752 kumaneko 111 record_type = IP_RECORD_TYPE_IPv6;
753 kumaneko 1052 goto ok;
754     }
755     count = sscanf(cp2, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
756     &min_address[0], &min_address[1],
757     &min_address[2], &min_address[3],
758     &max_address[0], &max_address[1],
759     &max_address[2], &max_address[3]);
760     if (count == 4 || count == 8) {
761     u32 ip = htonl((((u8) min_address[0]) << 24)
762     + (((u8) min_address[1]) << 16)
763     + (((u8) min_address[2]) << 8)
764     + (u8) min_address[3]);
765     *(u32 *) min_address = ip;
766     if (count == 8)
767     ip = htonl((((u8) max_address[0]) << 24)
768     + (((u8) max_address[1]) << 16)
769     + (((u8) max_address[2]) << 8)
770     + (u8) max_address[3]);
771     *(u32 *) max_address = ip;
772 kumaneko 111 record_type = IP_RECORD_TYPE_IPv4;
773     } else if (*cp2 == '@') {
774 kumaneko 1052 group = find_or_assign_new_address_group(cp2 + 1);
775     if (!group)
776     return -ENOMEM;
777 kumaneko 111 record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
778     } else {
779     goto out;
780     }
781 kumaneko 1052 ok:
782     if (strchr(cp1, ' '))
783     goto out;
784     count = sscanf(cp1, "%hu-%hu", &min_port, &max_port);
785     if (count != 1 && count != 2)
786     goto out;
787     if (count == 1)
788     max_port = min_port;
789     return update_network_entry(operation, record_type, group,
790     (u32 *) min_address, (u32 *) max_address,
791     min_port, max_port, domain, condition,
792     is_delete);
793     out:
794 kumaneko 111 return -EINVAL;
795     }
796    
797 kumaneko 1052 /**
798     * ccs_check_network_listen_acl - Check permission for listen() operation.
799     *
800     * @is_ipv6: True if @address is an IPv6 address.
801     * @address: An IPv4 or IPv6 address.
802     * @port: Port number.
803     *
804     * Returns 0 on success, negative value otherwise.
805     */
806     int ccs_check_network_listen_acl(const _Bool is_ipv6, const u8 *address,
807     const u16 port)
808 kumaneko 111 {
809 kumaneko 1052 return check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,
810     (const u32 *) address, ntohs(port));
811 kumaneko 111 }
812    
813 kumaneko 1052 /**
814     * ccs_check_network_connect_acl - Check permission for connect() operation.
815     *
816     * @is_ipv6: True if @address is an IPv6 address.
817     * @sock_type: Type of socket. (TCP or UDP or RAW)
818     * @address: An IPv4 or IPv6 address.
819     * @port: Port number.
820     *
821     * Returns 0 on success, negative value otherwise.
822     */
823     int ccs_check_network_connect_acl(const _Bool is_ipv6, const int sock_type,
824     const u8 *address, const u16 port)
825 kumaneko 111 {
826 kumaneko 1052 u8 operation;
827     switch (sock_type) {
828     case SOCK_STREAM:
829     operation = NETWORK_ACL_TCP_CONNECT;
830     break;
831     case SOCK_DGRAM:
832     operation = NETWORK_ACL_UDP_CONNECT;
833     break;
834     default:
835     operation = NETWORK_ACL_RAW_CONNECT;
836     }
837     return check_network_entry(is_ipv6, operation, (const u32 *) address,
838     ntohs(port));
839 kumaneko 111 }
840    
841 kumaneko 1052 /**
842     * ccs_check_network_bind_acl - Check permission for bind() operation.
843     *
844     * @is_ipv6: True if @address is an IPv6 address.
845     * @sock_type: Type of socket. (TCP or UDP or RAW)
846     * @address: An IPv4 or IPv6 address.
847     * @port: Port number.
848     *
849     * Returns 0 on success, negative value otherwise.
850     */
851     int ccs_check_network_bind_acl(const _Bool is_ipv6, const int sock_type,
852     const u8 *address, const u16 port)
853 kumaneko 111 {
854 kumaneko 1052 u8 operation;
855     switch (sock_type) {
856     case SOCK_STREAM:
857     operation = NETWORK_ACL_TCP_BIND;
858     break;
859     case SOCK_DGRAM:
860     operation = NETWORK_ACL_UDP_BIND;
861     break;
862     default:
863     operation = NETWORK_ACL_RAW_BIND;
864     }
865     return check_network_entry(is_ipv6, operation, (const u32 *) address,
866     ntohs(port));
867 kumaneko 111 }
868    
869 kumaneko 1052 /**
870     * ccs_check_network_accept_acl - Check permission for accept() operation.
871     *
872     * @is_ipv6: True if @address is an IPv6 address.
873     * @address: An IPv4 or IPv6 address.
874     * @port: Port number.
875     *
876     * Returns 0 on success, negative value otherwise.
877     */
878     int ccs_check_network_accept_acl(const _Bool is_ipv6, const u8 *address,
879     const u16 port)
880 kumaneko 111 {
881 kumaneko 708 int retval;
882     current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
883 kumaneko 1052 retval = check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,
884     (const u32 *) address, ntohs(port));
885 kumaneko 708 current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
886     return retval;
887 kumaneko 111 }
888    
889 kumaneko 1052 /**
890     * ccs_check_network_sendmsg_acl - Check permission for sendmsg() operation.
891     *
892     * @is_ipv6: True if @address is an IPv6 address.
893     * @sock_type: Type of socket. (UDP or RAW)
894     * @address: An IPv4 or IPv6 address.
895     * @port: Port number.
896     *
897     * Returns 0 on success, negative value otherwise.
898     */
899     int ccs_check_network_sendmsg_acl(const _Bool is_ipv6, const int sock_type,
900     const u8 *address, const u16 port)
901 kumaneko 111 {
902 kumaneko 1052 u8 operation;
903     if (sock_type == SOCK_DGRAM)
904     operation = NETWORK_ACL_UDP_CONNECT;
905     else
906     operation = NETWORK_ACL_RAW_CONNECT;
907     return check_network_entry(is_ipv6, operation, (const u32 *) address,
908     ntohs(port));
909 kumaneko 111 }
910    
911 kumaneko 1052 /**
912     * ccs_check_network_recvmsg_acl - Check permission for recvmsg() operation.
913     *
914     * @is_ipv6: True if @address is an IPv6 address.
915     * @sock_type: Type of socket. (UDP or RAW)
916     * @address: An IPv4 or IPv6 address.
917     * @port: Port number.
918     *
919     * Returns 0 on success, negative value otherwise.
920     */
921     int ccs_check_network_recvmsg_acl(const _Bool is_ipv6, const int sock_type,
922     const u8 *address, const u16 port)
923 kumaneko 111 {
924 kumaneko 708 int retval;
925 kumaneko 1052 const u8 operation
926     = sock_type == SOCK_DGRAM ?
927     NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;
928 kumaneko 708 current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
929 kumaneko 1052 retval = check_network_entry(is_ipv6, operation, (const u32 *) address,
930     ntohs(port));
931 kumaneko 708 current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
932     return retval;
933 kumaneko 111 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26