• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdlib.h>
2 #include <string.h>
3 #include <netinet/in.h>
4 #include <arpa/inet.h>
5 #include <errno.h>
6 #include <sepol/ibpkey_record.h>
7 
8 #include "ibpkey_internal.h"
9 #include "context_internal.h"
10 #include "debug.h"
11 
12 struct sepol_ibpkey {
13 	/* Subnet prefix */
14 	uint64_t subnet_prefix;
15 
16 	/* Low - High range. Same for single ibpkeys. */
17 	int low, high;
18 
19 	/* Context */
20 	sepol_context_t *con;
21 };
22 
23 struct sepol_ibpkey_key {
24 	/* Subnet prefix */
25 	uint64_t subnet_prefix;
26 
27 	/* Low - High range. Same for single ibpkeys. */
28 	int low, high;
29 };
30 
31 /* Converts a string represtation (subnet_prefix_str)
32  * to a numeric representation (subnet_prefix_bytes)
33  */
ibpkey_parse_subnet_prefix(sepol_handle_t * handle,const char * subnet_prefix_str,uint64_t * subnet_prefix)34 static int ibpkey_parse_subnet_prefix(sepol_handle_t *handle,
35 				      const char *subnet_prefix_str,
36 				      uint64_t *subnet_prefix)
37 {
38 	struct in6_addr in_addr;
39 
40 	if (inet_pton(AF_INET6, subnet_prefix_str, &in_addr) <= 0) {
41 		ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %s",
42 		    subnet_prefix_str, strerror(errno));
43 		return STATUS_ERR;
44 	}
45 
46 	memcpy(subnet_prefix, in_addr.s6_addr, sizeof(*subnet_prefix));
47 
48 	return STATUS_SUCCESS;
49 }
50 
51 /* Converts a numeric representation (subnet_prefix_bytes)
52  * to a string representation (subnet_prefix_str)
53  */
54 
ibpkey_expand_subnet_prefix(sepol_handle_t * handle,uint64_t subnet_prefix,char * subnet_prefix_str)55 static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle,
56 				       uint64_t subnet_prefix,
57 				       char *subnet_prefix_str)
58 {
59 	struct in6_addr addr;
60 
61 	memset(&addr, 0, sizeof(struct in6_addr));
62 	memcpy(&addr.s6_addr[0], &subnet_prefix, sizeof(subnet_prefix));
63 
64 	if (inet_ntop(AF_INET6, &addr, subnet_prefix_str,
65 		      INET6_ADDRSTRLEN) == NULL) {
66 		ERR(handle,
67 		    "could not expand IPv6 address to string: %s",
68 		    strerror(errno));
69 		return STATUS_ERR;
70 	}
71 
72 	return STATUS_SUCCESS;
73 }
74 
75 /* Allocates a sufficiently large string (subnet_prefix)
76  * for an IPV6 address for the subnet prefix
77  */
ibpkey_alloc_subnet_prefix_string(sepol_handle_t * handle,char ** subnet_prefix)78 static int ibpkey_alloc_subnet_prefix_string(sepol_handle_t *handle,
79 					     char **subnet_prefix)
80 {
81 	char *tmp_subnet_prefix = NULL;
82 
83 	tmp_subnet_prefix = malloc(INET6_ADDRSTRLEN);
84 
85 	if (!tmp_subnet_prefix)
86 		goto omem;
87 
88 	*subnet_prefix = tmp_subnet_prefix;
89 	return STATUS_SUCCESS;
90 
91 omem:
92 	ERR(handle, "out of memory");
93 
94 	ERR(handle, "could not allocate string buffer for subnet_prefix");
95 	return STATUS_ERR;
96 }
97 
98 /* Key */
sepol_ibpkey_key_create(sepol_handle_t * handle,const char * subnet_prefix,int low,int high,sepol_ibpkey_key_t ** key_ptr)99 int sepol_ibpkey_key_create(sepol_handle_t *handle,
100 			    const char *subnet_prefix,
101 			    int low, int high,
102 			    sepol_ibpkey_key_t **key_ptr)
103 {
104 	sepol_ibpkey_key_t *tmp_key =
105 	    (sepol_ibpkey_key_t *)malloc(sizeof(sepol_ibpkey_key_t));
106 
107 	if (!tmp_key) {
108 		ERR(handle, "out of memory, could not create ibpkey key");
109 		goto omem;
110 	}
111 
112 	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix, &tmp_key->subnet_prefix) < 0)
113 		goto err;
114 
115 	tmp_key->low = low;
116 	tmp_key->high = high;
117 
118 	*key_ptr = tmp_key;
119 	return STATUS_SUCCESS;
120 
121 omem:
122 	ERR(handle, "out of memory");
123 
124 err:
125 	sepol_ibpkey_key_free(tmp_key);
126 	ERR(handle, "could not create ibpkey key for subnet prefix%s, range %u, %u",
127 	    subnet_prefix, low, high);
128 	return STATUS_ERR;
129 }
130 
hidden_def(sepol_ibpkey_key_create)131 hidden_def(sepol_ibpkey_key_create)
132 
133 void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key,
134 			     uint64_t *subnet_prefix, int *low, int *high)
135 {
136 	*subnet_prefix = key->subnet_prefix;
137 	*low = key->low;
138 	*high = key->high;
139 }
140 
hidden_def(sepol_ibpkey_key_unpack)141 hidden_def(sepol_ibpkey_key_unpack)
142 
143 int sepol_ibpkey_key_extract(sepol_handle_t *handle,
144 			     const sepol_ibpkey_t *ibpkey,
145 			     sepol_ibpkey_key_t **key_ptr)
146 {
147 	char subnet_prefix_str[INET6_ADDRSTRLEN];
148 
149 	ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, subnet_prefix_str);
150 
151 	if (sepol_ibpkey_key_create
152 	    (handle, subnet_prefix_str, ibpkey->low, ibpkey->high, key_ptr) < 0) {
153 		ERR(handle, "could not extract key from ibpkey %s %d:%d",
154 		    subnet_prefix_str,
155 		    ibpkey->low, ibpkey->high);
156 
157 		return STATUS_ERR;
158 	}
159 
160 	return STATUS_SUCCESS;
161 }
162 
sepol_ibpkey_key_free(sepol_ibpkey_key_t * key)163 void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key)
164 {
165 	if (!key)
166 		return;
167 	free(key);
168 }
169 
sepol_ibpkey_compare(const sepol_ibpkey_t * ibpkey,const sepol_ibpkey_key_t * key)170 int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_key_t *key)
171 {
172 	if (ibpkey->subnet_prefix < key->subnet_prefix)
173 		return -1;
174 	if (key->subnet_prefix < ibpkey->subnet_prefix)
175 		return 1;
176 
177 	if (ibpkey->low < key->low)
178 		return -1;
179 	if (key->low < ibpkey->low)
180 		return 1;
181 
182 	if (ibpkey->high < key->high)
183 		return -1;
184 	if (key->high < ibpkey->high)
185 		return 1;
186 
187 	return 0;
188 }
189 
sepol_ibpkey_compare2(const sepol_ibpkey_t * ibpkey,const sepol_ibpkey_t * ibpkey2)190 int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_t *ibpkey2)
191 {
192 	if (ibpkey->subnet_prefix < ibpkey2->subnet_prefix)
193 		return -1;
194 	if (ibpkey2->subnet_prefix < ibpkey->subnet_prefix)
195 		return 1;
196 
197 	if (ibpkey->low < ibpkey2->low)
198 		return -1;
199 	if (ibpkey2->low < ibpkey->low)
200 		return 1;
201 
202 	if (ibpkey->high < ibpkey2->high)
203 		return -1;
204 	if (ibpkey2->high < ibpkey->high)
205 		return 1;
206 
207 	return 0;
208 }
209 
210 /* Pkey */
sepol_ibpkey_get_low(const sepol_ibpkey_t * ibpkey)211 int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey)
212 {
213 	return ibpkey->low;
214 }
215 
hidden_def(sepol_ibpkey_get_low)216 hidden_def(sepol_ibpkey_get_low)
217 
218 int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey)
219 {
220 	return ibpkey->high;
221 }
222 
hidden_def(sepol_ibpkey_get_high)223 hidden_def(sepol_ibpkey_get_high)
224 
225 void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num)
226 {
227 	ibpkey->low = pkey_num;
228 	ibpkey->high = pkey_num;
229 }
230 
sepol_ibpkey_set_range(sepol_ibpkey_t * ibpkey,int low,int high)231 void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high)
232 {
233 	ibpkey->low = low;
234 	ibpkey->high = high;
235 }
236 
hidden_def(sepol_ibpkey_set_range)237 hidden_def(sepol_ibpkey_set_range)
238 
239 int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle,
240 				   const sepol_ibpkey_t *ibpkey,
241 				   char **subnet_prefix)
242 {
243 	char *tmp_subnet_prefix = NULL;
244 
245 	if (ibpkey_alloc_subnet_prefix_string(handle, &tmp_subnet_prefix) < 0)
246 		goto err;
247 
248 	if (ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, tmp_subnet_prefix) < 0)
249 		goto err;
250 
251 	*subnet_prefix = tmp_subnet_prefix;
252 	return STATUS_SUCCESS;
253 
254 err:
255 	free(tmp_subnet_prefix);
256 	ERR(handle, "could not get ibpkey subnet_prefix");
257 	return STATUS_ERR;
258 }
259 
hidden_def(sepol_ibpkey_get_subnet_prefix)260 hidden_def(sepol_ibpkey_get_subnet_prefix)
261 
262 /* Subnet prefix */
263 uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey)
264 {
265 	return ibpkey->subnet_prefix;
266 }
267 
hidden_def(sepol_ibpkey_get_subnet_prefix_bytes)268 hidden_def(sepol_ibpkey_get_subnet_prefix_bytes)
269 
270 int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle,
271 				   sepol_ibpkey_t *ibpkey,
272 				   const char *subnet_prefix_str)
273 {
274 	uint64_t tmp = 0;
275 
276 	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix_str, &tmp) < 0)
277 		goto err;
278 
279 	ibpkey->subnet_prefix = tmp;
280 	return STATUS_SUCCESS;
281 
282 err:
283 	ERR(handle, "could not set ibpkey subnet prefix to %s", subnet_prefix_str);
284 	return STATUS_ERR;
285 }
286 
hidden_def(sepol_ibpkey_set_subnet_prefix)287 hidden_def(sepol_ibpkey_set_subnet_prefix)
288 
289 void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey,
290 					  uint64_t subnet_prefix)
291 {
292 	ibpkey->subnet_prefix = subnet_prefix;
293 }
294 
hidden_def(sepol_ibpkey_set_subnet_prefix_bytes)295 hidden_def(sepol_ibpkey_set_subnet_prefix_bytes)
296 
297 /* Create */
298 int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey)
299 {
300 	sepol_ibpkey_t *tmp_ibpkey = (sepol_ibpkey_t *)malloc(sizeof(sepol_ibpkey_t));
301 
302 	if (!tmp_ibpkey) {
303 		ERR(handle, "out of memory, could not create ibpkey record");
304 		return STATUS_ERR;
305 	}
306 
307 	tmp_ibpkey->subnet_prefix = 0;
308 	tmp_ibpkey->low = 0;
309 	tmp_ibpkey->high = 0;
310 	tmp_ibpkey->con = NULL;
311 	*ibpkey = tmp_ibpkey;
312 
313 	return STATUS_SUCCESS;
314 }
315 
hidden_def(sepol_ibpkey_create)316 hidden_def(sepol_ibpkey_create)
317 
318 /* Deep copy clone */
319 int sepol_ibpkey_clone(sepol_handle_t *handle,
320 		       const sepol_ibpkey_t *ibpkey, sepol_ibpkey_t **ibpkey_ptr)
321 {
322 	sepol_ibpkey_t *new_ibpkey = NULL;
323 
324 	if (sepol_ibpkey_create(handle, &new_ibpkey) < 0)
325 		goto err;
326 
327 	new_ibpkey->subnet_prefix = ibpkey->subnet_prefix;
328 	new_ibpkey->low = ibpkey->low;
329 	new_ibpkey->high = ibpkey->high;
330 
331 	if (ibpkey->con &&
332 	    (sepol_context_clone(handle, ibpkey->con, &new_ibpkey->con) < 0))
333 		goto err;
334 
335 	*ibpkey_ptr = new_ibpkey;
336 	return STATUS_SUCCESS;
337 
338 err:
339 	ERR(handle, "could not clone ibpkey record");
340 	sepol_ibpkey_free(new_ibpkey);
341 	return STATUS_ERR;
342 }
343 
344 /* Destroy */
sepol_ibpkey_free(sepol_ibpkey_t * ibpkey)345 void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey)
346 {
347 	if (!ibpkey)
348 		return;
349 
350 	sepol_context_free(ibpkey->con);
351 	free(ibpkey);
352 }
353 
hidden_def(sepol_ibpkey_free)354 hidden_def(sepol_ibpkey_free)
355 
356 /* Context */
357 sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey)
358 {
359 	return ibpkey->con;
360 }
361 
hidden_def(sepol_ibpkey_get_con)362 hidden_def(sepol_ibpkey_get_con)
363 
364 int sepol_ibpkey_set_con(sepol_handle_t *handle,
365 			 sepol_ibpkey_t *ibpkey, sepol_context_t *con)
366 {
367 	sepol_context_t *newcon;
368 
369 	if (sepol_context_clone(handle, con, &newcon) < 0) {
370 		ERR(handle, "out of memory, could not set ibpkey context");
371 		return STATUS_ERR;
372 	}
373 
374 	sepol_context_free(ibpkey->con);
375 	ibpkey->con = newcon;
376 	return STATUS_SUCCESS;
377 }
378 
379 hidden_def(sepol_ibpkey_set_con)
380