• 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: %m",
42 		    subnet_prefix_str);
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: %m");
68 		return STATUS_ERR;
69 	}
70 
71 	return STATUS_SUCCESS;
72 }
73 
74 /* Allocates a sufficiently large string (subnet_prefix)
75  * for an IPV6 address for the subnet prefix
76  */
ibpkey_alloc_subnet_prefix_string(sepol_handle_t * handle,char ** subnet_prefix)77 static int ibpkey_alloc_subnet_prefix_string(sepol_handle_t *handle,
78 					     char **subnet_prefix)
79 {
80 	char *tmp_subnet_prefix = NULL;
81 
82 	tmp_subnet_prefix = malloc(INET6_ADDRSTRLEN);
83 
84 	if (!tmp_subnet_prefix)
85 		goto omem;
86 
87 	*subnet_prefix = tmp_subnet_prefix;
88 	return STATUS_SUCCESS;
89 
90 omem:
91 	ERR(handle, "out of memory");
92 
93 	ERR(handle, "could not allocate string buffer for subnet_prefix");
94 	return STATUS_ERR;
95 }
96 
97 /* Key */
sepol_ibpkey_key_create(sepol_handle_t * handle,const char * subnet_prefix,int low,int high,sepol_ibpkey_key_t ** key_ptr)98 int sepol_ibpkey_key_create(sepol_handle_t *handle,
99 			    const char *subnet_prefix,
100 			    int low, int high,
101 			    sepol_ibpkey_key_t **key_ptr)
102 {
103 	sepol_ibpkey_key_t *tmp_key =
104 	    (sepol_ibpkey_key_t *)malloc(sizeof(sepol_ibpkey_key_t));
105 
106 	if (!tmp_key) {
107 		ERR(handle, "out of memory, could not create ibpkey key");
108 		goto omem;
109 	}
110 
111 	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix, &tmp_key->subnet_prefix) < 0)
112 		goto err;
113 
114 	tmp_key->low = low;
115 	tmp_key->high = high;
116 
117 	*key_ptr = tmp_key;
118 	return STATUS_SUCCESS;
119 
120 omem:
121 	ERR(handle, "out of memory");
122 
123 err:
124 	sepol_ibpkey_key_free(tmp_key);
125 	ERR(handle, "could not create ibpkey key for subnet prefix%s, range %u, %u",
126 	    subnet_prefix, low, high);
127 	return STATUS_ERR;
128 }
129 
130 
sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t * key,uint64_t * subnet_prefix,int * low,int * high)131 void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key,
132 			     uint64_t *subnet_prefix, int *low, int *high)
133 {
134 	*subnet_prefix = key->subnet_prefix;
135 	*low = key->low;
136 	*high = key->high;
137 }
138 
139 
sepol_ibpkey_key_extract(sepol_handle_t * handle,const sepol_ibpkey_t * ibpkey,sepol_ibpkey_key_t ** key_ptr)140 int sepol_ibpkey_key_extract(sepol_handle_t *handle,
141 			     const sepol_ibpkey_t *ibpkey,
142 			     sepol_ibpkey_key_t **key_ptr)
143 {
144 	char subnet_prefix_str[INET6_ADDRSTRLEN];
145 
146 	ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, subnet_prefix_str);
147 
148 	if (sepol_ibpkey_key_create
149 	    (handle, subnet_prefix_str, ibpkey->low, ibpkey->high, key_ptr) < 0) {
150 		ERR(handle, "could not extract key from ibpkey %s %d:%d",
151 		    subnet_prefix_str,
152 		    ibpkey->low, ibpkey->high);
153 
154 		return STATUS_ERR;
155 	}
156 
157 	return STATUS_SUCCESS;
158 }
159 
sepol_ibpkey_key_free(sepol_ibpkey_key_t * key)160 void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key)
161 {
162 	if (!key)
163 		return;
164 	free(key);
165 }
166 
sepol_ibpkey_compare(const sepol_ibpkey_t * ibpkey,const sepol_ibpkey_key_t * key)167 int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_key_t *key)
168 {
169 	if (ibpkey->subnet_prefix < key->subnet_prefix)
170 		return -1;
171 	if (key->subnet_prefix < ibpkey->subnet_prefix)
172 		return 1;
173 
174 	if (ibpkey->low < key->low)
175 		return -1;
176 	if (key->low < ibpkey->low)
177 		return 1;
178 
179 	if (ibpkey->high < key->high)
180 		return -1;
181 	if (key->high < ibpkey->high)
182 		return 1;
183 
184 	return 0;
185 }
186 
sepol_ibpkey_compare2(const sepol_ibpkey_t * ibpkey,const sepol_ibpkey_t * ibpkey2)187 int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_t *ibpkey2)
188 {
189 	if (ibpkey->subnet_prefix < ibpkey2->subnet_prefix)
190 		return -1;
191 	if (ibpkey2->subnet_prefix < ibpkey->subnet_prefix)
192 		return 1;
193 
194 	if (ibpkey->low < ibpkey2->low)
195 		return -1;
196 	if (ibpkey2->low < ibpkey->low)
197 		return 1;
198 
199 	if (ibpkey->high < ibpkey2->high)
200 		return -1;
201 	if (ibpkey2->high < ibpkey->high)
202 		return 1;
203 
204 	return 0;
205 }
206 
207 /* Pkey */
sepol_ibpkey_get_low(const sepol_ibpkey_t * ibpkey)208 int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey)
209 {
210 	return ibpkey->low;
211 }
212 
213 
sepol_ibpkey_get_high(const sepol_ibpkey_t * ibpkey)214 int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey)
215 {
216 	return ibpkey->high;
217 }
218 
219 
sepol_ibpkey_set_pkey(sepol_ibpkey_t * ibpkey,int pkey_num)220 void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num)
221 {
222 	ibpkey->low = pkey_num;
223 	ibpkey->high = pkey_num;
224 }
225 
sepol_ibpkey_set_range(sepol_ibpkey_t * ibpkey,int low,int high)226 void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high)
227 {
228 	ibpkey->low = low;
229 	ibpkey->high = high;
230 }
231 
232 
sepol_ibpkey_get_subnet_prefix(sepol_handle_t * handle,const sepol_ibpkey_t * ibpkey,char ** subnet_prefix)233 int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle,
234 				   const sepol_ibpkey_t *ibpkey,
235 				   char **subnet_prefix)
236 {
237 	char *tmp_subnet_prefix = NULL;
238 
239 	if (ibpkey_alloc_subnet_prefix_string(handle, &tmp_subnet_prefix) < 0)
240 		goto err;
241 
242 	if (ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, tmp_subnet_prefix) < 0)
243 		goto err;
244 
245 	*subnet_prefix = tmp_subnet_prefix;
246 	return STATUS_SUCCESS;
247 
248 err:
249 	free(tmp_subnet_prefix);
250 	ERR(handle, "could not get ibpkey subnet_prefix");
251 	return STATUS_ERR;
252 }
253 
254 
255 /* Subnet prefix */
sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t * ibpkey)256 uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey)
257 {
258 	return ibpkey->subnet_prefix;
259 }
260 
261 
sepol_ibpkey_set_subnet_prefix(sepol_handle_t * handle,sepol_ibpkey_t * ibpkey,const char * subnet_prefix_str)262 int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle,
263 				   sepol_ibpkey_t *ibpkey,
264 				   const char *subnet_prefix_str)
265 {
266 	uint64_t tmp = 0;
267 
268 	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix_str, &tmp) < 0)
269 		goto err;
270 
271 	ibpkey->subnet_prefix = tmp;
272 	return STATUS_SUCCESS;
273 
274 err:
275 	ERR(handle, "could not set ibpkey subnet prefix to %s", subnet_prefix_str);
276 	return STATUS_ERR;
277 }
278 
279 
sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t * ibpkey,uint64_t subnet_prefix)280 void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey,
281 					  uint64_t subnet_prefix)
282 {
283 	ibpkey->subnet_prefix = subnet_prefix;
284 }
285 
286 
287 /* Create */
sepol_ibpkey_create(sepol_handle_t * handle,sepol_ibpkey_t ** ibpkey)288 int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey)
289 {
290 	sepol_ibpkey_t *tmp_ibpkey = (sepol_ibpkey_t *)malloc(sizeof(sepol_ibpkey_t));
291 
292 	if (!tmp_ibpkey) {
293 		ERR(handle, "out of memory, could not create ibpkey record");
294 		return STATUS_ERR;
295 	}
296 
297 	tmp_ibpkey->subnet_prefix = 0;
298 	tmp_ibpkey->low = 0;
299 	tmp_ibpkey->high = 0;
300 	tmp_ibpkey->con = NULL;
301 	*ibpkey = tmp_ibpkey;
302 
303 	return STATUS_SUCCESS;
304 }
305 
306 
307 /* Deep copy clone */
sepol_ibpkey_clone(sepol_handle_t * handle,const sepol_ibpkey_t * ibpkey,sepol_ibpkey_t ** ibpkey_ptr)308 int sepol_ibpkey_clone(sepol_handle_t *handle,
309 		       const sepol_ibpkey_t *ibpkey, sepol_ibpkey_t **ibpkey_ptr)
310 {
311 	sepol_ibpkey_t *new_ibpkey = NULL;
312 
313 	if (sepol_ibpkey_create(handle, &new_ibpkey) < 0)
314 		goto err;
315 
316 	new_ibpkey->subnet_prefix = ibpkey->subnet_prefix;
317 	new_ibpkey->low = ibpkey->low;
318 	new_ibpkey->high = ibpkey->high;
319 
320 	if (ibpkey->con &&
321 	    (sepol_context_clone(handle, ibpkey->con, &new_ibpkey->con) < 0))
322 		goto err;
323 
324 	*ibpkey_ptr = new_ibpkey;
325 	return STATUS_SUCCESS;
326 
327 err:
328 	ERR(handle, "could not clone ibpkey record");
329 	sepol_ibpkey_free(new_ibpkey);
330 	return STATUS_ERR;
331 }
332 
333 /* Destroy */
sepol_ibpkey_free(sepol_ibpkey_t * ibpkey)334 void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey)
335 {
336 	if (!ibpkey)
337 		return;
338 
339 	sepol_context_free(ibpkey->con);
340 	free(ibpkey);
341 }
342 
343 
344 /* Context */
sepol_ibpkey_get_con(const sepol_ibpkey_t * ibpkey)345 sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey)
346 {
347 	return ibpkey->con;
348 }
349 
350 
sepol_ibpkey_set_con(sepol_handle_t * handle,sepol_ibpkey_t * ibpkey,sepol_context_t * con)351 int sepol_ibpkey_set_con(sepol_handle_t *handle,
352 			 sepol_ibpkey_t *ibpkey, sepol_context_t *con)
353 {
354 	sepol_context_t *newcon;
355 
356 	if (sepol_context_clone(handle, con, &newcon) < 0) {
357 		ERR(handle, "out of memory, could not set ibpkey context");
358 		return STATUS_ERR;
359 	}
360 
361 	sepol_context_free(ibpkey->con);
362 	ibpkey->con = newcon;
363 	return STATUS_SUCCESS;
364 }
365 
366