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