16cd6a6acSopenharmony_ci#include <netinet/in.h> 26cd6a6acSopenharmony_ci#include <stdlib.h> 36cd6a6acSopenharmony_ci#include <inttypes.h> 46cd6a6acSopenharmony_ci 56cd6a6acSopenharmony_ci#include "debug.h" 66cd6a6acSopenharmony_ci#include "context.h" 76cd6a6acSopenharmony_ci#include "handle.h" 86cd6a6acSopenharmony_ci 96cd6a6acSopenharmony_ci#include <sepol/ibpkey_record.h> 106cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 116cd6a6acSopenharmony_ci#include "ibpkey_internal.h" 126cd6a6acSopenharmony_ci 136cd6a6acSopenharmony_ci/* Create a low level ibpkey structure from 146cd6a6acSopenharmony_ci * a high level representation 156cd6a6acSopenharmony_ci */ 166cd6a6acSopenharmony_cistatic int ibpkey_from_record(sepol_handle_t *handle, 176cd6a6acSopenharmony_ci const policydb_t *policydb, 186cd6a6acSopenharmony_ci ocontext_t **ibpkey, const sepol_ibpkey_t *data) 196cd6a6acSopenharmony_ci{ 206cd6a6acSopenharmony_ci ocontext_t *tmp_ibpkey = NULL; 216cd6a6acSopenharmony_ci context_struct_t *tmp_con = NULL; 226cd6a6acSopenharmony_ci char *subnet_prefix_buf = NULL; 236cd6a6acSopenharmony_ci int low = sepol_ibpkey_get_low(data); 246cd6a6acSopenharmony_ci int high = sepol_ibpkey_get_high(data); 256cd6a6acSopenharmony_ci 266cd6a6acSopenharmony_ci tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey)); 276cd6a6acSopenharmony_ci if (!tmp_ibpkey) 286cd6a6acSopenharmony_ci goto omem; 296cd6a6acSopenharmony_ci 306cd6a6acSopenharmony_ci tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data); 316cd6a6acSopenharmony_ci 326cd6a6acSopenharmony_ci /* Pkey range */ 336cd6a6acSopenharmony_ci tmp_ibpkey->u.ibpkey.low_pkey = low; 346cd6a6acSopenharmony_ci tmp_ibpkey->u.ibpkey.high_pkey = high; 356cd6a6acSopenharmony_ci if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) { 366cd6a6acSopenharmony_ci ERR(handle, "low ibpkey %d exceeds high ibpkey %d", 376cd6a6acSopenharmony_ci tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey); 386cd6a6acSopenharmony_ci goto err; 396cd6a6acSopenharmony_ci } 406cd6a6acSopenharmony_ci 416cd6a6acSopenharmony_ci /* Context */ 426cd6a6acSopenharmony_ci if (context_from_record(handle, policydb, &tmp_con, 436cd6a6acSopenharmony_ci sepol_ibpkey_get_con(data)) < 0) 446cd6a6acSopenharmony_ci goto err; 456cd6a6acSopenharmony_ci context_cpy(&tmp_ibpkey->context[0], tmp_con); 466cd6a6acSopenharmony_ci context_destroy(tmp_con); 476cd6a6acSopenharmony_ci free(tmp_con); 486cd6a6acSopenharmony_ci tmp_con = NULL; 496cd6a6acSopenharmony_ci 506cd6a6acSopenharmony_ci *ibpkey = tmp_ibpkey; 516cd6a6acSopenharmony_ci return STATUS_SUCCESS; 526cd6a6acSopenharmony_ci 536cd6a6acSopenharmony_ciomem: 546cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 556cd6a6acSopenharmony_ci 566cd6a6acSopenharmony_cierr: 576cd6a6acSopenharmony_ci if (tmp_ibpkey) { 586cd6a6acSopenharmony_ci context_destroy(&tmp_ibpkey->context[0]); 596cd6a6acSopenharmony_ci free(tmp_ibpkey); 606cd6a6acSopenharmony_ci } 616cd6a6acSopenharmony_ci context_destroy(tmp_con); 626cd6a6acSopenharmony_ci free(tmp_con); 636cd6a6acSopenharmony_ci free(subnet_prefix_buf); 646cd6a6acSopenharmony_ci ERR(handle, "could not create ibpkey structure"); 656cd6a6acSopenharmony_ci return STATUS_ERR; 666cd6a6acSopenharmony_ci} 676cd6a6acSopenharmony_ci 686cd6a6acSopenharmony_cistatic int ibpkey_to_record(sepol_handle_t *handle, 696cd6a6acSopenharmony_ci const policydb_t *policydb, 706cd6a6acSopenharmony_ci ocontext_t *ibpkey, sepol_ibpkey_t **record) 716cd6a6acSopenharmony_ci{ 726cd6a6acSopenharmony_ci context_struct_t *con = &ibpkey->context[0]; 736cd6a6acSopenharmony_ci sepol_context_t *tmp_con = NULL; 746cd6a6acSopenharmony_ci sepol_ibpkey_t *tmp_record = NULL; 756cd6a6acSopenharmony_ci 766cd6a6acSopenharmony_ci if (sepol_ibpkey_create(handle, &tmp_record) < 0) 776cd6a6acSopenharmony_ci goto err; 786cd6a6acSopenharmony_ci 796cd6a6acSopenharmony_ci sepol_ibpkey_set_subnet_prefix_bytes(tmp_record, 806cd6a6acSopenharmony_ci ibpkey->u.ibpkey.subnet_prefix); 816cd6a6acSopenharmony_ci 826cd6a6acSopenharmony_ci sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey, 836cd6a6acSopenharmony_ci ibpkey->u.ibpkey.high_pkey); 846cd6a6acSopenharmony_ci 856cd6a6acSopenharmony_ci if (context_to_record(handle, policydb, con, &tmp_con) < 0) 866cd6a6acSopenharmony_ci goto err; 876cd6a6acSopenharmony_ci 886cd6a6acSopenharmony_ci if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0) 896cd6a6acSopenharmony_ci goto err; 906cd6a6acSopenharmony_ci 916cd6a6acSopenharmony_ci sepol_context_free(tmp_con); 926cd6a6acSopenharmony_ci *record = tmp_record; 936cd6a6acSopenharmony_ci return STATUS_SUCCESS; 946cd6a6acSopenharmony_ci 956cd6a6acSopenharmony_cierr: 966cd6a6acSopenharmony_ci ERR(handle, "could not convert ibpkey to record"); 976cd6a6acSopenharmony_ci sepol_context_free(tmp_con); 986cd6a6acSopenharmony_ci sepol_ibpkey_free(tmp_record); 996cd6a6acSopenharmony_ci return STATUS_ERR; 1006cd6a6acSopenharmony_ci} 1016cd6a6acSopenharmony_ci 1026cd6a6acSopenharmony_ci/* Return the number of ibpkeys */ 1036cd6a6acSopenharmony_ciextern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)), 1046cd6a6acSopenharmony_ci const sepol_policydb_t *p, unsigned int *response) 1056cd6a6acSopenharmony_ci{ 1066cd6a6acSopenharmony_ci unsigned int count = 0; 1076cd6a6acSopenharmony_ci ocontext_t *c, *head; 1086cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1096cd6a6acSopenharmony_ci 1106cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_IBPKEY]; 1116cd6a6acSopenharmony_ci for (c = head; c; c = c->next) 1126cd6a6acSopenharmony_ci count++; 1136cd6a6acSopenharmony_ci 1146cd6a6acSopenharmony_ci *response = count; 1156cd6a6acSopenharmony_ci 1166cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1176cd6a6acSopenharmony_ci} 1186cd6a6acSopenharmony_ci 1196cd6a6acSopenharmony_ci/* Check if a ibpkey exists */ 1206cd6a6acSopenharmony_ciint sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)), 1216cd6a6acSopenharmony_ci const sepol_policydb_t *p, 1226cd6a6acSopenharmony_ci const sepol_ibpkey_key_t *key, int *response) 1236cd6a6acSopenharmony_ci{ 1246cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1256cd6a6acSopenharmony_ci ocontext_t *c, *head; 1266cd6a6acSopenharmony_ci int low, high; 1276cd6a6acSopenharmony_ci uint64_t subnet_prefix; 1286cd6a6acSopenharmony_ci 1296cd6a6acSopenharmony_ci sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); 1306cd6a6acSopenharmony_ci 1316cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_IBPKEY]; 1326cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 1336cd6a6acSopenharmony_ci uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; 1346cd6a6acSopenharmony_ci uint16_t low2 = c->u.ibpkey.low_pkey; 1356cd6a6acSopenharmony_ci uint16_t high2 = c->u.ibpkey.high_pkey; 1366cd6a6acSopenharmony_ci 1376cd6a6acSopenharmony_ci if (low2 == low && 1386cd6a6acSopenharmony_ci high2 == high && 1396cd6a6acSopenharmony_ci subnet_prefix == subnet_prefix2) { 1406cd6a6acSopenharmony_ci *response = 1; 1416cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1426cd6a6acSopenharmony_ci } 1436cd6a6acSopenharmony_ci } 1446cd6a6acSopenharmony_ci 1456cd6a6acSopenharmony_ci *response = 0; 1466cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1476cd6a6acSopenharmony_ci} 1486cd6a6acSopenharmony_ci 1496cd6a6acSopenharmony_ci/* Query a ibpkey */ 1506cd6a6acSopenharmony_ciint sepol_ibpkey_query(sepol_handle_t *handle, 1516cd6a6acSopenharmony_ci const sepol_policydb_t *p, 1526cd6a6acSopenharmony_ci const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response) 1536cd6a6acSopenharmony_ci{ 1546cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1556cd6a6acSopenharmony_ci ocontext_t *c, *head; 1566cd6a6acSopenharmony_ci int low, high; 1576cd6a6acSopenharmony_ci uint64_t subnet_prefix; 1586cd6a6acSopenharmony_ci 1596cd6a6acSopenharmony_ci sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); 1606cd6a6acSopenharmony_ci 1616cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_IBPKEY]; 1626cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 1636cd6a6acSopenharmony_ci uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; 1646cd6a6acSopenharmony_ci int low2 = c->u.ibpkey.low_pkey; 1656cd6a6acSopenharmony_ci int high2 = c->u.ibpkey.high_pkey; 1666cd6a6acSopenharmony_ci 1676cd6a6acSopenharmony_ci if (low2 == low && 1686cd6a6acSopenharmony_ci high2 == high && 1696cd6a6acSopenharmony_ci subnet_prefix == subnet_prefix2) { 1706cd6a6acSopenharmony_ci if (ibpkey_to_record(handle, policydb, c, response) < 0) 1716cd6a6acSopenharmony_ci goto err; 1726cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1736cd6a6acSopenharmony_ci } 1746cd6a6acSopenharmony_ci } 1756cd6a6acSopenharmony_ci 1766cd6a6acSopenharmony_ci *response = NULL; 1776cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1786cd6a6acSopenharmony_ci 1796cd6a6acSopenharmony_cierr: 1806cd6a6acSopenharmony_ci ERR(handle, "could not query ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists", 1816cd6a6acSopenharmony_ci subnet_prefix, low, high); 1826cd6a6acSopenharmony_ci return STATUS_ERR; 1836cd6a6acSopenharmony_ci} 1846cd6a6acSopenharmony_ci 1856cd6a6acSopenharmony_ci/* Load a ibpkey into policy */ 1866cd6a6acSopenharmony_ciint sepol_ibpkey_modify(sepol_handle_t *handle, 1876cd6a6acSopenharmony_ci sepol_policydb_t *p, 1886cd6a6acSopenharmony_ci const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data) 1896cd6a6acSopenharmony_ci{ 1906cd6a6acSopenharmony_ci policydb_t *policydb = &p->p; 1916cd6a6acSopenharmony_ci ocontext_t *ibpkey = NULL; 1926cd6a6acSopenharmony_ci int low, high; 1936cd6a6acSopenharmony_ci uint64_t subnet_prefix; 1946cd6a6acSopenharmony_ci 1956cd6a6acSopenharmony_ci sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); 1966cd6a6acSopenharmony_ci 1976cd6a6acSopenharmony_ci if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0) 1986cd6a6acSopenharmony_ci goto err; 1996cd6a6acSopenharmony_ci 2006cd6a6acSopenharmony_ci /* Attach to context list */ 2016cd6a6acSopenharmony_ci ibpkey->next = policydb->ocontexts[OCON_IBPKEY]; 2026cd6a6acSopenharmony_ci policydb->ocontexts[OCON_IBPKEY] = ibpkey; 2036cd6a6acSopenharmony_ci 2046cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2056cd6a6acSopenharmony_ci 2066cd6a6acSopenharmony_cierr: 2076cd6a6acSopenharmony_ci ERR(handle, "could not load ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists", 2086cd6a6acSopenharmony_ci subnet_prefix, low, high); 2096cd6a6acSopenharmony_ci if (ibpkey) { 2106cd6a6acSopenharmony_ci context_destroy(&ibpkey->context[0]); 2116cd6a6acSopenharmony_ci free(ibpkey); 2126cd6a6acSopenharmony_ci } 2136cd6a6acSopenharmony_ci return STATUS_ERR; 2146cd6a6acSopenharmony_ci} 2156cd6a6acSopenharmony_ci 2166cd6a6acSopenharmony_ciint sepol_ibpkey_iterate(sepol_handle_t *handle, 2176cd6a6acSopenharmony_ci const sepol_policydb_t *p, 2186cd6a6acSopenharmony_ci int (*fn)(const sepol_ibpkey_t *ibpkey, 2196cd6a6acSopenharmony_ci void *fn_arg), void *arg) 2206cd6a6acSopenharmony_ci{ 2216cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 2226cd6a6acSopenharmony_ci ocontext_t *c, *head; 2236cd6a6acSopenharmony_ci sepol_ibpkey_t *ibpkey = NULL; 2246cd6a6acSopenharmony_ci 2256cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_IBPKEY]; 2266cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 2276cd6a6acSopenharmony_ci int status; 2286cd6a6acSopenharmony_ci 2296cd6a6acSopenharmony_ci if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0) 2306cd6a6acSopenharmony_ci goto err; 2316cd6a6acSopenharmony_ci 2326cd6a6acSopenharmony_ci /* Invoke handler */ 2336cd6a6acSopenharmony_ci status = fn(ibpkey, arg); 2346cd6a6acSopenharmony_ci if (status < 0) 2356cd6a6acSopenharmony_ci goto err; 2366cd6a6acSopenharmony_ci 2376cd6a6acSopenharmony_ci sepol_ibpkey_free(ibpkey); 2386cd6a6acSopenharmony_ci ibpkey = NULL; 2396cd6a6acSopenharmony_ci 2406cd6a6acSopenharmony_ci /* Handler requested exit */ 2416cd6a6acSopenharmony_ci if (status > 0) 2426cd6a6acSopenharmony_ci break; 2436cd6a6acSopenharmony_ci } 2446cd6a6acSopenharmony_ci 2456cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2466cd6a6acSopenharmony_ci 2476cd6a6acSopenharmony_cierr: 2486cd6a6acSopenharmony_ci ERR(handle, "could not iterate over ibpkeys"); 2496cd6a6acSopenharmony_ci sepol_ibpkey_free(ibpkey); 2506cd6a6acSopenharmony_ci return STATUS_ERR; 2516cd6a6acSopenharmony_ci} 252