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

Subversion リポジトリの参照

Annotation of /trunk/1.6.x/ccs-patch/fs/tomoyo_network.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1052 - (hide annotations) (download) (as text)
Mon Mar 24 03:50:04 2008 UTC (16 years, 2 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 27221 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     * address_matches_to_group - Check whether the given address matches members
299     * of the given address group.
300     *
301     * @is_ipv6: True if @address is an IPv6 address.
302     * @address: An IPv4 or IPv6 address.
303     * @group: Pointer to "struct address_group_entry".
304     *
305     * Returns true if @address matches addresses in @group group, false otherwise.
306     */
307     static bool address_matches_to_group(const bool is_ipv6, const u32 *address,
308     const struct address_group_entry *group)
309 kumaneko 111 {
310 kumaneko 214 struct address_group_member *member;
311 kumaneko 111 const u32 ip = ntohl(*address);
312 kumaneko 722 list1_for_each_entry(member, &group->address_group_member_list, list) {
313 kumaneko 1052 if (member->is_deleted)
314     continue;
315 kumaneko 111 if (member->is_ipv6) {
316 kumaneko 1052 if (is_ipv6 &&
317     memcmp(member->min.ipv6, address, 16) <= 0 &&
318     memcmp(address, member->max.ipv6, 16) <= 0)
319     return true;
320 kumaneko 111 } else {
321 kumaneko 1052 if (!is_ipv6 &&
322     member->min.ipv4 <= ip && ip <= member->max.ipv4)
323     return true;
324 kumaneko 111 }
325     }
326 kumaneko 1016 return false;
327 kumaneko 111 }
328    
329 kumaneko 1052 /**
330     * ccs_read_address_group_policy - Dump "struct address_group_entry" list.
331     *
332     * @head: Pointer to "struct ccs_io_buffer".
333     *
334     * Returns true on success, false otherwise.
335     */
336     bool ccs_read_address_group_policy(struct ccs_io_buffer *head)
337 kumaneko 111 {
338 kumaneko 722 struct list1_head *gpos;
339     struct list1_head *mpos;
340     list1_for_each_cookie(gpos, head->read_var1, &address_group_list) {
341 kumaneko 708 struct address_group_entry *group;
342 kumaneko 722 group = list1_entry(gpos, struct address_group_entry, list);
343 kumaneko 1052 list1_for_each_cookie(mpos, head->read_var2,
344     &group->address_group_member_list) {
345 kumaneko 708 char buf[128];
346     struct address_group_member *member;
347 kumaneko 1052 member = list1_entry(mpos, struct address_group_member,
348     list);
349     if (member->is_deleted)
350     continue;
351     if (!member->is_ipv6) {
352     const struct in6_addr *min_address
353     = member->min.ipv6;
354     const struct in6_addr *max_address
355     = member->max.ipv6;
356     ccs_print_ipv6(buf, sizeof(buf), min_address);
357 kumaneko 719 if (min_address != max_address) {
358 kumaneko 1052 int len;
359 kumaneko 708 char *cp = strchr(buf, '\0');
360     *cp++ = '-';
361 kumaneko 1052 len = strlen(buf);
362     ccs_print_ipv6(cp, sizeof(buf) - len,
363     max_address);
364 kumaneko 111 }
365 kumaneko 708 } else {
366 kumaneko 1052 const u32 min_address = member->min.ipv4;
367     const u32 max_address = member->max.ipv4;
368 kumaneko 708 memset(buf, 0, sizeof(buf));
369 kumaneko 1052 snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u",
370     HIPQUAD(min_address));
371 kumaneko 708 if (min_address != max_address) {
372     const int len = strlen(buf);
373 kumaneko 1052 snprintf(buf + len,
374     sizeof(buf) - 1 - len,
375     "-%u.%u.%u.%u",
376     HIPQUAD(max_address));
377 kumaneko 708 }
378 kumaneko 111 }
379 kumaneko 1052 if (!ccs_io_printf(head, KEYWORD_ADDRESS_GROUP
380     "%s %s\n", group->group_name->name,
381     buf))
382     goto out;
383 kumaneko 111 }
384     }
385 kumaneko 1052 return true;
386     out:
387     return false;
388 kumaneko 111 }
389    
390 kumaneko 719 #if !defined(NIP6)
391 kumaneko 1052 #define NIP6(addr) \
392     ntohs((addr).s6_addr16[0]),ntohs((addr).s6_addr16[1]),\
393     ntohs((addr).s6_addr16[2]),ntohs((addr).s6_addr16[3]),\
394     ntohs((addr).s6_addr16[4]),ntohs((addr).s6_addr16[5]),\
395     ntohs((addr).s6_addr16[6]),ntohs((addr).s6_addr16[7])
396 kumaneko 719 #endif
397    
398 kumaneko 1052 /**
399     * ccs_print_ipv6 - Dump an IPv6 address.
400     *
401     * @buffer: Buffer to write to.
402     * @buffer_len: Size of @buffer .
403     * @ip: Pointer to "struct in6_addr".
404     *
405     * Returns @buffer.
406     */
407     char *ccs_print_ipv6(char *buffer, const int buffer_len,
408     const struct in6_addr *ip)
409 kumaneko 111 {
410     memset(buffer, 0, buffer_len);
411 kumaneko 719 snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip));
412 kumaneko 111 return buffer;
413     }
414    
415 kumaneko 1052 /**
416     * ccs_net2keyword - Convert network operation index to network operation name.
417     *
418     * @operation: Type of operation.
419     *
420     * Returns the name of operation.
421     */
422     const char *ccs_net2keyword(const u8 operation)
423 kumaneko 111 {
424     const char *keyword = "unknown";
425     switch (operation) {
426     case NETWORK_ACL_UDP_BIND:
427     keyword = "UDP bind";
428     break;
429     case NETWORK_ACL_UDP_CONNECT:
430     keyword = "UDP connect";
431     break;
432     case NETWORK_ACL_TCP_BIND:
433     keyword = "TCP bind";
434     break;
435     case NETWORK_ACL_TCP_LISTEN:
436     keyword = "TCP listen";
437     break;
438     case NETWORK_ACL_TCP_CONNECT:
439     keyword = "TCP connect";
440     break;
441     case NETWORK_ACL_TCP_ACCEPT:
442     keyword = "TCP accept";
443     break;
444     case NETWORK_ACL_RAW_BIND:
445     keyword = "RAW bind";
446     break;
447     case NETWORK_ACL_RAW_CONNECT:
448     keyword = "RAW connect";
449     break;
450     }
451     return keyword;
452     }
453    
454 kumaneko 1052 /**
455     * update_network_entry - Update "struct ip_network_acl_record" list.
456     *
457     * @operation: Type of operation.
458     * @record_type: Type of address.
459     * @group: Pointer to "struct address_group_entry". May be NULL.
460     * @min_address: Start of IPv4 or IPv6 address range.
461     * @max_address: End of IPv4 or IPv6 address range.
462     * @min_port: Start of port number range.
463     * @max_port: End of port number range.
464     * @domain: Pointer to "struct domain_info".
465     * @condition: Pointer to "struct condition_list". May be NULL.
466     * @is_delete: True if it is a delete request.
467     *
468     * Returns 0 on success, negative value otherwise.
469     */
470     static int update_network_entry(const u8 operation, const u8 record_type,
471     const struct address_group_entry *group,
472     const u32 *min_address, const u32 *max_address,
473     const u16 min_port, const u16 max_port,
474     struct domain_info *domain,
475     const struct condition_list *condition,
476     const bool is_delete)
477 kumaneko 111 {
478     struct acl_info *ptr;
479 kumaneko 708 struct ip_network_acl_record *acl;
480 kumaneko 111 int error = -ENOMEM;
481 kumaneko 1052 /* using host byte order to allow u32 comparison than memcmp().*/
482     const u32 min_ip = ntohl(*min_address);
483     const u32 max_ip = ntohl(*max_address);
484     const struct in6_addr *saved_min_address = NULL;
485     const struct in6_addr *saved_max_address = NULL;
486     if (!domain)
487     return -EINVAL;
488     if (record_type != IP_RECORD_TYPE_IPv6)
489     goto not_ipv6;
490     saved_min_address = save_ipv6_address((struct in6_addr *) min_address);
491     saved_max_address = save_ipv6_address((struct in6_addr *) max_address);
492     if (!saved_min_address || !saved_max_address)
493     return -ENOMEM;
494     not_ipv6:
495 kumaneko 652 mutex_lock(&domain_acl_lock);
496 kumaneko 1052 if (is_delete)
497     goto delete;
498     list1_for_each_entry(ptr, &domain->acl_info_list, list) {
499     if ((ptr->type & ~(ACL_DELETED | ACL_WITH_CONDITION))
500     != TYPE_IP_NETWORK_ACL)
501     continue;
502     if (ccs_get_condition_part(ptr) != condition)
503     continue;
504     acl = container_of(ptr, struct ip_network_acl_record, head);
505     if (acl->operation_type != operation ||
506     acl->record_type != record_type ||
507     acl->min_port != min_port || max_port != acl->max_port)
508     continue;
509 kumaneko 708 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
510 kumaneko 1052 if (acl->u.group != group)
511     continue;
512 kumaneko 708 } else if (record_type == IP_RECORD_TYPE_IPv4) {
513 kumaneko 1052 if (acl->u.ipv4.min != min_ip ||
514     max_ip != acl->u.ipv4.max)
515     continue;
516     } else if (record_type == IP_RECORD_TYPE_IPv6) {
517     if (acl->u.ipv6.min != saved_min_address ||
518     saved_max_address != acl->u.ipv6.max)
519     continue;
520 kumaneko 708 }
521 kumaneko 1052 error = ccs_add_domain_acl(NULL, ptr);
522     goto out;
523     }
524     /* Not found. Append it to the tail. */
525     acl = ccs_alloc_acl_element(TYPE_IP_NETWORK_ACL, condition);
526     if (!acl)
527     goto out;
528     acl->operation_type = operation;
529     acl->record_type = record_type;
530     if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
531     acl->u.group = group;
532     } else if (record_type == IP_RECORD_TYPE_IPv4) {
533     acl->u.ipv4.min = min_ip;
534     acl->u.ipv4.max = max_ip;
535 kumaneko 111 } else {
536 kumaneko 1052 acl->u.ipv6.min = saved_min_address;
537     acl->u.ipv6.max = saved_max_address;
538     }
539     acl->min_port = min_port;
540     acl->max_port = max_port;
541     error = ccs_add_domain_acl(domain, &acl->head);
542     goto out;
543     delete:
544     error = -ENOENT;
545     list1_for_each_entry(ptr, &domain->acl_info_list, list) {
546     if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_IP_NETWORK_ACL)
547     continue;
548     if (ccs_get_condition_part(ptr) != condition)
549     continue;
550     acl = container_of(ptr, struct ip_network_acl_record, head);
551     if (acl->operation_type != operation ||
552     acl->record_type != record_type ||
553     acl->min_port != min_port || max_port != acl->max_port)
554     continue;
555     if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
556     if (acl->u.group != group)
557     continue;
558     } else if (record_type == IP_RECORD_TYPE_IPv4) {
559     if (acl->u.ipv4.min != min_ip ||
560     max_ip != acl->u.ipv4.max)
561     continue;
562     } else if (record_type == IP_RECORD_TYPE_IPv6) {
563     if (acl->u.ipv6.min != saved_min_address ||
564     saved_max_address != acl->u.ipv6.max)
565     continue;
566 kumaneko 111 }
567 kumaneko 1052 error = ccs_del_domain_acl(ptr);
568     break;
569 kumaneko 111 }
570 kumaneko 1052 out:
571 kumaneko 652 mutex_unlock(&domain_acl_lock);
572 kumaneko 111 return error;
573     }
574    
575 kumaneko 1052 /**
576     * check_network_entry - Check permission for network operation.
577     *
578     * @is_ipv6: True if @address is an IPv6 address.
579     * @operation: Type of operation.
580     * @address: An IPv4 or IPv6 address.
581     * @port: Port number.
582     *
583     * Returns 0 on success, negative value otherwise.
584     */
585     static int check_network_entry(const bool is_ipv6, const u8 operation,
586     const u32 *address, const u16 port)
587 kumaneko 111 {
588     struct domain_info * const domain = current->domain_info;
589     struct acl_info *ptr;
590 kumaneko 1052 const char *keyword = ccs_net2keyword(operation);
591 kumaneko 815 const u8 profile = current->domain_info->profile;
592 kumaneko 1052 const u8 mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_NETWORK);
593 kumaneko 815 const bool is_enforce = (mode == 3);
594 kumaneko 1052 /* using host byte order to allow u32 comparison than memcmp().*/
595     const u32 ip = ntohl(*address);
596 kumaneko 1016 bool found = false;
597 kumaneko 1052 if (!mode)
598     return 0;
599 kumaneko 722 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
600 kumaneko 708 struct ip_network_acl_record *acl;
601 kumaneko 1052 if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_IP_NETWORK_ACL)
602     continue;
603 kumaneko 912 acl = container_of(ptr, struct ip_network_acl_record, head);
604 kumaneko 1052 if (acl->operation_type != operation || port < acl->min_port ||
605     acl->max_port < port || !ccs_check_condition(ptr, NULL))
606     continue;
607 kumaneko 708 if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
608 kumaneko 1052 if (!address_matches_to_group(is_ipv6, address,
609     acl->u.group))
610     continue;
611 kumaneko 708 } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {
612 kumaneko 1052 if (is_ipv6 ||
613     ip < acl->u.ipv4.min || acl->u.ipv4.max < ip)
614     continue;
615 kumaneko 111 } else {
616 kumaneko 1052 if (!is_ipv6 ||
617     memcmp(acl->u.ipv6.min, address, 16) > 0 ||
618     memcmp(address, acl->u.ipv6.max, 16) > 0)
619     continue;
620 kumaneko 111 }
621 kumaneko 1052 ccs_update_condition(ptr);
622 kumaneko 1016 found = true;
623 kumaneko 708 break;
624 kumaneko 111 }
625 kumaneko 1052 audit_network_log(is_ipv6, keyword, address, port, found, profile,
626     mode);
627     if (found)
628     return 0;
629     if (ccs_verbose_mode()) {
630 kumaneko 111 if (is_ipv6) {
631     char buf[64];
632 kumaneko 1052 ccs_print_ipv6(buf, sizeof(buf),
633     (const struct in6_addr *) address);
634     printk(KERN_WARNING "TOMOYO-%s: %s to %s %u "
635     "denied for %s\n", ccs_get_msg(is_enforce),
636     keyword, buf, port, ccs_get_last_name(domain));
637 kumaneko 111 } else {
638 kumaneko 1052 printk(KERN_WARNING "TOMOYO-%s: %s to %u.%u.%u.%u %u "
639     "denied for %s\n", ccs_get_msg(is_enforce),
640     keyword, HIPQUAD(ip), port,
641     ccs_get_last_name(domain));
642 kumaneko 111 }
643     }
644     if (is_enforce) {
645     if (is_ipv6) {
646     char buf[64];
647 kumaneko 1052 ccs_print_ipv6(buf, sizeof(buf),
648     (const struct in6_addr *) address);
649     return ccs_check_supervisor("%s\n"
650     KEYWORD_ALLOW_NETWORK "%s "
651     "%s %u\n",
652     domain->domainname->name,
653     keyword, buf, port);
654 kumaneko 111 }
655 kumaneko 1052 return ccs_check_supervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s "
656     "%u.%u.%u.%u %u\n",
657     domain->domainname->name, keyword,
658     HIPQUAD(ip), port);
659     } else if (mode == 1 && ccs_check_domain_quota(domain))
660     update_network_entry(operation, is_ipv6 ?
661     IP_RECORD_TYPE_IPv6 : IP_RECORD_TYPE_IPv4,
662     NULL, address, address, port, port, domain,
663     NULL, 0);
664 kumaneko 111 return 0;
665     }
666    
667 kumaneko 1052 /**
668     * ccs_write_network_policy - Write "struct ip_network_acl_record" list.
669     *
670     * @data: String to parse.
671     * @domain: Pointer to "struct domain_info".
672     * @condition: Pointer to "struct condition_list". May be NULL.
673     * @is_delete: True if it is a delete request.
674     *
675     * Returns 0 on success, negative value otherwise.
676     */
677     int ccs_write_network_policy(char *data, struct domain_info *domain,
678     const struct condition_list *condition,
679     const bool is_delete)
680 kumaneko 111 {
681     u8 sock_type, operation, record_type;
682     u16 min_address[8], max_address[8];
683     struct address_group_entry *group = NULL;
684     u16 min_port, max_port;
685 kumaneko 853 u8 count;
686 kumaneko 111 char *cp1 = NULL, *cp2 = NULL;
687 kumaneko 1052 cp1 = strchr(data, ' ');
688     if (!cp1)
689     goto out;
690     cp1++;
691     if (!strncmp(data, "TCP ", 4))
692     sock_type = SOCK_STREAM;
693     else if (!strncmp(data, "UDP ", 4))
694     sock_type = SOCK_DGRAM;
695     else if (!strncmp(data, "RAW ", 4))
696     sock_type = SOCK_RAW;
697     else
698     goto out;
699     cp2 = strchr(cp1, ' ');
700     if (!cp2)
701     goto out;
702     cp2++;
703     if (!strncmp(cp1, "bind ", 5))
704     switch (sock_type) {
705     case SOCK_STREAM:
706     operation = NETWORK_ACL_TCP_BIND;
707     break;
708     case SOCK_DGRAM:
709     operation = NETWORK_ACL_UDP_BIND;
710     break;
711     default:
712     operation = NETWORK_ACL_RAW_BIND;
713     }
714     else if (!strncmp(cp1, "connect ", 8))
715     switch (sock_type) {
716     case SOCK_STREAM:
717     operation = NETWORK_ACL_TCP_CONNECT;
718     break;
719     case SOCK_DGRAM:
720     operation = NETWORK_ACL_UDP_CONNECT;
721     break;
722     default:
723     operation = NETWORK_ACL_RAW_CONNECT;
724     }
725     else if (sock_type == SOCK_STREAM && !strncmp(cp1, "listen ", 7))
726 kumaneko 111 operation = NETWORK_ACL_TCP_LISTEN;
727 kumaneko 1052 else if (sock_type == SOCK_STREAM && !strncmp(cp1, "accept ", 7))
728 kumaneko 111 operation = NETWORK_ACL_TCP_ACCEPT;
729 kumaneko 1052 else
730 kumaneko 111 goto out;
731 kumaneko 1052 cp1 = strchr(cp2, ' ');
732     if (!cp1)
733     goto out;
734     *cp1++ = '\0';
735     count = sscanf(cp2, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
736     "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
737     &min_address[0], &min_address[1],
738     &min_address[2], &min_address[3],
739     &min_address[4], &min_address[5],
740     &min_address[6], &min_address[7],
741     &max_address[0], &max_address[1],
742     &max_address[2], &max_address[3],
743     &max_address[4], &max_address[5],
744     &max_address[6], &max_address[7]);
745     if (count == 8 || count == 16) {
746 kumaneko 853 u8 i;
747 kumaneko 111 for (i = 0; i < 8; i++) {
748     min_address[i] = htons(min_address[i]);
749     max_address[i] = htons(max_address[i]);
750     }
751 kumaneko 1052 if (count == 8)
752     memmove(max_address, min_address, sizeof(min_address));
753 kumaneko 111 record_type = IP_RECORD_TYPE_IPv6;
754 kumaneko 1052 goto ok;
755     }
756     count = sscanf(cp2, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
757     &min_address[0], &min_address[1],
758     &min_address[2], &min_address[3],
759     &max_address[0], &max_address[1],
760     &max_address[2], &max_address[3]);
761     if (count == 4 || count == 8) {
762     u32 ip = htonl((((u8) min_address[0]) << 24)
763     + (((u8) min_address[1]) << 16)
764     + (((u8) min_address[2]) << 8)
765     + (u8) min_address[3]);
766     *(u32 *) min_address = ip;
767     if (count == 8)
768     ip = htonl((((u8) max_address[0]) << 24)
769     + (((u8) max_address[1]) << 16)
770     + (((u8) max_address[2]) << 8)
771     + (u8) max_address[3]);
772     *(u32 *) max_address = ip;
773 kumaneko 111 record_type = IP_RECORD_TYPE_IPv4;
774     } else if (*cp2 == '@') {
775 kumaneko 1052 group = find_or_assign_new_address_group(cp2 + 1);
776     if (!group)
777     return -ENOMEM;
778 kumaneko 111 record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
779     } else {
780     goto out;
781     }
782 kumaneko 1052 ok:
783     if (strchr(cp1, ' '))
784     goto out;
785     count = sscanf(cp1, "%hu-%hu", &min_port, &max_port);
786     if (count != 1 && count != 2)
787     goto out;
788     if (count == 1)
789     max_port = min_port;
790     return update_network_entry(operation, record_type, group,
791     (u32 *) min_address, (u32 *) max_address,
792     min_port, max_port, domain, condition,
793     is_delete);
794     out:
795 kumaneko 111 return -EINVAL;
796     }
797    
798 kumaneko 1052 /**
799     * ccs_check_network_listen_acl - Check permission for listen() operation.
800     *
801     * @is_ipv6: True if @address is an IPv6 address.
802     * @address: An IPv4 or IPv6 address.
803     * @port: Port number.
804     *
805     * Returns 0 on success, negative value otherwise.
806     */
807     int ccs_check_network_listen_acl(const _Bool is_ipv6, const u8 *address,
808     const u16 port)
809 kumaneko 111 {
810 kumaneko 1052 return check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,
811     (const u32 *) address, ntohs(port));
812 kumaneko 111 }
813    
814 kumaneko 1052 /**
815     * ccs_check_network_connect_acl - Check permission for connect() operation.
816     *
817     * @is_ipv6: True if @address is an IPv6 address.
818     * @sock_type: Type of socket. (TCP or UDP or RAW)
819     * @address: An IPv4 or IPv6 address.
820     * @port: Port number.
821     *
822     * Returns 0 on success, negative value otherwise.
823     */
824     int ccs_check_network_connect_acl(const _Bool is_ipv6, const int sock_type,
825     const u8 *address, const u16 port)
826 kumaneko 111 {
827 kumaneko 1052 u8 operation;
828     switch (sock_type) {
829     case SOCK_STREAM:
830     operation = NETWORK_ACL_TCP_CONNECT;
831     break;
832     case SOCK_DGRAM:
833     operation = NETWORK_ACL_UDP_CONNECT;
834     break;
835     default:
836     operation = NETWORK_ACL_RAW_CONNECT;
837     }
838     return check_network_entry(is_ipv6, operation, (const u32 *) address,
839     ntohs(port));
840 kumaneko 111 }
841    
842 kumaneko 1052 /**
843     * ccs_check_network_bind_acl - Check permission for bind() operation.
844     *
845     * @is_ipv6: True if @address is an IPv6 address.
846     * @sock_type: Type of socket. (TCP or UDP or RAW)
847     * @address: An IPv4 or IPv6 address.
848     * @port: Port number.
849     *
850     * Returns 0 on success, negative value otherwise.
851     */
852     int ccs_check_network_bind_acl(const _Bool is_ipv6, const int sock_type,
853     const u8 *address, const u16 port)
854 kumaneko 111 {
855 kumaneko 1052 u8 operation;
856     switch (sock_type) {
857     case SOCK_STREAM:
858     operation = NETWORK_ACL_TCP_BIND;
859     break;
860     case SOCK_DGRAM:
861     operation = NETWORK_ACL_UDP_BIND;
862     break;
863     default:
864     operation = NETWORK_ACL_RAW_BIND;
865     }
866     return check_network_entry(is_ipv6, operation, (const u32 *) address,
867     ntohs(port));
868 kumaneko 111 }
869    
870 kumaneko 1052 /**
871     * ccs_check_network_accept_acl - Check permission for accept() operation.
872     *
873     * @is_ipv6: True if @address is an IPv6 address.
874     * @address: An IPv4 or IPv6 address.
875     * @port: Port number.
876     *
877     * Returns 0 on success, negative value otherwise.
878     */
879     int ccs_check_network_accept_acl(const _Bool is_ipv6, const u8 *address,
880     const u16 port)
881 kumaneko 111 {
882 kumaneko 708 int retval;
883     current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
884 kumaneko 1052 retval = check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,
885     (const u32 *) address, ntohs(port));
886 kumaneko 708 current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
887     return retval;
888 kumaneko 111 }
889    
890 kumaneko 1052 /**
891     * ccs_check_network_sendmsg_acl - Check permission for sendmsg() operation.
892     *
893     * @is_ipv6: True if @address is an IPv6 address.
894     * @sock_type: Type of socket. (UDP or RAW)
895     * @address: An IPv4 or IPv6 address.
896     * @port: Port number.
897     *
898     * Returns 0 on success, negative value otherwise.
899     */
900     int ccs_check_network_sendmsg_acl(const _Bool is_ipv6, const int sock_type,
901     const u8 *address, const u16 port)
902 kumaneko 111 {
903 kumaneko 1052 u8 operation;
904     if (sock_type == SOCK_DGRAM)
905     operation = NETWORK_ACL_UDP_CONNECT;
906     else
907     operation = NETWORK_ACL_RAW_CONNECT;
908     return check_network_entry(is_ipv6, operation, (const u32 *) address,
909     ntohs(port));
910 kumaneko 111 }
911    
912 kumaneko 1052 /**
913     * ccs_check_network_recvmsg_acl - Check permission for recvmsg() operation.
914     *
915     * @is_ipv6: True if @address is an IPv6 address.
916     * @sock_type: Type of socket. (UDP or RAW)
917     * @address: An IPv4 or IPv6 address.
918     * @port: Port number.
919     *
920     * Returns 0 on success, negative value otherwise.
921     */
922     int ccs_check_network_recvmsg_acl(const _Bool is_ipv6, const int sock_type,
923     const u8 *address, const u16 port)
924 kumaneko 111 {
925 kumaneko 708 int retval;
926 kumaneko 1052 const u8 operation
927     = sock_type == SOCK_DGRAM ?
928     NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;
929 kumaneko 708 current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
930 kumaneko 1052 retval = check_network_entry(is_ipv6, operation, (const u32 *) address,
931     ntohs(port));
932 kumaneko 708 current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
933     return retval;
934 kumaneko 111 }

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