summaryrefslogtreecommitdiffstats
path: root/ipsec-tools/src/racoon/security.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipsec-tools/src/racoon/security.c')
-rw-r--r--ipsec-tools/src/racoon/security.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/ipsec-tools/src/racoon/security.c b/ipsec-tools/src/racoon/security.c
new file mode 100644
index 00000000..e4b5a0d6
--- /dev/null
+++ b/ipsec-tools/src/racoon/security.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2005 International Business Machines Corporation
+ * Copyright (c) 2005 by Trusted Computer Solutions, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <selinux/selinux.h>
+#include <selinux/flask.h>
+#include <selinux/av_permissions.h>
+#include <selinux/avc.h>
+#include <selinux/context.h>
+
+#include "var.h"
+#include "vmbuf.h"
+#include "misc.h"
+#include "plog.h"
+
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "policy.h"
+#include "proposal.h"
+#include "strnames.h"
+#include "handler.h"
+
+/*
+ * Get the security context information from SA.
+ */
+int
+get_security_context(sa, p)
+ vchar_t *sa;
+ struct policyindex *p;
+{
+ int len = 0;
+ int flag, type = 0;
+ u_int16_t lorv;
+ caddr_t bp;
+ vchar_t *pbuf = NULL;
+ vchar_t *tbuf = NULL;
+ struct isakmp_parse_t *pa;
+ struct isakmp_parse_t *ta;
+ struct isakmp_pl_p *prop;
+ struct isakmp_pl_t *trns;
+ struct isakmp_data *d;
+ struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
+
+ /* check SA payload size */
+ if (sa->l < sizeof(*sab)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Invalid SA length = %zu.\n", sa->l);
+ return -1;
+ }
+
+ bp = (caddr_t)(sab + 1); /* here bp points to first proposal payload */
+ len = sa->l - sizeof(*sab);
+
+ pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, len);
+ if (pbuf == NULL)
+ return -1;
+
+ pa = (struct isakmp_parse_t *)pbuf->v;
+ /* check the value of next payload */
+ if (pa->type != ISAKMP_NPTYPE_P) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Invalid payload type=%u\n", pa->type);
+ vfree(pbuf);
+ return -1;
+ }
+
+ if (pa->len == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid proposal with length %d\n", pa->len);
+ vfree(pbuf);
+ return -1;
+ }
+
+ /* our first proposal */
+ prop = (struct isakmp_pl_p *)pa->ptr;
+
+ /* now get transform */
+ bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
+ len = ntohs(prop->h.len) -
+ (sizeof(struct isakmp_pl_p) + prop->spi_size);
+ tbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, len);
+ if (tbuf == NULL)
+ return -1;
+
+ ta = (struct isakmp_parse_t *)tbuf->v;
+ if (ta->type != ISAKMP_NPTYPE_T) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Invalid payload type=%u\n", ta->type);
+ return -1;
+ }
+
+ trns = (struct isakmp_pl_t *)ta->ptr;
+
+ len = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
+ d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
+
+ while (len > 0) {
+ type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+ flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+ lorv = ntohs(d->lorv);
+
+ if (type != IPSECDOI_ATTR_SECCTX) {
+ if (flag) {
+ len -= sizeof(*d);
+ d = (struct isakmp_data *)((char *)d
+ + sizeof(*d));
+ } else {
+ len -= (sizeof(*d) + lorv);
+ d = (struct isakmp_data *)((caddr_t)d
+ + sizeof(*d) + lorv);
+ }
+ } else {
+ flag = ntohs(d->type & ISAKMP_GEN_MASK);
+ if (flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "SECCTX must be in TLV.\n");
+ return -1;
+ }
+ memcpy(&p->sec_ctx, d + 1, lorv);
+ p->sec_ctx.ctx_strlen = ntohs(p->sec_ctx.ctx_strlen);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+void
+set_secctx_in_proposal(iph2, spidx)
+ struct ph2handle *iph2;
+ struct policyindex spidx;
+{
+ iph2->proposal->sctx.ctx_doi = spidx.sec_ctx.ctx_doi;
+ iph2->proposal->sctx.ctx_alg = spidx.sec_ctx.ctx_alg;
+ iph2->proposal->sctx.ctx_strlen = spidx.sec_ctx.ctx_strlen;
+ memcpy(iph2->proposal->sctx.ctx_str, spidx.sec_ctx.ctx_str,
+ spidx.sec_ctx.ctx_strlen);
+}
+
+
+/*
+ * function: init_avc
+ * description: function performs the steps necessary to initialize the
+ * userspace avc.
+ * input: void
+ * return: 0 if avc was successfully initialized
+ * 1 if the avc could not be initialized
+ */
+
+static int mls_ready = 0;
+
+void
+init_avc(void)
+{
+ if (!is_selinux_mls_enabled()) {
+ plog(LLV_ERROR, LOCATION, NULL, "racoon: MLS support is not"
+ " enabled.\n");
+ return;
+ }
+
+ if (avc_init("racoon", NULL, NULL, NULL, NULL) == 0)
+ mls_ready = 1;
+ else
+ plog(LLV_ERROR, LOCATION, NULL,
+ "racoon: could not initialize avc.\n");
+}
+
+/*
+ * function: within_range
+ * description: function determines if the specified sl is within the
+ * configured range for a policy rule.
+ * input: security_context *sl SL
+ * char *range Range
+ * return: 1 if the sl is within the range
+ * 0 if the sl is not within the range or an error
+ * occurred which prevented the determination
+ */
+
+int
+within_range(security_context_t sl, security_context_t range)
+{
+ int rtn = 1;
+ security_id_t slsid;
+ security_id_t rangesid;
+ struct av_decision avd;
+ security_class_t tclass;
+ access_vector_t av;
+
+ if (!*range) /* This policy doesn't have security context */
+ return 1;
+
+ if (!mls_ready) /* mls may not be enabled */
+ return 0;
+
+ /*
+ * Get the sids for the sl and range contexts
+ */
+ rtn = avc_context_to_sid(sl, &slsid);
+ if (rtn != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "within_range: Unable to retrieve "
+ "sid for sl context (%s).\n", sl);
+ return 0;
+ }
+ rtn = avc_context_to_sid(range, &rangesid);
+ if (rtn != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "within_range: Unable to retrieve "
+ "sid for range context (%s).\n", range);
+ sidput(slsid);
+ return 0;
+ }
+
+ /*
+ * Straight up test between sl and range
+ */
+ tclass = SECCLASS_ASSOCIATION;
+ av = ASSOCIATION__POLMATCH;
+ rtn = avc_has_perm(slsid, rangesid, tclass, av, NULL, &avd);
+ if (rtn != 0) {
+ plog(LLV_INFO, LOCATION, NULL,
+ "within_range: The sl is not within range\n");
+ sidput(slsid);
+ sidput(rangesid);
+ return 0;
+ }
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "within_range: The sl (%s) is within range (%s)\n", sl, range);
+ return 1;
+}