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