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 */
iface_from_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t ** iface,const sepol_iface_t * record)12 static 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
iface_to_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t * iface,sepol_iface_t ** record)66 static 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 */
sepol_iface_exists(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_iface_key_t * key,int * response)109 int 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 */
sepol_iface_query(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_iface_key_t * key,sepol_iface_t ** response)134 int 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 */
sepol_iface_modify(sepol_handle_t * handle,sepol_policydb_t * p,const sepol_iface_key_t * key,const sepol_iface_t * data)165 int 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 */
sepol_iface_count(sepol_handle_t * handle,const sepol_policydb_t * p,unsigned int * response)219 extern 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
sepol_iface_iterate(sepol_handle_t * handle,const sepol_policydb_t * p,int (* fn)(const sepol_iface_t * iface,void * fn_arg),void * arg)237 int 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