Home | History | Annotate | Download | only in src
      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  */
     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 
     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  */
     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 */
     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 
    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 
    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 
    163 void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key)
    164 {
    165 	if (!key)
    166 		return;
    167 	free(key);
    168 }
    169 
    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 
    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 */
    211 int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey)
    212 {
    213 	return ibpkey->low;
    214 }
    215 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 */
    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 
    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 
    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