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