| #include <string.h> |
| #include <stdlib.h> |
| |
| #include "handle.h" |
| #include "private.h" |
| #include "debug.h" |
| |
| #include <sepol/booleans.h> |
| #include <sepol/policydb/hashtab.h> |
| #include <sepol/policydb/policydb.h> |
| #include <sepol/policydb/conditional.h> |
| #include "boolean_internal.h" |
| |
| static int bool_update(sepol_handle_t * handle, |
| policydb_t * policydb, |
| const sepol_bool_key_t * key, const sepol_bool_t * data) |
| { |
| |
| const char *cname; |
| char *name; |
| int value; |
| |
| sepol_bool_key_unpack(key, &cname); |
| name = strdup(cname); |
| value = sepol_bool_get_value(data); |
| |
| if (!name) |
| goto omem; |
| |
| cond_bool_datum_t *datum = |
| hashtab_search(policydb->p_bools.table, name); |
| if (!datum) { |
| ERR(handle, "boolean %s no longer in policy", name); |
| goto err; |
| } |
| if (value != 0 && value != 1) { |
| ERR(handle, "illegal value %d for boolean %s", value, name); |
| goto err; |
| } |
| |
| free(name); |
| datum->state = value; |
| return STATUS_SUCCESS; |
| |
| omem: |
| ERR(handle, "out of memory"); |
| |
| err: |
| free(name); |
| ERR(handle, "could not update boolean %s", cname); |
| return STATUS_ERR; |
| } |
| |
| static int bool_to_record(sepol_handle_t * handle, |
| const policydb_t * policydb, |
| int bool_idx, sepol_bool_t ** record) |
| { |
| |
| const char *name = policydb->p_bool_val_to_name[bool_idx]; |
| cond_bool_datum_t *booldatum = policydb->bool_val_to_struct[bool_idx]; |
| int value = booldatum->state; |
| |
| sepol_bool_t *tmp_record = NULL; |
| |
| if (sepol_bool_create(handle, &tmp_record) < 0) |
| goto err; |
| |
| if (sepol_bool_set_name(handle, tmp_record, name) < 0) |
| goto err; |
| |
| sepol_bool_set_value(tmp_record, value); |
| |
| *record = tmp_record; |
| return STATUS_SUCCESS; |
| |
| err: |
| ERR(handle, "could not convert boolean %s to record", name); |
| sepol_bool_free(tmp_record); |
| return STATUS_ERR; |
| } |
| |
| int sepol_bool_set(sepol_handle_t * handle, |
| sepol_policydb_t * p, |
| const sepol_bool_key_t * key, const sepol_bool_t * data) |
| { |
| |
| const char *name; |
| sepol_bool_key_unpack(key, &name); |
| |
| policydb_t *policydb = &p->p; |
| if (bool_update(handle, policydb, key, data) < 0) |
| goto err; |
| |
| if (evaluate_conds(policydb) < 0) { |
| ERR(handle, "error while re-evaluating conditionals"); |
| goto err; |
| } |
| |
| return STATUS_SUCCESS; |
| |
| err: |
| ERR(handle, "could not set boolean %s", name); |
| return STATUS_ERR; |
| } |
| |
| int sepol_bool_count(sepol_handle_t * handle __attribute__ ((unused)), |
| const sepol_policydb_t * p, unsigned int *response) |
| { |
| |
| const policydb_t *policydb = &p->p; |
| *response = policydb->p_bools.nprim; |
| |
| return STATUS_SUCCESS; |
| } |
| |
| int sepol_bool_exists(sepol_handle_t * handle, |
| const sepol_policydb_t * p, |
| const sepol_bool_key_t * key, int *response) |
| { |
| |
| const policydb_t *policydb = &p->p; |
| |
| const char *cname; |
| char *name = NULL; |
| sepol_bool_key_unpack(key, &cname); |
| name = strdup(cname); |
| |
| if (!name) { |
| ERR(handle, "out of memory, could not check " |
| "if user %s exists", cname); |
| return STATUS_ERR; |
| } |
| |
| *response = (hashtab_search(policydb->p_bools.table, name) != NULL); |
| free(name); |
| return STATUS_SUCCESS; |
| } |
| |
| int sepol_bool_query(sepol_handle_t * handle, |
| const sepol_policydb_t * p, |
| const sepol_bool_key_t * key, sepol_bool_t ** response) |
| { |
| |
| const policydb_t *policydb = &p->p; |
| cond_bool_datum_t *booldatum = NULL; |
| |
| const char *cname; |
| char *name = NULL; |
| sepol_bool_key_unpack(key, &cname); |
| name = strdup(cname); |
| |
| if (!name) |
| goto omem; |
| |
| booldatum = hashtab_search(policydb->p_bools.table, name); |
| if (!booldatum) { |
| *response = NULL; |
| return STATUS_SUCCESS; |
| } |
| |
| if (bool_to_record(handle, policydb, |
| booldatum->s.value - 1, response) < 0) |
| goto err; |
| |
| free(name); |
| return STATUS_SUCCESS; |
| |
| omem: |
| ERR(handle, "out of memory"); |
| |
| err: |
| ERR(handle, "could not query boolean %s", cname); |
| free(name); |
| return STATUS_ERR; |
| } |
| |
| int sepol_bool_iterate(sepol_handle_t * handle, |
| const sepol_policydb_t * p, |
| int (*fn) (const sepol_bool_t * boolean, |
| void *fn_arg), void *arg) |
| { |
| |
| const policydb_t *policydb = &p->p; |
| unsigned int nbools = policydb->p_bools.nprim; |
| sepol_bool_t *boolean = NULL; |
| unsigned int i; |
| |
| /* For each boolean */ |
| for (i = 0; i < nbools; i++) { |
| |
| int status; |
| |
| if (bool_to_record(handle, policydb, i, &boolean) < 0) |
| goto err; |
| |
| /* Invoke handler */ |
| status = fn(boolean, arg); |
| if (status < 0) |
| goto err; |
| |
| sepol_bool_free(boolean); |
| boolean = NULL; |
| |
| /* Handler requested exit */ |
| if (status > 0) |
| break; |
| } |
| |
| return STATUS_SUCCESS; |
| |
| err: |
| ERR(handle, "could not iterate over booleans"); |
| sepol_bool_free(boolean); |
| return STATUS_ERR; |
| } |