summaryrefslogtreecommitdiff
path: root/src/ports.c
diff options
context:
space:
mode:
authorSE Android <seandroid@taiga.selinuxproject.org>2012-01-24 05:26:38 -0800
committerSE Android <seandroid@taiga.selinuxproject.org>2012-01-24 05:26:38 -0800
commit255e72915d4cbddceb435e13d81601755714e9f3 (patch)
treed9e146f714ac6197865554529bcd1e3d10cbaec2 /src/ports.c
downloadlibsepol-255e72915d4cbddceb435e13d81601755714e9f3.tar.gz
Import libsepol 2.1.0 (Release 2011-07-27).
Diffstat (limited to 'src/ports.c')
-rw-r--r--src/ports.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/src/ports.c b/src/ports.c
new file mode 100644
index 0000000..cbf2a0b
--- /dev/null
+++ b/src/ports.c
@@ -0,0 +1,312 @@
+#include <netinet/in.h>
+#include <stdlib.h>
+
+#include "debug.h"
+#include "context.h"
+#include "handle.h"
+
+#include <sepol/policydb/policydb.h>
+#include "port_internal.h"
+
+static inline int sepol2ipproto(sepol_handle_t * handle, int proto)
+{
+
+ switch (proto) {
+ case SEPOL_PROTO_TCP:
+ return IPPROTO_TCP;
+ case SEPOL_PROTO_UDP:
+ return IPPROTO_UDP;
+ default:
+ ERR(handle, "unsupported protocol %u", proto);
+ return STATUS_ERR;
+ }
+}
+
+static inline int ipproto2sepol(sepol_handle_t * handle, int proto)
+{
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ return SEPOL_PROTO_TCP;
+ case IPPROTO_UDP:
+ return SEPOL_PROTO_UDP;
+ default:
+ ERR(handle, "invalid protocol %u " "found in policy", proto);
+ return STATUS_ERR;
+ }
+}
+
+/* Create a low level port structure from
+ * a high level representation */
+static int port_from_record(sepol_handle_t * handle,
+ const policydb_t * policydb,
+ ocontext_t ** port, const sepol_port_t * data)
+{
+
+ ocontext_t *tmp_port = NULL;
+ context_struct_t *tmp_con = NULL;
+ int tmp_proto;
+
+ int low = sepol_port_get_low(data);
+ int high = sepol_port_get_high(data);
+ int proto = sepol_port_get_proto(data);
+
+ tmp_port = (ocontext_t *) calloc(1, sizeof(ocontext_t));
+ if (!tmp_port)
+ goto omem;
+
+ /* Process protocol */
+ tmp_proto = sepol2ipproto(handle, proto);
+ if (tmp_proto < 0)
+ goto err;
+ tmp_port->u.port.protocol = tmp_proto;
+
+ /* Port range */
+ tmp_port->u.port.low_port = low;
+ tmp_port->u.port.high_port = high;
+ if (tmp_port->u.port.low_port > tmp_port->u.port.high_port) {
+ ERR(handle, "low port %d exceeds high port %d",
+ tmp_port->u.port.low_port, tmp_port->u.port.high_port);
+ goto err;
+ }
+
+ /* Context */
+ if (context_from_record(handle, policydb, &tmp_con,
+ sepol_port_get_con(data)) < 0)
+ goto err;
+ context_cpy(&tmp_port->context[0], tmp_con);
+ context_destroy(tmp_con);
+ free(tmp_con);
+ tmp_con = NULL;
+
+ *port = tmp_port;
+ return STATUS_SUCCESS;
+
+ omem:
+ ERR(handle, "out of memory");
+
+ err:
+ if (tmp_port != NULL) {
+ context_destroy(&tmp_port->context[0]);
+ free(tmp_port);
+ }
+ context_destroy(tmp_con);
+ free(tmp_con);
+ ERR(handle, "could not create port structure for range %u:%u (%s)",
+ low, high, sepol_port_get_proto_str(proto));
+ return STATUS_ERR;
+}
+
+static int port_to_record(sepol_handle_t * handle,
+ const policydb_t * policydb,
+ ocontext_t * port, sepol_port_t ** record)
+{
+
+ int proto = port->u.port.protocol;
+ int low = port->u.port.low_port;
+ int high = port->u.port.high_port;
+ context_struct_t *con = &port->context[0];
+ int rec_proto = -1;
+
+ sepol_context_t *tmp_con = NULL;
+ sepol_port_t *tmp_record = NULL;
+
+ if (sepol_port_create(handle, &tmp_record) < 0)
+ goto err;
+
+ rec_proto = ipproto2sepol(handle, proto);
+ if (rec_proto < 0)
+ goto err;
+
+ sepol_port_set_proto(tmp_record, rec_proto);
+ sepol_port_set_range(tmp_record, low, high);
+
+ if (context_to_record(handle, policydb, con, &tmp_con) < 0)
+ goto err;
+
+ if (sepol_port_set_con(handle, tmp_record, tmp_con) < 0)
+ goto err;
+
+ sepol_context_free(tmp_con);
+ *record = tmp_record;
+ return STATUS_SUCCESS;
+
+ err:
+ ERR(handle, "could not convert port range %u - %u (%s) "
+ "to record", low, high, sepol_port_get_proto_str(rec_proto));
+ sepol_context_free(tmp_con);
+ sepol_port_free(tmp_record);
+ return STATUS_ERR;
+}
+
+/* Return the number of ports */
+extern int sepol_port_count(sepol_handle_t * handle __attribute__ ((unused)),
+ const sepol_policydb_t * p, unsigned int *response)
+{
+
+ unsigned int count = 0;
+ ocontext_t *c, *head;
+ const policydb_t *policydb = &p->p;
+
+ head = policydb->ocontexts[OCON_PORT];
+ for (c = head; c != NULL; c = c->next)
+ count++;
+
+ *response = count;
+
+ handle = NULL;
+ return STATUS_SUCCESS;
+}
+
+/* Check if a port exists */
+int sepol_port_exists(sepol_handle_t * handle,
+ const sepol_policydb_t * p,
+ const sepol_port_key_t * key, int *response)
+{
+
+ const policydb_t *policydb = &p->p;
+ ocontext_t *c, *head;
+
+ int low, high, proto;
+ const char *proto_str;
+ sepol_port_key_unpack(key, &low, &high, &proto);
+ proto_str = sepol_port_get_proto_str(proto);
+ proto = sepol2ipproto(handle, proto);
+ if (proto < 0)
+ goto err;
+
+ head = policydb->ocontexts[OCON_PORT];
+ for (c = head; c; c = c->next) {
+ int proto2 = c->u.port.protocol;
+ int low2 = c->u.port.low_port;
+ int high2 = c->u.port.high_port;
+
+ if (proto == proto2 && low2 == low && high2 == high) {
+ *response = 1;
+ return STATUS_SUCCESS;
+ }
+ }
+
+ *response = 0;
+ return STATUS_SUCCESS;
+
+ err:
+ ERR(handle, "could not check if port range %u - %u (%s) exists",
+ low, high, proto_str);
+ return STATUS_ERR;
+}
+
+/* Query a port */
+int sepol_port_query(sepol_handle_t * handle,
+ const sepol_policydb_t * p,
+ const sepol_port_key_t * key, sepol_port_t ** response)
+{
+
+ const policydb_t *policydb = &p->p;
+ ocontext_t *c, *head;
+
+ int low, high, proto;
+ const char *proto_str;
+ sepol_port_key_unpack(key, &low, &high, &proto);
+ proto_str = sepol_port_get_proto_str(proto);
+ proto = sepol2ipproto(handle, proto);
+ if (proto < 0)
+ goto err;
+
+ head = policydb->ocontexts[OCON_PORT];
+ for (c = head; c; c = c->next) {
+ int proto2 = c->u.port.protocol;
+ int low2 = c->u.port.low_port;
+ int high2 = c->u.port.high_port;
+
+ if (proto == proto2 && low2 == low && high2 == high) {
+ if (port_to_record(handle, policydb, c, response) < 0)
+ goto err;
+ return STATUS_SUCCESS;
+ }
+ }
+
+ *response = NULL;
+ return STATUS_SUCCESS;
+
+ err:
+ ERR(handle, "could not query port range %u - %u (%s)",
+ low, high, proto_str);
+ return STATUS_ERR;
+
+}
+
+/* Load a port into policy */
+int sepol_port_modify(sepol_handle_t * handle,
+ sepol_policydb_t * p,
+ const sepol_port_key_t * key, const sepol_port_t * data)
+{
+
+ policydb_t *policydb = &p->p;
+ ocontext_t *port = NULL;
+
+ int low, high, proto;
+ const char *proto_str;
+
+ sepol_port_key_unpack(key, &low, &high, &proto);
+ proto_str = sepol_port_get_proto_str(proto);
+ proto = sepol2ipproto(handle, proto);
+ if (proto < 0)
+ goto err;
+
+ if (port_from_record(handle, policydb, &port, data) < 0)
+ goto err;
+
+ /* Attach to context list */
+ port->next = policydb->ocontexts[OCON_PORT];
+ policydb->ocontexts[OCON_PORT] = port;
+
+ return STATUS_SUCCESS;
+
+ err:
+ ERR(handle, "could not load port range %u - %u (%s)",
+ low, high, proto_str);
+ if (port != NULL) {
+ context_destroy(&port->context[0]);
+ free(port);
+ }
+ return STATUS_ERR;
+}
+
+int sepol_port_iterate(sepol_handle_t * handle,
+ const sepol_policydb_t * p,
+ int (*fn) (const sepol_port_t * port,
+ void *fn_arg), void *arg)
+{
+
+ const policydb_t *policydb = &p->p;
+ ocontext_t *c, *head;
+ sepol_port_t *port = NULL;
+
+ head = policydb->ocontexts[OCON_PORT];
+ for (c = head; c; c = c->next) {
+ int status;
+
+ if (port_to_record(handle, policydb, c, &port) < 0)
+ goto err;
+
+ /* Invoke handler */
+ status = fn(port, arg);
+ if (status < 0)
+ goto err;
+
+ sepol_port_free(port);
+ port = NULL;
+
+ /* Handler requested exit */
+ if (status > 0)
+ break;
+ }
+
+ return STATUS_SUCCESS;
+
+ err:
+ ERR(handle, "could not iterate over ports");
+ sepol_port_free(port);
+ return STATUS_ERR;
+}