| #include <stdlib.h> |
| |
| #include "debug.h" |
| #include "context.h" |
| #include "handle.h" |
| |
| #include <sepol/policydb/policydb.h> |
| #include <sepol/interfaces.h> |
| #include "iface_internal.h" |
| |
| /* Create a low level structure from record */ |
| static int iface_from_record(sepol_handle_t * handle, |
| const policydb_t * policydb, |
| ocontext_t ** iface, const sepol_iface_t * record) |
| { |
| |
| ocontext_t *tmp_iface = NULL; |
| context_struct_t *tmp_con = NULL; |
| |
| tmp_iface = (ocontext_t *) calloc(1, sizeof(ocontext_t)); |
| if (!tmp_iface) |
| goto omem; |
| |
| /* Name */ |
| tmp_iface->u.name = strdup(sepol_iface_get_name(record)); |
| if (!tmp_iface->u.name) |
| goto omem; |
| |
| /* Interface Context */ |
| if (context_from_record(handle, policydb, |
| &tmp_con, sepol_iface_get_ifcon(record)) < 0) |
| goto err; |
| context_cpy(&tmp_iface->context[0], tmp_con); |
| context_destroy(tmp_con); |
| free(tmp_con); |
| tmp_con = NULL; |
| |
| /* Message Context */ |
| if (context_from_record(handle, policydb, |
| &tmp_con, sepol_iface_get_msgcon(record)) < 0) |
| goto err; |
| context_cpy(&tmp_iface->context[1], tmp_con); |
| context_destroy(tmp_con); |
| free(tmp_con); |
| tmp_con = NULL; |
| |
| *iface = tmp_iface; |
| return STATUS_SUCCESS; |
| |
| omem: |
| ERR(handle, "out of memory"); |
| |
| err: |
| if (tmp_iface != NULL) { |
| free(tmp_iface->u.name); |
| context_destroy(&tmp_iface->context[0]); |
| context_destroy(&tmp_iface->context[1]); |
| free(tmp_iface); |
| } |
| context_destroy(tmp_con); |
| free(tmp_con); |
| ERR(handle, "error creating interface structure"); |
| return STATUS_ERR; |
| } |
| |
| static int iface_to_record(sepol_handle_t * handle, |
| const policydb_t * policydb, |
| ocontext_t * iface, sepol_iface_t ** record) |
| { |
| |
| char *name = iface->u.name; |
| context_struct_t *ifcon = &iface->context[0]; |
| context_struct_t *msgcon = &iface->context[1]; |
| |
| sepol_context_t *tmp_con = NULL; |
| sepol_iface_t *tmp_record = NULL; |
| |
| if (sepol_iface_create(handle, &tmp_record) < 0) |
| goto err; |
| |
| if (sepol_iface_set_name(handle, tmp_record, name) < 0) |
| goto err; |
| |
| if (context_to_record(handle, policydb, ifcon, &tmp_con) < 0) |
| goto err; |
| if (sepol_iface_set_ifcon(handle, tmp_record, tmp_con) < 0) |
| goto err; |
| sepol_context_free(tmp_con); |
| tmp_con = NULL; |
| |
| if (context_to_record(handle, policydb, msgcon, &tmp_con) < 0) |
| goto err; |
| if (sepol_iface_set_msgcon(handle, tmp_record, tmp_con) < 0) |
| goto err; |
| sepol_context_free(tmp_con); |
| tmp_con = NULL; |
| |
| *record = tmp_record; |
| return STATUS_SUCCESS; |
| |
| err: |
| ERR(handle, "could not convert interface %s to record", name); |
| sepol_context_free(tmp_con); |
| sepol_iface_free(tmp_record); |
| return STATUS_ERR; |
| } |
| |
| /* Check if an interface exists */ |
| int sepol_iface_exists(sepol_handle_t * handle __attribute__ ((unused)), |
| const sepol_policydb_t * p, |
| const sepol_iface_key_t * key, int *response) |
| { |
| |
| const policydb_t *policydb = &p->p; |
| ocontext_t *c, *head; |
| |
| const char *name; |
| sepol_iface_key_unpack(key, &name); |
| |
| head = policydb->ocontexts[OCON_NETIF]; |
| for (c = head; c; c = c->next) { |
| if (!strcmp(name, c->u.name)) { |
| *response = 1; |
| return STATUS_SUCCESS; |
| } |
| } |
| *response = 0; |
| |
| return STATUS_SUCCESS; |
| } |
| |
| /* Query an interface */ |
| int sepol_iface_query(sepol_handle_t * handle, |
| const sepol_policydb_t * p, |
| const sepol_iface_key_t * key, sepol_iface_t ** response) |
| { |
| |
| const policydb_t *policydb = &p->p; |
| ocontext_t *c, *head; |
| |
| const char *name; |
| sepol_iface_key_unpack(key, &name); |
| |
| head = policydb->ocontexts[OCON_NETIF]; |
| for (c = head; c; c = c->next) { |
| if (!strcmp(name, c->u.name)) { |
| |
| if (iface_to_record(handle, policydb, c, response) < 0) |
| goto err; |
| |
| return STATUS_SUCCESS; |
| } |
| } |
| |
| *response = NULL; |
| return STATUS_SUCCESS; |
| |
| err: |
| ERR(handle, "could not query interface %s", name); |
| return STATUS_ERR; |
| } |
| |
| /* Load an interface into policy */ |
| int sepol_iface_modify(sepol_handle_t * handle, |
| sepol_policydb_t * p, |
| const sepol_iface_key_t * key, |
| const sepol_iface_t * data) |
| { |
| |
| policydb_t *policydb = &p->p; |
| ocontext_t *head, *prev, *c, *iface = NULL; |
| |
| const char *name; |
| sepol_iface_key_unpack(key, &name); |
| |
| if (iface_from_record(handle, policydb, &iface, data) < 0) |
| goto err; |
| |
| prev = NULL; |
| head = policydb->ocontexts[OCON_NETIF]; |
| for (c = head; c; c = c->next) { |
| if (!strcmp(name, c->u.name)) { |
| |
| /* Replace */ |
| iface->next = c->next; |
| if (prev == NULL) |
| policydb->ocontexts[OCON_NETIF] = iface; |
| else |
| prev->next = iface; |
| free(c->u.name); |
| context_destroy(&c->context[0]); |
| context_destroy(&c->context[1]); |
| free(c); |
| |
| return STATUS_SUCCESS; |
| } |
| prev = c; |
| } |
| |
| /* Attach to context list */ |
| iface->next = policydb->ocontexts[OCON_NETIF]; |
| policydb->ocontexts[OCON_NETIF] = iface; |
| return STATUS_SUCCESS; |
| |
| err: |
| ERR(handle, "error while loading interface %s", name); |
| |
| if (iface != NULL) { |
| free(iface->u.name); |
| context_destroy(&iface->context[0]); |
| context_destroy(&iface->context[1]); |
| free(iface); |
| } |
| return STATUS_ERR; |
| } |
| |
| /* Return the number of interfaces */ |
| extern int sepol_iface_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_NETIF]; |
| for (c = head; c != NULL; c = c->next) |
| count++; |
| |
| *response = count; |
| |
| return STATUS_SUCCESS; |
| } |
| |
| int sepol_iface_iterate(sepol_handle_t * handle, |
| const sepol_policydb_t * p, |
| int (*fn) (const sepol_iface_t * iface, |
| void *fn_arg), void *arg) |
| { |
| |
| const policydb_t *policydb = &p->p; |
| ocontext_t *c, *head; |
| sepol_iface_t *iface = NULL; |
| |
| head = policydb->ocontexts[OCON_NETIF]; |
| for (c = head; c; c = c->next) { |
| int status; |
| |
| if (iface_to_record(handle, policydb, c, &iface) < 0) |
| goto err; |
| |
| /* Invoke handler */ |
| status = fn(iface, arg); |
| if (status < 0) |
| goto err; |
| |
| sepol_iface_free(iface); |
| iface = NULL; |
| |
| /* Handler requested exit */ |
| if (status > 0) |
| break; |
| } |
| |
| return STATUS_SUCCESS; |
| |
| err: |
| ERR(handle, "could not iterate over interfaces"); |
| sepol_iface_free(iface); |
| return STATUS_ERR; |
| } |