Return to sainfo.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 ! misho 1: /* $NetBSD: sainfo.c,v 1.14 2011/02/02 15:21:34 vanhu 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: for (i = 0; i < MAXALGCLASS; i++) ! 210: delsainfoalg(si->algs[i]); ! 211: ! 212: if (si->idsrc) ! 213: vfree(si->idsrc); ! 214: if (si->iddst != NULL && ! 215: si->iddst != SAINFO_CLIENTADDR) ! 216: vfree(si->iddst); ! 217: ! 218: #ifdef ENABLE_HYBRID ! 219: if (si->group) ! 220: vfree(si->group); ! 221: #endif ! 222: ! 223: racoon_free(si); ! 224: } ! 225: ! 226: int prisainfo(s) ! 227: struct sainfo *s; ! 228: { ! 229: /* ! 230: * determine the matching priority ! 231: * of an sainfo section ! 232: */ ! 233: ! 234: int pri = 0; ! 235: ! 236: if(s->remoteid) ! 237: pri += 3; ! 238: ! 239: if(s->id_i) ! 240: pri += 3; ! 241: ! 242: if(s->idsrc) ! 243: pri++; ! 244: ! 245: if(s->iddst) ! 246: pri++; ! 247: ! 248: return pri; ! 249: } ! 250: ! 251: void ! 252: inssainfo(new) ! 253: struct sainfo *new; ! 254: { ! 255: if(LIST_EMPTY(&sitree)) { ! 256: ! 257: /* first in list */ ! 258: LIST_INSERT_HEAD(&sitree, new, chain); ! 259: } ! 260: else { ! 261: int npri, spri; ! 262: struct sainfo *s, *n; ! 263: ! 264: /* ! 265: * insert our new sainfo section ! 266: * into our list which is sorted ! 267: * based on the match priority ! 268: */ ! 269: ! 270: npri = prisainfo(new); ! 271: ! 272: s = LIST_FIRST(&sitree); ! 273: while (1) { ! 274: ! 275: spri = prisainfo(s); ! 276: n = LIST_NEXT(s, chain); ! 277: ! 278: if(npri > spri) ! 279: { ! 280: /* higher priority */ ! 281: LIST_INSERT_BEFORE(s, new, chain); ! 282: return; ! 283: } ! 284: ! 285: if(n == NULL) ! 286: { ! 287: /* last in list */ ! 288: LIST_INSERT_AFTER(s, new, chain); ! 289: return; ! 290: } ! 291: ! 292: s = n; ! 293: } ! 294: } ! 295: } ! 296: ! 297: void ! 298: remsainfo(si) ! 299: struct sainfo *si; ! 300: { ! 301: LIST_REMOVE(si, chain); ! 302: } ! 303: ! 304: void ! 305: flushsainfo() ! 306: { ! 307: struct sainfo *s, *next; ! 308: ! 309: for (s = LIST_FIRST(&sitree); s; s = next) { ! 310: next = LIST_NEXT(s, chain); ! 311: remsainfo(s); ! 312: delsainfo(s); ! 313: } ! 314: } ! 315: ! 316: void ! 317: initsainfo() ! 318: { ! 319: LIST_INIT(&sitree); ! 320: } ! 321: ! 322: struct sainfoalg * ! 323: newsainfoalg() ! 324: { ! 325: struct sainfoalg *new; ! 326: ! 327: new = racoon_calloc(1, sizeof(*new)); ! 328: if (new == NULL) ! 329: return NULL; ! 330: ! 331: return new; ! 332: } ! 333: ! 334: void ! 335: delsainfoalg(alg) ! 336: struct sainfoalg *alg; ! 337: { ! 338: struct sainfoalg *a, *next; ! 339: ! 340: for (a = alg; a; a = next) { ! 341: next = a->next; ! 342: racoon_free(a); ! 343: } ! 344: } ! 345: ! 346: void ! 347: inssainfoalg(head, new) ! 348: struct sainfoalg **head; ! 349: struct sainfoalg *new; ! 350: { ! 351: struct sainfoalg *a; ! 352: ! 353: for (a = *head; a && a->next; a = a->next) ! 354: ; ! 355: if (a) ! 356: a->next = new; ! 357: else ! 358: *head = new; ! 359: } ! 360: ! 361: const char * ! 362: sainfo2str(si) ! 363: const struct sainfo *si; ! 364: { ! 365: static char buf[256]; ! 366: ! 367: char *idloc = NULL, *idrmt = NULL, *id_i; ! 368: ! 369: if (si->idsrc == SAINFO_ANONYMOUS) ! 370: idloc = strdup("ANONYMOUS"); ! 371: else ! 372: idloc = ipsecdoi_id2str(si->idsrc); ! 373: ! 374: if (si->iddst == SAINFO_ANONYMOUS) ! 375: idrmt = strdup("ANONYMOUS"); ! 376: else if (si->iddst == SAINFO_CLIENTADDR) ! 377: idrmt = strdup("CLIENTADDR"); ! 378: else ! 379: idrmt = ipsecdoi_id2str(si->iddst); ! 380: ! 381: if (si->id_i == NULL) ! 382: id_i = strdup("ANY"); ! 383: else ! 384: id_i = ipsecdoi_id2str(si->id_i); ! 385: ! 386: snprintf(buf, 255, "loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%u", ! 387: idloc, idrmt, id_i, si->remoteid); ! 388: ! 389: racoon_free(idloc); ! 390: racoon_free(idrmt); ! 391: racoon_free(id_i); ! 392: ! 393: return buf; ! 394: } ! 395: ! 396: void sainfo_start_reload(void){ ! 397: sitree_save=sitree; ! 398: initsainfo(); ! 399: } ! 400: ! 401: void sainfo_finish_reload(void){ ! 402: sainfo_tailq_head_t sitree_tmp; ! 403: ! 404: sitree_tmp=sitree; ! 405: sitree=sitree_save; ! 406: flushsainfo(); ! 407: sitree=sitree_tmp; ! 408: } ! 409: ! 410: void save_sainfotree_restore(void){ ! 411: flushsainfo(); ! 412: sitree=sitree_save; ! 413: }