1 /* $NetBSD: sainfo.c,v 1.15 2012/01/01 15:29:28 tteras Exp $ */ 2 3 /* $KAME: sainfo.c,v 1.16 2003/06/27 07:32:39 sakane Exp $ */ 4 5 /* 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "config.h" 35 36 #include <sys/param.h> 37 #include <sys/types.h> 38 #include <sys/socket.h> 39 #include <sys/queue.h> 40 41 #include <netinet/in.h> 42 #include <netinet/in.h> 43 #include PATH_IPSEC_H 44 45 #include <stdlib.h> 46 #include <stdio.h> 47 #include <string.h> 48 #include <errno.h> 49 50 #include "var.h" 51 #include "misc.h" 52 #include "vmbuf.h" 53 #include "plog.h" 54 #include "sockmisc.h" 55 #include "debug.h" 56 57 #include "localconf.h" 58 #include "isakmp_var.h" 59 #include "isakmp.h" 60 #include "ipsec_doi.h" 61 #include "oakley.h" 62 #include "handler.h" 63 #include "algorithm.h" 64 #include "sainfo.h" 65 #include "gcmalloc.h" 66 67 typedef LIST_HEAD(_sitree, sainfo) sainfo_tailq_head_t; 68 static sainfo_tailq_head_t sitree, sitree_save; 69 70 /* %%% 71 * modules for ipsec sa info 72 */ 73 /* 74 * return matching entry. 75 * no matching entry found and if there is anonymous entry, return it. 76 * else return NULL. 77 * First pass is for sainfo from a specified peer, second for others. 78 */ 79 struct sainfo * 80 getsainfo(loc, rmt, peer, client, remoteid) 81 const vchar_t *loc, *rmt, *peer, *client; 82 uint32_t remoteid; 83 { 84 struct sainfo *s = NULL; 85 86 /* debug level output */ 87 if(loglevel >= LLV_DEBUG) { 88 char *dloc, *drmt, *dpeer, *dclient; 89 90 if (loc == NULL) 91 dloc = strdup("ANONYMOUS"); 92 else 93 dloc = ipsecdoi_id2str(loc); 94 95 if (rmt == SAINFO_ANONYMOUS) 96 drmt = strdup("ANONYMOUS"); 97 else if (rmt == SAINFO_CLIENTADDR) 98 drmt = strdup("CLIENTADDR"); 99 else 100 drmt = ipsecdoi_id2str(rmt); 101 102 if (peer == NULL) 103 dpeer = strdup("NULL"); 104 else 105 dpeer = ipsecdoi_id2str(peer); 106 107 if (client == NULL) 108 dclient = strdup("NULL"); 109 else 110 dclient = ipsecdoi_id2str(client); 111 112 plog(LLV_DEBUG, LOCATION, NULL, 113 "getsainfo params: loc=\'%s\' rmt=\'%s\' peer=\'%s\' client=\'%s\' id=%u\n", 114 dloc, drmt, dpeer, dclient, remoteid ); 115 116 racoon_free(dloc); 117 racoon_free(drmt); 118 racoon_free(dpeer); 119 racoon_free(dclient); 120 } 121 122 LIST_FOREACH(s, &sitree, chain) { 123 const char *sainfostr = sainfo2str(s); 124 plog(LLV_DEBUG, LOCATION, NULL, 125 "evaluating sainfo: %s\n", sainfostr); 126 127 if(s->remoteid != remoteid) { 128 plog(LLV_DEBUG, LOCATION, NULL, 129 "remoteid mismatch: %u != %u\n", 130 s->remoteid, remoteid); 131 continue; 132 } 133 134 /* compare 'from' id value */ 135 if (s->id_i != NULL) 136 if (ipsecdoi_chkcmpids(peer, s->id_i, 0)) 137 continue; 138 139 /* compare ids - client */ 140 if( s->iddst == SAINFO_CLIENTADDR ) { 141 /* 142 * This sainfo section enforces client address 143 * checking. Prevent match if the client value 144 * ( modecfg or tunnel address ) is NULL. 145 */ 146 147 if (client == NULL) 148 continue; 149 150 if( rmt == SAINFO_CLIENTADDR ) { 151 /* 152 * In the case where a supplied rmt value is 153 * also SAINFO_CLIENTADDR, we are comparing 154 * with another sainfo to check for duplicate. 155 * Only compare the local values to determine 156 * a match. 157 */ 158 159 if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0)) 160 return s; 161 } 162 else { 163 /* 164 * In the case where a supplied rmt value is 165 * not SAINFO_CLIENTADDR, do a standard match 166 * for local values and enforce that the rmt 167 * id matches the client address value. 168 */ 169 170 if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) && 171 !ipsecdoi_chkcmpids(rmt, client, 0)) 172 return s; 173 } 174 175 continue; 176 } 177 178 179 /* compare ids - standard */ 180 if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) && 181 !ipsecdoi_chkcmpids(rmt, s->iddst, 0)) 182 return s; 183 } 184 185 return NULL; 186 } 187 188 struct sainfo * 189 newsainfo() 190 { 191 struct sainfo *new; 192 193 new = racoon_calloc(1, sizeof(*new)); 194 if (new == NULL) 195 return NULL; 196 197 new->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT; 198 new->lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX; 199 200 return new; 201 } 202 203 void 204 delsainfo(si) 205 struct sainfo *si; 206 { 207 int i; 208 209 if (si == NULL) 210 return; 211 212 for (i = 0; i < MAXALGCLASS; i++) 213 delsainfoalg(si->algs[i]); 214 215 if (si->idsrc) 216 vfree(si->idsrc); 217 if (si->iddst != NULL && 218 si->iddst != SAINFO_CLIENTADDR) 219 vfree(si->iddst); 220 221 #ifdef ENABLE_HYBRID 222 if (si->group) 223 vfree(si->group); 224 #endif 225 226 racoon_free(si); 227 } 228 229 int prisainfo(s) 230 struct sainfo *s; 231 { 232 /* 233 * determine the matching priority 234 * of an sainfo section 235 */ 236 237 int pri = 0; 238 239 if(s->remoteid) 240 pri += 3; 241 242 if(s->id_i) 243 pri += 3; 244 245 if(s->idsrc) 246 pri++; 247 248 if(s->iddst) 249 pri++; 250 251 return pri; 252 } 253 254 void 255 inssainfo(new) 256 struct sainfo *new; 257 { 258 if(LIST_EMPTY(&sitree)) { 259 260 /* first in list */ 261 LIST_INSERT_HEAD(&sitree, new, chain); 262 } 263 else { 264 int npri, spri; 265 struct sainfo *s, *n; 266 267 /* 268 * insert our new sainfo section 269 * into our list which is sorted 270 * based on the match priority 271 */ 272 273 npri = prisainfo(new); 274 275 s = LIST_FIRST(&sitree); 276 while (1) { 277 278 spri = prisainfo(s); 279 n = LIST_NEXT(s, chain); 280 281 if(npri > spri) 282 { 283 /* higher priority */ 284 LIST_INSERT_BEFORE(s, new, chain); 285 return; 286 } 287 288 if(n == NULL) 289 { 290 /* last in list */ 291 LIST_INSERT_AFTER(s, new, chain); 292 return; 293 } 294 295 s = n; 296 } 297 } 298 } 299 300 void 301 remsainfo(si) 302 struct sainfo *si; 303 { 304 LIST_REMOVE(si, chain); 305 } 306 307 void 308 flushsainfo() 309 { 310 struct sainfo *s, *next; 311 312 for (s = LIST_FIRST(&sitree); s; s = next) { 313 next = LIST_NEXT(s, chain); 314 remsainfo(s); 315 delsainfo(s); 316 } 317 } 318 319 void 320 initsainfo() 321 { 322 LIST_INIT(&sitree); 323 } 324 325 struct sainfoalg * 326 newsainfoalg() 327 { 328 struct sainfoalg *new; 329 330 new = racoon_calloc(1, sizeof(*new)); 331 if (new == NULL) 332 return NULL; 333 334 return new; 335 } 336 337 void 338 delsainfoalg(alg) 339 struct sainfoalg *alg; 340 { 341 struct sainfoalg *a, *next; 342 343 for (a = alg; a; a = next) { 344 next = a->next; 345 racoon_free(a); 346 } 347 } 348 349 void 350 inssainfoalg(head, new) 351 struct sainfoalg **head; 352 struct sainfoalg *new; 353 { 354 struct sainfoalg *a; 355 356 for (a = *head; a && a->next; a = a->next) 357 ; 358 if (a) 359 a->next = new; 360 else 361 *head = new; 362 } 363 364 const char * 365 sainfo2str(si) 366 const struct sainfo *si; 367 { 368 static char buf[256]; 369 370 char *idloc = NULL, *idrmt = NULL, *id_i; 371 372 if (si->idsrc == SAINFO_ANONYMOUS) 373 idloc = strdup("ANONYMOUS"); 374 else 375 idloc = ipsecdoi_id2str(si->idsrc); 376 377 if (si->iddst == SAINFO_ANONYMOUS) 378 idrmt = strdup("ANONYMOUS"); 379 else if (si->iddst == SAINFO_CLIENTADDR) 380 idrmt = strdup("CLIENTADDR"); 381 else 382 idrmt = ipsecdoi_id2str(si->iddst); 383 384 if (si->id_i == NULL) 385 id_i = strdup("ANY"); 386 else 387 id_i = ipsecdoi_id2str(si->id_i); 388 389 snprintf(buf, 255, "loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%u", 390 idloc, idrmt, id_i, si->remoteid); 391 392 racoon_free(idloc); 393 racoon_free(idrmt); 394 racoon_free(id_i); 395 396 return buf; 397 } 398 399 void sainfo_start_reload(void){ 400 sitree_save=sitree; 401 initsainfo(); 402 } 403 404 void sainfo_finish_reload(void){ 405 sainfo_tailq_head_t sitree_tmp; 406 407 sitree_tmp=sitree; 408 sitree=sitree_save; 409 flushsainfo(); 410 sitree=sitree_tmp; 411 } 412 413 void save_sainfotree_restore(void){ 414 flushsainfo(); 415 sitree=sitree_save; 416 } 417