• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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