diff options
author | SE Android <seandroid@taiga.selinuxproject.org> | 2012-01-24 05:26:38 -0800 |
---|---|---|
committer | SE Android <seandroid@taiga.selinuxproject.org> | 2012-01-24 05:26:38 -0800 |
commit | 255e72915d4cbddceb435e13d81601755714e9f3 (patch) | |
tree | d9e146f714ac6197865554529bcd1e3d10cbaec2 /src/ports.c | |
download | libsepol-255e72915d4cbddceb435e13d81601755714e9f3.tar.gz |
Import libsepol 2.1.0 (Release 2011-07-27).
Diffstat (limited to 'src/ports.c')
-rw-r--r-- | src/ports.c | 312 |
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; +} |