|
Packit Service |
102278 |
/* Copyright (C) 2005 Red Hat, Inc. */
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
#include <stdlib.h>
|
|
Packit Service |
102278 |
#include "policy.h"
|
|
Packit Service |
102278 |
#include "handle.h"
|
|
Packit Service |
102278 |
#include "database.h"
|
|
Packit Service |
102278 |
#include "modules.h"
|
|
Packit Service |
102278 |
#include "debug.h"
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Powers of two only */
|
|
Packit Service |
102278 |
#define MODE_SET 1
|
|
Packit Service |
102278 |
#define MODE_MODIFY 2
|
|
Packit Service |
102278 |
#define MODE_SORT 4
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static int clear_obsolete(semanage_handle_t * handle,
|
|
Packit Service |
102278 |
record_t ** records,
|
|
Packit Service |
102278 |
unsigned int nrecords,
|
|
Packit Service |
102278 |
dbase_config_t * src, dbase_config_t * dst)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
record_key_t *key = NULL;
|
|
Packit Service |
102278 |
unsigned int i;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
dbase_table_t *src_dtable = src->dtable;
|
|
Packit Service |
102278 |
dbase_table_t *dst_dtable = dst->dtable;
|
|
Packit Service |
102278 |
record_table_t *rtable = src_dtable->get_rtable(src->dbase);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < nrecords; i++) {
|
|
Packit Service |
102278 |
int exists;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (rtable->key_extract(handle, records[i], &key) < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (dst_dtable->exists(handle, dst->dbase, key, &exists) < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!exists) {
|
|
Packit Service |
102278 |
if (src_dtable->del(handle, src->dbase, key) < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rtable->free(records[i]);
|
|
Packit Service |
102278 |
records[i] = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* FIXME: notice to user */
|
|
Packit Service |
102278 |
/* INFO(handle, "boolean %s is obsolete, unsetting configured value..."); */
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rtable->key_free(key);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return STATUS_SUCCESS;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
err:
|
|
Packit Service |
102278 |
/* FIXME: handle error */
|
|
Packit Service |
102278 |
rtable->key_free(key);
|
|
Packit Service |
102278 |
return STATUS_ERR;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static int load_records(semanage_handle_t * handle,
|
|
Packit Service |
102278 |
dbase_config_t * dst,
|
|
Packit Service |
102278 |
record_t ** records, unsigned int nrecords, int mode)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
unsigned int i;
|
|
Packit Service |
102278 |
record_key_t *rkey = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
dbase_t *dbase = dst->dbase;
|
|
Packit Service |
102278 |
dbase_table_t *dtable = dst->dtable;
|
|
Packit Service |
102278 |
record_table_t *rtable = dtable->get_rtable(dbase);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < nrecords; i++) {
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Possibly obsoleted */
|
|
Packit Service |
102278 |
if (!records[i])
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (rtable->key_extract(handle, records[i], &rkey) < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (mode & MODE_SET &&
|
|
Packit Service |
102278 |
dtable->set(handle, dbase, rkey, records[i]) < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
else if (mode & MODE_MODIFY &&
|
|
Packit Service |
102278 |
dtable->modify(handle, dbase, rkey, records[i]) < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rtable->key_free(rkey);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return STATUS_SUCCESS;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
err:
|
|
Packit Service |
102278 |
/* FIXME: handle error */
|
|
Packit Service |
102278 |
rtable->key_free(rkey);
|
|
Packit Service |
102278 |
return STATUS_ERR;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
typedef struct load_table {
|
|
Packit Service |
102278 |
dbase_config_t *src;
|
|
Packit Service |
102278 |
dbase_config_t *dst;
|
|
Packit Service |
102278 |
int mode;
|
|
Packit Service |
102278 |
} load_table_t;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* This function must be called AFTER all modules are loaded.
|
|
Packit Service |
102278 |
* Modules could be represented as a database, in which case
|
|
Packit Service |
102278 |
* they should be loaded at the beginning of this function */
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int semanage_base_merge_components(semanage_handle_t * handle)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
unsigned int i, j;
|
|
Packit Service |
102278 |
int rc = STATUS_SUCCESS;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Order is important here - change things carefully.
|
|
Packit Service |
102278 |
* System components first, local next. Verify runs with
|
|
Packit Service |
102278 |
* mutual dependencies are ran after everything is merged */
|
|
Packit Service |
102278 |
load_table_t components[] = {
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
{semanage_user_base_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_user_base_dbase_policy(handle), MODE_MODIFY},
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
{semanage_user_extra_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_user_extra_dbase_policy(handle), MODE_MODIFY},
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
{semanage_port_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_port_dbase_policy(handle), MODE_MODIFY},
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
{semanage_iface_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_iface_dbase_policy(handle), MODE_MODIFY},
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
{semanage_bool_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_bool_dbase_policy(handle), MODE_SET},
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
{semanage_seuser_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_seuser_dbase_policy(handle), MODE_MODIFY},
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
{semanage_node_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_node_dbase_policy(handle), MODE_MODIFY | MODE_SORT},
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
{semanage_ibpkey_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_ibpkey_dbase_policy(handle), MODE_MODIFY},
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
{semanage_ibendport_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_ibendport_dbase_policy(handle), MODE_MODIFY},
|
|
Packit Service |
102278 |
};
|
|
Packit Service |
102278 |
const unsigned int CCOUNT = sizeof(components) / sizeof(components[0]);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Merge components into policy (and validate) */
|
|
Packit Service |
102278 |
for (i = 0; i < CCOUNT; i++) {
|
|
Packit Service |
102278 |
record_t **records = NULL;
|
|
Packit Service |
102278 |
unsigned int nrecords = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
dbase_config_t *src = components[i].src;
|
|
Packit Service |
102278 |
dbase_config_t *dst = components[i].dst;
|
|
Packit Service |
102278 |
int mode = components[i].mode;
|
|
Packit Service |
102278 |
record_table_t *rtable = src->dtable->get_rtable(src->dbase);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Must invoke cache function first */
|
|
Packit Service |
102278 |
if (src->dtable->cache(handle, src->dbase) < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
if (dst->dtable->cache(handle, dst->dbase) < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* List all records */
|
|
Packit Service |
102278 |
if (src->dtable->list(handle, src->dbase,
|
|
Packit Service |
102278 |
&records, &nrecords) < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Sort records on MODE_SORT */
|
|
Packit Service |
102278 |
if (mode & MODE_SORT) {
|
|
Packit Service |
102278 |
qsort(records, nrecords, sizeof(record_t *),
|
|
Packit Service |
102278 |
(int (*)(const void *, const void *))rtable->
|
|
Packit Service |
102278 |
compare2_qsort);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Clear obsolete ones for MODE_SET */
|
|
Packit Service |
102278 |
if (mode & MODE_SET &&
|
|
Packit Service |
102278 |
clear_obsolete(handle, records, nrecords, src, dst) < 0) {
|
|
Packit Service |
102278 |
rc = STATUS_ERR;
|
|
Packit Service |
102278 |
goto dbase_exit;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Load records */
|
|
Packit Service |
102278 |
if (load_records(handle, dst, records, nrecords, mode) < 0) {
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rc = STATUS_ERR;
|
|
Packit Service |
102278 |
goto dbase_exit;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Cleanup */
|
|
Packit Service |
102278 |
dbase_exit:
|
|
Packit Service |
102278 |
for (j = 0; j < nrecords; j++)
|
|
Packit Service |
102278 |
rtable->free(records[j]);
|
|
Packit Service |
102278 |
free(records);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Abort on error */
|
|
Packit Service |
102278 |
if (rc < 0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return rc;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
err:
|
|
Packit Service |
102278 |
ERR(handle, "could not merge local modifications into policy");
|
|
Packit Service |
102278 |
return STATUS_ERR;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int semanage_commit_components(semanage_handle_t * handle)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int i;
|
|
Packit Service |
102278 |
dbase_config_t *components[] = {
|
|
Packit Service |
102278 |
semanage_iface_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_bool_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_user_base_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_user_extra_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_user_extra_dbase_policy(handle),
|
|
Packit Service |
102278 |
semanage_port_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_fcontext_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_fcontext_dbase_policy(handle),
|
|
Packit Service |
102278 |
semanage_seuser_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_seuser_dbase_policy(handle),
|
|
Packit Service |
102278 |
semanage_bool_dbase_active(handle),
|
|
Packit Service |
102278 |
semanage_node_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_ibpkey_dbase_local(handle),
|
|
Packit Service |
102278 |
semanage_ibendport_dbase_local(handle),
|
|
Packit Service |
102278 |
};
|
|
Packit Service |
102278 |
const int CCOUNT = sizeof(components) / sizeof(components[0]);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < CCOUNT; i++) {
|
|
Packit Service |
102278 |
/* Flush to disk */
|
|
Packit Service |
102278 |
if (components[i]->dtable->flush(handle, components[i]->dbase) <
|
|
Packit Service |
102278 |
0)
|
|
Packit Service |
102278 |
goto err;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return STATUS_SUCCESS;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
err:
|
|
Packit Service |
102278 |
ERR(handle, "could not commit local/active modifications");
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < CCOUNT; i++)
|
|
Packit Service |
102278 |
components[i]->dtable->drop_cache(components[i]->dbase);
|
|
Packit Service |
102278 |
return STATUS_ERR;
|
|
Packit Service |
102278 |
}
|