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

Subversion リポジトリの参照

Contents of /trunk/1.8.x/ccs-patch/security/ccsecurity/group.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3935 - (show annotations) (download) (as text)
Wed Sep 1 14:07:02 2010 UTC (13 years, 8 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 5947 byte(s)


1 /*
2 * security/ccsecurity/group.c
3 *
4 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 *
6 * Version: 1.8.0-pre 2010/09/01
7 *
8 * This file is applicable to both 2.4.30 and 2.6.11 and later.
9 * See README.ccs for ChangeLog.
10 *
11 */
12
13 #include "internal.h"
14
15 static bool ccs_same_path_group(const struct ccs_acl_head *a,
16 const struct ccs_acl_head *b)
17 {
18 return container_of(a, struct ccs_path_group, head)->member_name ==
19 container_of(b, struct ccs_path_group, head)->member_name;
20 }
21
22 static bool ccs_same_number_group(const struct ccs_acl_head *a,
23 const struct ccs_acl_head *b)
24 {
25 return !memcmp(&container_of(a, struct ccs_number_group, head)->number,
26 &container_of(b, struct ccs_number_group, head)->number,
27 sizeof(container_of(a, struct ccs_number_group, head)
28 ->number));
29 }
30
31 static bool ccs_same_address_group(const struct ccs_acl_head *a,
32 const struct ccs_acl_head *b)
33 {
34 const struct ccs_address_group *p1 = container_of(a, typeof(*p1),
35 head);
36 const struct ccs_address_group *p2 = container_of(b, typeof(*p2),
37 head);
38 return p1->is_ipv6 == p2->is_ipv6 &&
39 p1->min.ipv4 == p2->min.ipv4 && p1->min.ipv6 == p2->min.ipv6 &&
40 p1->max.ipv4 == p2->max.ipv4 && p1->max.ipv6 == p2->max.ipv6;
41 }
42
43 /**
44 * ccs_write_group - Write "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
45 *
46 * @data: String to parse.
47 * @is_delete: True if it is a delete request.
48 * @type: Type of this group.
49 *
50 * Returns 0 on success, negative value otherwise.
51 */
52 int ccs_write_group(char *data, const bool is_delete, const u8 type)
53 {
54 struct ccs_group *group;
55 struct list_head *member;
56 char *w[2];
57 int error = -EINVAL;
58 if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])
59 return -EINVAL;
60 group = ccs_get_group(w[0], type);
61 if (!group)
62 return -ENOMEM;
63 member = &group->member_list;
64 if (type == CCS_PATH_GROUP) {
65 struct ccs_path_group e = { };
66 e.member_name = ccs_get_name(w[1]);
67 if (!e.member_name) {
68 error = -ENOMEM;
69 goto out;
70 }
71 error = ccs_update_policy(&e.head, sizeof(e), is_delete,
72 member, ccs_same_path_group);
73 ccs_put_name(e.member_name);
74 } else if (type == CCS_NUMBER_GROUP) {
75 struct ccs_number_group e = { };
76 if (w[1][0] == '@' || !ccs_parse_number_union(w[1], &e.number)
77 || e.number.values[0] > e.number.values[1])
78 goto out;
79 error = ccs_update_policy(&e.head, sizeof(e), is_delete,
80 member, ccs_same_number_group);
81 /*
82 * ccs_put_number_union() is not needed because w[1][0] != '@'.
83 */
84 } else {
85 struct ccs_address_group e = { };
86 u16 min_address[8];
87 u16 max_address[8];
88 switch (ccs_parse_ip_address(w[1], min_address, max_address)) {
89 case CCS_IP_ADDRESS_TYPE_IPv6:
90 e.is_ipv6 = true;
91 e.min.ipv6 = ccs_get_ipv6_address((struct in6_addr *)
92 min_address);
93 e.max.ipv6 = ccs_get_ipv6_address((struct in6_addr *)
94 max_address);
95 if (!e.min.ipv6 || !e.max.ipv6)
96 goto out_address;
97 break;
98 case CCS_IP_ADDRESS_TYPE_IPv4:
99 e.min.ipv4 = ntohl(*(u32 *) min_address);
100 e.max.ipv4 = ntohl(*(u32 *) max_address);
101 break;
102 default:
103 goto out_address;
104 }
105 error = ccs_update_policy(&e.head, sizeof(e), is_delete,
106 member, ccs_same_address_group);
107 out_address:
108 if (e.is_ipv6) {
109 ccs_put_ipv6_address(e.min.ipv6);
110 ccs_put_ipv6_address(e.max.ipv6);
111 }
112 }
113 out:
114 ccs_put_group(group);
115 return error;
116 }
117
118 /**
119 * ccs_path_matches_group - Check whether the given pathname matches members of the given pathname group.
120 *
121 * @pathname: The name of pathname.
122 * @group: Pointer to "struct ccs_path_group".
123 *
124 * Returns matched member's pathname if @pathname matches pathnames in @group,
125 * NULL otherwise.
126 *
127 * Caller holds ccs_read_lock().
128 */
129 const struct ccs_path_info *
130 ccs_path_matches_group(const struct ccs_path_info *pathname,
131 const struct ccs_group *group)
132 {
133 struct ccs_path_group *member;
134 list_for_each_entry_rcu(member, &group->member_list, head.list) {
135 if (member->head.is_deleted)
136 continue;
137 if (!ccs_path_matches_pattern(pathname, member->member_name))
138 continue;
139 return member->member_name;
140 }
141 return NULL;
142 }
143
144 /**
145 * ccs_number_matches_group - Check whether the given number matches members of the given number group.
146 *
147 * @min: Min number.
148 * @max: Max number.
149 * @group: Pointer to "struct ccs_number_group".
150 *
151 * Returns true if @min and @max partially overlaps @group, false otherwise.
152 *
153 * Caller holds ccs_read_lock().
154 */
155 bool ccs_number_matches_group(const unsigned long min, const unsigned long max,
156 const struct ccs_group *group)
157 {
158 struct ccs_number_group *member;
159 bool matched = false;
160 list_for_each_entry_rcu(member, &group->member_list, head.list) {
161 if (member->head.is_deleted)
162 continue;
163 if (min > member->number.values[1] ||
164 max < member->number.values[0])
165 continue;
166 matched = true;
167 break;
168 }
169 return matched;
170 }
171
172 /**
173 * ccs_address_matches_group - Check whether the given address matches members of the given address group.
174 *
175 * @is_ipv6: True if @address is an IPv6 address.
176 * @address: An IPv4 or IPv6 address.
177 * @group: Pointer to "struct ccs_address_group".
178 *
179 * Returns true if @address matches addresses in @group group, false otherwise.
180 *
181 * Caller holds ccs_read_lock().
182 */
183 bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
184 const struct ccs_group *group)
185 {
186 struct ccs_address_group *member;
187 const u32 ip = ntohl(*address);
188 bool matched = false;
189 list_for_each_entry_rcu(member, &group->member_list, head.list) {
190 if (member->head.is_deleted)
191 continue;
192 if (member->is_ipv6) {
193 if (is_ipv6 &&
194 memcmp(member->min.ipv6, address, 16) <= 0 &&
195 memcmp(address, member->max.ipv6, 16) <= 0) {
196 matched = true;
197 break;
198 }
199 } else {
200 if (!is_ipv6 &&
201 member->min.ipv4 <= ip && ip <= member->max.ipv4) {
202 matched = true;
203 break;
204 }
205 }
206 }
207 return matched;
208 }

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