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
get_security_context(sa,p)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
set_secctx_in_proposal(iph2,spidx)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
init_avc(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
within_range(security_context_t sl,security_context_t range)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