summaryrefslogtreecommitdiffstats
path: root/sechecker/modules/inc_net_access.c
diff options
context:
space:
mode:
Diffstat (limited to 'sechecker/modules/inc_net_access.c')
-rw-r--r--sechecker/modules/inc_net_access.c1852
1 files changed, 1852 insertions, 0 deletions
diff --git a/sechecker/modules/inc_net_access.c b/sechecker/modules/inc_net_access.c
new file mode 100644
index 0000000..a8903ea
--- /dev/null
+++ b/sechecker/modules/inc_net_access.c
@@ -0,0 +1,1852 @@
+/**
+ * @file
+ * Defines the interface for the incomplete network access module.
+ *
+ * @author Kevin Carr kcarr@tresys.com
+ * @author Jeremy A. Mowery jmowery@tresys.com
+ * @author Jason Tang jtang@tresys.com
+ * @author David Windsor dwindsor@tresys.com
+ *
+ * Copyright (C) 2005-2007 Tresys Technology, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "inc_net_access.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+static const char *const mod_name = "inc_net_access";
+
+/* The register function registers all of a module's functions
+ * with the library. You should not need to edit this function
+ * unless you are adding additional functions you need other modules
+ * to call. See the note at the bottom of this function to do so. */
+int inc_net_access_register(sechk_lib_t * lib)
+{
+ sechk_module_t *mod = NULL;
+ sechk_fn_t *fn_struct = NULL;
+
+ if (!lib) {
+ ERR(NULL, "%s", "No library");
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Modules are declared by the config file and their name and options
+ * are stored in the module array. The name is looked up to determine
+ * where to store the function structures */
+ mod = sechk_lib_get_module(mod_name, lib);
+ if (!mod) {
+ ERR(NULL, "%s", "Module unknown");
+ errno = EINVAL;
+ return -1;
+ }
+ mod->parent_lib = lib;
+
+ /* assign the descriptions */
+ mod->brief_description = "finds network domains with inadequate permissions";
+ mod->detailed_description =
+ "--------------------------------------------------------------------------------\n"
+ "This module finds all network domains in a policy which do not have the \n"
+ "required permissions needed to facilitate network communication. For network\n"
+ "domains to communicate, the following conditions must be true:\n"
+ " 1) the domain must have read or receive permissions on a socket of the same\n"
+ " type\n"
+ " 2) the domain must have send or receive permissions on an IPsec association\n"
+ " (see find_assoc_types)\n"
+ " 3) the domain must have send or receive permissions on netif objects for a\n"
+ " netif type (see find_netif_types)\n"
+ " 4) the domain must have send or receive permissions on node objects for a\n"
+ " node type (see find_node_types)\n"
+ " 5) the domain must have send or receive permissions on port objects for a\n"
+ " port type (see find_port_types)\n";
+ mod->opt_description =
+ " Module requirements:\n"
+ " none\n" " Module dependencies:\n" " find_net_domains\n" " Module options:\n" " none\n";
+ mod->severity = SECHK_SEV_MED;
+ /* assign dependencies */
+ if (apol_vector_append(mod->dependencies, sechk_name_value_new("module", "find_net_domains")) < 0) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* register functions */
+ fn_struct = sechk_fn_new();
+ if (!fn_struct) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->name = strdup(SECHK_MOD_FN_INIT);
+ if (!fn_struct->name) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->fn = inc_net_access_init;
+ if (apol_vector_append(mod->functions, (void *)fn_struct) < 0) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ fn_struct = sechk_fn_new();
+ if (!fn_struct) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->name = strdup(SECHK_MOD_FN_RUN);
+ if (!fn_struct->name) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->fn = inc_net_access_run;
+ if (apol_vector_append(mod->functions, (void *)fn_struct) < 0) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ mod->data_free = NULL;
+
+ fn_struct = sechk_fn_new();
+ if (!fn_struct) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->name = strdup(SECHK_MOD_FN_PRINT);
+ if (!fn_struct->name) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->fn = inc_net_access_print;
+ if (apol_vector_append(mod->functions, (void *)fn_struct) < 0) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ return 0;
+}
+
+/* The init function creates the module's private data storage object
+ * and initializes its values based on the options parsed in the config
+ * file.
+ * Add any option processing logic as indicated below. */
+int inc_net_access_init(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
+{
+ if (!mod || !policy) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return -1;
+ }
+ if (strcmp(mod_name, mod->name)) {
+ ERR(policy, "Wrong module (%s)", mod->name);
+ errno = EINVAL;
+ return -1;
+ }
+
+ mod->data = NULL;
+
+ return 0;
+}
+
+/* This set of defines represents individual permission bits for
+ * the permissions needed to have complete network access */
+/* allow domain self : sock_file {read write getattr}; */
+#define PERM_SELF_SOCK_FILE_READ 0x00000001
+#define PERM_SELF_SOCK_FILE_WRITE 0x00000002
+#define PERM_SELF_SOCK_FILE_GETATTR 0x00000004
+/* allow domain self : tcp_socket {create read write}; */
+#define PERM_SELF_TCP_SOC_READ 0x00000008
+#define PERM_SELF_TCP_SOC_WRITE 0x00000010
+#define PERM_SELF_TCP_SOC_CREATE 0x00000020
+/* allow domain self : udp_socket {create read write}; */
+#define PERM_SELF_UDP_SOC_READ 0x00000040
+#define PERM_SELF_UDP_SOC_WRITE 0x00000080
+#define PERM_SELF_UDP_SOC_CREATE 0x00000100
+/* allow domain if_type : netif {tcp_send udp_send tcp_recv tcp_send}; */
+#define PERM_NETIF_TCP_SEND 0x00000200
+#define PERM_NETIF_UDP_SEND 0x00000400
+#define PERM_NETIF_TCP_RECV 0x00000800
+#define PERM_NETIF_UDP_RECV 0x00001000
+/* allow domain node_type : node {tcp_send udp_send tcp_recv tcp_send}; */
+#define PERM_NODE_TCP_SEND 0x00002000
+#define PERM_NODE_UDP_SEND 0x00004000
+#define PERM_NODE_TCP_RECV 0x00008000
+#define PERM_NODE_UDP_RECV 0x00010000
+/* allow domain port_type : tcp_socket {send_msg recv_msg}; */
+#define PERM_PORT_TCP_SEND 0x00020000
+#define PERM_PORT_TCP_RECV 0x00040000
+/* allow domain port_type : udp_socket {send_msg recv_msg}; */
+#define PERM_PORT_UDP_SEND 0x00080000
+#define PERM_PORT_UDP_RECV 0x00100000
+/* allow domain assoc_type : association {sendto recvfrom}; */
+#define PERM_ASSOC_SEND 0x00200000
+#define PERM_ASSOC_RECV 0x00400000
+
+/* this set of defines represents masks for individual rules */
+#define RULE_TCP_SOCK_FILE (PERM_SELF_SOCK_FILE_READ|PERM_SELF_SOCK_FILE_WRITE|PERM_SELF_SOCK_FILE_GETATTR)
+#define RULE_UDPs_SOCK_FILE (PERM_SELF_SOCK_FILE_WRITE|PERM_SELF_SOCK_FILE_GETATTR)
+#define RULE_UDPr_SOCK_FILE (PERM_SELF_SOCK_FILE_READ|PERM_SELF_SOCK_FILE_GETATTR)
+#define RULE_TCP_SELF_SOC (PERM_SELF_TCP_SOC_READ|PERM_SELF_TCP_SOC_WRITE|PERM_SELF_TCP_SOC_CREATE)
+#define RULE_UDPs_SELF_SOC (PERM_SELF_UDP_SOC_WRITE|PERM_SELF_UDP_SOC_CREATE)
+#define RULE_UDPr_SELF_SOC (PERM_SELF_UDP_SOC_READ|PERM_SELF_UDP_SOC_CREATE)
+#define RULE_TCP_NETIF (PERM_NETIF_TCP_SEND|PERM_NETIF_TCP_RECV)
+#define RULE_UDPs_NETIF (PERM_NETIF_UDP_SEND)
+#define RULE_UDPr_NETIF (PERM_NETIF_UDP_RECV)
+#define RULE_TCP_NODE (PERM_NODE_TCP_SEND|PERM_NODE_TCP_RECV)
+#define RULE_UDPs_NODE (PERM_NODE_UDP_SEND)
+#define RULE_UDPr_NODE (PERM_NODE_UDP_RECV)
+#define RULE_TCP_PORT (PERM_PORT_TCP_SEND|PERM_PORT_TCP_RECV)
+#define RULE_UDPs_PORT (PERM_PORT_UDP_SEND)
+#define RULE_UDPr_PORT (PERM_PORT_UDP_RECV)
+#define RULE_TCP_ASSOC (PERM_ASSOC_SEND|PERM_ASSOC_RECV)
+#define RULE_UDPs_ASSOC (PERM_ASSOC_SEND)
+#define RULE_UDPr_ASSOC (PERM_ASSOC_RECV)
+
+/* This set of defines represents mask sets to represent access types */
+#define UDP_RECV_PERM_SET (RULE_UDPr_SOCK_FILE|RULE_UDPr_SELF_SOC|RULE_UDPr_NETIF|RULE_UDPr_NODE|RULE_UDPr_PORT|RULE_UDPr_ASSOC)
+#define UDP_SEND_PERM_SET (RULE_UDPs_SOCK_FILE|RULE_UDPs_SELF_SOC|RULE_UDPs_NETIF|RULE_UDPs_NODE|RULE_UDPs_PORT|RULE_UDPs_ASSOC)
+#define TCP_FULL_PERM_SET (RULE_TCP_SOCK_FILE|RULE_TCP_SELF_SOC|RULE_TCP_NETIF|RULE_TCP_NODE|RULE_TCP_PORT|RULE_TCP_ASSOC)
+#define COMMON_ACCESS_SET (PERM_SELF_SOCK_FILE_READ|PERM_SELF_SOCK_FILE_WRITE|PERM_SELF_SOCK_FILE_GETATTR|PERM_ASSOC_SEND|PERM_ASSOC_RECV)
+
+typedef struct net_state
+{
+ uint32_t perms;
+ apol_vector_t *netifs;
+ apol_vector_t *nodes;
+ apol_vector_t *tcpsocs;
+ apol_vector_t *udpsocs;
+ apol_vector_t *assocs;
+} net_state_t;
+
+typedef struct name_perm
+{
+ const char *name; /* will be from policy do not free */
+ uint32_t perms;
+} name_perm_t;
+
+static void net_state_destroy(net_state_t ** n)
+{
+ if (!n || !(*n))
+ return;
+
+ apol_vector_destroy(&((*n)->netifs));
+ apol_vector_destroy(&((*n)->nodes));
+ apol_vector_destroy(&((*n)->tcpsocs));
+ apol_vector_destroy(&((*n)->udpsocs));
+ apol_vector_destroy(&((*n)->assocs));
+ free(*n);
+ *n = NULL;
+}
+
+static net_state_t *net_state_create(void)
+{
+ net_state_t *n = NULL;
+
+ n = calloc(1, sizeof(*n));
+ n->netifs = apol_vector_create(free);
+ n->nodes = apol_vector_create(free);
+ n->tcpsocs = apol_vector_create(free);
+ n->udpsocs = apol_vector_create(free);
+ n->assocs = apol_vector_create(free);
+
+ return n;
+}
+
+static int name_perm_comp(const void *a, const void *b, void *arg __attribute__ ((unused)))
+{
+ const name_perm_t *x = a;
+ const name_perm_t *y = b;
+
+ return strcmp(x->name, y->name);
+}
+
+static name_perm_t *name_perm_create(const char *name)
+{
+ name_perm_t *np = NULL;
+
+ np = calloc(1, sizeof(*np));
+ np->name = name;
+
+ return np;
+}
+
+static int name_perm_vector_has_incomplete_perms(apol_vector_t * v, uint32_t mask)
+{
+ uint32_t tmp;
+ name_perm_t *np = NULL;
+ size_t i = 0;
+
+ if (!apol_vector_get_size(v))
+ return 1;
+ for (i = 0; i < apol_vector_get_size(v); i++) {
+ np = apol_vector_get_element(v, i);
+ tmp = np->perms & mask;
+ if (tmp != mask)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void name_perm_vector_add_perm(apol_vector_t * v, const char *name, uint32_t perm)
+{
+ name_perm_t *np = NULL;
+ size_t i = 0;
+ int retv;
+
+ np = name_perm_create(name);
+ retv = apol_vector_get_index(v, np, name_perm_comp, NULL, &i);
+ if (retv) {
+ np->perms = perm;
+ apol_vector_append(v, (void *)np);
+ } else {
+ free(np); /* already exists free temp one */
+ np = apol_vector_get_element(v, i);
+ np->perms |= perm;
+ }
+}
+
+static char *generate_tcp_proof_text(const char *domain, net_state_t * state)
+{
+ char *text = NULL, *tmp = NULL;
+ size_t text_sz = 0, i;
+ uint32_t attempt = 0, missing = 0;
+ name_perm_t *np = NULL;
+
+ if (state->perms == TCP_FULL_PERM_SET) {
+ if (apol_str_append(&text, &text_sz, "Domain has TCP access, but some accesses are incomplete."))
+ goto err;
+ } else {
+ if (apol_str_append(&text, &text_sz, "Domain has incomplete TCP access."))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tsock_file permissions:"))
+ goto err;
+ attempt = state->perms & RULE_TCP_SOCK_FILE;
+ missing = attempt ^ RULE_TCP_SOCK_FILE;
+ asprintf(&tmp, "allow %s self : sock_file { ", domain);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_SELF_SOCK_FILE_READ) {
+ if (apol_str_append(&text, &text_sz, "read "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_SOCK_FILE_WRITE) {
+ if (apol_str_append(&text, &text_sz, "write "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_SOCK_FILE_GETATTR) {
+ if (apol_str_append(&text, &text_sz, "getattr "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_SELF_SOCK_FILE_READ) {
+ if (apol_str_append(&text, &text_sz, "read "))
+ goto err;
+ }
+ if (missing & PERM_SELF_SOCK_FILE_WRITE) {
+ if (apol_str_append(&text, &text_sz, "write "))
+ goto err;
+ }
+ if (missing & PERM_SELF_SOCK_FILE_GETATTR) {
+ if (apol_str_append(&text, &text_sz, "getattr "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+
+ if (apol_str_append(&text, &text_sz, "\n\tsocket creation permissions:"))
+ goto err;
+ attempt = state->perms & RULE_TCP_SELF_SOC;
+ missing = attempt ^ RULE_TCP_SELF_SOC;
+ asprintf(&tmp, "allow %s self : tcp_socket { ", domain);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_SELF_TCP_SOC_READ) {
+ if (apol_str_append(&text, &text_sz, "read "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_TCP_SOC_WRITE) {
+ if (apol_str_append(&text, &text_sz, "write "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_TCP_SOC_CREATE) {
+ if (apol_str_append(&text, &text_sz, "create "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_SELF_TCP_SOC_READ) {
+ if (apol_str_append(&text, &text_sz, "read "))
+ goto err;
+ }
+ if (missing & PERM_SELF_TCP_SOC_WRITE) {
+ if (apol_str_append(&text, &text_sz, "write "))
+ goto err;
+ }
+ if (missing & PERM_SELF_TCP_SOC_CREATE) {
+ if (apol_str_append(&text, &text_sz, "create "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+
+ if (apol_str_append(&text, &text_sz, "\n\tnetif permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->netifs); i++) {
+ np = apol_vector_get_element(state->netifs, i);
+ attempt = state->perms & RULE_TCP_NETIF;
+ missing = attempt ^ RULE_TCP_NETIF;
+ asprintf(&tmp, "allow %s %s : netif { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_NETIF_TCP_SEND) {
+ if (apol_str_append(&text, &text_sz, "tcp_send "))
+ goto err;
+ }
+ if (attempt & PERM_NETIF_TCP_RECV) {
+ if (apol_str_append(&text, &text_sz, "tcp_recv "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_NETIF_TCP_SEND) {
+ if (apol_str_append(&text, &text_sz, "tcp_send "))
+ goto err;
+ }
+ if (missing & PERM_NETIF_TCP_RECV) {
+ if (apol_str_append(&text, &text_sz, "tcp_recv "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->netifs)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <netif_type> : netif { tcp_send tcp_recv };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tnode permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->nodes); i++) {
+ np = apol_vector_get_element(state->nodes, i);
+ attempt = state->perms & RULE_TCP_NODE;
+ missing = attempt ^ RULE_TCP_NODE;
+ asprintf(&tmp, "allow %s %s : node { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_NODE_TCP_SEND) {
+ if (apol_str_append(&text, &text_sz, "tcp_send "))
+ goto err;
+ }
+ if (attempt & PERM_NODE_TCP_RECV) {
+ if (apol_str_append(&text, &text_sz, "tcp_recv "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_NODE_TCP_SEND) {
+ if (apol_str_append(&text, &text_sz, "tcp_send "))
+ goto err;
+ }
+ if (missing & PERM_NODE_TCP_RECV) {
+ if (apol_str_append(&text, &text_sz, "tcp_recv "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->nodes)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <node_type> : node { tcp_send tcp_recv };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tport socket permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->tcpsocs); i++) {
+ np = apol_vector_get_element(state->tcpsocs, i);
+ attempt = state->perms & RULE_TCP_PORT;
+ missing = attempt ^ RULE_TCP_PORT;
+ asprintf(&tmp, "allow %s %s : tcp_socket { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_PORT_TCP_SEND) {
+ if (apol_str_append(&text, &text_sz, "send_msg "))
+ goto err;
+ }
+ if (attempt & PERM_PORT_TCP_RECV) {
+ if (apol_str_append(&text, &text_sz, "recv_msg "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_PORT_TCP_SEND) {
+ if (apol_str_append(&text, &text_sz, "send_msg "))
+ goto err;
+ }
+ if (missing & PERM_PORT_TCP_RECV) {
+ if (apol_str_append(&text, &text_sz, "recv_msg "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->tcpsocs)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <port_type> : tcp_socket { send_msg recv_msg };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tassociation permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->assocs); i++) {
+ np = apol_vector_get_element(state->assocs, i);
+ attempt = state->perms & RULE_TCP_ASSOC;
+ missing = attempt ^ RULE_TCP_ASSOC;
+ asprintf(&tmp, "allow %s %s : association { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_ASSOC_SEND) {
+ if (apol_str_append(&text, &text_sz, "sendto "))
+ goto err;
+ }
+ if (attempt & PERM_ASSOC_RECV) {
+ if (apol_str_append(&text, &text_sz, "recvfrom "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_ASSOC_SEND) {
+ if (apol_str_append(&text, &text_sz, "sendto "))
+ goto err;
+ }
+ if (missing & PERM_ASSOC_RECV) {
+ if (apol_str_append(&text, &text_sz, "recvfrom "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->assocs)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <association_type> : association { sendto recvfrom };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n"))
+ goto err;
+
+ return text;
+
+ err:
+ free(text);
+ free(tmp);
+ return NULL;
+}
+
+static char *generate_udp_send_proof_text(const char *domain, net_state_t * state)
+{
+ char *text = NULL, *tmp = NULL;
+ size_t text_sz = 0, i;
+ uint32_t attempt = 0, missing = 0;
+ name_perm_t *np = NULL;
+
+ if (state->perms == UDP_SEND_PERM_SET) {
+ if (apol_str_append(&text, &text_sz, "Domain has UDP send access, but some accesses are incomplete."))
+ goto err;
+ } else {
+ if (apol_str_append(&text, &text_sz, "Domain has incomplete UDP send access."))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tsock_file permissions:"))
+ goto err;
+ attempt = state->perms & RULE_UDPs_SOCK_FILE;
+ missing = attempt ^ RULE_UDPs_SOCK_FILE;
+ asprintf(&tmp, "allow %s self : sock_file { ", domain);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_SELF_SOCK_FILE_WRITE) {
+ if (apol_str_append(&text, &text_sz, "write "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_SOCK_FILE_GETATTR) {
+ if (apol_str_append(&text, &text_sz, "getattr "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_SELF_SOCK_FILE_WRITE) {
+ if (apol_str_append(&text, &text_sz, "write "))
+ goto err;
+ }
+ if (missing & PERM_SELF_SOCK_FILE_GETATTR) {
+ if (apol_str_append(&text, &text_sz, "getattr "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+
+ if (apol_str_append(&text, &text_sz, "\n\tsocket creation permissions:"))
+ goto err;
+ attempt = state->perms & RULE_UDPs_SELF_SOC;
+ missing = attempt ^ RULE_UDPs_SELF_SOC;
+ asprintf(&tmp, "allow %s self : udp_socket { ", domain);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_SELF_UDP_SOC_WRITE) {
+ if (apol_str_append(&text, &text_sz, "write "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_UDP_SOC_CREATE) {
+ if (apol_str_append(&text, &text_sz, "create "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_SELF_UDP_SOC_WRITE) {
+ if (apol_str_append(&text, &text_sz, "write "))
+ goto err;
+ }
+ if (missing & PERM_SELF_UDP_SOC_CREATE) {
+ if (apol_str_append(&text, &text_sz, "create "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+
+ if (apol_str_append(&text, &text_sz, "\n\tnetif permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->netifs); i++) {
+ np = apol_vector_get_element(state->netifs, i);
+ attempt = state->perms & RULE_UDPs_NETIF;
+ missing = attempt ^ RULE_UDPs_NETIF;
+ asprintf(&tmp, "allow %s %s : netif { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_NETIF_UDP_SEND) {
+ if (apol_str_append(&text, &text_sz, "udp_send "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_NETIF_UDP_SEND) {
+ if (apol_str_append(&text, &text_sz, "udp_send "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->netifs)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <netif_type> : netif { udp_send };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tnode permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->nodes); i++) {
+ np = apol_vector_get_element(state->nodes, i);
+ attempt = state->perms & RULE_UDPs_NODE;
+ missing = attempt ^ RULE_UDPs_NODE;
+ asprintf(&tmp, "allow %s %s : node { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_NODE_UDP_SEND) {
+ if (apol_str_append(&text, &text_sz, "udp_send "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_NODE_UDP_SEND) {
+ if (apol_str_append(&text, &text_sz, "udp_send "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->nodes)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <node_type> : node { udp_send };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tport socket permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->udpsocs); i++) {
+ np = apol_vector_get_element(state->udpsocs, i);
+ attempt = state->perms & RULE_UDPs_PORT;
+ missing = attempt ^ RULE_UDPs_PORT;
+ asprintf(&tmp, "allow %s %s : udp_socket { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_PORT_UDP_SEND) {
+ if (apol_str_append(&text, &text_sz, "send_msg "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_PORT_UDP_SEND) {
+ if (apol_str_append(&text, &text_sz, "send_msg "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->udpsocs)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <port_type> : udp_socket { send_msg };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tassociation permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->assocs); i++) {
+ np = apol_vector_get_element(state->assocs, i);
+ attempt = state->perms & RULE_UDPs_ASSOC;
+ missing = attempt ^ RULE_UDPs_ASSOC;
+ asprintf(&tmp, "allow %s %s : association { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_ASSOC_SEND) {
+ if (apol_str_append(&text, &text_sz, "sendto "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_ASSOC_SEND) {
+ if (apol_str_append(&text, &text_sz, "sendto "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->assocs)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <association_type> : association { sendto };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n"))
+ goto err;
+
+ return text;
+
+ err:
+ free(text);
+ free(tmp);
+ return NULL;
+}
+
+static char *generate_udp_recv_proof_text(const char *domain, net_state_t * state)
+{
+ char *text = NULL, *tmp = NULL;
+ size_t text_sz = 0, i;
+ uint32_t attempt = 0, missing = 0;
+ name_perm_t *np = NULL;
+
+ if (state->perms == UDP_RECV_PERM_SET) {
+ if (apol_str_append(&text, &text_sz, "Domain has UDP receive access, but some accesses are incomplete."))
+ goto err;
+ } else {
+ if (apol_str_append(&text, &text_sz, "Domain has incomplete UDP receive access."))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tsock_file permissions:"))
+ goto err;
+ attempt = state->perms & RULE_UDPr_SOCK_FILE;
+ missing = attempt ^ RULE_UDPr_SOCK_FILE;
+ asprintf(&tmp, "allow %s self : sock_file { ", domain);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_SELF_SOCK_FILE_READ) {
+ if (apol_str_append(&text, &text_sz, "read "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_SOCK_FILE_GETATTR) {
+ if (apol_str_append(&text, &text_sz, "getattr "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_SELF_SOCK_FILE_READ) {
+ if (apol_str_append(&text, &text_sz, "read "))
+ goto err;
+ }
+ if (missing & PERM_SELF_SOCK_FILE_GETATTR) {
+ if (apol_str_append(&text, &text_sz, "getattr "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+
+ if (apol_str_append(&text, &text_sz, "\n\tsocket creation permissions:"))
+ goto err;
+ attempt = state->perms & RULE_UDPr_SELF_SOC;
+ missing = attempt ^ RULE_UDPr_SELF_SOC;
+ asprintf(&tmp, "allow %s self : udp_socket { ", domain);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_SELF_UDP_SOC_READ) {
+ if (apol_str_append(&text, &text_sz, "read "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_UDP_SOC_CREATE) {
+ if (apol_str_append(&text, &text_sz, "create "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_SELF_UDP_SOC_READ) {
+ if (apol_str_append(&text, &text_sz, "read "))
+ goto err;
+ }
+ if (missing & PERM_SELF_UDP_SOC_CREATE) {
+ if (apol_str_append(&text, &text_sz, "create "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+
+ if (apol_str_append(&text, &text_sz, "\n\tnetif permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->netifs); i++) {
+ np = apol_vector_get_element(state->netifs, i);
+ attempt = state->perms & RULE_UDPr_NETIF;
+ missing = attempt ^ RULE_UDPr_NETIF;
+ asprintf(&tmp, "allow %s %s : netif { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_NETIF_UDP_RECV) {
+ if (apol_str_append(&text, &text_sz, "udp_recv "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_NETIF_UDP_RECV) {
+ if (apol_str_append(&text, &text_sz, "udp_recv "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->netifs)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <netif_type> : netif { udp_recv };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tnode permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->nodes); i++) {
+ np = apol_vector_get_element(state->nodes, i);
+ attempt = state->perms & RULE_UDPr_NODE;
+ missing = attempt ^ RULE_UDPr_NODE;
+ asprintf(&tmp, "allow %s %s : node { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_NODE_UDP_RECV) {
+ if (apol_str_append(&text, &text_sz, "udp_recv "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_NODE_UDP_RECV) {
+ if (apol_str_append(&text, &text_sz, "udp_recv "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->nodes)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <node_type> : node { udp_recv };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tport socket permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->udpsocs); i++) {
+ np = apol_vector_get_element(state->udpsocs, i);
+ attempt = state->perms & RULE_UDPr_PORT;
+ missing = attempt ^ RULE_UDPr_PORT;
+ asprintf(&tmp, "allow %s %s : udp_socket { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_PORT_UDP_RECV) {
+ if (apol_str_append(&text, &text_sz, "recv_msg "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_PORT_UDP_RECV) {
+ if (apol_str_append(&text, &text_sz, "recv_msg "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->udpsocs)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <port_type> : udp_socket { recv_msg };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n\tassociation permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->assocs); i++) {
+ np = apol_vector_get_element(state->assocs, i);
+ attempt = state->perms & RULE_UDPr_ASSOC;
+ missing = attempt ^ RULE_UDPr_ASSOC;
+ asprintf(&tmp, "allow %s %s : association { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_ASSOC_RECV) {
+ if (apol_str_append(&text, &text_sz, "recvfrom "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ if (missing) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (missing & PERM_ASSOC_RECV) {
+ if (apol_str_append(&text, &text_sz, "recvfrom "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+ if (!apol_vector_get_size(state->assocs)) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tMissing: allow "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, domain))
+ goto err;
+ if (apol_str_append(&text, &text_sz, " <association_type> : association { recvfrom };"))
+ goto err;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n"))
+ goto err;
+
+ return text;
+
+ err:
+ free(text);
+ free(tmp);
+ return NULL;
+}
+
+static char *generate_common_only_proof_text(const char *domain, net_state_t * state)
+{
+ char *text = NULL, *tmp = NULL;
+ size_t text_sz = 0, i;
+ uint32_t attempt = 0;
+ name_perm_t *np = NULL;
+
+ if (apol_str_append
+ (&text, &text_sz,
+ "Domain has incomplete network access.\n\tDomain has no protocol specific permissions only the following:"))
+ goto err;
+
+ if (apol_str_append(&text, &text_sz, "\n\tsock_file permissions:"))
+ goto err;
+ attempt = state->perms & RULE_TCP_SOCK_FILE;
+ asprintf(&tmp, "allow %s self : sock_file { ", domain);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_SELF_SOCK_FILE_READ) {
+ if (apol_str_append(&text, &text_sz, "read "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_SOCK_FILE_WRITE) {
+ if (apol_str_append(&text, &text_sz, "write "))
+ goto err;
+ }
+ if (attempt & PERM_SELF_SOCK_FILE_GETATTR) {
+ if (apol_str_append(&text, &text_sz, "getattr "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+
+ if (apol_str_append(&text, &text_sz, "\n\tassociation permissions:"))
+ goto err;
+ for (i = 0; i < apol_vector_get_size(state->assocs); i++) {
+ np = apol_vector_get_element(state->assocs, i);
+ attempt = state->perms & RULE_TCP_ASSOC;
+ asprintf(&tmp, "allow %s %s : association { ", domain, np->name);
+ if (attempt) {
+ if (apol_str_append(&text, &text_sz, "\n\t\tHas: "))
+ goto err;
+ if (apol_str_append(&text, &text_sz, tmp))
+ goto err;
+ if (attempt & PERM_ASSOC_SEND) {
+ if (apol_str_append(&text, &text_sz, "sendto "))
+ goto err;
+ }
+ if (attempt & PERM_ASSOC_RECV) {
+ if (apol_str_append(&text, &text_sz, "recvfrom "))
+ goto err;
+ }
+ if (apol_str_append(&text, &text_sz, "};"))
+ goto err;
+ }
+ free(tmp);
+ tmp = NULL;
+ }
+
+ if (apol_str_append(&text, &text_sz, "\n"))
+ goto err;
+
+ return text;
+
+ err:
+ free(text);
+ free(tmp);
+ return NULL;
+}
+
+/* The run function performs the check. This function runs only once
+ * even if called multiple times. This function allocates the result
+ * structure and fills in all relavant item and proof data.
+ * Return Values:
+ * -1 System error
+ * 0 The module "succeeded" - no negative results found
+ * 1 The module "failed" - some negative results found */
+int inc_net_access_run(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
+{
+ sechk_result_t *res = NULL;
+ sechk_item_t *item = NULL, *tmp_item = NULL;
+ sechk_proof_t *proof = NULL;
+ sechk_result_t *net_domain_res = NULL;
+ sechk_name_value_t *dep = NULL;
+ sechk_mod_fn_t run_fn = NULL;
+ size_t i = 0, j = 0;
+ int error = 0;
+ apol_avrule_query_t *avrule_query = NULL;
+ apol_vector_t *avrule_vector = NULL, *net_domain_vector = NULL;
+ const qpol_type_t *net_domain = NULL, *tmp_type = NULL;
+ const char *net_domain_name = NULL, *tgt_name = NULL;
+ char *perm_name = NULL;
+ const qpol_avrule_t *rule = NULL;
+ qpol_iterator_t *iter = NULL;
+ qpol_policy_t *q = apol_policy_get_qpol(policy);
+ net_state_t *state = NULL;
+
+ if (!mod || !policy) {
+ ERR(policy, "%s", "Invalid parameters");
+ errno = EINVAL;
+ return -1;
+ }
+ if (strcmp(mod_name, mod->name)) {
+ ERR(policy, "Wrong module (%s)", mod->name);
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* if already run return */
+ if (mod->result)
+ return 0;
+
+ res = sechk_result_new();
+ if (!res) {
+ ERR(policy, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ res->test_name = strdup(mod_name);
+ if (!res->test_name) {
+ error = errno;
+ ERR(policy, "%s", strerror(ENOMEM));
+ goto inc_net_access_run_fail;
+ }
+ res->item_type = SECHK_ITEM_TYPE;
+ if (!(res->items = apol_vector_create(sechk_item_free))) {
+ error = errno;
+ ERR(policy, "%s", strerror(ENOMEM));
+ goto inc_net_access_run_fail;
+ }
+
+ /* run dependencies */
+ for (i = 0; i < apol_vector_get_size(mod->dependencies); i++) {
+ dep = apol_vector_get_element(mod->dependencies, i);
+ run_fn = sechk_lib_get_module_function(dep->value, SECHK_MOD_FN_RUN, mod->parent_lib);
+ run_fn(sechk_lib_get_module(dep->value, mod->parent_lib), policy, NULL);
+ }
+
+ net_domain_res = sechk_lib_get_module_result("find_net_domains", mod->parent_lib);
+ if (!net_domain_res) {
+ error = errno;
+ ERR(policy, "%s", "Unable to get results for module find_net_domains");
+ goto inc_net_access_run_fail;
+ }
+ net_domain_vector = (apol_vector_t *) net_domain_res->items;
+
+ avrule_query = apol_avrule_query_create();
+ if (!avrule_query) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ apol_avrule_query_set_rules(policy, avrule_query, QPOL_RULE_ALLOW);
+
+ for (i = 0; i < apol_vector_get_size(net_domain_vector); i++) {
+ tmp_item = apol_vector_get_element(net_domain_vector, i);
+ net_domain = tmp_item->item;
+ qpol_type_get_name(q, net_domain, &net_domain_name);
+ state = net_state_create();
+
+ /* find any self sock_file perms */
+ apol_avrule_query_set_source(policy, avrule_query, net_domain_name, 1);
+ apol_avrule_query_set_target(policy, avrule_query, net_domain_name, 1);
+ apol_avrule_query_append_class(policy, avrule_query, NULL);
+ apol_avrule_query_append_class(policy, avrule_query, "sock_file");
+ apol_avrule_get_by_query(policy, avrule_query, &avrule_vector);
+ for (j = 0; j < apol_vector_get_size(avrule_vector); j++) {
+ rule = apol_vector_get_element(avrule_vector, j);
+ qpol_avrule_get_perm_iter(q, rule, &iter);
+ for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
+ qpol_iterator_get_item(iter, (void **)(&perm_name));
+ if (!strcmp(perm_name, "read")) {
+ state->perms |= PERM_SELF_SOCK_FILE_READ;
+ } else if (!strcmp(perm_name, "write")) {
+ state->perms |= PERM_SELF_SOCK_FILE_WRITE;
+ } else if (!strcmp(perm_name, "getattr")) {
+ state->perms |= PERM_SELF_SOCK_FILE_GETATTR;
+ } /* no general case else */
+ free(perm_name);
+ perm_name = NULL;
+ }
+ qpol_iterator_destroy(&iter);
+ }
+ apol_vector_destroy(&avrule_vector);
+
+ /* find any self tcp_socket perms */
+ apol_avrule_query_append_class(policy, avrule_query, NULL);
+ apol_avrule_query_append_class(policy, avrule_query, "tcp_socket");
+ apol_avrule_get_by_query(policy, avrule_query, &avrule_vector);
+ for (j = 0; j < apol_vector_get_size(avrule_vector); j++) {
+ rule = apol_vector_get_element(avrule_vector, j);
+ qpol_avrule_get_perm_iter(q, rule, &iter);
+ for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
+ qpol_iterator_get_item(iter, (void **)(&perm_name));
+ if (!strcmp(perm_name, "read")) {
+ state->perms |= PERM_SELF_TCP_SOC_READ;
+ } else if (!strcmp(perm_name, "write")) {
+ state->perms |= PERM_SELF_TCP_SOC_WRITE;
+ } else if (!strcmp(perm_name, "create")) {
+ state->perms |= PERM_SELF_TCP_SOC_CREATE;
+ } /* no general case else */
+ free(perm_name);
+ perm_name = NULL;
+ }
+ qpol_iterator_destroy(&iter);
+ }
+ apol_vector_destroy(&avrule_vector);
+
+ /* find any self udp_socket perms */
+ apol_avrule_query_append_class(policy, avrule_query, NULL);
+ apol_avrule_query_append_class(policy, avrule_query, "udp_socket");
+ apol_avrule_get_by_query(policy, avrule_query, &avrule_vector);
+ for (j = 0; j < apol_vector_get_size(avrule_vector); j++) {
+ rule = apol_vector_get_element(avrule_vector, j);
+ qpol_avrule_get_perm_iter(q, rule, &iter);
+ for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
+ qpol_iterator_get_item(iter, (void **)(&perm_name));
+ if (!strcmp(perm_name, "read")) {
+ state->perms |= PERM_SELF_UDP_SOC_READ;
+ } else if (!strcmp(perm_name, "write")) {
+ state->perms |= PERM_SELF_UDP_SOC_WRITE;
+ } else if (!strcmp(perm_name, "create")) {
+ state->perms |= PERM_SELF_UDP_SOC_CREATE;
+ } /* no general case else */
+ free(perm_name);
+ perm_name = NULL;
+ }
+ qpol_iterator_destroy(&iter);
+ }
+ apol_vector_destroy(&avrule_vector);
+
+ /* find any if_t netif perms */
+ apol_avrule_query_set_target(policy, avrule_query, NULL, 0);
+ apol_avrule_query_append_class(policy, avrule_query, NULL);
+ apol_avrule_query_append_class(policy, avrule_query, "netif");
+ apol_avrule_get_by_query(policy, avrule_query, &avrule_vector);
+ for (j = 0; j < apol_vector_get_size(avrule_vector); j++) {
+ rule = apol_vector_get_element(avrule_vector, j);
+ qpol_avrule_get_target_type(q, rule, &tmp_type);
+ qpol_type_get_name(q, tmp_type, &tgt_name);
+ qpol_avrule_get_perm_iter(q, rule, &iter);
+ for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
+ qpol_iterator_get_item(iter, (void **)(&perm_name));
+ if (!strcmp(perm_name, "tcp_send")) {
+ state->perms |= PERM_NETIF_TCP_SEND;
+ name_perm_vector_add_perm(state->netifs, tgt_name, PERM_NETIF_TCP_SEND);
+ } else if (!strcmp(perm_name, "tcp_recv")) {
+ state->perms |= PERM_NETIF_TCP_RECV;
+ name_perm_vector_add_perm(state->netifs, tgt_name, PERM_NETIF_TCP_RECV);
+ } else if (!strcmp(perm_name, "udp_send")) {
+ state->perms |= PERM_NETIF_UDP_SEND;
+ name_perm_vector_add_perm(state->netifs, tgt_name, PERM_NETIF_UDP_SEND);
+ } else if (!strcmp(perm_name, "udp_recv")) {
+ state->perms |= PERM_NETIF_UDP_RECV;
+ name_perm_vector_add_perm(state->netifs, tgt_name, PERM_NETIF_UDP_RECV);
+ } /* no general case else */
+ free(perm_name);
+ perm_name = NULL;
+ }
+ qpol_iterator_destroy(&iter);
+ }
+ apol_vector_destroy(&avrule_vector);
+
+ /* find any node_t node perms */
+ apol_avrule_query_append_class(policy, avrule_query, NULL);
+ apol_avrule_query_append_class(policy, avrule_query, "node");
+ apol_avrule_get_by_query(policy, avrule_query, &avrule_vector);
+ for (j = 0; j < apol_vector_get_size(avrule_vector); j++) {
+ rule = apol_vector_get_element(avrule_vector, j);
+ qpol_avrule_get_target_type(q, rule, &tmp_type);
+ qpol_type_get_name(q, tmp_type, &tgt_name);
+ qpol_avrule_get_perm_iter(q, rule, &iter);
+ for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
+ qpol_iterator_get_item(iter, (void **)(&perm_name));
+ if (!strcmp(perm_name, "tcp_send")) {
+ state->perms |= PERM_NODE_TCP_SEND;
+ name_perm_vector_add_perm(state->nodes, tgt_name, PERM_NODE_TCP_SEND);
+ } else if (!strcmp(perm_name, "tcp_recv")) {
+ state->perms |= PERM_NODE_TCP_RECV;
+ name_perm_vector_add_perm(state->nodes, tgt_name, PERM_NODE_TCP_RECV);
+ } else if (!strcmp(perm_name, "udp_send")) {
+ state->perms |= PERM_NODE_UDP_SEND;
+ name_perm_vector_add_perm(state->nodes, tgt_name, PERM_NODE_UDP_SEND);
+ } else if (!strcmp(perm_name, "udp_recv")) {
+ state->perms |= PERM_NODE_UDP_RECV;
+ name_perm_vector_add_perm(state->nodes, tgt_name, PERM_NODE_UDP_RECV);
+ } /* no general case else */
+ free(perm_name);
+ perm_name = NULL;
+ }
+ qpol_iterator_destroy(&iter);
+ }
+ apol_vector_destroy(&avrule_vector);
+
+ /* find any port_t tcp_socket perms */
+ apol_avrule_query_append_class(policy, avrule_query, NULL);
+ apol_avrule_query_append_class(policy, avrule_query, "tcp_socket");
+ apol_avrule_get_by_query(policy, avrule_query, &avrule_vector);
+ for (j = 0; j < apol_vector_get_size(avrule_vector); j++) {
+ rule = apol_vector_get_element(avrule_vector, j);
+ qpol_avrule_get_target_type(q, rule, &tmp_type);
+ qpol_type_get_name(q, tmp_type, &tgt_name);
+ /* skip self */
+ if (!strcmp(net_domain_name, tgt_name))
+ continue;
+ qpol_avrule_get_perm_iter(q, rule, &iter);
+ for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
+ qpol_iterator_get_item(iter, (void **)(&perm_name));
+ if (!strcmp(perm_name, "send_msg")) {
+ state->perms |= PERM_PORT_TCP_SEND;
+ name_perm_vector_add_perm(state->tcpsocs, tgt_name, PERM_PORT_TCP_SEND);
+ } else if (!strcmp(perm_name, "recv_msg")) {
+ state->perms |= PERM_PORT_TCP_RECV;
+ name_perm_vector_add_perm(state->tcpsocs, tgt_name, PERM_PORT_TCP_RECV);
+ } /* no general case else */
+ free(perm_name);
+ perm_name = NULL;
+ }
+ qpol_iterator_destroy(&iter);
+ }
+ apol_vector_destroy(&avrule_vector);
+
+ /* find any port_t udp_socket perms */
+ apol_avrule_query_append_class(policy, avrule_query, NULL);
+ apol_avrule_query_append_class(policy, avrule_query, "udp_socket");
+ apol_avrule_get_by_query(policy, avrule_query, &avrule_vector);
+ for (j = 0; j < apol_vector_get_size(avrule_vector); j++) {
+ rule = apol_vector_get_element(avrule_vector, j);
+ qpol_avrule_get_target_type(q, rule, &tmp_type);
+ qpol_type_get_name(q, tmp_type, &tgt_name);
+ /* skip self */
+ if (!strcmp(net_domain_name, tgt_name))
+ continue;
+ qpol_avrule_get_perm_iter(q, rule, &iter);
+ for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
+ qpol_iterator_get_item(iter, (void **)(&perm_name));
+ if (!strcmp(perm_name, "send_msg")) {
+ state->perms |= PERM_PORT_UDP_SEND;
+ name_perm_vector_add_perm(state->udpsocs, tgt_name, PERM_PORT_UDP_SEND);
+ } else if (!strcmp(perm_name, "recv_msg")) {
+ state->perms |= PERM_PORT_UDP_RECV;
+ name_perm_vector_add_perm(state->udpsocs, tgt_name, PERM_PORT_UDP_RECV);
+ } /* no general case else */
+ free(perm_name);
+ perm_name = NULL;
+ }
+ qpol_iterator_destroy(&iter);
+ }
+ apol_vector_destroy(&avrule_vector);
+
+ /* find any assoc_t association perms */
+ apol_avrule_query_append_class(policy, avrule_query, NULL);
+ apol_avrule_query_append_class(policy, avrule_query, "association");
+ apol_avrule_get_by_query(policy, avrule_query, &avrule_vector);
+ for (j = 0; j < apol_vector_get_size(avrule_vector); j++) {
+ rule = apol_vector_get_element(avrule_vector, j);
+ qpol_avrule_get_target_type(q, rule, &tmp_type);
+ qpol_type_get_name(q, tmp_type, &tgt_name);
+ qpol_avrule_get_perm_iter(q, rule, &iter);
+ for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
+ qpol_iterator_get_item(iter, (void **)(&perm_name));
+ if (!strcmp(perm_name, "sendto")) {
+ state->perms |= PERM_ASSOC_SEND;
+ name_perm_vector_add_perm(state->assocs, tgt_name, PERM_ASSOC_SEND);
+ } else if (!strcmp(perm_name, "recvfrom")) {
+ state->perms |= PERM_ASSOC_RECV;
+ name_perm_vector_add_perm(state->assocs, tgt_name, PERM_ASSOC_RECV);
+ } /* no general case else */
+ free(perm_name);
+ perm_name = NULL;
+ }
+ qpol_iterator_destroy(&iter);
+ }
+ apol_vector_destroy(&avrule_vector);
+
+ /* if has tcp perms check for missing ones */
+ if ((state->perms & ((~(COMMON_ACCESS_SET)) & (TCP_FULL_PERM_SET))) &&
+ ((state->perms & RULE_TCP_SOCK_FILE) != RULE_TCP_SOCK_FILE ||
+ (state->perms & RULE_TCP_SELF_SOC) != RULE_TCP_SELF_SOC ||
+ name_perm_vector_has_incomplete_perms(state->netifs, RULE_TCP_NETIF) ||
+ name_perm_vector_has_incomplete_perms(state->nodes, RULE_TCP_NODE) ||
+ name_perm_vector_has_incomplete_perms(state->tcpsocs, RULE_TCP_PORT) ||
+ name_perm_vector_has_incomplete_perms(state->assocs, RULE_TCP_ASSOC))) {
+ item = sechk_item_new(NULL);
+ if (!item) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ item->item = (void *)net_domain;
+ item->test_result = 1;
+ item->proof = apol_vector_create(sechk_proof_free);
+ if (!item->proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof = sechk_proof_new(NULL);
+ if (!proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof->type = SECHK_ITEM_NONE;
+ proof->elem = NULL;
+ proof->text = generate_tcp_proof_text(net_domain_name, state);
+ //TODO check that it succeeded
+ if (apol_vector_append(item->proof, (void *)proof)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof = NULL;
+ }
+ /* if has udp send perms check for missing perms */
+ if ((state->perms & ((~(COMMON_ACCESS_SET | PERM_SELF_UDP_SOC_CREATE)) & (UDP_SEND_PERM_SET))) &&
+ ((state->perms & RULE_UDPs_SOCK_FILE) != RULE_UDPs_SOCK_FILE ||
+ (state->perms & RULE_UDPs_SELF_SOC) != RULE_UDPs_SELF_SOC ||
+ name_perm_vector_has_incomplete_perms(state->netifs, RULE_UDPs_NETIF) ||
+ name_perm_vector_has_incomplete_perms(state->nodes, RULE_UDPs_NODE) ||
+ name_perm_vector_has_incomplete_perms(state->udpsocs, RULE_UDPs_PORT) ||
+ name_perm_vector_has_incomplete_perms(state->assocs, RULE_UDPs_ASSOC))) {
+ if (!item) {
+ item = sechk_item_new(NULL);
+ if (!item) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ item->item = (void *)net_domain;
+ item->test_result = 1;
+ item->proof = apol_vector_create(sechk_proof_free);
+ if (!item->proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ }
+ proof = sechk_proof_new(NULL);
+ if (!proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof->type = SECHK_ITEM_NONE;
+ proof->elem = NULL;
+ proof->text = generate_udp_send_proof_text(net_domain_name, state);
+ //TODO check that it succeeded
+ if (apol_vector_append(item->proof, (void *)proof)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof = NULL;
+ }
+ /* if has udp reveive perms check for missing perms */
+ if ((state->perms & ((~(COMMON_ACCESS_SET | PERM_SELF_UDP_SOC_CREATE)) & (UDP_RECV_PERM_SET))) &&
+ ((state->perms & RULE_UDPr_SOCK_FILE) != RULE_UDPr_SOCK_FILE ||
+ (state->perms & RULE_UDPr_SELF_SOC) != RULE_UDPr_SELF_SOC ||
+ name_perm_vector_has_incomplete_perms(state->netifs, RULE_UDPr_NETIF) ||
+ name_perm_vector_has_incomplete_perms(state->nodes, RULE_UDPr_NODE) ||
+ name_perm_vector_has_incomplete_perms(state->udpsocs, RULE_UDPr_PORT) ||
+ name_perm_vector_has_incomplete_perms(state->assocs, RULE_UDPr_ASSOC))) {
+ if (!item) {
+ item = sechk_item_new(NULL);
+ if (!item) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ item->item = (void *)net_domain;
+ item->test_result = 1;
+ item->proof = apol_vector_create(sechk_proof_free);
+ if (!item->proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ }
+ proof = sechk_proof_new(NULL);
+ if (!proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof->type = SECHK_ITEM_NONE;
+ proof->elem = NULL;
+ proof->text = generate_udp_recv_proof_text(net_domain_name, state);
+ //TODO check that it succeeded
+ if (apol_vector_append(item->proof, (void *)proof)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof = NULL;
+ }
+ /* if has only common access perms report that */
+ if (!(state->perms & (~(COMMON_ACCESS_SET)))) {
+ item = sechk_item_new(NULL);
+ if (!item) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ item->item = (void *)net_domain;
+ item->test_result = 1;
+ item->proof = apol_vector_create(sechk_proof_free);
+ if (!item->proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof = sechk_proof_new(NULL);
+ if (!proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof->type = SECHK_ITEM_NONE;
+ proof->elem = NULL;
+ proof->text = generate_common_only_proof_text(net_domain_name, state);
+ //TODO check that it succeeded
+ if (apol_vector_append(item->proof, (void *)proof)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ proof = NULL;
+ }
+
+ if (item) {
+ if (apol_vector_append(res->items, (void *)item)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto inc_net_access_run_fail;
+ }
+ item = NULL;
+ }
+ net_state_destroy(&state);
+ }
+ mod->result = res;
+
+ if (apol_vector_get_size(res->items))
+ return 1;
+ return 0;
+
+ inc_net_access_run_fail:
+ apol_avrule_query_destroy(&avrule_query);
+ apol_vector_destroy(&avrule_vector);
+ qpol_iterator_destroy(&iter);
+ free(perm_name);
+ net_state_destroy(&state);
+ sechk_item_free(item);
+ sechk_proof_free(proof);
+ sechk_result_destroy(&res);
+ errno = error;
+ return -1;
+}
+
+/* The print function generates the text and prints the
+ * results to stdout. */
+int inc_net_access_print(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
+{
+ unsigned char outformat = 0x00;
+ sechk_item_t *item = NULL;
+ sechk_proof_t *proof = NULL;
+ size_t i = 0, j = 0, k = 0, l = 0, num_items;
+ const qpol_type_t *type;
+ qpol_policy_t *q = apol_policy_get_qpol(policy);
+ const char *type_name;
+
+ if (!mod || !policy) {
+ ERR(policy, "%s", "Invalid parameters");
+ errno = EINVAL;
+ return -1;
+ }
+ if (strcmp(mod_name, mod->name)) {
+ ERR(policy, "Wrong module (%s)", mod->name);
+ errno = EINVAL;
+ return -1;
+ }
+
+ outformat = mod->outputformat;
+ num_items = apol_vector_get_size(mod->result->items);
+
+ if (!mod->result) {
+ ERR(policy, "%s", "Module has not been run");
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (!outformat || (outformat & SECHK_OUT_QUIET))
+ return 0; /* not an error - no output is requested */
+
+ if (outformat & SECHK_OUT_STATS) {
+ printf("Found %i network domains with insufficient permissions.\n", num_items);
+ }
+
+ /* Print current permissions then the permissions that are missing */
+ if (outformat & SECHK_OUT_PROOF) {
+ printf("\n");
+ for (k = 0; k < num_items; k++) {
+ item = apol_vector_get_element(mod->result->items, k);
+ if (item) {
+ type = item->item;
+ qpol_type_get_name(q, type, &type_name);
+ printf("%s\n", (char *)type_name);
+ for (l = 0; l < apol_vector_get_size(item->proof); l++) {
+ proof = apol_vector_get_element(item->proof, l);
+ if (proof)
+ printf("\t%s\n", proof->text);
+ }
+ }
+ }
+ printf("\n");
+ }
+
+ i = 0;
+ if (outformat & SECHK_OUT_LIST) {
+ printf("\n");
+ for (i = 0; i < num_items; i++) {
+ j++;
+ item = apol_vector_get_element(mod->result->items, i);
+ type = item->item;
+ qpol_type_get_name(q, type, &type_name);
+ j %= 4;
+ printf("%s%s", type_name, (char *)((j && i != num_items - 1) ? ", " : "\n"));
+ }
+ printf("\n");
+ }
+
+ return 0;
+}