272 lines
5.9 KiB
C
272 lines
5.9 KiB
C
#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;
|
|
}
|