| #include <netinet/in.h> |
| #include <stdlib.h> |
| #include <inttypes.h> |
| |
| #include "debug.h" |
| #include "context.h" |
| #include "handle.h" |
| |
| #include <sepol/ibpkey_record.h> |
| #include <sepol/policydb/policydb.h> |
| #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; |
| } |