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