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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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