File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / proposal.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 4 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    1: /*	$NetBSD: proposal.c,v 1.17 2008/09/19 11:14:49 tteras Exp $	*/
    2: 
    3: /* $Id: proposal.c,v 1.1.1.1 2012/02/21 22:39:10 misho 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 PATH_IPSEC_H
   43: 
   44: #include <stdlib.h>
   45: #include <stdio.h>
   46: #include <string.h>
   47: #include <errno.h>
   48: 
   49: #include "var.h"
   50: #include "misc.h"
   51: #include "vmbuf.h"
   52: #include "plog.h"
   53: #include "sockmisc.h"
   54: #include "debug.h"
   55: 
   56: #include "policy.h"
   57: #include "pfkey.h"
   58: #include "isakmp_var.h"
   59: #include "isakmp.h"
   60: #include "ipsec_doi.h"
   61: #include "algorithm.h"
   62: #include "proposal.h"
   63: #include "sainfo.h"
   64: #include "localconf.h"
   65: #include "remoteconf.h"
   66: #include "oakley.h"
   67: #include "handler.h"
   68: #include "strnames.h"
   69: #include "gcmalloc.h"
   70: #ifdef ENABLE_NATT
   71: #include "nattraversal.h"
   72: #endif
   73: 
   74: static uint g_nextreqid = 1;
   75: 
   76: /* %%%
   77:  * modules for ipsec sa spec
   78:  */
   79: struct saprop *
   80: newsaprop()
   81: {
   82: 	struct saprop *new;
   83: 
   84: 	new = racoon_calloc(1, sizeof(*new));
   85: 	if (new == NULL)
   86: 		return NULL;
   87: 
   88: 	return new;
   89: }
   90: 
   91: struct saproto *
   92: newsaproto()
   93: {
   94: 	struct saproto *new;
   95: 
   96: 	new = racoon_calloc(1, sizeof(*new));
   97: 	if (new == NULL)
   98: 		return NULL;
   99: 
  100: 	return new;
  101: }
  102: 
  103: /* set saprop to last part of the prop tree */
  104: void
  105: inssaprop(head, new)
  106: 	struct saprop **head;
  107: 	struct saprop *new;
  108: {
  109: 	struct saprop *p;
  110: 
  111: 	if (*head == NULL) {
  112: 		*head = new;
  113: 		return;
  114: 	}
  115: 
  116: 	for (p = *head; p->next; p = p->next)
  117: 		;
  118: 	p->next = new;
  119: 
  120: 	return;
  121: }
  122: 
  123: /* set saproto to the end of the proto tree in saprop */
  124: void
  125: inssaproto(pp, new)
  126: 	struct saprop *pp;
  127: 	struct saproto *new;
  128: {
  129: 	struct saproto *p;
  130: 
  131: 	for (p = pp->head; p && p->next; p = p->next)
  132: 		;
  133: 	if (p == NULL)
  134: 		pp->head = new;
  135: 	else
  136: 		p->next = new;
  137: 
  138: 	return;
  139: }
  140: 
  141: /* set saproto to the top of the proto tree in saprop */
  142: void
  143: inssaprotorev(pp, new)
  144:       struct saprop *pp;
  145:       struct saproto *new;
  146: {
  147:       new->next = pp->head;
  148:       pp->head = new;
  149: 
  150:       return;
  151: }
  152: 
  153: struct satrns *
  154: newsatrns()
  155: {
  156: 	struct satrns *new;
  157: 
  158: 	new = racoon_calloc(1, sizeof(*new));
  159: 	if (new == NULL)
  160: 		return NULL;
  161: 
  162: 	return new;
  163: }
  164: 
  165: /* set saproto to last part of the proto tree in saprop */
  166: void
  167: inssatrns(pr, new)
  168: 	struct saproto *pr;
  169: 	struct satrns *new;
  170: {
  171: 	struct satrns *tr;
  172: 
  173: 	for (tr = pr->head; tr && tr->next; tr = tr->next)
  174: 		;
  175: 	if (tr == NULL)
  176: 		pr->head = new;
  177: 	else
  178: 		tr->next = new;
  179: 
  180: 	return;
  181: }
  182: 
  183: /*
  184:  * take a single match between saprop.  allocate a new proposal and return it
  185:  * for future use (like picking single proposal from a bundle).
  186:  *	pp1: peer's proposal.
  187:  *	pp2: my proposal.
  188:  * NOTE: In the case of initiator, must be ensured that there is no
  189:  * modification of the proposal by calling cmp_aproppair_i() before
  190:  * this function.
  191:  * XXX cannot understand the comment!
  192:  */
  193: struct saprop *
  194: cmpsaprop_alloc(ph1, pp1, pp2, side)
  195: 	struct ph1handle *ph1;
  196: 	const struct saprop *pp1, *pp2;
  197: 	int side;
  198: {
  199: 	struct saprop *newpp = NULL;
  200: 	struct saproto *pr1, *pr2, *newpr = NULL;
  201: 	struct satrns *tr1, *tr2, *newtr;
  202: 	const int ordermatters = 0;
  203: 	int npr1, npr2;
  204: 	int spisizematch;
  205: 
  206: 	newpp = newsaprop();
  207: 	if (newpp == NULL) {
  208: 		plog(LLV_ERROR, LOCATION, NULL,
  209: 			"failed to allocate saprop.\n");
  210: 		return NULL;
  211: 	}
  212: 	newpp->prop_no = pp1->prop_no;
  213: 
  214: 	/* see proposal.h about lifetime/key length and PFS selection. */
  215: 
  216: 	/* check time/bytes lifetime and PFS */
  217: 	switch (ph1->rmconf->pcheck_level) {
  218: 	case PROP_CHECK_OBEY:
  219: 		newpp->lifetime = pp1->lifetime;
  220: 		newpp->lifebyte = pp1->lifebyte;
  221: 		newpp->pfs_group = pp1->pfs_group;
  222: 		break;
  223: 
  224: 	case PROP_CHECK_STRICT:
  225: 		if (pp1->lifetime > pp2->lifetime) {
  226: 			plog(LLV_ERROR, LOCATION, NULL,
  227: 				"long lifetime proposed: "
  228: 				"my:%d peer:%d\n",
  229: 				(int)pp2->lifetime, (int)pp1->lifetime);
  230: 			goto err;
  231: 		}
  232: 		if (pp1->lifebyte > pp2->lifebyte) {
  233: 			plog(LLV_ERROR, LOCATION, NULL,
  234: 				"long lifebyte proposed: "
  235: 				"my:%d peer:%d\n",
  236: 				pp2->lifebyte, pp1->lifebyte);
  237: 			goto err;
  238: 		}
  239: 		newpp->lifetime = pp1->lifetime;
  240: 		newpp->lifebyte = pp1->lifebyte;
  241: 
  242:     prop_pfs_check:
  243: 		if (pp2->pfs_group != 0 && pp1->pfs_group != pp2->pfs_group) {
  244: 			plog(LLV_ERROR, LOCATION, NULL,
  245: 				"pfs group mismatched: "
  246: 				"my:%d peer:%d\n",
  247: 				pp2->pfs_group, pp1->pfs_group);
  248: 			goto err;
  249: 		}
  250: 		newpp->pfs_group = pp1->pfs_group;
  251: 		break;
  252: 
  253: 	case PROP_CHECK_CLAIM:
  254: 		/* lifetime */
  255: 		if (pp1->lifetime <= pp2->lifetime) {
  256: 			newpp->lifetime = pp1->lifetime;
  257: 		} else {
  258: 			newpp->lifetime = pp2->lifetime;
  259: 			newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
  260: 			plog(LLV_NOTIFY, LOCATION, NULL,
  261: 				"use own lifetime: "
  262: 				"my:%d peer:%d\n",
  263: 				(int)pp2->lifetime, (int)pp1->lifetime);
  264: 		}
  265: 
  266: 		/* lifebyte */
  267: 		if (pp1->lifebyte > pp2->lifebyte) {
  268: 			newpp->lifebyte = pp2->lifebyte;
  269: 			newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
  270: 			plog(LLV_NOTIFY, LOCATION, NULL,
  271: 				"use own lifebyte: "
  272: 				"my:%d peer:%d\n",
  273: 				pp2->lifebyte, pp1->lifebyte);
  274: 		}
  275: 		newpp->lifebyte = pp1->lifebyte;
  276: 
  277:     		goto prop_pfs_check;
  278: 		break;
  279: 
  280: 	case PROP_CHECK_EXACT:
  281: 		if (pp1->lifetime != pp2->lifetime) {
  282: 			plog(LLV_ERROR, LOCATION, NULL,
  283: 				"lifetime mismatched: "
  284: 				"my:%d peer:%d\n",
  285: 				(int)pp2->lifetime, (int)pp1->lifetime);
  286: 			goto err;
  287: 		}
  288: 
  289: 		if (pp1->lifebyte != pp2->lifebyte) {
  290: 			plog(LLV_ERROR, LOCATION, NULL,
  291: 				"lifebyte mismatched: "
  292: 				"my:%d peer:%d\n",
  293: 				pp2->lifebyte, pp1->lifebyte);
  294: 			goto err;
  295: 		}
  296: 		if (pp1->pfs_group != pp2->pfs_group) {
  297: 			plog(LLV_ERROR, LOCATION, NULL,
  298: 				"pfs group mismatched: "
  299: 				"my:%d peer:%d\n",
  300: 				pp2->pfs_group, pp1->pfs_group);
  301: 			goto err;
  302: 		}
  303: 		newpp->lifetime = pp1->lifetime;
  304: 		newpp->lifebyte = pp1->lifebyte;
  305: 		newpp->pfs_group = pp1->pfs_group;
  306: 		break;
  307: 
  308: 	default:
  309: 		plog(LLV_ERROR, LOCATION, NULL,
  310: 			"invalid pcheck_level why?.\n");
  311: 		goto err;
  312: 	}
  313: 
  314: #ifdef HAVE_SECCTX
  315: 	/* check the security_context properties.
  316: 	 * It is possible for one side to have a security context
  317: 	 * and the other side doesn't. If so, this is an error.
  318: 	 */
  319: 
  320: 	if (*pp1->sctx.ctx_str && !(*pp2->sctx.ctx_str)) {
  321: 		plog(LLV_ERROR, LOCATION, NULL,
  322: 		     "My proposal missing security context\n");
  323: 		goto err;
  324: 	}
  325: 	if (!(*pp1->sctx.ctx_str) && *pp2->sctx.ctx_str) {
  326: 		plog(LLV_ERROR, LOCATION, NULL, 
  327: 		     "Peer is missing security context\n");
  328: 		goto err;
  329: 	}
  330: 
  331: 	if (*pp1->sctx.ctx_str && *pp2->sctx.ctx_str) {
  332: 		if (pp1->sctx.ctx_doi == pp2->sctx.ctx_doi)
  333: 			newpp->sctx.ctx_doi = pp1->sctx.ctx_doi;
  334: 		else {
  335: 			plog(LLV_ERROR, LOCATION, NULL, 
  336: 			     "sec doi mismatched: my:%d peer:%d\n",
  337: 			     pp2->sctx.ctx_doi, pp1->sctx.ctx_doi);
  338: 			     goto err;
  339: 		}
  340: 
  341: 		if (pp1->sctx.ctx_alg == pp2->sctx.ctx_alg)
  342: 			newpp->sctx.ctx_alg = pp1->sctx.ctx_alg;
  343: 		else {
  344: 			plog(LLV_ERROR, LOCATION, NULL,
  345: 			     "sec alg mismatched: my:%d peer:%d\n",
  346: 			     pp2->sctx.ctx_alg, pp1->sctx.ctx_alg);
  347: 			goto err;
  348: 		}
  349: 
  350: 		if ((pp1->sctx.ctx_strlen != pp2->sctx.ctx_strlen) ||
  351: 		     memcmp(pp1->sctx.ctx_str, pp2->sctx.ctx_str,
  352: 		     pp1->sctx.ctx_strlen) != 0) {
  353: 			plog(LLV_ERROR, LOCATION, NULL,
  354: 			     "sec ctx string mismatched: my:%s peer:%s\n",
  355: 			     pp2->sctx.ctx_str, pp1->sctx.ctx_str);
  356: 				goto err;
  357: 		} else {
  358: 			newpp->sctx.ctx_strlen = pp1->sctx.ctx_strlen;
  359: 			memcpy(newpp->sctx.ctx_str, pp1->sctx.ctx_str,
  360: 				pp1->sctx.ctx_strlen);
  361: 		}
  362: 	}
  363: #endif /* HAVE_SECCTX */
  364: 
  365: 	npr1 = npr2 = 0;
  366: 	for (pr1 = pp1->head; pr1; pr1 = pr1->next)
  367: 		npr1++;
  368: 	for (pr2 = pp2->head; pr2; pr2 = pr2->next)
  369: 		npr2++;
  370: 	if (npr1 != npr2)
  371: 		goto err;
  372: 
  373: 	/* check protocol order */
  374: 	pr1 = pp1->head;
  375: 	pr2 = pp2->head;
  376: 
  377: 	while (1) {
  378: 		if (!ordermatters) {
  379: 			/*
  380: 			 * XXX does not work if we have multiple proposals
  381: 			 * with the same proto_id
  382: 			 */
  383: 			switch (side) {
  384: 			case RESPONDER:
  385: 				if (!pr2)
  386: 					break;
  387: 				for (pr1 = pp1->head; pr1; pr1 = pr1->next) {
  388: 					if (pr1->proto_id == pr2->proto_id)
  389: 						break;
  390: 				}
  391: 				break;
  392: 			case INITIATOR:
  393: 				if (!pr1)
  394: 					break;
  395: 				for (pr2 = pp2->head; pr2; pr2 = pr2->next) {
  396: 					if (pr2->proto_id == pr1->proto_id)
  397: 						break;
  398: 				}
  399: 				break;
  400: 			}
  401: 		}
  402: 		if (!pr1 || !pr2)
  403: 			break;
  404: 
  405: 		if (pr1->proto_id != pr2->proto_id) {
  406: 			plog(LLV_ERROR, LOCATION, NULL,
  407: 				"proto_id mismatched: "
  408: 				"my:%s peer:%s\n",
  409: 				s_ipsecdoi_proto(pr2->proto_id),
  410: 				s_ipsecdoi_proto(pr1->proto_id));
  411: 			goto err;
  412: 		}
  413: 		spisizematch = 0;
  414: 		if (pr1->spisize == pr2->spisize)
  415: 			spisizematch = 1;
  416: 		else if (pr1->proto_id == IPSECDOI_PROTO_IPCOMP) {
  417: 			/*
  418: 			 * draft-shacham-ippcp-rfc2393bis-05.txt:
  419: 			 * need to accept 16bit and 32bit SPI (CPI) for IPComp.
  420: 			 */
  421: 			if (pr1->spisize == sizeof(u_int16_t) &&
  422: 			    pr2->spisize == sizeof(u_int32_t)) {
  423: 				spisizematch = 1;
  424: 			} else if (pr2->spisize == sizeof(u_int16_t) &&
  425: 				 pr1->spisize == sizeof(u_int32_t)) {
  426: 				spisizematch = 1;
  427: 			}
  428: 			if (spisizematch) {
  429: 				plog(LLV_ERROR, LOCATION, NULL,
  430: 				    "IPComp SPI size promoted "
  431: 				    "from 16bit to 32bit\n");
  432: 			}
  433: 		}
  434: 		if (!spisizematch) {
  435: 			plog(LLV_ERROR, LOCATION, NULL,
  436: 				"spisize mismatched: "
  437: 				"my:%d peer:%d\n",
  438: 				(int)pr2->spisize, (int)pr1->spisize);
  439: 			goto err;
  440: 		}
  441: 
  442: #ifdef ENABLE_NATT
  443: 		if ((ph1->natt_flags & NAT_DETECTED) && 
  444: 		    natt_udp_encap (pr2->encmode))
  445: 		{
  446: 			plog(LLV_INFO, LOCATION, NULL, "Adjusting my encmode %s->%s\n",
  447: 			     s_ipsecdoi_encmode(pr2->encmode),
  448: 			     s_ipsecdoi_encmode(pr2->encmode - ph1->natt_options->mode_udp_diff));
  449: 			pr2->encmode -= ph1->natt_options->mode_udp_diff;
  450: 			pr2->udp_encap = 1;
  451: 		}
  452: 
  453: 		if ((ph1->natt_flags & NAT_DETECTED) &&
  454: 		    natt_udp_encap (pr1->encmode))
  455: 		{
  456: 			plog(LLV_INFO, LOCATION, NULL, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
  457: 			     s_ipsecdoi_encmode(pr1->encmode),
  458: 			     pr1->encmode,
  459: 			     s_ipsecdoi_encmode(pr1->encmode - ph1->natt_options->mode_udp_diff),
  460: 			     pr1->encmode - ph1->natt_options->mode_udp_diff);
  461: 			pr1->encmode -= ph1->natt_options->mode_udp_diff;
  462: 			pr1->udp_encap = 1;
  463: 		}
  464: #endif
  465: 
  466: 		if (pr1->encmode != pr2->encmode) {
  467: 			plog(LLV_ERROR, LOCATION, NULL,
  468: 				"encmode mismatched: "
  469: 				"my:%s peer:%s\n",
  470: 				s_ipsecdoi_encmode(pr2->encmode),
  471: 				s_ipsecdoi_encmode(pr1->encmode));
  472: 			goto err;
  473: 		}
  474: 
  475: 		for (tr1 = pr1->head; tr1; tr1 = tr1->next) {
  476: 			for (tr2 = pr2->head; tr2; tr2 = tr2->next) {
  477: 				if (cmpsatrns(pr1->proto_id, tr1, tr2, ph1->rmconf->pcheck_level) == 0)
  478: 					goto found;
  479: 			}
  480: 		}
  481: 
  482: 		goto err;
  483: 
  484: 	    found:
  485: 		newpr = newsaproto();
  486: 		if (newpr == NULL) {
  487: 			plog(LLV_ERROR, LOCATION, NULL,
  488: 				"failed to allocate saproto.\n");
  489: 			goto err;
  490: 		}
  491: 		newpr->proto_id = pr1->proto_id;
  492: 		newpr->spisize = pr1->spisize;
  493: 		newpr->encmode = pr1->encmode;
  494: 		newpr->spi = pr2->spi;		/* copy my SPI */
  495: 		newpr->spi_p = pr1->spi;	/* copy peer's SPI */
  496: 		newpr->reqid_in = pr2->reqid_in;
  497: 		newpr->reqid_out = pr2->reqid_out;
  498: #ifdef ENABLE_NATT
  499: 		newpr->udp_encap = pr1->udp_encap | pr2->udp_encap;
  500: #endif
  501: 
  502: 		newtr = newsatrns();
  503: 		if (newtr == NULL) {
  504: 			plog(LLV_ERROR, LOCATION, NULL,
  505: 				"failed to allocate satrns.\n");
  506: 			racoon_free(newpr);
  507: 			goto err;
  508: 		}
  509: 		newtr->trns_no = tr1->trns_no;
  510: 		newtr->trns_id = tr1->trns_id;
  511: 		newtr->encklen = tr1->encklen;
  512: 		newtr->authtype = tr1->authtype;
  513: 
  514: 		inssatrns(newpr, newtr);
  515: 		inssaproto(newpp, newpr);
  516: 
  517: 		pr1 = pr1->next;
  518: 		pr2 = pr2->next;
  519: 	}
  520: 
  521: 	/* XXX should check if we have visited all items or not */
  522: 	if (!ordermatters) {
  523: 		switch (side) {
  524: 		case RESPONDER:
  525: 			if (!pr2)
  526: 				pr1 = NULL;
  527: 			break;
  528: 		case INITIATOR:
  529: 			if (!pr1)
  530: 				pr2 = NULL;
  531: 			break;
  532: 		}
  533: 	}
  534: 
  535: 	/* should be matched all protocols in a proposal */
  536: 	if (pr1 != NULL || pr2 != NULL)
  537: 		goto err;
  538: 
  539: 	return newpp;
  540: 
  541: err:
  542: 	flushsaprop(newpp);
  543: 	return NULL;
  544: }
  545: 
  546: /* take a single match between saprop.  returns 0 if pp1 equals to pp2. */
  547: int
  548: cmpsaprop(pp1, pp2)
  549: 	const struct saprop *pp1, *pp2;
  550: {
  551: 	if (pp1->pfs_group != pp2->pfs_group) {
  552: 		plog(LLV_WARNING, LOCATION, NULL,
  553: 			"pfs_group mismatch. mine:%d peer:%d\n",
  554: 			pp1->pfs_group, pp2->pfs_group);
  555: 		/* FALLTHRU */
  556: 	}
  557: 
  558: 	if (pp1->lifetime > pp2->lifetime) {
  559: 		plog(LLV_WARNING, LOCATION, NULL,
  560: 			"less lifetime proposed. mine:%d peer:%d\n",
  561: 			(int)pp1->lifetime, (int)pp2->lifetime);
  562: 		/* FALLTHRU */
  563: 	}
  564: 	if (pp1->lifebyte > pp2->lifebyte) {
  565: 		plog(LLV_WARNING, LOCATION, NULL,
  566: 			"less lifebyte proposed. mine:%d peer:%d\n",
  567: 			pp1->lifebyte, pp2->lifebyte);
  568: 		/* FALLTHRU */
  569: 	}
  570: 
  571: 	return 0;
  572: }
  573: 
  574: /*
  575:  * take a single match between satrns.  returns 0 if tr1 equals to tr2.
  576:  * tr1: peer's satrns
  577:  * tr2: my satrns
  578:  */
  579: int
  580: cmpsatrns(proto_id, tr1, tr2, check_level)
  581: 	int proto_id;
  582: 	const struct satrns *tr1, *tr2;
  583: 	int check_level;
  584: {
  585: 	if (tr1->trns_id != tr2->trns_id) {
  586: 		plog(LLV_WARNING, LOCATION, NULL,
  587: 			"trns_id mismatched: "
  588: 			"my:%s peer:%s\n",
  589: 			s_ipsecdoi_trns(proto_id, tr2->trns_id),
  590: 			s_ipsecdoi_trns(proto_id, tr1->trns_id));
  591: 		return 1;
  592: 	}
  593: 
  594: 	if (tr1->authtype != tr2->authtype) {
  595: 		plog(LLV_WARNING, LOCATION, NULL,
  596: 			"authtype mismatched: "
  597: 			"my:%s peer:%s\n",
  598: 			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr2->authtype),
  599: 			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr1->authtype));
  600: 		return 1;
  601: 	}
  602: 
  603: 	/* Check key length regarding checkmode
  604: 	 * XXX Shall we send some kind of notify message when key length rejected ?
  605: 	 */
  606: 	switch(check_level){
  607: 	case PROP_CHECK_OBEY:
  608: 		return 0;
  609: 		break;
  610: 
  611: 	case PROP_CHECK_STRICT:
  612: 		/* FALLTHROUGH */
  613: 	case PROP_CHECK_CLAIM:
  614: 		if (tr1->encklen < tr2->encklen) {
  615: 		plog(LLV_WARNING, LOCATION, NULL,
  616: 				 "low key length proposed, "
  617: 				 "mine:%d peer:%d.\n",
  618: 			tr2->encklen, tr1->encklen);
  619: 			return 1;
  620: 		}
  621: 		break;
  622: 	case PROP_CHECK_EXACT:
  623: 		if (tr1->encklen != tr2->encklen) {
  624: 			plog(LLV_WARNING, LOCATION, NULL,
  625: 				 "key length mismatched, "
  626: 				 "mine:%d peer:%d.\n",
  627: 				 tr2->encklen, tr1->encklen);
  628: 			return 1;
  629: 		}
  630: 		break;
  631: 	}
  632: 
  633: 	return 0;
  634: }
  635: 
  636: int
  637: set_satrnsbysainfo(pr, sainfo)
  638: 	struct saproto *pr;
  639: 	struct sainfo *sainfo;
  640: {
  641: 	struct sainfoalg *a, *b;
  642: 	struct satrns *newtr;
  643: 	int t;
  644: 
  645: 	switch (pr->proto_id) {
  646: 	case IPSECDOI_PROTO_IPSEC_AH:
  647: 		if (sainfo->algs[algclass_ipsec_auth] == NULL) {
  648: 			plog(LLV_ERROR, LOCATION, NULL,
  649: 				"no auth algorithm found\n");
  650: 			goto err;
  651: 		}
  652: 		t = 1;
  653: 		for (a = sainfo->algs[algclass_ipsec_auth]; a; a = a->next) {
  654: 
  655: 			if (a->alg == IPSECDOI_ATTR_AUTH_NONE)
  656: 				continue;
  657: 				
  658: 			/* allocate satrns */
  659: 			newtr = newsatrns();
  660: 			if (newtr == NULL) {
  661: 				plog(LLV_ERROR, LOCATION, NULL,
  662: 					"failed to allocate satrns.\n");
  663: 				goto err;
  664: 			}
  665: 
  666: 			newtr->trns_no = t++;
  667: 			newtr->trns_id = ipsecdoi_authalg2trnsid(a->alg);
  668: 			newtr->authtype = a->alg;
  669: 
  670: 			inssatrns(pr, newtr);
  671: 		}
  672: 		break;
  673: 	case IPSECDOI_PROTO_IPSEC_ESP:
  674: 		if (sainfo->algs[algclass_ipsec_enc] == NULL) {
  675: 			plog(LLV_ERROR, LOCATION, NULL,
  676: 				"no encryption algorithm found\n");
  677: 			goto err;
  678: 		}
  679: 		t = 1;
  680: 		for (a = sainfo->algs[algclass_ipsec_enc]; a; a = a->next) {
  681: 			for (b = sainfo->algs[algclass_ipsec_auth]; b; b = b->next) {
  682: 				/* allocate satrns */
  683: 				newtr = newsatrns();
  684: 				if (newtr == NULL) {
  685: 					plog(LLV_ERROR, LOCATION, NULL,
  686: 						"failed to allocate satrns.\n");
  687: 					goto err;
  688: 				}
  689: 
  690: 				newtr->trns_no = t++;
  691: 				newtr->trns_id = a->alg;
  692: 				newtr->encklen = a->encklen;
  693: 				newtr->authtype = b->alg;
  694: 
  695: 				inssatrns(pr, newtr);
  696: 			}
  697: 		}
  698: 		break;
  699: 	case IPSECDOI_PROTO_IPCOMP:
  700: 		if (sainfo->algs[algclass_ipsec_comp] == NULL) {
  701: 			plog(LLV_ERROR, LOCATION, NULL,
  702: 				"no ipcomp algorithm found\n");
  703: 			goto err;
  704: 		}
  705: 		t = 1;
  706: 		for (a = sainfo->algs[algclass_ipsec_comp]; a; a = a->next) {
  707: 
  708: 			/* allocate satrns */
  709: 			newtr = newsatrns();
  710: 			if (newtr == NULL) {
  711: 				plog(LLV_ERROR, LOCATION, NULL,
  712: 					"failed to allocate satrns.\n");
  713: 				goto err;
  714: 			}
  715: 
  716: 			newtr->trns_no = t++;
  717: 			newtr->trns_id = a->alg;
  718: 			newtr->authtype = IPSECDOI_ATTR_AUTH_NONE; /*no auth*/
  719: 
  720: 			inssatrns(pr, newtr);
  721: 		}
  722: 		break;
  723: 	default:
  724: 		plog(LLV_ERROR, LOCATION, NULL,
  725: 			"unknown proto_id (%d).\n", pr->proto_id);
  726: 		goto err;
  727: 	}
  728: 
  729: 	/* no proposal found */
  730: 	if (pr->head == NULL) {
  731: 		plog(LLV_ERROR, LOCATION, NULL, "no algorithms found.\n");
  732: 		return -1;
  733: 	}
  734: 
  735: 	return 0;
  736: 
  737: err:
  738: 	flushsatrns(pr->head);
  739: 	return -1;
  740: }
  741: 
  742: struct saprop *
  743: aproppair2saprop(p0)
  744: 	struct prop_pair *p0;
  745: {
  746: 	struct prop_pair *p, *t;
  747: 	struct saprop *newpp;
  748: 	struct saproto *newpr;
  749: 	struct satrns *newtr;
  750: 	u_int8_t *spi;
  751: 
  752: 	if (p0 == NULL)
  753: 		return NULL;
  754: 
  755: 	/* allocate ipsec a sa proposal */
  756: 	newpp = newsaprop();
  757: 	if (newpp == NULL) {
  758: 		plog(LLV_ERROR, LOCATION, NULL,
  759: 			"failed to allocate saprop.\n");
  760: 		return NULL;
  761: 	}
  762: 	newpp->prop_no = p0->prop->p_no;
  763: 	/* lifetime & lifebyte must be updated later */
  764: 
  765: 	for (p = p0; p; p = p->next) {
  766: 
  767: 		/* allocate ipsec sa protocol */
  768: 		newpr = newsaproto();
  769: 		if (newpr == NULL) {
  770: 			plog(LLV_ERROR, LOCATION, NULL,
  771: 				"failed to allocate saproto.\n");
  772: 			goto err;
  773: 		}
  774: 
  775: 		/* check spi size */
  776: 		/* XXX should be handled isakmp cookie */
  777: 		if (sizeof(newpr->spi) < p->prop->spi_size) {
  778: 			plog(LLV_ERROR, LOCATION, NULL,
  779: 				"invalid spi size %d.\n", p->prop->spi_size);
  780: 			racoon_free(newpr);
  781: 			goto err;
  782: 		}
  783: 
  784: 		/*
  785: 		 * XXX SPI bits are left-filled, for use with IPComp.
  786: 		 * we should be switching to variable-length spi field...
  787: 		 */
  788: 		newpr->proto_id = p->prop->proto_id;
  789: 		newpr->spisize = p->prop->spi_size;
  790: 		memset(&newpr->spi, 0, sizeof(newpr->spi));
  791: 		spi = (u_int8_t *)&newpr->spi;
  792: 		spi += sizeof(newpr->spi);
  793: 		spi -= p->prop->spi_size;
  794: 		memcpy(spi, p->prop + 1, p->prop->spi_size);
  795: 		newpr->reqid_in = 0;
  796: 		newpr->reqid_out = 0;
  797: 
  798: 		for (t = p; t; t = t->tnext) {
  799: 
  800: 			plog(LLV_DEBUG, LOCATION, NULL,
  801: 				"prop#=%d prot-id=%s spi-size=%d "
  802: 				"#trns=%d trns#=%d trns-id=%s\n",
  803: 				t->prop->p_no,
  804: 				s_ipsecdoi_proto(t->prop->proto_id),
  805: 				t->prop->spi_size, t->prop->num_t,
  806: 				t->trns->t_no,
  807: 				s_ipsecdoi_trns(t->prop->proto_id,
  808: 				t->trns->t_id));
  809: 
  810: 			/* allocate ipsec sa transform */
  811: 			newtr = newsatrns();
  812: 			if (newtr == NULL) {
  813: 				plog(LLV_ERROR, LOCATION, NULL,
  814: 					"failed to allocate satrns.\n");
  815: 				racoon_free(newpr);
  816: 				goto err;
  817: 			}
  818: 
  819: 			if (ipsecdoi_t2satrns(t->trns, 
  820: 			    newpp, newpr, newtr) < 0) {
  821: 				flushsaprop(newpp);
  822: 				racoon_free(newtr);
  823: 				racoon_free(newpr);
  824: 				return NULL;
  825: 			}
  826: 
  827: 			inssatrns(newpr, newtr);
  828: 		}
  829: 
  830: 		/*
  831: 		 * If the peer does not specify encryption mode, use 
  832: 		 * transport mode by default.  This is to conform to
  833: 		 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies
  834: 		 * that unspecified == transport), as well as RFC2407
  835: 		 * (unspecified == implementation dependent default).
  836: 		 */
  837: 		if (newpr->encmode == 0)
  838: 			newpr->encmode = IPSECDOI_ATTR_ENC_MODE_TRNS;
  839: 
  840: 		inssaproto(newpp, newpr);
  841: 	}
  842: 
  843: 	return newpp;
  844: 
  845: err:
  846: 	flushsaprop(newpp);
  847: 	return NULL;
  848: }
  849: 
  850: void
  851: flushsaprop(head)
  852: 	struct saprop *head;
  853: {
  854: 	struct saprop *p, *save;
  855: 
  856: 	for (p = head; p != NULL; p = save) {
  857: 		save = p->next;
  858: 		flushsaproto(p->head);
  859: 		racoon_free(p);
  860: 	}
  861: 
  862: 	return;
  863: }
  864: 
  865: void
  866: flushsaproto(head)
  867: 	struct saproto *head;
  868: {
  869: 	struct saproto *p, *save;
  870: 
  871: 	for (p = head; p != NULL; p = save) {
  872: 		save = p->next;
  873: 		flushsatrns(p->head);
  874: 		vfree(p->keymat);
  875: 		vfree(p->keymat_p);
  876: 		racoon_free(p);
  877: 	}
  878: 
  879: 	return;
  880: }
  881: 
  882: void
  883: flushsatrns(head)
  884: 	struct satrns *head;
  885: {
  886: 	struct satrns *p, *save;
  887: 
  888: 	for (p = head; p != NULL; p = save) {
  889: 		save = p->next;
  890: 		racoon_free(p);
  891: 	}
  892: 
  893: 	return;
  894: }
  895: 
  896: /*
  897:  * print multiple proposals
  898:  */
  899: void
  900: printsaprop(pri, pp)
  901: 	const int pri;
  902: 	const struct saprop *pp;
  903: {
  904: 	const struct saprop *p;
  905: 
  906: 	if (pp == NULL) {
  907: 		plog(pri, LOCATION, NULL, "(null)");
  908: 		return;
  909: 	}
  910: 
  911: 	for (p = pp; p; p = p->next) {
  912: 		printsaprop0(pri, p);
  913: 	}
  914: 
  915: 	return;
  916: }
  917: 
  918: /*
  919:  * print one proposal.
  920:  */
  921: void
  922: printsaprop0(pri, pp)
  923: 	int pri;
  924: 	const struct saprop *pp;
  925: {
  926: 	const struct saproto *p;
  927: 
  928: 	if (pp == NULL)
  929: 		return;
  930: 
  931: 	for (p = pp->head; p; p = p->next) {
  932: 		printsaproto(pri, p);
  933: 	}
  934: 
  935: 	return;
  936: }
  937: 
  938: void
  939: printsaproto(pri, pr)
  940: 	const int pri;
  941: 	const struct saproto *pr;
  942: {
  943: 	struct satrns *tr;
  944: 
  945: 	if (pr == NULL)
  946: 		return;
  947: 
  948: 	plog(pri, LOCATION, NULL,
  949: 		" (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx "
  950: 		"encmode=%s reqid=%d:%d)\n",
  951: 		s_ipsecdoi_proto(pr->proto_id),
  952: 		(int)pr->spisize,
  953: 		(unsigned long)ntohl(pr->spi),
  954: 		(unsigned long)ntohl(pr->spi_p),
  955: 		s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE, pr->encmode),
  956: 		(int)pr->reqid_in, (int)pr->reqid_out);
  957: 
  958: 	for (tr = pr->head; tr; tr = tr->next) {
  959: 		printsatrns(pri, pr->proto_id, tr);
  960: 	}
  961: 
  962: 	return;
  963: }
  964: 
  965: void
  966: printsatrns(pri, proto_id, tr)
  967: 	const int pri;
  968: 	const int proto_id;
  969: 	const struct satrns *tr;
  970: {
  971: 	if (tr == NULL)
  972: 		return;
  973: 
  974: 	switch (proto_id) {
  975: 	case IPSECDOI_PROTO_IPSEC_AH:
  976: 		plog(pri, LOCATION, NULL,
  977: 			"  (trns_id=%s authtype=%s)\n",
  978: 			s_ipsecdoi_trns(proto_id, tr->trns_id),
  979: 			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
  980: 		break;
  981: 	case IPSECDOI_PROTO_IPSEC_ESP:
  982: 		plog(pri, LOCATION, NULL,
  983: 			"  (trns_id=%s encklen=%d authtype=%s)\n",
  984: 			s_ipsecdoi_trns(proto_id, tr->trns_id),
  985: 			tr->encklen,
  986: 			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
  987: 		break;
  988: 	case IPSECDOI_PROTO_IPCOMP:
  989: 		plog(pri, LOCATION, NULL,
  990: 			"  (trns_id=%s)\n",
  991: 			s_ipsecdoi_trns(proto_id, tr->trns_id));
  992: 		break;
  993: 	default:
  994: 		plog(pri, LOCATION, NULL,
  995: 			"(unknown proto_id %d)\n", proto_id);
  996: 	}
  997: 
  998: 	return;
  999: }
 1000: 
 1001: void
 1002: print_proppair0(pri, p, level)
 1003: 	int pri; 
 1004: 	struct prop_pair *p;
 1005: 	int level;
 1006: {
 1007: 	char spc[21];
 1008: 
 1009: 	memset(spc, ' ', sizeof(spc));
 1010: 	spc[sizeof(spc) - 1] = '\0';
 1011: 	if (level < 20) {
 1012: 		spc[level] = '\0';
 1013: 	}
 1014: 
 1015: 	plog(pri, LOCATION, NULL,
 1016: 		"%s%p: next=%p tnext=%p\n", spc, p, p->next, p->tnext);
 1017: 	if (p->next)
 1018: 		print_proppair0(pri, p->next, level + 1);
 1019: 	if (p->tnext)
 1020: 		print_proppair0(pri, p->tnext, level + 1);
 1021: }
 1022: 
 1023: void
 1024: print_proppair(pri, p)
 1025: 	int pri;
 1026: 	struct prop_pair *p;
 1027: {
 1028: 	print_proppair0(pri, p, 1);
 1029: }
 1030: 
 1031: int
 1032: set_proposal_from_policy(iph2, sp_main, sp_sub)
 1033: 	struct ph2handle *iph2;
 1034: 	struct secpolicy *sp_main, *sp_sub;
 1035: {
 1036: 	struct saprop *newpp;
 1037: 	struct ipsecrequest *req;
 1038: 	int encmodesv = IPSECDOI_ATTR_ENC_MODE_TRNS; /* use only when complex_bundle */
 1039: 
 1040: 	newpp = newsaprop();
 1041: 	if (newpp == NULL) {
 1042: 		plog(LLV_ERROR, LOCATION, NULL,
 1043: 			"failed to allocate saprop.\n");
 1044: 		goto err;
 1045: 	}
 1046: 	newpp->prop_no = 1;
 1047: 	newpp->lifetime = iph2->sainfo->lifetime;
 1048: 	newpp->lifebyte = iph2->sainfo->lifebyte;
 1049: 	newpp->pfs_group = iph2->sainfo->pfs_group;
 1050: 
 1051: 	if (lcconf->complex_bundle)
 1052: 		goto skip1;
 1053: 
 1054: 	/*
 1055: 	 * decide the encryption mode of this SA bundle.
 1056: 	 * the mode becomes tunnel mode when there is even one policy
 1057: 	 * of tunnel mode in the SPD.  otherwise the mode becomes
 1058: 	 * transport mode.
 1059: 	 */
 1060: 	for (req = sp_main->req; req; req = req->next) {
 1061: 		if (req->saidx.mode == IPSEC_MODE_TUNNEL) {
 1062: 			encmodesv = pfkey2ipsecdoi_mode(req->saidx.mode);
 1063: #ifdef ENABLE_NATT
 1064: 			if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
 1065: 				encmodesv += iph2->ph1->natt_options->mode_udp_diff;
 1066: #endif
 1067: 			break;
 1068: 		}
 1069: 	}
 1070: 
 1071:     skip1:
 1072: 	for (req = sp_main->req; req; req = req->next) {
 1073: 		struct saproto *newpr;
 1074: 		caddr_t paddr = NULL;
 1075: 
 1076: 		/*
 1077: 		 * check if SA bundle ?
 1078: 		 * nested SAs negotiation is NOT supported.
 1079: 		 *       me +--- SA1 ---+ peer1
 1080: 		 *       me +--- SA2 --------------+ peer2
 1081: 		 */
 1082: #ifdef __linux__
 1083: 		if (req->saidx.src.ss_family && req->saidx.dst.ss_family) {
 1084: #else
 1085: 		if (req->saidx.src.ss_len && req->saidx.dst.ss_len) {
 1086: #endif
 1087: 			/* check the end of ip addresses of SA */
 1088: 			if (iph2->side == INITIATOR)
 1089: 				paddr = (caddr_t)&req->saidx.dst;
 1090: 			else
 1091: 				paddr = (caddr_t)&req->saidx.src;
 1092: 		}
 1093: 
 1094: 		/* allocate ipsec sa protocol */
 1095: 		newpr = newsaproto();
 1096: 		if (newpr == NULL) {
 1097: 			plog(LLV_ERROR, LOCATION, NULL,
 1098: 				"failed to allocate saproto.\n");
 1099: 			goto err;
 1100: 		}
 1101: 
 1102: 		newpr->proto_id = ipproto2doi(req->saidx.proto);
 1103: 		if (newpr->proto_id == IPSECDOI_PROTO_IPCOMP)
 1104: 			newpr->spisize = 2;
 1105: 		else
 1106: 			newpr->spisize = 4;
 1107: 		if (lcconf->complex_bundle) {
 1108: 			newpr->encmode = pfkey2ipsecdoi_mode(req->saidx.mode);
 1109: #ifdef ENABLE_NATT
 1110: 			if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
 1111: 				newpr->encmode += 
 1112: 				    iph2->ph1->natt_options->mode_udp_diff;
 1113: #endif
 1114: 		}
 1115: 		else
 1116: 			newpr->encmode = encmodesv;
 1117: 
 1118: 		if (iph2->side == INITIATOR)
 1119: 			newpr->reqid_out = req->saidx.reqid;
 1120: 		else
 1121: 			newpr->reqid_in = req->saidx.reqid;
 1122: 
 1123: 		if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0) {
 1124: 			plog(LLV_ERROR, LOCATION, NULL,
 1125: 				"failed to get algorithms.\n");
 1126: 			racoon_free(newpr);
 1127: 			goto err;
 1128: 		}
 1129: 
 1130: 		/* set new saproto */
 1131: 		inssaprotorev(newpp, newpr);
 1132: 	}
 1133: 
 1134: 	/* get reqid_in from inbound policy */
 1135: 	if (sp_sub) {
 1136: 		struct saproto *pr;
 1137: 
 1138: 		req = sp_sub->req;
 1139: 		pr = newpp->head;
 1140: 		while (req && pr) {
 1141: 			if (iph2->side == INITIATOR)
 1142: 				pr->reqid_in = req->saidx.reqid;
 1143: 			else
 1144: 				pr->reqid_out = req->saidx.reqid;
 1145: 			pr = pr->next;
 1146: 			req = req->next;
 1147: 		}
 1148: 		if (pr || req) {
 1149: 			plog(LLV_NOTIFY, LOCATION, NULL,
 1150: 				"There is a difference "
 1151: 				"between the in/out bound policies in SPD.\n");
 1152: 		}
 1153: 	}
 1154: 
 1155: 	iph2->proposal = newpp;
 1156: 
 1157: 	printsaprop0(LLV_DEBUG, newpp);
 1158: 
 1159: 	return 0;
 1160: err:
 1161: 	flushsaprop(newpp);
 1162: 	return -1;
 1163: }
 1164: 
 1165: /*
 1166:  * generate a policy from peer's proposal.
 1167:  * this function unconditionally choices first proposal in SA payload
 1168:  * passed by peer.
 1169:  */
 1170: int
 1171: set_proposal_from_proposal(iph2)
 1172: 	struct ph2handle *iph2;
 1173: {
 1174:         struct saprop *newpp = NULL, *pp0, *pp_peer = NULL;
 1175: 	struct saproto *newpr = NULL, *pr;
 1176: 	struct prop_pair **pair;
 1177: 	int error = -1;
 1178: 	int i;
 1179: 
 1180: 	/* get proposal pair */
 1181: 	pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
 1182: 	if (pair == NULL)
 1183: 		goto end;
 1184: 
 1185: 	/*
 1186: 	 * make my proposal according as the client proposal.
 1187: 	 * XXX assumed there is only one proposal even if it's the SA bundle.
 1188: 	 */
 1189: 	for (i = 0; i < MAXPROPPAIRLEN; i++) {
 1190: 		if (pair[i] == NULL)
 1191: 			continue;
 1192: 		
 1193: 		if (pp_peer != NULL)
 1194: 			flushsaprop(pp_peer);
 1195: 
 1196: 		pp_peer = aproppair2saprop(pair[i]);
 1197: 		if (pp_peer == NULL)
 1198: 			goto end;
 1199: 
 1200: 		pp0 = newsaprop();
 1201: 		if (pp0 == NULL) {
 1202: 			plog(LLV_ERROR, LOCATION, NULL,
 1203: 				"failed to allocate saprop.\n");
 1204: 			goto end;
 1205: 		}
 1206: 		pp0->prop_no = 1;
 1207: 		pp0->lifetime = iph2->sainfo->lifetime;
 1208: 		pp0->lifebyte = iph2->sainfo->lifebyte;
 1209: 		pp0->pfs_group = iph2->sainfo->pfs_group;
 1210: 
 1211: #ifdef HAVE_SECCTX
 1212: 		if (*pp_peer->sctx.ctx_str) {
 1213: 			pp0->sctx.ctx_doi = pp_peer->sctx.ctx_doi;
 1214: 			pp0->sctx.ctx_alg = pp_peer->sctx.ctx_alg;
 1215: 			pp0->sctx.ctx_strlen = pp_peer->sctx.ctx_strlen;
 1216: 			memcpy(pp0->sctx.ctx_str, pp_peer->sctx.ctx_str,
 1217: 			       pp_peer->sctx.ctx_strlen);
 1218: 		}
 1219: #endif /* HAVE_SECCTX */
 1220: 
 1221: 		if (pp_peer->next != NULL) {
 1222: 			plog(LLV_ERROR, LOCATION, NULL,
 1223: 				"pp_peer is inconsistency, ignore it.\n");
 1224: 			/*FALLTHROUGH*/
 1225: 		}
 1226: 
 1227: 		for (pr = pp_peer->head; pr; pr = pr->next)
 1228: 		{
 1229: 			newpr = newsaproto();
 1230: 			if (newpr == NULL)
 1231: 			{
 1232: 				plog(LLV_ERROR, LOCATION, NULL,
 1233: 					"failed to allocate saproto.\n");
 1234: 				racoon_free(pp0);
 1235: 				goto end;
 1236: 			}
 1237: 			newpr->proto_id = pr->proto_id;
 1238: 			newpr->spisize = pr->spisize;
 1239: 			newpr->encmode = pr->encmode;
 1240: 			newpr->spi = 0;
 1241: 			newpr->spi_p = pr->spi;     /* copy peer's SPI */
 1242: 			newpr->reqid_in = 0;
 1243: 			newpr->reqid_out = 0;
 1244: 
 1245: 			if (iph2->ph1->rmconf->gen_policy == GENERATE_POLICY_UNIQUE){
 1246: 				newpr->reqid_in = g_nextreqid ;
 1247: 				newpr->reqid_out = g_nextreqid ++;
 1248: 				/* 
 1249: 				 * XXX there is a (very limited) 
 1250: 				 * risk of reusing the same reqid
 1251: 				 * as another SP entry for the same peer
 1252: 				 */
 1253: 				if(g_nextreqid >= IPSEC_MANUAL_REQID_MAX)
 1254: 					g_nextreqid = 1;
 1255: 			}else{
 1256: 				newpr->reqid_in = 0;
 1257: 				newpr->reqid_out = 0;
 1258: 			}
 1259:  
 1260: 			if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0)
 1261: 			{
 1262: 				plog(LLV_ERROR, LOCATION, NULL,
 1263: 					"failed to get algorithms.\n");
 1264: 				racoon_free(newpr);
 1265: 				racoon_free(pp0);
 1266: 				goto end;
 1267: 			}
 1268: 			inssaproto(pp0, newpr);
 1269: 		}
 1270: 
 1271: 		inssaprop(&newpp, pp0);
 1272:         }
 1273: 
 1274: 	plog(LLV_DEBUG, LOCATION, NULL, "make a proposal from peer's:\n");
 1275: 	printsaprop0(LLV_DEBUG, newpp);  
 1276: 
 1277: 	iph2->proposal = newpp;
 1278: 
 1279: 	error = 0;
 1280: 
 1281: end:
 1282: 	if (error && newpp)
 1283: 		flushsaprop(newpp);
 1284: 
 1285: 	if (pp_peer)
 1286: 		flushsaprop(pp_peer);
 1287: 	if (pair)
 1288: 		free_proppair(pair);
 1289: 	return error;
 1290: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>