mirror of
https://github.com/SELinuxProject/selinux
synced 2025-03-11 04:37:29 +00:00
Follow the project style of no declaration after statement. Found by the gcc warning -Wdeclaration-after-statement Signed-off-by: Christian Göttsche <cgzones@googlemail.com> Acked-by: James Carter <jwcart2@gmail.com>
401 lines
8.5 KiB
C
401 lines
8.5 KiB
C
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "debug.h"
|
|
#include "context.h"
|
|
#include "handle.h"
|
|
|
|
#include <sepol/policydb/policydb.h>
|
|
#include "node_internal.h"
|
|
|
|
/* Create a low level node structure from
|
|
* a high level representation */
|
|
static int node_from_record(sepol_handle_t * handle,
|
|
const policydb_t * policydb,
|
|
ocontext_t ** node, const sepol_node_t * data)
|
|
{
|
|
|
|
ocontext_t *tmp_node = NULL;
|
|
context_struct_t *tmp_con = NULL;
|
|
char *addr_buf = NULL, *mask_buf = NULL;
|
|
size_t addr_bsize, mask_bsize;
|
|
int proto;
|
|
|
|
tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t));
|
|
if (!tmp_node)
|
|
goto omem;
|
|
|
|
/* Address and netmask */
|
|
if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0)
|
|
goto err;
|
|
if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0)
|
|
goto err;
|
|
|
|
proto = sepol_node_get_proto(data);
|
|
|
|
switch (proto) {
|
|
case SEPOL_PROTO_IP4:
|
|
memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize);
|
|
memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize);
|
|
break;
|
|
case SEPOL_PROTO_IP6:
|
|
memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize);
|
|
memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize);
|
|
break;
|
|
default:
|
|
ERR(handle, "unsupported protocol %u", proto);
|
|
goto err;
|
|
}
|
|
free(addr_buf);
|
|
free(mask_buf);
|
|
addr_buf = NULL;
|
|
mask_buf = NULL;
|
|
|
|
/* Context */
|
|
if (context_from_record(handle, policydb, &tmp_con,
|
|
sepol_node_get_con(data)) < 0)
|
|
goto err;
|
|
context_cpy(&tmp_node->context[0], tmp_con);
|
|
context_destroy(tmp_con);
|
|
free(tmp_con);
|
|
tmp_con = NULL;
|
|
|
|
*node = tmp_node;
|
|
return STATUS_SUCCESS;
|
|
|
|
omem:
|
|
ERR(handle, "out of memory");
|
|
|
|
err:
|
|
if (tmp_node != NULL) {
|
|
context_destroy(&tmp_node->context[0]);
|
|
free(tmp_node);
|
|
}
|
|
context_destroy(tmp_con);
|
|
free(tmp_con);
|
|
free(addr_buf);
|
|
free(mask_buf);
|
|
ERR(handle, "could not create node structure");
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
static int node_to_record(sepol_handle_t * handle,
|
|
const policydb_t * policydb,
|
|
ocontext_t * node, int proto, sepol_node_t ** record)
|
|
{
|
|
|
|
context_struct_t *con = &node->context[0];
|
|
|
|
sepol_context_t *tmp_con = NULL;
|
|
sepol_node_t *tmp_record = NULL;
|
|
|
|
if (sepol_node_create(handle, &tmp_record) < 0)
|
|
goto err;
|
|
|
|
sepol_node_set_proto(tmp_record, proto);
|
|
|
|
switch (proto) {
|
|
|
|
case SEPOL_PROTO_IP4:
|
|
if (sepol_node_set_addr_bytes(handle, tmp_record,
|
|
(const char *)&node->u.node.addr,
|
|
4) < 0)
|
|
goto err;
|
|
|
|
if (sepol_node_set_mask_bytes(handle, tmp_record,
|
|
(const char *)&node->u.node.mask,
|
|
4) < 0)
|
|
goto err;
|
|
break;
|
|
|
|
case SEPOL_PROTO_IP6:
|
|
if (sepol_node_set_addr_bytes(handle, tmp_record,
|
|
(const char *)&node->u.node6.addr,
|
|
16) < 0)
|
|
goto err;
|
|
|
|
if (sepol_node_set_mask_bytes(handle, tmp_record,
|
|
(const char *)&node->u.node6.mask,
|
|
16) < 0)
|
|
goto err;
|
|
break;
|
|
|
|
default:
|
|
ERR(handle, "unsupported protocol %u", proto);
|
|
goto err;
|
|
}
|
|
|
|
if (context_to_record(handle, policydb, con, &tmp_con) < 0)
|
|
goto err;
|
|
|
|
if (sepol_node_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 node to record");
|
|
sepol_context_free(tmp_con);
|
|
sepol_node_free(tmp_record);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
/* Return the number of nodes */
|
|
extern int sepol_node_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_NODE];
|
|
for (c = head; c != NULL; c = c->next)
|
|
count++;
|
|
|
|
head = policydb->ocontexts[OCON_NODE6];
|
|
for (c = head; c != NULL; c = c->next)
|
|
count++;
|
|
|
|
*response = count;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* Check if a node exists */
|
|
int sepol_node_exists(sepol_handle_t * handle,
|
|
const sepol_policydb_t * p,
|
|
const sepol_node_key_t * key, int *response)
|
|
{
|
|
|
|
const policydb_t *policydb = &p->p;
|
|
ocontext_t *c, *head;
|
|
|
|
int proto;
|
|
const char *addr, *mask;
|
|
sepol_node_key_unpack(key, &addr, &mask, &proto);
|
|
|
|
switch (proto) {
|
|
|
|
case SEPOL_PROTO_IP4:
|
|
{
|
|
head = policydb->ocontexts[OCON_NODE];
|
|
for (c = head; c; c = c->next) {
|
|
unsigned int *addr2 = &c->u.node.addr;
|
|
unsigned int *mask2 = &c->u.node.mask;
|
|
|
|
if (!memcmp(addr, addr2, 4) &&
|
|
!memcmp(mask, mask2, 4)) {
|
|
|
|
*response = 1;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case SEPOL_PROTO_IP6:
|
|
{
|
|
head = policydb->ocontexts[OCON_NODE6];
|
|
for (c = head; c; c = c->next) {
|
|
unsigned int *addr2 = c->u.node6.addr;
|
|
unsigned int *mask2 = c->u.node6.mask;
|
|
|
|
if (!memcmp(addr, addr2, 16) &&
|
|
!memcmp(mask, mask2, 16)) {
|
|
*response = 1;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
ERR(handle, "unsupported protocol %u", proto);
|
|
goto err;
|
|
}
|
|
|
|
*response = 0;
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
ERR(handle, "could not check if node %s/%s (%s) exists",
|
|
addr, mask, sepol_node_get_proto_str(proto));
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
/* Query a node */
|
|
int sepol_node_query(sepol_handle_t * handle,
|
|
const sepol_policydb_t * p,
|
|
const sepol_node_key_t * key, sepol_node_t ** response)
|
|
{
|
|
|
|
const policydb_t *policydb = &p->p;
|
|
ocontext_t *c, *head;
|
|
|
|
int proto;
|
|
const char *addr, *mask;
|
|
sepol_node_key_unpack(key, &addr, &mask, &proto);
|
|
|
|
switch (proto) {
|
|
|
|
case SEPOL_PROTO_IP4:
|
|
{
|
|
head = policydb->ocontexts[OCON_NODE];
|
|
for (c = head; c; c = c->next) {
|
|
unsigned int *addr2 = &c->u.node.addr;
|
|
unsigned int *mask2 = &c->u.node.mask;
|
|
|
|
if (!memcmp(addr, addr2, 4) &&
|
|
!memcmp(mask, mask2, 4)) {
|
|
|
|
if (node_to_record(handle, policydb,
|
|
c, SEPOL_PROTO_IP4,
|
|
response) < 0)
|
|
goto err;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case SEPOL_PROTO_IP6:
|
|
{
|
|
head = policydb->ocontexts[OCON_NODE6];
|
|
for (c = head; c; c = c->next) {
|
|
unsigned int *addr2 = c->u.node6.addr;
|
|
unsigned int *mask2 = c->u.node6.mask;
|
|
|
|
if (!memcmp(addr, addr2, 16) &&
|
|
!memcmp(mask, mask2, 16)) {
|
|
|
|
if (node_to_record(handle, policydb,
|
|
c, SEPOL_PROTO_IP6,
|
|
response) < 0)
|
|
goto err;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
ERR(handle, "unsupported protocol %u", proto);
|
|
goto err;
|
|
}
|
|
*response = NULL;
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
ERR(handle, "could not query node %s/%s (%s)",
|
|
addr, mask, sepol_node_get_proto_str(proto));
|
|
return STATUS_ERR;
|
|
|
|
}
|
|
|
|
/* Load a node into policy */
|
|
int sepol_node_modify(sepol_handle_t * handle,
|
|
sepol_policydb_t * p,
|
|
const sepol_node_key_t * key, const sepol_node_t * data)
|
|
{
|
|
|
|
policydb_t *policydb = &p->p;
|
|
ocontext_t *node = NULL;
|
|
|
|
int proto;
|
|
const char *addr, *mask;
|
|
|
|
sepol_node_key_unpack(key, &addr, &mask, &proto);
|
|
|
|
if (node_from_record(handle, policydb, &node, data) < 0)
|
|
goto err;
|
|
|
|
switch (proto) {
|
|
|
|
case SEPOL_PROTO_IP4:
|
|
{
|
|
/* Attach to context list */
|
|
node->next = policydb->ocontexts[OCON_NODE];
|
|
policydb->ocontexts[OCON_NODE] = node;
|
|
break;
|
|
}
|
|
case SEPOL_PROTO_IP6:
|
|
{
|
|
/* Attach to context list */
|
|
node->next = policydb->ocontexts[OCON_NODE6];
|
|
policydb->ocontexts[OCON_NODE6] = node;
|
|
break;
|
|
}
|
|
default:
|
|
ERR(handle, "unsupported protocol %u", proto);
|
|
goto err;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
ERR(handle, "could not load node %s/%s (%s)",
|
|
addr, mask, sepol_node_get_proto_str(proto));
|
|
if (node != NULL) {
|
|
context_destroy(&node->context[0]);
|
|
free(node);
|
|
}
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
int sepol_node_iterate(sepol_handle_t * handle,
|
|
const sepol_policydb_t * p,
|
|
int (*fn) (const sepol_node_t * node,
|
|
void *fn_arg), void *arg)
|
|
{
|
|
|
|
const policydb_t *policydb = &p->p;
|
|
ocontext_t *c, *head;
|
|
sepol_node_t *node = NULL;
|
|
int status;
|
|
|
|
head = policydb->ocontexts[OCON_NODE];
|
|
for (c = head; c; c = c->next) {
|
|
if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node)
|
|
< 0)
|
|
goto err;
|
|
|
|
/* Invoke handler */
|
|
status = fn(node, arg);
|
|
if (status < 0)
|
|
goto err;
|
|
|
|
sepol_node_free(node);
|
|
node = NULL;
|
|
|
|
/* Handler requested exit */
|
|
if (status > 0)
|
|
break;
|
|
}
|
|
|
|
head = policydb->ocontexts[OCON_NODE6];
|
|
for (c = head; c; c = c->next) {
|
|
if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node)
|
|
< 0)
|
|
goto err;
|
|
|
|
/* Invoke handler */
|
|
status = fn(node, arg);
|
|
if (status < 0)
|
|
goto err;
|
|
|
|
sepol_node_free(node);
|
|
node = NULL;
|
|
|
|
/* Handler requested exit */
|
|
if (status > 0)
|
|
break;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
ERR(handle, "could not iterate over nodes");
|
|
sepol_node_free(node);
|
|
return STATUS_ERR;
|
|
}
|