#include #include #include #include "debug.h" #include "context.h" #include "handle.h" #include #include #include "ibpkey_internal.h" /* Create a low level ibpkey structure from * a high level representation */ static int ibpkey_from_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t **ibpkey, const sepol_ibpkey_t *data) { ocontext_t *tmp_ibpkey = NULL; context_struct_t *tmp_con = NULL; char *subnet_prefix_buf = NULL; int low = sepol_ibpkey_get_low(data); int high = sepol_ibpkey_get_high(data); tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey)); if (!tmp_ibpkey) goto omem; tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data); /* Pkey range */ tmp_ibpkey->u.ibpkey.low_pkey = low; tmp_ibpkey->u.ibpkey.high_pkey = high; if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) { ERR(handle, "low ibpkey %d exceeds high ibpkey %d", tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey); goto err; } /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_ibpkey_get_con(data)) < 0) goto err; context_cpy(&tmp_ibpkey->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *ibpkey = tmp_ibpkey; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_ibpkey) { context_destroy(&tmp_ibpkey->context[0]); free(tmp_ibpkey); } context_destroy(tmp_con); free(tmp_con); free(subnet_prefix_buf); ERR(handle, "could not create ibpkey structure"); return STATUS_ERR; } static int ibpkey_to_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t *ibpkey, sepol_ibpkey_t **record) { context_struct_t *con = &ibpkey->context[0]; sepol_context_t *tmp_con = NULL; sepol_ibpkey_t *tmp_record = NULL; if (sepol_ibpkey_create(handle, &tmp_record) < 0) goto err; sepol_ibpkey_set_subnet_prefix_bytes(tmp_record, ibpkey->u.ibpkey.subnet_prefix); sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey, ibpkey->u.ibpkey.high_pkey); if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert ibpkey to record"); sepol_context_free(tmp_con); sepol_ibpkey_free(tmp_record); return STATUS_ERR; } /* Return the number of ibpkeys */ extern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a ibpkey exists */ int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, const sepol_ibpkey_key_t *key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high; uint64_t subnet_prefix; sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) { uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; uint16_t low2 = c->u.ibpkey.low_pkey; uint16_t high2 = c->u.ibpkey.high_pkey; if (low2 == low && high2 == high && subnet_prefix == subnet_prefix2) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; } /* Query a ibpkey */ int sepol_ibpkey_query(sepol_handle_t *handle, const sepol_policydb_t *p, const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high; uint64_t subnet_prefix; sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) { uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; int low2 = c->u.ibpkey.low_pkey; int high2 = c->u.ibpkey.high_pkey; if (low2 == low && high2 == high && subnet_prefix == subnet_prefix2) { if (ibpkey_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists", subnet_prefix, low, high); return STATUS_ERR; } /* Load a ibpkey into policy */ int sepol_ibpkey_modify(sepol_handle_t *handle, sepol_policydb_t *p, const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data) { policydb_t *policydb = &p->p; ocontext_t *ibpkey = NULL; int low, high; uint64_t subnet_prefix; sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0) goto err; /* Attach to context list */ ibpkey->next = policydb->ocontexts[OCON_IBPKEY]; policydb->ocontexts[OCON_IBPKEY] = ibpkey; return STATUS_SUCCESS; err: ERR(handle, "could not load ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists", subnet_prefix, low, high); if (ibpkey) { context_destroy(&ibpkey->context[0]); free(ibpkey); } return STATUS_ERR; } int sepol_ibpkey_iterate(sepol_handle_t *handle, const sepol_policydb_t *p, int (*fn)(const sepol_ibpkey_t *ibpkey, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_ibpkey_t *ibpkey = NULL; head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) { int status; if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0) goto err; /* Invoke handler */ status = fn(ibpkey, arg); if (status < 0) goto err; sepol_ibpkey_free(ibpkey); ibpkey = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over ibpkeys"); sepol_ibpkey_free(ibpkey); return STATUS_ERR; }