Blame src/policy_components.c

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
}