#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;
}