16cd6a6acSopenharmony_ci#include <stdlib.h>
26cd6a6acSopenharmony_ci
36cd6a6acSopenharmony_ci#include "debug.h"
46cd6a6acSopenharmony_ci#include "context.h"
56cd6a6acSopenharmony_ci#include "handle.h"
66cd6a6acSopenharmony_ci
76cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
86cd6a6acSopenharmony_ci#include <sepol/interfaces.h>
96cd6a6acSopenharmony_ci#include "iface_internal.h"
106cd6a6acSopenharmony_ci
116cd6a6acSopenharmony_ci/* Create a low level structure from record */
126cd6a6acSopenharmony_cistatic int iface_from_record(sepol_handle_t * handle,
136cd6a6acSopenharmony_ci			     const policydb_t * policydb,
146cd6a6acSopenharmony_ci			     ocontext_t ** iface, const sepol_iface_t * record)
156cd6a6acSopenharmony_ci{
166cd6a6acSopenharmony_ci
176cd6a6acSopenharmony_ci	ocontext_t *tmp_iface = NULL;
186cd6a6acSopenharmony_ci	context_struct_t *tmp_con = NULL;
196cd6a6acSopenharmony_ci
206cd6a6acSopenharmony_ci	tmp_iface = (ocontext_t *) calloc(1, sizeof(ocontext_t));
216cd6a6acSopenharmony_ci	if (!tmp_iface)
226cd6a6acSopenharmony_ci		goto omem;
236cd6a6acSopenharmony_ci
246cd6a6acSopenharmony_ci	/* Name */
256cd6a6acSopenharmony_ci	tmp_iface->u.name = strdup(sepol_iface_get_name(record));
266cd6a6acSopenharmony_ci	if (!tmp_iface->u.name)
276cd6a6acSopenharmony_ci		goto omem;
286cd6a6acSopenharmony_ci
296cd6a6acSopenharmony_ci	/* Interface Context */
306cd6a6acSopenharmony_ci	if (context_from_record(handle, policydb,
316cd6a6acSopenharmony_ci				&tmp_con, sepol_iface_get_ifcon(record)) < 0)
326cd6a6acSopenharmony_ci		goto err;
336cd6a6acSopenharmony_ci	context_cpy(&tmp_iface->context[0], tmp_con);
346cd6a6acSopenharmony_ci	context_destroy(tmp_con);
356cd6a6acSopenharmony_ci	free(tmp_con);
366cd6a6acSopenharmony_ci	tmp_con = NULL;
376cd6a6acSopenharmony_ci
386cd6a6acSopenharmony_ci	/* Message Context */
396cd6a6acSopenharmony_ci	if (context_from_record(handle, policydb,
406cd6a6acSopenharmony_ci				&tmp_con, sepol_iface_get_msgcon(record)) < 0)
416cd6a6acSopenharmony_ci		goto err;
426cd6a6acSopenharmony_ci	context_cpy(&tmp_iface->context[1], tmp_con);
436cd6a6acSopenharmony_ci	context_destroy(tmp_con);
446cd6a6acSopenharmony_ci	free(tmp_con);
456cd6a6acSopenharmony_ci	tmp_con = NULL;
466cd6a6acSopenharmony_ci
476cd6a6acSopenharmony_ci	*iface = tmp_iface;
486cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
496cd6a6acSopenharmony_ci
506cd6a6acSopenharmony_ci      omem:
516cd6a6acSopenharmony_ci	ERR(handle, "out of memory");
526cd6a6acSopenharmony_ci
536cd6a6acSopenharmony_ci      err:
546cd6a6acSopenharmony_ci	if (tmp_iface != NULL) {
556cd6a6acSopenharmony_ci		free(tmp_iface->u.name);
566cd6a6acSopenharmony_ci		context_destroy(&tmp_iface->context[0]);
576cd6a6acSopenharmony_ci		context_destroy(&tmp_iface->context[1]);
586cd6a6acSopenharmony_ci		free(tmp_iface);
596cd6a6acSopenharmony_ci	}
606cd6a6acSopenharmony_ci	context_destroy(tmp_con);
616cd6a6acSopenharmony_ci	free(tmp_con);
626cd6a6acSopenharmony_ci	ERR(handle, "error creating interface structure");
636cd6a6acSopenharmony_ci	return STATUS_ERR;
646cd6a6acSopenharmony_ci}
656cd6a6acSopenharmony_ci
666cd6a6acSopenharmony_cistatic int iface_to_record(sepol_handle_t * handle,
676cd6a6acSopenharmony_ci			   const policydb_t * policydb,
686cd6a6acSopenharmony_ci			   ocontext_t * iface, sepol_iface_t ** record)
696cd6a6acSopenharmony_ci{
706cd6a6acSopenharmony_ci
716cd6a6acSopenharmony_ci	char *name = iface->u.name;
726cd6a6acSopenharmony_ci	context_struct_t *ifcon = &iface->context[0];
736cd6a6acSopenharmony_ci	context_struct_t *msgcon = &iface->context[1];
746cd6a6acSopenharmony_ci
756cd6a6acSopenharmony_ci	sepol_context_t *tmp_con = NULL;
766cd6a6acSopenharmony_ci	sepol_iface_t *tmp_record = NULL;
776cd6a6acSopenharmony_ci
786cd6a6acSopenharmony_ci	if (sepol_iface_create(handle, &tmp_record) < 0)
796cd6a6acSopenharmony_ci		goto err;
806cd6a6acSopenharmony_ci
816cd6a6acSopenharmony_ci	if (sepol_iface_set_name(handle, tmp_record, name) < 0)
826cd6a6acSopenharmony_ci		goto err;
836cd6a6acSopenharmony_ci
846cd6a6acSopenharmony_ci	if (context_to_record(handle, policydb, ifcon, &tmp_con) < 0)
856cd6a6acSopenharmony_ci		goto err;
866cd6a6acSopenharmony_ci	if (sepol_iface_set_ifcon(handle, tmp_record, tmp_con) < 0)
876cd6a6acSopenharmony_ci		goto err;
886cd6a6acSopenharmony_ci	sepol_context_free(tmp_con);
896cd6a6acSopenharmony_ci	tmp_con = NULL;
906cd6a6acSopenharmony_ci
916cd6a6acSopenharmony_ci	if (context_to_record(handle, policydb, msgcon, &tmp_con) < 0)
926cd6a6acSopenharmony_ci		goto err;
936cd6a6acSopenharmony_ci	if (sepol_iface_set_msgcon(handle, tmp_record, tmp_con) < 0)
946cd6a6acSopenharmony_ci		goto err;
956cd6a6acSopenharmony_ci	sepol_context_free(tmp_con);
966cd6a6acSopenharmony_ci	tmp_con = NULL;
976cd6a6acSopenharmony_ci
986cd6a6acSopenharmony_ci	*record = tmp_record;
996cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1006cd6a6acSopenharmony_ci
1016cd6a6acSopenharmony_ci      err:
1026cd6a6acSopenharmony_ci	ERR(handle, "could not convert interface %s to record", name);
1036cd6a6acSopenharmony_ci	sepol_context_free(tmp_con);
1046cd6a6acSopenharmony_ci	sepol_iface_free(tmp_record);
1056cd6a6acSopenharmony_ci	return STATUS_ERR;
1066cd6a6acSopenharmony_ci}
1076cd6a6acSopenharmony_ci
1086cd6a6acSopenharmony_ci/* Check if an interface exists */
1096cd6a6acSopenharmony_ciint sepol_iface_exists(sepol_handle_t * handle __attribute__ ((unused)),
1106cd6a6acSopenharmony_ci		       const sepol_policydb_t * p,
1116cd6a6acSopenharmony_ci		       const sepol_iface_key_t * key, int *response)
1126cd6a6acSopenharmony_ci{
1136cd6a6acSopenharmony_ci
1146cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
1156cd6a6acSopenharmony_ci	ocontext_t *c, *head;
1166cd6a6acSopenharmony_ci
1176cd6a6acSopenharmony_ci	const char *name;
1186cd6a6acSopenharmony_ci	sepol_iface_key_unpack(key, &name);
1196cd6a6acSopenharmony_ci
1206cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_NETIF];
1216cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
1226cd6a6acSopenharmony_ci		if (!strcmp(name, c->u.name)) {
1236cd6a6acSopenharmony_ci			*response = 1;
1246cd6a6acSopenharmony_ci			return STATUS_SUCCESS;
1256cd6a6acSopenharmony_ci		}
1266cd6a6acSopenharmony_ci	}
1276cd6a6acSopenharmony_ci	*response = 0;
1286cd6a6acSopenharmony_ci
1296cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1306cd6a6acSopenharmony_ci}
1316cd6a6acSopenharmony_ci
1326cd6a6acSopenharmony_ci/* Query an interface */
1336cd6a6acSopenharmony_ciint sepol_iface_query(sepol_handle_t * handle,
1346cd6a6acSopenharmony_ci		      const sepol_policydb_t * p,
1356cd6a6acSopenharmony_ci		      const sepol_iface_key_t * key, sepol_iface_t ** response)
1366cd6a6acSopenharmony_ci{
1376cd6a6acSopenharmony_ci
1386cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
1396cd6a6acSopenharmony_ci	ocontext_t *c, *head;
1406cd6a6acSopenharmony_ci
1416cd6a6acSopenharmony_ci	const char *name;
1426cd6a6acSopenharmony_ci	sepol_iface_key_unpack(key, &name);
1436cd6a6acSopenharmony_ci
1446cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_NETIF];
1456cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
1466cd6a6acSopenharmony_ci		if (!strcmp(name, c->u.name)) {
1476cd6a6acSopenharmony_ci
1486cd6a6acSopenharmony_ci			if (iface_to_record(handle, policydb, c, response) < 0)
1496cd6a6acSopenharmony_ci				goto err;
1506cd6a6acSopenharmony_ci
1516cd6a6acSopenharmony_ci			return STATUS_SUCCESS;
1526cd6a6acSopenharmony_ci		}
1536cd6a6acSopenharmony_ci	}
1546cd6a6acSopenharmony_ci
1556cd6a6acSopenharmony_ci	*response = NULL;
1566cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1576cd6a6acSopenharmony_ci
1586cd6a6acSopenharmony_ci      err:
1596cd6a6acSopenharmony_ci	ERR(handle, "could not query interface %s", name);
1606cd6a6acSopenharmony_ci	return STATUS_ERR;
1616cd6a6acSopenharmony_ci}
1626cd6a6acSopenharmony_ci
1636cd6a6acSopenharmony_ci/* Load an interface into policy */
1646cd6a6acSopenharmony_ciint sepol_iface_modify(sepol_handle_t * handle,
1656cd6a6acSopenharmony_ci		       sepol_policydb_t * p,
1666cd6a6acSopenharmony_ci		       const sepol_iface_key_t * key,
1676cd6a6acSopenharmony_ci		       const sepol_iface_t * data)
1686cd6a6acSopenharmony_ci{
1696cd6a6acSopenharmony_ci
1706cd6a6acSopenharmony_ci	policydb_t *policydb = &p->p;
1716cd6a6acSopenharmony_ci	ocontext_t *head, *prev, *c, *iface = NULL;
1726cd6a6acSopenharmony_ci
1736cd6a6acSopenharmony_ci	const char *name;
1746cd6a6acSopenharmony_ci	sepol_iface_key_unpack(key, &name);
1756cd6a6acSopenharmony_ci
1766cd6a6acSopenharmony_ci	if (iface_from_record(handle, policydb, &iface, data) < 0)
1776cd6a6acSopenharmony_ci		goto err;
1786cd6a6acSopenharmony_ci
1796cd6a6acSopenharmony_ci	prev = NULL;
1806cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_NETIF];
1816cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
1826cd6a6acSopenharmony_ci		if (!strcmp(name, c->u.name)) {
1836cd6a6acSopenharmony_ci
1846cd6a6acSopenharmony_ci			/* Replace */
1856cd6a6acSopenharmony_ci			iface->next = c->next;
1866cd6a6acSopenharmony_ci			if (prev == NULL)
1876cd6a6acSopenharmony_ci				policydb->ocontexts[OCON_NETIF] = iface;
1886cd6a6acSopenharmony_ci			else
1896cd6a6acSopenharmony_ci				prev->next = iface;
1906cd6a6acSopenharmony_ci			free(c->u.name);
1916cd6a6acSopenharmony_ci			context_destroy(&c->context[0]);
1926cd6a6acSopenharmony_ci			context_destroy(&c->context[1]);
1936cd6a6acSopenharmony_ci			free(c);
1946cd6a6acSopenharmony_ci
1956cd6a6acSopenharmony_ci			return STATUS_SUCCESS;
1966cd6a6acSopenharmony_ci		}
1976cd6a6acSopenharmony_ci		prev = c;
1986cd6a6acSopenharmony_ci	}
1996cd6a6acSopenharmony_ci
2006cd6a6acSopenharmony_ci	/* Attach to context list */
2016cd6a6acSopenharmony_ci	iface->next = policydb->ocontexts[OCON_NETIF];
2026cd6a6acSopenharmony_ci	policydb->ocontexts[OCON_NETIF] = iface;
2036cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2046cd6a6acSopenharmony_ci
2056cd6a6acSopenharmony_ci      err:
2066cd6a6acSopenharmony_ci	ERR(handle, "error while loading interface %s", name);
2076cd6a6acSopenharmony_ci
2086cd6a6acSopenharmony_ci	if (iface != NULL) {
2096cd6a6acSopenharmony_ci		free(iface->u.name);
2106cd6a6acSopenharmony_ci		context_destroy(&iface->context[0]);
2116cd6a6acSopenharmony_ci		context_destroy(&iface->context[1]);
2126cd6a6acSopenharmony_ci		free(iface);
2136cd6a6acSopenharmony_ci	}
2146cd6a6acSopenharmony_ci	return STATUS_ERR;
2156cd6a6acSopenharmony_ci}
2166cd6a6acSopenharmony_ci
2176cd6a6acSopenharmony_ci/* Return the number of interfaces */
2186cd6a6acSopenharmony_ciextern int sepol_iface_count(sepol_handle_t * handle __attribute__ ((unused)),
2196cd6a6acSopenharmony_ci			     const sepol_policydb_t * p, unsigned int *response)
2206cd6a6acSopenharmony_ci{
2216cd6a6acSopenharmony_ci
2226cd6a6acSopenharmony_ci	unsigned int count = 0;
2236cd6a6acSopenharmony_ci	ocontext_t *c, *head;
2246cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
2256cd6a6acSopenharmony_ci
2266cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_NETIF];
2276cd6a6acSopenharmony_ci	for (c = head; c != NULL; c = c->next)
2286cd6a6acSopenharmony_ci		count++;
2296cd6a6acSopenharmony_ci
2306cd6a6acSopenharmony_ci	*response = count;
2316cd6a6acSopenharmony_ci
2326cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2336cd6a6acSopenharmony_ci}
2346cd6a6acSopenharmony_ci
2356cd6a6acSopenharmony_ciint sepol_iface_iterate(sepol_handle_t * handle,
2366cd6a6acSopenharmony_ci			const sepol_policydb_t * p,
2376cd6a6acSopenharmony_ci			int (*fn) (const sepol_iface_t * iface,
2386cd6a6acSopenharmony_ci				   void *fn_arg), void *arg)
2396cd6a6acSopenharmony_ci{
2406cd6a6acSopenharmony_ci
2416cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
2426cd6a6acSopenharmony_ci	ocontext_t *c, *head;
2436cd6a6acSopenharmony_ci	sepol_iface_t *iface = NULL;
2446cd6a6acSopenharmony_ci
2456cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_NETIF];
2466cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
2476cd6a6acSopenharmony_ci		int status;
2486cd6a6acSopenharmony_ci
2496cd6a6acSopenharmony_ci		if (iface_to_record(handle, policydb, c, &iface) < 0)
2506cd6a6acSopenharmony_ci			goto err;
2516cd6a6acSopenharmony_ci
2526cd6a6acSopenharmony_ci		/* Invoke handler */
2536cd6a6acSopenharmony_ci		status = fn(iface, arg);
2546cd6a6acSopenharmony_ci		if (status < 0)
2556cd6a6acSopenharmony_ci			goto err;
2566cd6a6acSopenharmony_ci
2576cd6a6acSopenharmony_ci		sepol_iface_free(iface);
2586cd6a6acSopenharmony_ci		iface = NULL;
2596cd6a6acSopenharmony_ci
2606cd6a6acSopenharmony_ci		/* Handler requested exit */
2616cd6a6acSopenharmony_ci		if (status > 0)
2626cd6a6acSopenharmony_ci			break;
2636cd6a6acSopenharmony_ci	}
2646cd6a6acSopenharmony_ci
2656cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2666cd6a6acSopenharmony_ci
2676cd6a6acSopenharmony_ci      err:
2686cd6a6acSopenharmony_ci	ERR(handle, "could not iterate over interfaces");
2696cd6a6acSopenharmony_ci	sepol_iface_free(iface);
2706cd6a6acSopenharmony_ci	return STATUS_ERR;
2716cd6a6acSopenharmony_ci}
272