Blame netlabelctl/map.c

Packit 51d0f7
/*
Packit 51d0f7
 * Domain/Protocol Mapping Functions
Packit 51d0f7
 *
Packit 51d0f7
 * Author: Paul Moore <paul@paul-moore.com>
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
Packit 51d0f7
/*
Packit 51d0f7
 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
Packit 51d0f7
 *
Packit 51d0f7
 * This program is free software: you can redistribute it and/or modify
Packit 51d0f7
 * it under the terms of version 2 of the GNU General Public License as
Packit 51d0f7
 * published by the Free Software Foundation.
Packit 51d0f7
 *
Packit 51d0f7
 * This program is distributed in the hope that it will be useful,
Packit 51d0f7
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 51d0f7
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 51d0f7
 * GNU General Public License for more details.
Packit 51d0f7
 *
Packit 51d0f7
 * You should have received a copy of the GNU General Public License
Packit 51d0f7
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
Packit 51d0f7
#include <stdlib.h>
Packit 51d0f7
#include <stdio.h>
Packit 51d0f7
#include <string.h>
Packit 51d0f7
#include <errno.h>
Packit 51d0f7
#include <sys/types.h>
Packit 51d0f7
#include <sys/socket.h>
Packit 51d0f7
#include <arpa/inet.h>
Packit 51d0f7
Packit 51d0f7
#include <libnetlabel.h>
Packit 51d0f7
Packit 51d0f7
#include "netlabelctl.h"
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Add a domain mapping to NetLabel
Packit 51d0f7
 * @param argc the number of arguments
Packit 51d0f7
 * @param argv the argument list
Packit 51d0f7
 *
Packit 51d0f7
 * Add the specified domain mapping to the NetLabel system.  Returns zero on
Packit 51d0f7
 * success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static int map_add(int argc, char *argv[])
Packit 51d0f7
{
Packit 51d0f7
	uint32_t iter;
Packit 51d0f7
	uint8_t def_flag = 0;
Packit 51d0f7
	struct nlbl_dommap domain;
Packit 51d0f7
	struct nlbl_netaddr addr;
Packit 51d0f7
	char *domain_proto_extra = NULL;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (argc <= 0 || argv == NULL || argv[0] == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
Packit 51d0f7
	memset(&domain, 0, sizeof(domain));
Packit 51d0f7
	memset(&addr, 0, sizeof(addr));
Packit 51d0f7
Packit 51d0f7
	/* parse the arguments */
Packit 51d0f7
	for (iter = 0; iter < argc && argv[iter] != NULL; iter++) {
Packit 51d0f7
		if (strncmp(argv[iter], "domain:", 7) == 0) {
Packit 51d0f7
			domain.domain = argv[iter] + 7;
Packit 51d0f7
		} else if (strncmp(argv[iter], "address:", 8) == 0) {
Packit 51d0f7
			if (nlctl_addr_parse(argv[iter] + 8, &addr) != 0)
Packit 51d0f7
				return -EINVAL;
Packit 51d0f7
		} else if (strncmp(argv[iter], "protocol:", 9) == 0) {
Packit 51d0f7
			/* protocol specifics */
Packit 51d0f7
			if (strncmp(argv[iter] + 9, "cipsov4", 7) == 0 ||
Packit 51d0f7
			    strncmp(argv[iter] + 9, "cipso", 5) == 0) {
Packit 51d0f7
				domain.proto_type = NETLBL_NLTYPE_CIPSOV4;
Packit 51d0f7
				domain.family = AF_INET;
Packit 51d0f7
			} else if (strncmp(argv[iter] + 9, "calipso", 7) == 0) {
Packit 51d0f7
				domain.proto_type = NETLBL_NLTYPE_CALIPSO;
Packit 51d0f7
				domain.family = AF_INET6;
Packit 51d0f7
			} else if (strncmp(argv[iter] + 9, "unlbl", 5) == 0) {
Packit 51d0f7
				domain.proto_type = NETLBL_NLTYPE_UNLABELED;
Packit 51d0f7
				domain.family = AF_UNSPEC;
Packit 51d0f7
			} else {
Packit 51d0f7
				return -EINVAL;
Packit 51d0f7
			}
Packit 51d0f7
			domain_proto_extra = strstr(argv[iter] + 9, ",");
Packit 51d0f7
			if (domain_proto_extra)
Packit 51d0f7
				domain_proto_extra++;
Packit 51d0f7
		} else if (strncmp(argv[iter], "default", 7) == 0) {
Packit 51d0f7
			def_flag = 1;
Packit 51d0f7
		} else
Packit 51d0f7
			return -EINVAL;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* handle the protocol "extra" field */
Packit 51d0f7
	switch (domain.proto_type) {
Packit 51d0f7
	case NETLBL_NLTYPE_CIPSOV4:
Packit 51d0f7
		if (domain_proto_extra == NULL)
Packit 51d0f7
			return -EINVAL;
Packit 51d0f7
		domain.proto.cip_doi = atoi(domain_proto_extra);
Packit 51d0f7
		break;
Packit 51d0f7
	case NETLBL_NLTYPE_CALIPSO:
Packit 51d0f7
		if (domain_proto_extra == NULL)
Packit 51d0f7
			return -EINVAL;
Packit 51d0f7
		domain.proto.clp_doi = atoi(domain_proto_extra);
Packit 51d0f7
		break;
Packit 51d0f7
	case NETLBL_NLTYPE_UNLABELED:
Packit 51d0f7
		if (domain_proto_extra != NULL) {
Packit 51d0f7
			int family = atoi(domain_proto_extra);
Packit 51d0f7
			switch (family) {
Packit 51d0f7
			case 4:
Packit 51d0f7
				domain.family = AF_INET;
Packit 51d0f7
				break;
Packit 51d0f7
			case 6:
Packit 51d0f7
				domain.family = AF_INET6;
Packit 51d0f7
				break;
Packit 51d0f7
			default:
Packit 51d0f7
				return -EINVAL;
Packit 51d0f7
			}
Packit 51d0f7
		}
Packit 51d0f7
		break;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	if (domain.family == AF_UNSPEC && addr.type != 0)
Packit 51d0f7
		domain.family = addr.type;
Packit 51d0f7
Packit 51d0f7
	/* add the mapping */
Packit 51d0f7
	if (def_flag != 0)
Packit 51d0f7
		return nlbl_mgmt_adddef(NULL, &domain, &addr);
Packit 51d0f7
	else
Packit 51d0f7
		return nlbl_mgmt_add(NULL, &domain, &addr);
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Delete a domain mapping from NetLabel
Packit 51d0f7
 * @param argc the number of arguments
Packit 51d0f7
 * @param argv the argument list
Packit 51d0f7
 *
Packit 51d0f7
 * Description:
Packit 51d0f7
 * Remove the specified domain mapping from the NetLabel system.  Returns zero
Packit 51d0f7
 * on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static int map_del(int argc, char *argv[])
Packit 51d0f7
{
Packit 51d0f7
	uint32_t iter;
Packit 51d0f7
	uint32_t def_flag = 0;
Packit 51d0f7
	char *domain = NULL;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (argc <= 0 || argv == NULL || argv[0] == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
Packit 51d0f7
	/* parse the arguments */
Packit 51d0f7
	for (iter = 0; iter < argc && argv[iter] != NULL; iter++) {
Packit 51d0f7
		if (strncmp(argv[iter], "domain:", 7) == 0) {
Packit 51d0f7
			domain = argv[iter] + 7;
Packit 51d0f7
		} else if (strncmp(argv[iter], "default", 7) == 0) {
Packit 51d0f7
			def_flag = 1;
Packit 51d0f7
		} else
Packit 51d0f7
			return -EINVAL;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* remove the mapping */
Packit 51d0f7
	if (def_flag != 0)
Packit 51d0f7
		return nlbl_mgmt_deldef(NULL);
Packit 51d0f7
	else
Packit 51d0f7
		return nlbl_mgmt_del(NULL, domain);
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Output the NetLabel domain mappings
Packit 51d0f7
 * @param mapping the domain mappings
Packit 51d0f7
 * @param count the number of domain mappings
Packit 51d0f7
 *
Packit 51d0f7
 * Helper function to be called by map_list().  Note that we have preserved
Packit 51d0f7
 * the "CIPSOv4" so we don't break any scripts that may be in use.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static void map_list_print(struct nlbl_dommap *mapping, size_t count)
Packit 51d0f7
{
Packit 51d0f7
	uint32_t iter_a;
Packit 51d0f7
	struct nlbl_dommap_addr *iter_b;
Packit 51d0f7
Packit 51d0f7
	for (iter_a = 0; iter_a < count; iter_a++) {
Packit 51d0f7
		/* domain string */
Packit 51d0f7
		printf("domain:");
Packit 51d0f7
		if (mapping[iter_a].domain != NULL)
Packit 51d0f7
			printf("\"%s\",", mapping[iter_a].domain);
Packit 51d0f7
		else
Packit 51d0f7
			printf("DEFAULT,");
Packit 51d0f7
		/* protocol */
Packit 51d0f7
		switch (mapping[iter_a].proto_type) {
Packit 51d0f7
		case NETLBL_NLTYPE_UNLABELED:
Packit 51d0f7
			printf("UNLABELED");
Packit 51d0f7
			if (mapping[iter_a].family == AF_INET)
Packit 51d0f7
				printf(",4");
Packit 51d0f7
			else if (mapping[iter_a].family == AF_INET6)
Packit 51d0f7
				printf(",6");
Packit 51d0f7
			break;
Packit 51d0f7
		case NETLBL_NLTYPE_CIPSOV4:
Packit 51d0f7
			printf("CIPSOv4,%u", mapping[iter_a].proto.cip_doi);
Packit 51d0f7
			break;
Packit 51d0f7
		case NETLBL_NLTYPE_CALIPSO:
Packit 51d0f7
			printf("CALIPSO,%u", mapping[iter_a].proto.clp_doi);
Packit 51d0f7
			break;
Packit 51d0f7
		case NETLBL_NLTYPE_ADDRSELECT:
Packit 51d0f7
			iter_b = mapping[iter_a].proto.addrsel;
Packit 51d0f7
			while (iter_b) {
Packit 51d0f7
				printf("address:");
Packit 51d0f7
				nlctl_addr_print(&iter_b->addr);
Packit 51d0f7
				printf(",protocol:");
Packit 51d0f7
				switch (iter_b->proto_type) {
Packit 51d0f7
				case NETLBL_NLTYPE_UNLABELED:
Packit 51d0f7
					printf("UNLABELED");
Packit 51d0f7
					break;
Packit 51d0f7
				case NETLBL_NLTYPE_CIPSOV4:
Packit 51d0f7
					printf("CIPSOv4,%u",
Packit 51d0f7
					       iter_b->proto.cip_doi);
Packit 51d0f7
					break;
Packit 51d0f7
				case NETLBL_NLTYPE_CALIPSO:
Packit 51d0f7
					printf("CALIPSO,%u",
Packit 51d0f7
					       iter_b->proto.clp_doi);
Packit 51d0f7
					break;
Packit 51d0f7
				default:
Packit 51d0f7
					printf("UNKNOWN(%u)",
Packit 51d0f7
					       iter_b->proto_type);
Packit 51d0f7
					break;
Packit 51d0f7
				}
Packit 51d0f7
				iter_b = iter_b->next;
Packit 51d0f7
				if (iter_b)
Packit 51d0f7
					printf(",");
Packit 51d0f7
			}
Packit 51d0f7
			break;
Packit 51d0f7
		default:
Packit 51d0f7
			printf("UNKNOWN(%u)", mapping[iter_a].proto_type);
Packit 51d0f7
			break;
Packit 51d0f7
		}
Packit 51d0f7
		if (iter_a + 1 < count)
Packit 51d0f7
			printf(" ");
Packit 51d0f7
	}
Packit 51d0f7
	printf("\n");
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Output the NetLabel domain mappings in human readable format
Packit 51d0f7
 * @param mapping the domain mappings
Packit 51d0f7
 * @param count the number of domain mappings
Packit 51d0f7
 *
Packit 51d0f7
 * Helper function to be called by map_list().
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static void map_list_print_pretty(struct nlbl_dommap *mapping, size_t count)
Packit 51d0f7
{
Packit 51d0f7
	uint32_t iter_a;
Packit 51d0f7
	struct nlbl_dommap_addr *iter_b;
Packit 51d0f7
Packit 51d0f7
	printf("Configured NetLabel domain mappings (%zu)\n", count);
Packit 51d0f7
	for (iter_a = 0; iter_a < count; iter_a++) {
Packit 51d0f7
		/* domain string */
Packit 51d0f7
		printf(" domain: ");
Packit 51d0f7
		if (mapping[iter_a].domain != NULL)
Packit 51d0f7
			printf("\"%s\"", mapping[iter_a].domain);
Packit 51d0f7
		else
Packit 51d0f7
			printf("DEFAULT");
Packit 51d0f7
		/* family */
Packit 51d0f7
		if (mapping[iter_a].family == AF_INET)
Packit 51d0f7
			printf(" (IPv4)\n");
Packit 51d0f7
		else if (mapping[iter_a].family == AF_INET6)
Packit 51d0f7
			printf(" (IPv6)\n");
Packit 51d0f7
		else if (mapping[iter_a].family == AF_UNSPEC)
Packit 51d0f7
			printf(" (IPv4/IPv6)\n");
Packit 51d0f7
		/* protocol */
Packit 51d0f7
		switch (mapping[iter_a].proto_type) {
Packit 51d0f7
		case NETLBL_NLTYPE_UNLABELED:
Packit 51d0f7
			printf("   protocol: UNLABELED\n");
Packit 51d0f7
			break;
Packit 51d0f7
		case NETLBL_NLTYPE_CIPSOV4:
Packit 51d0f7
			printf("   protocol: CIPSO, DOI = %u\n",
Packit 51d0f7
			       mapping[iter_a].proto.cip_doi);
Packit 51d0f7
			break;
Packit 51d0f7
		case NETLBL_NLTYPE_CALIPSO:
Packit 51d0f7
			printf("   protocol: CALIPSO, DOI = %u\n",
Packit 51d0f7
			       mapping[iter_a].proto.clp_doi);
Packit 51d0f7
			break;
Packit 51d0f7
		case NETLBL_NLTYPE_ADDRSELECT:
Packit 51d0f7
			iter_b = mapping[iter_a].proto.addrsel;
Packit 51d0f7
			while (iter_b) {
Packit 51d0f7
				printf("   address: ");
Packit 51d0f7
				nlctl_addr_print(&iter_b->addr);
Packit 51d0f7
				printf("\n"
Packit 51d0f7
				       "    protocol: ");
Packit 51d0f7
				switch (iter_b->proto_type) {
Packit 51d0f7
				case NETLBL_NLTYPE_UNLABELED:
Packit 51d0f7
					printf("UNLABELED\n");
Packit 51d0f7
					break;
Packit 51d0f7
				case NETLBL_NLTYPE_CIPSOV4:
Packit 51d0f7
					printf("CIPSO, DOI = %u\n",
Packit 51d0f7
					       iter_b->proto.cip_doi);
Packit 51d0f7
					break;
Packit 51d0f7
				case NETLBL_NLTYPE_CALIPSO:
Packit 51d0f7
					printf("CALIPSO, DOI = %u\n",
Packit 51d0f7
					       iter_b->proto.clp_doi);
Packit 51d0f7
					break;
Packit 51d0f7
				default:
Packit 51d0f7
					printf("UNKNOWN(%u)\n",
Packit 51d0f7
					       iter_b->proto_type);
Packit 51d0f7
					break;
Packit 51d0f7
				}
Packit 51d0f7
				iter_b = iter_b->next;
Packit 51d0f7
			}
Packit 51d0f7
			break;
Packit 51d0f7
		default:
Packit 51d0f7
			printf("UNKNOWN(%u)\n", mapping[iter_a].proto_type);
Packit 51d0f7
			break;
Packit 51d0f7
		}
Packit 51d0f7
	}
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * List the NetLabel domains mappings
Packit 51d0f7
 * @param argc the number of arguments
Packit 51d0f7
 * @param argv the argument list
Packit 51d0f7
 *
Packit 51d0f7
 * List the configured NetLabel domain mappings.  Returns zero on success,
Packit 51d0f7
 * negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static int map_list(int argc, char *argv[])
Packit 51d0f7
{
Packit 51d0f7
	int rc;
Packit 51d0f7
	struct nlbl_dommap *mapping, *mapping_new;
Packit 51d0f7
	size_t count, def_count;
Packit 51d0f7
	uint32_t iter;
Packit 51d0f7
	uint16_t *family, families[] = {AF_INET, AF_INET6, AF_UNSPEC /* terminator */};
Packit 51d0f7
Packit 51d0f7
	/* get the list of mappings */
Packit 51d0f7
	rc = nlbl_mgmt_listall(NULL, &mapping);
Packit 51d0f7
	if (rc < 0)
Packit 51d0f7
		return rc;
Packit 51d0f7
	count = rc;
Packit 51d0f7
Packit 51d0f7
	/* get the default mapping */
Packit 51d0f7
	mapping_new = realloc(mapping, sizeof(*mapping) * (count + 2));
Packit 51d0f7
	if (mapping_new == NULL)
Packit 51d0f7
		goto list_return;
Packit 51d0f7
	mapping = mapping_new;
Packit 51d0f7
	memset(&mapping[count], 0, sizeof(*mapping) * 2);
Packit 51d0f7
Packit 51d0f7
	for (family = families, def_count = 0; *family != AF_UNSPEC; family++) {
Packit 51d0f7
		rc = nlbl_mgmt_listdef(NULL, *family, &mapping[count + def_count]);
Packit 51d0f7
		if (rc < 0 && rc != -ENOENT)
Packit 51d0f7
			goto list_return;
Packit 51d0f7
		else if (rc == 0)
Packit 51d0f7
			def_count += 1;
Packit 51d0f7
		else
Packit 51d0f7
			rc = 0;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* If both defaults are unlabeled then combine them into a single entry */
Packit 51d0f7
	if (def_count == 2 && mapping[count].proto_type == NETLBL_NLTYPE_UNLABELED &&
Packit 51d0f7
	    mapping[count + 1].proto_type == NETLBL_NLTYPE_UNLABELED) {
Packit 51d0f7
		mapping[count].family = AF_UNSPEC;
Packit 51d0f7
		def_count--;
Packit 51d0f7
	}
Packit 51d0f7
	count += def_count;
Packit 51d0f7
Packit 51d0f7
	/* display the results */
Packit 51d0f7
	if (opt_pretty != 0)
Packit 51d0f7
		map_list_print_pretty(mapping, count);
Packit 51d0f7
	else
Packit 51d0f7
		map_list_print(mapping, count);
Packit 51d0f7
Packit 51d0f7
list_return:
Packit 51d0f7
	if (mapping != NULL) {
Packit 51d0f7
		for (iter = 0; iter < count; iter++)
Packit 51d0f7
			if (mapping[iter].domain != NULL)
Packit 51d0f7
				free(mapping[iter].domain);
Packit 51d0f7
		free(mapping);
Packit 51d0f7
	}
Packit 51d0f7
	return rc;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Entry point for the NetLabel mapping functions
Packit 51d0f7
 * @param argc the number of arguments
Packit 51d0f7
 * @param argv the argument list
Packit 51d0f7
 *
Packit 51d0f7
 * Parses the argument list and performs the requested operation.  Returns zero
Packit 51d0f7
 * on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int map_main(int argc, char *argv[])
Packit 51d0f7
{
Packit 51d0f7
	int rc;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (argc <= 0 || argv == NULL || argv[0] == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
Packit 51d0f7
	/* handle the request */
Packit 51d0f7
	if (strcmp(argv[0], "add") == 0) {
Packit 51d0f7
		/* add a domain mapping */
Packit 51d0f7
		rc = map_add(argc - 1, argv + 1);
Packit 51d0f7
	} else if (strcmp(argv[0], "del") == 0) {
Packit 51d0f7
		/* delete a domain mapping */
Packit 51d0f7
		rc = map_del(argc - 1, argv + 1);
Packit 51d0f7
	} else if (strcmp(argv[0], "list") == 0) {
Packit 51d0f7
		/* list the domain mappings */
Packit 51d0f7
		rc = map_list(argc - 1, argv + 1);
Packit 51d0f7
	} else {
Packit 51d0f7
		/* unknown request */
Packit 51d0f7
		rc = -EINVAL;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	return rc;
Packit 51d0f7
}