Home | History | Annotate | Download | only in racoon
      1 /*
      2  * Copyright (C) 2005 International Business Machines Corporation
      3  * Copyright (c) 2005 by Trusted Computer Solutions, Inc.
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. Neither the name of the project nor the names of its contributors
     15  *    may be used to endorse or promote products derived from this software
     16  *    without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  * SUCH DAMAGE.
     29  */
     30 
     31 
     32 #include "config.h"
     33 
     34 #include <sys/types.h>
     35 
     36 #include <stdlib.h>
     37 #include <stdio.h>
     38 #include <string.h>
     39 
     40 #include <selinux/selinux.h>
     41 #include <selinux/flask.h>
     42 #include <selinux/av_permissions.h>
     43 #include <selinux/avc.h>
     44 #include <selinux/context.h>
     45 
     46 #include "var.h"
     47 #include "vmbuf.h"
     48 #include "misc.h"
     49 #include "plog.h"
     50 
     51 #include "isakmp_var.h"
     52 #include "isakmp.h"
     53 #include "ipsec_doi.h"
     54 #include "policy.h"
     55 #include "proposal.h"
     56 #include "strnames.h"
     57 #include "handler.h"
     58 
     59 /*
     60  * Get the security context information from SA.
     61  */
     62 int
     63 get_security_context(sa, p)
     64 	vchar_t *sa;
     65 	struct policyindex *p;
     66 {
     67 	int len = 0;
     68 	int flag, type = 0;
     69 	u_int16_t lorv;
     70 	caddr_t bp;
     71 	vchar_t *pbuf = NULL;
     72 	vchar_t *tbuf = NULL;
     73 	struct isakmp_parse_t *pa;
     74 	struct isakmp_parse_t *ta;
     75 	struct isakmp_pl_p *prop;
     76 	struct isakmp_pl_t *trns;
     77 	struct isakmp_data *d;
     78 	struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
     79 
     80 	/* check SA payload size */
     81 	if (sa->l < sizeof(*sab)) {
     82 		plog(LLV_ERROR, LOCATION, NULL,
     83 			"Invalid SA length = %zu.\n", sa->l);
     84 		return -1;
     85 	}
     86 
     87 	bp = (caddr_t)(sab + 1); /* here bp points to first proposal payload */
     88 	len = sa->l - sizeof(*sab);
     89 
     90 	pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, len);
     91 	if (pbuf == NULL)
     92 		return -1;
     93 
     94 	pa = (struct isakmp_parse_t *)pbuf->v;
     95         /* check the value of next payload */
     96 	if (pa->type != ISAKMP_NPTYPE_P) {
     97 		plog(LLV_ERROR, LOCATION, NULL,
     98 			"Invalid payload type=%u\n", pa->type);
     99 		vfree(pbuf);
    100 		return -1;
    101 	}
    102 
    103 	if (pa->len == 0) {
    104 		plog(LLV_ERROR, LOCATION, NULL,
    105 		"invalid proposal with length %d\n", pa->len);
    106 		vfree(pbuf);
    107 		return -1;
    108 	}
    109 
    110 	/* our first proposal */
    111 	prop = (struct isakmp_pl_p *)pa->ptr;
    112 
    113 	/* now get transform */
    114 	bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
    115 	len = ntohs(prop->h.len) -
    116 		(sizeof(struct isakmp_pl_p) + prop->spi_size);
    117 	tbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, len);
    118 	if (tbuf == NULL)
    119 		return -1;
    120 
    121 	ta = (struct isakmp_parse_t *)tbuf->v;
    122 	if (ta->type != ISAKMP_NPTYPE_T) {
    123 		plog(LLV_ERROR, LOCATION, NULL,
    124 		     "Invalid payload type=%u\n", ta->type);
    125 		return -1;
    126 	}
    127 
    128 	trns = (struct isakmp_pl_t *)ta->ptr;
    129 
    130 	len = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
    131 	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
    132 
    133 	while (len > 0) {
    134 		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
    135 		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
    136 		lorv = ntohs(d->lorv);
    137 
    138 		if (type != IPSECDOI_ATTR_SECCTX) {
    139 			if (flag) {
    140 				len -= sizeof(*d);
    141 				d = (struct isakmp_data *)((char *)d
    142 				     + sizeof(*d));
    143 			} else {
    144 				len -= (sizeof(*d) + lorv);
    145 				d = (struct isakmp_data *)((caddr_t)d
    146 				     + sizeof(*d) + lorv);
    147 			}
    148 		} else {
    149 			flag = ntohs(d->type & ISAKMP_GEN_MASK);
    150 			if (flag) {
    151 				plog(LLV_ERROR, LOCATION, NULL,
    152 				     "SECCTX must be in TLV.\n");
    153 				return -1;
    154 			}
    155 			memcpy(&p->sec_ctx, d + 1, lorv);
    156 			p->sec_ctx.ctx_strlen = ntohs(p->sec_ctx.ctx_strlen);
    157 			return 0;
    158 		}
    159 	}
    160 	return 0;
    161 }
    162 
    163 void
    164 set_secctx_in_proposal(iph2, spidx)
    165 	struct ph2handle *iph2;
    166 	struct policyindex spidx;
    167 {
    168 	iph2->proposal->sctx.ctx_doi = spidx.sec_ctx.ctx_doi;
    169 	iph2->proposal->sctx.ctx_alg = spidx.sec_ctx.ctx_alg;
    170 	iph2->proposal->sctx.ctx_strlen = spidx.sec_ctx.ctx_strlen;
    171 		memcpy(iph2->proposal->sctx.ctx_str, spidx.sec_ctx.ctx_str,
    172 			spidx.sec_ctx.ctx_strlen);
    173 }
    174 
    175 
    176 /*
    177  * function: 	init_avc
    178  * description:	function performs the steps necessary to initialize the
    179  *		userspace avc.
    180  * input:	void
    181  * return:	0	if avc was successfully initialized
    182  * 		1	if the avc could not be initialized
    183  */
    184 
    185 static int mls_ready = 0;
    186 
    187 void
    188 init_avc(void)
    189 {
    190 	if (!is_selinux_mls_enabled()) {
    191 		plog(LLV_ERROR, LOCATION, NULL, "racoon: MLS support is not"
    192 				" enabled.\n");
    193 		return;
    194 	}
    195 
    196 	if (avc_init("racoon", NULL, NULL, NULL, NULL) == 0)
    197 		mls_ready = 1;
    198 	else
    199 		plog(LLV_ERROR, LOCATION, NULL,
    200 		     "racoon: could not initialize avc.\n");
    201 }
    202 
    203 /*
    204  * function: 	within_range
    205  * description:	function determines if the specified sl is within the
    206  * 		configured range for a policy rule.
    207  * input:	security_context *sl		SL
    208  * 		char *range		Range
    209  * return:	1	if the sl is within the range
    210  * 		0	if the sl is not within the range or an error
    211  * 			occurred which prevented the determination
    212  */
    213 
    214 int
    215 within_range(security_context_t sl, security_context_t range)
    216 {
    217 	int rtn = 1;
    218 	security_id_t slsid;
    219 	security_id_t rangesid;
    220 	struct av_decision avd;
    221 	security_class_t tclass;
    222 	access_vector_t av;
    223 
    224 	if (!*range)	/* This policy doesn't have security context */
    225 		return 1;
    226 
    227 	if (!mls_ready)  /* mls may not be enabled */
    228 		return 0;
    229 
    230 	/*
    231 	 * Get the sids for the sl and range contexts
    232 	 */
    233 	rtn = avc_context_to_sid(sl, &slsid);
    234 	if (rtn != 0) {
    235 		plog(LLV_ERROR, LOCATION, NULL,
    236 				"within_range: Unable to retrieve "
    237 				"sid for sl context (%s).\n", sl);
    238 		return 0;
    239 	}
    240 	rtn = avc_context_to_sid(range, &rangesid);
    241 	if (rtn != 0) {
    242 		plog(LLV_ERROR, LOCATION, NULL,
    243 				"within_range: Unable to retrieve "
    244 				"sid for range context (%s).\n", range);
    245 		sidput(slsid);
    246 		return 0;
    247 	}
    248 
    249 	/*
    250 	 * Straight up test between sl and range
    251 	 */
    252 	tclass = SECCLASS_ASSOCIATION;
    253 	av = ASSOCIATION__POLMATCH;
    254 	rtn = avc_has_perm(slsid, rangesid, tclass, av, NULL, &avd);
    255 	if (rtn != 0) {
    256 		plog(LLV_INFO, LOCATION, NULL,
    257 			"within_range: The sl is not within range\n");
    258 		sidput(slsid);
    259 		sidput(rangesid);
    260 		return 0;
    261 	}
    262 	plog(LLV_DEBUG, LOCATION, NULL,
    263 		"within_range: The sl (%s) is within range (%s)\n", sl, range);
    264 		return 1;
    265 }
    266