/*
 * Author: Mary Garvin <mgarvin@tresys.com>
 *
 * Copyright (C) 2007-2008 Tresys Technology, LLC
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "test-downgrade.h"
#include "parse_util.h"
#include "helpers.h"

#include <sepol/debug.h>
#include <sepol/handle.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/link.h>
#include <sepol/policydb/expand.h>
#include <sepol/policydb/conditional.h>
#include <limits.h>
#include <CUnit/Basic.h>

#define POLICY_BIN_HI	"policies/test-downgrade/policy.hi"
#define POLICY_BIN_LO	"policies/test-downgrade/policy.lo"

static policydb_t policydb;

/*
 * Function Name:  downgrade_test_init
 *
 * Input: None
 *
 * Output: None
 *
 * Description: Initialize the policydb (policy data base structure)
 */
int downgrade_test_init(void)
{
	/* Initialize the policydb_t structure */
	if (policydb_init(&policydb)) {
		fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
		return -1;
	}

	return 0;
}

/*
 * Function Name:  downgrade_test_cleanup
 *
 * Input: None
 *
 * Output: None
 *
 * Description: Destroys policydb structure
 */
int downgrade_test_cleanup(void)
{
	policydb_destroy(&policydb);

	return 0;
}

/*
 * Function Name: downgrade_add_tests
 *
 * Input: CU_pSuite
 *
 * Output: Returns 0 upon success.  Returns a CUnit error value on failure.
 *
 * Description:  Add the given downgrade tests to the downgrade suite.
 */
int downgrade_add_tests(CU_pSuite suite)
{
	if (CU_add_test(suite, "downgrade", test_downgrade) == NULL)
		return CU_get_error();

	return 0;
}

/*
 * Function Name:  test_downgrade_possible
 *
 * Input: None
 *
 * Output: None
 *
 * Description:
 * Tests the backward compatability of MLS and Non-MLS binary policy versions.
 */
void test_downgrade(void)
{
	if (do_downgrade_test(0) < 0)
		fprintf(stderr,
		        "\nError during downgrade testing of Non-MLS policy\n");


	if (do_downgrade_test(1) < 0)
		fprintf(stderr,
			"\nError during downgrade testing of MLS policy\n");
}

/*
 * Function Name:  do_downgrade_test
 *
 * Input: 0 for Non-MLS policy and 1 for MLS policy downgrade testing
 *
 * Output: 0 on success, negative number upon failure
 *
 * Description: This function handles the downgrade testing.
 *              A binary policy is read into the policydb structure, the
 *              policy version is decreased by a specific amount, written
 *              back out and then read back in again.  The process is
 *              repeated until the minimum policy version is reached.
 */
int do_downgrade_test(int mls)
{
	policydb_t policydb_tmp;
	int hi, lo, version;

	/* Reset policydb for re-use */
	policydb_destroy(&policydb);
	downgrade_test_init();

	/* Read in the hi policy from file */
	if (read_binary_policy(POLICY_BIN_HI, &policydb) != 0) {
		fprintf(stderr, "error reading %spolicy binary\n", mls ? "mls " : "");
		CU_FAIL("Unable to read the binary policy");
		return -1;
	}

	/* Change MLS value based on parameter */
	policydb.mls = mls ? 1 : 0;

	for (hi = policydb.policyvers; hi >= POLICYDB_VERSION_MIN; hi--) {
		/* Stash old version number */
		version = policydb.policyvers;

		/* Try downgrading to each possible version. */
		for (lo = hi - 1; lo >= POLICYDB_VERSION_MIN; lo--) {

			/* Reduce policy version */
			policydb.policyvers = lo;

			/* Write out modified binary policy */
			if (write_binary_policy(POLICY_BIN_LO, &policydb) != 0) {
				/*
				 * Error from MLS to pre-MLS is expected due
				 * to MLS re-implementation in version 19.
				 */
				if (mls && lo < POLICYDB_VERSION_MLS)
					continue;

				fprintf(stderr, "error writing %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi);
				CU_FAIL("Failed to write downgraded binary policy");
					return -1;
			}

			/* Make sure we can read back what we wrote. */
			if (policydb_init(&policydb_tmp)) {
				fprintf(stderr, "%s:  Out of memory!\n",
					__FUNCTION__);
				return -1;
			}
			if (read_binary_policy(POLICY_BIN_LO, &policydb_tmp) != 0) {
				fprintf(stderr, "error reading %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi);
				CU_FAIL("Unable to read downgraded binary policy");
				return -1;
			}
			policydb_destroy(&policydb_tmp);
		}
		/* Restore version number */
		policydb.policyvers = version;
    }

    return 0;
}

/*
 * Function Name: read_binary_policy
 *
 * Input: char * which is the path to the file containing the binary policy
 *
 * Output: Returns 0 upon success.  Upon failure, -1 is returned.
 *	   Possible failures are, filename with given path does not exist,
 *	   a failure to open the file, or a failure from prolicydb_read
 *	   function call.
 *
 * Description:  Get a filename, open file and read binary policy into policydb
 * 				 structure.
 */
int read_binary_policy(const char *path, policydb_t *p)
{
	FILE *in_fp = NULL;
	struct policy_file f;
	int rc;

	/* Open the binary policy file */
	if ((in_fp = fopen(path, "rb")) == NULL) {
		fprintf(stderr, "Unable to open %s: %s\n", path,
			strerror(errno));
		sepol_handle_destroy(f.handle);
		return -1;
	}

	/* Read in the binary policy.  */
	memset(&f, 0, sizeof(struct policy_file));
	f.type = PF_USE_STDIO;
	f.fp = in_fp;
	rc = policydb_read(p, &f, 0);

	sepol_handle_destroy(f.handle);
	fclose(in_fp);
	return rc;
}

/*
 * Function Name: write_binary_policy
 *
 * Input: char * which is the path to the file containing the binary policy
 *
 * Output: Returns 0 upon success.  Upon failure, -1 is returned.
 *	   Possible failures are, filename with given path does not exist,
 *	   a failure to open the file, or a failure from prolicydb_read
 *	   function call.
 *
 * Description:  open file and write the binary policy from policydb structure.
 */
int write_binary_policy(const char *path, policydb_t *p)
{
	FILE *out_fp = NULL;
	struct policy_file f;
	sepol_handle_t *handle;
	int rc;

	/* We don't want libsepol to print warnings to stderr */
	handle = sepol_handle_create();
	if (handle == NULL) {
		fprintf(stderr, "Out of memory!\n");
		return -1;
	}
	sepol_msg_set_callback(handle, NULL, NULL);

	/* Open the binary policy file for writing */
	if ((out_fp = fopen(path, "w" )) == NULL) {
		fprintf(stderr, "Unable to open %s: %s\n", path,
			strerror(errno));
		sepol_handle_destroy(f.handle);
		return -1;
	}

	/* Write the binary policy */
	memset(&f, 0, sizeof(struct policy_file));
	f.type = PF_USE_STDIO;
	f.fp = out_fp;
	f.handle = handle;
	rc = policydb_write(p, &f);

	sepol_handle_destroy(f.handle);
	fclose(out_fp);
	return rc;
}
