1 #include <netinet/in.h>
2 #include <arpa/inet.h>
3 #include <stdlib.h>
4
5 #include "debug.h"
6 #include "context.h"
7 #include "handle.h"
8
9 #include <sepol/policydb/policydb.h>
10 #include "node_internal.h"
11
12 /* Create a low level node structure from
13 * a high level representation */
node_from_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t ** node,const sepol_node_t * data)14 static int node_from_record(sepol_handle_t * handle,
15 const policydb_t * policydb,
16 ocontext_t ** node, const sepol_node_t * data)
17 {
18
19 ocontext_t *tmp_node = NULL;
20 context_struct_t *tmp_con = NULL;
21 char *addr_buf = NULL, *mask_buf = NULL;
22 size_t addr_bsize, mask_bsize;
23 int proto;
24
25 tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t));
26 if (!tmp_node)
27 goto omem;
28
29 /* Address and netmask */
30 if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0)
31 goto err;
32 if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0)
33 goto err;
34
35 proto = sepol_node_get_proto(data);
36
37 switch (proto) {
38 case SEPOL_PROTO_IP4:
39 memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize);
40 memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize);
41 break;
42 case SEPOL_PROTO_IP6:
43 memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize);
44 memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize);
45 break;
46 default:
47 ERR(handle, "unsupported protocol %u", proto);
48 goto err;
49 }
50 free(addr_buf);
51 free(mask_buf);
52 addr_buf = NULL;
53 mask_buf = NULL;
54
55 /* Context */
56 if (context_from_record(handle, policydb, &tmp_con,
57 sepol_node_get_con(data)) < 0)
58 goto err;
59 context_cpy(&tmp_node->context[0], tmp_con);
60 context_destroy(tmp_con);
61 free(tmp_con);
62 tmp_con = NULL;
63
64 *node = tmp_node;
65 return STATUS_SUCCESS;
66
67 omem:
68 ERR(handle, "out of memory");
69
70 err:
71 if (tmp_node != NULL) {
72 context_destroy(&tmp_node->context[0]);
73 free(tmp_node);
74 }
75 context_destroy(tmp_con);
76 free(tmp_con);
77 free(addr_buf);
78 free(mask_buf);
79 ERR(handle, "could not create node structure");
80 return STATUS_ERR;
81 }
82
node_to_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t * node,int proto,sepol_node_t ** record)83 static int node_to_record(sepol_handle_t * handle,
84 const policydb_t * policydb,
85 ocontext_t * node, int proto, sepol_node_t ** record)
86 {
87
88 context_struct_t *con = &node->context[0];
89
90 sepol_context_t *tmp_con = NULL;
91 sepol_node_t *tmp_record = NULL;
92
93 if (sepol_node_create(handle, &tmp_record) < 0)
94 goto err;
95
96 sepol_node_set_proto(tmp_record, proto);
97
98 switch (proto) {
99
100 case SEPOL_PROTO_IP4:
101 if (sepol_node_set_addr_bytes(handle, tmp_record,
102 (const char *)&node->u.node.addr,
103 4) < 0)
104 goto err;
105
106 if (sepol_node_set_mask_bytes(handle, tmp_record,
107 (const char *)&node->u.node.mask,
108 4) < 0)
109 goto err;
110 break;
111
112 case SEPOL_PROTO_IP6:
113 if (sepol_node_set_addr_bytes(handle, tmp_record,
114 (const char *)&node->u.node6.addr,
115 16) < 0)
116 goto err;
117
118 if (sepol_node_set_mask_bytes(handle, tmp_record,
119 (const char *)&node->u.node6.mask,
120 16) < 0)
121 goto err;
122 break;
123
124 default:
125 ERR(handle, "unsupported protocol %u", proto);
126 goto err;
127 }
128
129 if (context_to_record(handle, policydb, con, &tmp_con) < 0)
130 goto err;
131
132 if (sepol_node_set_con(handle, tmp_record, tmp_con) < 0)
133 goto err;
134
135 sepol_context_free(tmp_con);
136 *record = tmp_record;
137 return STATUS_SUCCESS;
138
139 err:
140 ERR(handle, "could not convert node to record");
141 sepol_context_free(tmp_con);
142 sepol_node_free(tmp_record);
143 return STATUS_ERR;
144 }
145
146 /* Return the number of nodes */
sepol_node_count(sepol_handle_t * handle,const sepol_policydb_t * p,unsigned int * response)147 extern int sepol_node_count(sepol_handle_t * handle __attribute__ ((unused)),
148 const sepol_policydb_t * p, unsigned int *response)
149 {
150
151 unsigned int count = 0;
152 ocontext_t *c, *head;
153 const policydb_t *policydb = &p->p;
154
155 head = policydb->ocontexts[OCON_NODE];
156 for (c = head; c != NULL; c = c->next)
157 count++;
158
159 head = policydb->ocontexts[OCON_NODE6];
160 for (c = head; c != NULL; c = c->next)
161 count++;
162
163 *response = count;
164
165 return STATUS_SUCCESS;
166 }
167
168 /* Check if a node exists */
sepol_node_exists(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_node_key_t * key,int * response)169 int sepol_node_exists(sepol_handle_t * handle,
170 const sepol_policydb_t * p,
171 const sepol_node_key_t * key, int *response)
172 {
173
174 const policydb_t *policydb = &p->p;
175 ocontext_t *c, *head;
176
177 int proto;
178 const char *addr, *mask;
179 sepol_node_key_unpack(key, &addr, &mask, &proto);
180
181 switch (proto) {
182
183 case SEPOL_PROTO_IP4:
184 {
185 head = policydb->ocontexts[OCON_NODE];
186 for (c = head; c; c = c->next) {
187 unsigned int *addr2 = &c->u.node.addr;
188 unsigned int *mask2 = &c->u.node.mask;
189
190 if (!memcmp(addr, addr2, 4) &&
191 !memcmp(mask, mask2, 4)) {
192
193 *response = 1;
194 return STATUS_SUCCESS;
195 }
196 }
197 break;
198 }
199 case SEPOL_PROTO_IP6:
200 {
201 head = policydb->ocontexts[OCON_NODE6];
202 for (c = head; c; c = c->next) {
203 unsigned int *addr2 = c->u.node6.addr;
204 unsigned int *mask2 = c->u.node6.mask;
205
206 if (!memcmp(addr, addr2, 16) &&
207 !memcmp(mask, mask2, 16)) {
208 *response = 1;
209 return STATUS_SUCCESS;
210 }
211 }
212 break;
213 }
214 default:
215 ERR(handle, "unsupported protocol %u", proto);
216 goto err;
217 }
218
219 *response = 0;
220 return STATUS_SUCCESS;
221
222 err:
223 ERR(handle, "could not check if node %s/%s (%s) exists",
224 addr, mask, sepol_node_get_proto_str(proto));
225 return STATUS_ERR;
226 }
227
228 /* Query a node */
sepol_node_query(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_node_key_t * key,sepol_node_t ** response)229 int sepol_node_query(sepol_handle_t * handle,
230 const sepol_policydb_t * p,
231 const sepol_node_key_t * key, sepol_node_t ** response)
232 {
233
234 const policydb_t *policydb = &p->p;
235 ocontext_t *c, *head;
236
237 int proto;
238 const char *addr, *mask;
239 sepol_node_key_unpack(key, &addr, &mask, &proto);
240
241 switch (proto) {
242
243 case SEPOL_PROTO_IP4:
244 {
245 head = policydb->ocontexts[OCON_NODE];
246 for (c = head; c; c = c->next) {
247 unsigned int *addr2 = &c->u.node.addr;
248 unsigned int *mask2 = &c->u.node.mask;
249
250 if (!memcmp(addr, addr2, 4) &&
251 !memcmp(mask, mask2, 4)) {
252
253 if (node_to_record(handle, policydb,
254 c, SEPOL_PROTO_IP4,
255 response) < 0)
256 goto err;
257 return STATUS_SUCCESS;
258 }
259 }
260 break;
261 }
262 case SEPOL_PROTO_IP6:
263 {
264 head = policydb->ocontexts[OCON_NODE6];
265 for (c = head; c; c = c->next) {
266 unsigned int *addr2 = c->u.node6.addr;
267 unsigned int *mask2 = c->u.node6.mask;
268
269 if (!memcmp(addr, addr2, 16) &&
270 !memcmp(mask, mask2, 16)) {
271
272 if (node_to_record(handle, policydb,
273 c, SEPOL_PROTO_IP6,
274 response) < 0)
275 goto err;
276 return STATUS_SUCCESS;
277 }
278 }
279 break;
280 }
281 default:
282 ERR(handle, "unsupported protocol %u", proto);
283 goto err;
284 }
285 *response = NULL;
286 return STATUS_SUCCESS;
287
288 err:
289 ERR(handle, "could not query node %s/%s (%s)",
290 addr, mask, sepol_node_get_proto_str(proto));
291 return STATUS_ERR;
292
293 }
294
295 /* Load a node into policy */
sepol_node_modify(sepol_handle_t * handle,sepol_policydb_t * p,const sepol_node_key_t * key,const sepol_node_t * data)296 int sepol_node_modify(sepol_handle_t * handle,
297 sepol_policydb_t * p,
298 const sepol_node_key_t * key, const sepol_node_t * data)
299 {
300
301 policydb_t *policydb = &p->p;
302 ocontext_t *node = NULL;
303
304 int proto;
305 const char *addr, *mask;
306
307 sepol_node_key_unpack(key, &addr, &mask, &proto);
308
309 if (node_from_record(handle, policydb, &node, data) < 0)
310 goto err;
311
312 switch (proto) {
313
314 case SEPOL_PROTO_IP4:
315 {
316 /* Attach to context list */
317 node->next = policydb->ocontexts[OCON_NODE];
318 policydb->ocontexts[OCON_NODE] = node;
319 break;
320 }
321 case SEPOL_PROTO_IP6:
322 {
323 /* Attach to context list */
324 node->next = policydb->ocontexts[OCON_NODE6];
325 policydb->ocontexts[OCON_NODE6] = node;
326 break;
327 }
328 default:
329 ERR(handle, "unsupported protocol %u", proto);
330 goto err;
331 }
332
333 return STATUS_SUCCESS;
334
335 err:
336 ERR(handle, "could not load node %s/%s (%s)",
337 addr, mask, sepol_node_get_proto_str(proto));
338 if (node != NULL) {
339 context_destroy(&node->context[0]);
340 free(node);
341 }
342 return STATUS_ERR;
343 }
344
sepol_node_iterate(sepol_handle_t * handle,const sepol_policydb_t * p,int (* fn)(const sepol_node_t * node,void * fn_arg),void * arg)345 int sepol_node_iterate(sepol_handle_t * handle,
346 const sepol_policydb_t * p,
347 int (*fn) (const sepol_node_t * node,
348 void *fn_arg), void *arg)
349 {
350
351 const policydb_t *policydb = &p->p;
352 ocontext_t *c, *head;
353 sepol_node_t *node = NULL;
354 int status;
355
356 head = policydb->ocontexts[OCON_NODE];
357 for (c = head; c; c = c->next) {
358 if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node)
359 < 0)
360 goto err;
361
362 /* Invoke handler */
363 status = fn(node, arg);
364 if (status < 0)
365 goto err;
366
367 sepol_node_free(node);
368 node = NULL;
369
370 /* Handler requested exit */
371 if (status > 0)
372 break;
373 }
374
375 head = policydb->ocontexts[OCON_NODE6];
376 for (c = head; c; c = c->next) {
377 if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node)
378 < 0)
379 goto err;
380
381 /* Invoke handler */
382 status = fn(node, arg);
383 if (status < 0)
384 goto err;
385
386 sepol_node_free(node);
387 node = NULL;
388
389 /* Handler requested exit */
390 if (status > 0)
391 break;
392 }
393
394 return STATUS_SUCCESS;
395
396 err:
397 ERR(handle, "could not iterate over nodes");
398 sepol_node_free(node);
399 return STATUS_ERR;
400 }
401