interfaces.c revision 255e72915d4cbddceb435e13d81601755714e9f3
1#include <stdlib.h>
2
3#include "debug.h"
4#include "context.h"
5#include "handle.h"
6
7#include <sepol/policydb/policydb.h>
8#include <sepol/interfaces.h>
9#include "iface_internal.h"
10
11/* Create a low level structure from record */
12static int iface_from_record(sepol_handle_t * handle,
13			     const policydb_t * policydb,
14			     ocontext_t ** iface, const sepol_iface_t * record)
15{
16
17	ocontext_t *tmp_iface = NULL;
18	context_struct_t *tmp_con = NULL;
19
20	tmp_iface = (ocontext_t *) calloc(1, sizeof(ocontext_t));
21	if (!tmp_iface)
22		goto omem;
23
24	/* Name */
25	tmp_iface->u.name = strdup(sepol_iface_get_name(record));
26	if (!tmp_iface->u.name)
27		goto omem;
28
29	/* Interface Context */
30	if (context_from_record(handle, policydb,
31				&tmp_con, sepol_iface_get_ifcon(record)) < 0)
32		goto err;
33	context_cpy(&tmp_iface->context[0], tmp_con);
34	context_destroy(tmp_con);
35	free(tmp_con);
36	tmp_con = NULL;
37
38	/* Message Context */
39	if (context_from_record(handle, policydb,
40				&tmp_con, sepol_iface_get_msgcon(record)) < 0)
41		goto err;
42	context_cpy(&tmp_iface->context[1], tmp_con);
43	context_destroy(tmp_con);
44	free(tmp_con);
45	tmp_con = NULL;
46
47	*iface = tmp_iface;
48	return STATUS_SUCCESS;
49
50      omem:
51	ERR(handle, "out of memory");
52
53      err:
54	if (tmp_iface != NULL) {
55		free(tmp_iface->u.name);
56		context_destroy(&tmp_iface->context[0]);
57		context_destroy(&tmp_iface->context[1]);
58		free(tmp_iface);
59	}
60	context_destroy(tmp_con);
61	free(tmp_con);
62	ERR(handle, "error creating interface structure");
63	return STATUS_ERR;
64}
65
66static int iface_to_record(sepol_handle_t * handle,
67			   const policydb_t * policydb,
68			   ocontext_t * iface, sepol_iface_t ** record)
69{
70
71	char *name = iface->u.name;
72	context_struct_t *ifcon = &iface->context[0];
73	context_struct_t *msgcon = &iface->context[1];
74
75	sepol_context_t *tmp_con = NULL;
76	sepol_iface_t *tmp_record = NULL;
77
78	if (sepol_iface_create(handle, &tmp_record) < 0)
79		goto err;
80
81	if (sepol_iface_set_name(handle, tmp_record, name) < 0)
82		goto err;
83
84	if (context_to_record(handle, policydb, ifcon, &tmp_con) < 0)
85		goto err;
86	if (sepol_iface_set_ifcon(handle, tmp_record, tmp_con) < 0)
87		goto err;
88	sepol_context_free(tmp_con);
89	tmp_con = NULL;
90
91	if (context_to_record(handle, policydb, msgcon, &tmp_con) < 0)
92		goto err;
93	if (sepol_iface_set_msgcon(handle, tmp_record, tmp_con) < 0)
94		goto err;
95	sepol_context_free(tmp_con);
96	tmp_con = NULL;
97
98	*record = tmp_record;
99	return STATUS_SUCCESS;
100
101      err:
102	ERR(handle, "could not convert interface %s to record", name);
103	sepol_context_free(tmp_con);
104	sepol_iface_free(tmp_record);
105	return STATUS_ERR;
106}
107
108/* Check if an interface exists */
109int sepol_iface_exists(sepol_handle_t * handle __attribute__ ((unused)),
110		       const sepol_policydb_t * p,
111		       const sepol_iface_key_t * key, int *response)
112{
113
114	const policydb_t *policydb = &p->p;
115	ocontext_t *c, *head;
116
117	const char *name;
118	sepol_iface_key_unpack(key, &name);
119
120	head = policydb->ocontexts[OCON_NETIF];
121	for (c = head; c; c = c->next) {
122		if (!strcmp(name, c->u.name)) {
123			*response = 1;
124			return STATUS_SUCCESS;
125		}
126	}
127	*response = 0;
128
129	handle = NULL;
130	return STATUS_SUCCESS;
131}
132
133/* Query an interface */
134int sepol_iface_query(sepol_handle_t * handle,
135		      const sepol_policydb_t * p,
136		      const sepol_iface_key_t * key, sepol_iface_t ** response)
137{
138
139	const policydb_t *policydb = &p->p;
140	ocontext_t *c, *head;
141
142	const char *name;
143	sepol_iface_key_unpack(key, &name);
144
145	head = policydb->ocontexts[OCON_NETIF];
146	for (c = head; c; c = c->next) {
147		if (!strcmp(name, c->u.name)) {
148
149			if (iface_to_record(handle, policydb, c, response) < 0)
150				goto err;
151
152			return STATUS_SUCCESS;
153		}
154	}
155
156	*response = NULL;
157	return STATUS_SUCCESS;
158
159      err:
160	ERR(handle, "could not query interface %s", name);
161	return STATUS_ERR;
162}
163
164/* Load an interface into policy */
165int sepol_iface_modify(sepol_handle_t * handle,
166		       sepol_policydb_t * p,
167		       const sepol_iface_key_t * key,
168		       const sepol_iface_t * data)
169{
170
171	policydb_t *policydb = &p->p;
172	ocontext_t *head, *prev, *c, *iface = NULL;
173
174	const char *name;
175	sepol_iface_key_unpack(key, &name);
176
177	if (iface_from_record(handle, policydb, &iface, data) < 0)
178		goto err;
179
180	prev = NULL;
181	head = policydb->ocontexts[OCON_NETIF];
182	for (c = head; c; c = c->next) {
183		if (!strcmp(name, c->u.name)) {
184
185			/* Replace */
186			iface->next = c->next;
187			if (prev == NULL)
188				policydb->ocontexts[OCON_NETIF] = iface;
189			else
190				prev->next = iface;
191			free(c->u.name);
192			context_destroy(&c->context[0]);
193			context_destroy(&c->context[1]);
194			free(c);
195
196			return STATUS_SUCCESS;
197		}
198		prev = c;
199	}
200
201	/* Attach to context list */
202	iface->next = policydb->ocontexts[OCON_NETIF];
203	policydb->ocontexts[OCON_NETIF] = iface;
204	return STATUS_SUCCESS;
205
206      err:
207	ERR(handle, "error while loading interface %s", name);
208
209	if (iface != NULL) {
210		free(iface->u.name);
211		context_destroy(&iface->context[0]);
212		context_destroy(&iface->context[1]);
213		free(iface);
214	}
215	return STATUS_ERR;
216}
217
218/* Return the number of interfaces */
219extern int sepol_iface_count(sepol_handle_t * handle __attribute__ ((unused)),
220			     const sepol_policydb_t * p, unsigned int *response)
221{
222
223	unsigned int count = 0;
224	ocontext_t *c, *head;
225	const policydb_t *policydb = &p->p;
226
227	head = policydb->ocontexts[OCON_NETIF];
228	for (c = head; c != NULL; c = c->next)
229		count++;
230
231	*response = count;
232
233	handle = NULL;
234	return STATUS_SUCCESS;
235}
236
237int sepol_iface_iterate(sepol_handle_t * handle,
238			const sepol_policydb_t * p,
239			int (*fn) (const sepol_iface_t * iface,
240				   void *fn_arg), void *arg)
241{
242
243	const policydb_t *policydb = &p->p;
244	ocontext_t *c, *head;
245	sepol_iface_t *iface = NULL;
246
247	head = policydb->ocontexts[OCON_NETIF];
248	for (c = head; c; c = c->next) {
249		int status;
250
251		if (iface_to_record(handle, policydb, c, &iface) < 0)
252			goto err;
253
254		/* Invoke handler */
255		status = fn(iface, arg);
256		if (status < 0)
257			goto err;
258
259		sepol_iface_free(iface);
260		iface = NULL;
261
262		/* Handler requested exit */
263		if (status > 0)
264			break;
265	}
266
267	return STATUS_SUCCESS;
268
269      err:
270	ERR(handle, "could not iterate over interfaces");
271	sepol_iface_free(iface);
272	return STATUS_ERR;
273}
274