1 #include <netinet/in.h>
2 #include <stdlib.h>
3 #include <inttypes.h>
4
5 #include "debug.h"
6 #include "context.h"
7 #include "handle.h"
8
9 #include <sepol/ibpkey_record.h>
10 #include <sepol/policydb/policydb.h>
11 #include "ibpkey_internal.h"
12
13 /* Create a low level ibpkey structure from
14 * a high level representation
15 */
ibpkey_from_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t ** ibpkey,const sepol_ibpkey_t * data)16 static int ibpkey_from_record(sepol_handle_t *handle,
17 const policydb_t *policydb,
18 ocontext_t **ibpkey, const sepol_ibpkey_t *data)
19 {
20 ocontext_t *tmp_ibpkey = NULL;
21 context_struct_t *tmp_con = NULL;
22 char *subnet_prefix_buf = NULL;
23 int low = sepol_ibpkey_get_low(data);
24 int high = sepol_ibpkey_get_high(data);
25
26 tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey));
27 if (!tmp_ibpkey)
28 goto omem;
29
30 tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data);
31
32 /* Pkey range */
33 tmp_ibpkey->u.ibpkey.low_pkey = low;
34 tmp_ibpkey->u.ibpkey.high_pkey = high;
35 if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) {
36 ERR(handle, "low ibpkey %d exceeds high ibpkey %d",
37 tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey);
38 goto err;
39 }
40
41 /* Context */
42 if (context_from_record(handle, policydb, &tmp_con,
43 sepol_ibpkey_get_con(data)) < 0)
44 goto err;
45 context_cpy(&tmp_ibpkey->context[0], tmp_con);
46 context_destroy(tmp_con);
47 free(tmp_con);
48 tmp_con = NULL;
49
50 *ibpkey = tmp_ibpkey;
51 return STATUS_SUCCESS;
52
53 omem:
54 ERR(handle, "out of memory");
55
56 err:
57 if (tmp_ibpkey) {
58 context_destroy(&tmp_ibpkey->context[0]);
59 free(tmp_ibpkey);
60 }
61 context_destroy(tmp_con);
62 free(tmp_con);
63 free(subnet_prefix_buf);
64 ERR(handle, "could not create ibpkey structure");
65 return STATUS_ERR;
66 }
67
ibpkey_to_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t * ibpkey,sepol_ibpkey_t ** record)68 static int ibpkey_to_record(sepol_handle_t *handle,
69 const policydb_t *policydb,
70 ocontext_t *ibpkey, sepol_ibpkey_t **record)
71 {
72 context_struct_t *con = &ibpkey->context[0];
73 sepol_context_t *tmp_con = NULL;
74 sepol_ibpkey_t *tmp_record = NULL;
75
76 if (sepol_ibpkey_create(handle, &tmp_record) < 0)
77 goto err;
78
79 sepol_ibpkey_set_subnet_prefix_bytes(tmp_record,
80 ibpkey->u.ibpkey.subnet_prefix);
81
82 sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey,
83 ibpkey->u.ibpkey.high_pkey);
84
85 if (context_to_record(handle, policydb, con, &tmp_con) < 0)
86 goto err;
87
88 if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0)
89 goto err;
90
91 sepol_context_free(tmp_con);
92 *record = tmp_record;
93 return STATUS_SUCCESS;
94
95 err:
96 ERR(handle, "could not convert ibpkey to record");
97 sepol_context_free(tmp_con);
98 sepol_ibpkey_free(tmp_record);
99 return STATUS_ERR;
100 }
101
102 /* Return the number of ibpkeys */
sepol_ibpkey_count(sepol_handle_t * handle,const sepol_policydb_t * p,unsigned int * response)103 extern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)),
104 const sepol_policydb_t *p, unsigned int *response)
105 {
106 unsigned int count = 0;
107 ocontext_t *c, *head;
108 const policydb_t *policydb = &p->p;
109
110 head = policydb->ocontexts[OCON_IBPKEY];
111 for (c = head; c; c = c->next)
112 count++;
113
114 *response = count;
115
116 return STATUS_SUCCESS;
117 }
118
119 /* Check if a ibpkey exists */
sepol_ibpkey_exists(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_ibpkey_key_t * key,int * response)120 int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)),
121 const sepol_policydb_t *p,
122 const sepol_ibpkey_key_t *key, int *response)
123 {
124 const policydb_t *policydb = &p->p;
125 ocontext_t *c, *head;
126 int low, high;
127 uint64_t subnet_prefix;
128
129 sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
130
131 head = policydb->ocontexts[OCON_IBPKEY];
132 for (c = head; c; c = c->next) {
133 uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
134 uint16_t low2 = c->u.ibpkey.low_pkey;
135 uint16_t high2 = c->u.ibpkey.high_pkey;
136
137 if (low2 == low &&
138 high2 == high &&
139 subnet_prefix == subnet_prefix2) {
140 *response = 1;
141 return STATUS_SUCCESS;
142 }
143 }
144
145 *response = 0;
146 return STATUS_SUCCESS;
147 }
148
149 /* Query a ibpkey */
sepol_ibpkey_query(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_ibpkey_key_t * key,sepol_ibpkey_t ** response)150 int sepol_ibpkey_query(sepol_handle_t *handle,
151 const sepol_policydb_t *p,
152 const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response)
153 {
154 const policydb_t *policydb = &p->p;
155 ocontext_t *c, *head;
156 int low, high;
157 uint64_t subnet_prefix;
158
159 sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
160
161 head = policydb->ocontexts[OCON_IBPKEY];
162 for (c = head; c; c = c->next) {
163 uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
164 int low2 = c->u.ibpkey.low_pkey;
165 int high2 = c->u.ibpkey.high_pkey;
166
167 if (low2 == low &&
168 high2 == high &&
169 subnet_prefix == subnet_prefix2) {
170 if (ibpkey_to_record(handle, policydb, c, response) < 0)
171 goto err;
172 return STATUS_SUCCESS;
173 }
174 }
175
176 *response = NULL;
177 return STATUS_SUCCESS;
178
179 err:
180 ERR(handle, "could not query ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists",
181 subnet_prefix, low, high);
182 return STATUS_ERR;
183 }
184
185 /* Load a ibpkey into policy */
sepol_ibpkey_modify(sepol_handle_t * handle,sepol_policydb_t * p,const sepol_ibpkey_key_t * key,const sepol_ibpkey_t * data)186 int sepol_ibpkey_modify(sepol_handle_t *handle,
187 sepol_policydb_t *p,
188 const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data)
189 {
190 policydb_t *policydb = &p->p;
191 ocontext_t *ibpkey = NULL;
192 int low, high;
193 uint64_t subnet_prefix;
194
195 sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
196
197 if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0)
198 goto err;
199
200 /* Attach to context list */
201 ibpkey->next = policydb->ocontexts[OCON_IBPKEY];
202 policydb->ocontexts[OCON_IBPKEY] = ibpkey;
203
204 return STATUS_SUCCESS;
205
206 err:
207 ERR(handle, "could not load ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists",
208 subnet_prefix, low, high);
209 if (ibpkey) {
210 context_destroy(&ibpkey->context[0]);
211 free(ibpkey);
212 }
213 return STATUS_ERR;
214 }
215
sepol_ibpkey_iterate(sepol_handle_t * handle,const sepol_policydb_t * p,int (* fn)(const sepol_ibpkey_t * ibpkey,void * fn_arg),void * arg)216 int sepol_ibpkey_iterate(sepol_handle_t *handle,
217 const sepol_policydb_t *p,
218 int (*fn)(const sepol_ibpkey_t *ibpkey,
219 void *fn_arg), void *arg)
220 {
221 const policydb_t *policydb = &p->p;
222 ocontext_t *c, *head;
223 sepol_ibpkey_t *ibpkey = NULL;
224
225 head = policydb->ocontexts[OCON_IBPKEY];
226 for (c = head; c; c = c->next) {
227 int status;
228
229 if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0)
230 goto err;
231
232 /* Invoke handler */
233 status = fn(ibpkey, arg);
234 if (status < 0)
235 goto err;
236
237 sepol_ibpkey_free(ibpkey);
238 ibpkey = NULL;
239
240 /* Handler requested exit */
241 if (status > 0)
242 break;
243 }
244
245 return STATUS_SUCCESS;
246
247 err:
248 ERR(handle, "could not iterate over ibpkeys");
249 sepol_ibpkey_free(ibpkey);
250 return STATUS_ERR;
251 }
252