1 /*      $KAME: ipsec_doi.c,v 1.168 2004/03/03 02:28:46 sakane Exp $     */
   2 
   3 /*
   4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
   5  * All rights reserved.
   6  * 
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  * 2. Redistributions in binary form must reproduce the above copyright
  13  *    notice, this list of conditions and the following disclaimer in the
  14  *    documentation and/or other materials provided with the distribution.
  15  * 3. Neither the name of the project nor the names of its contributors
  16  *    may be used to endorse or promote products derived from this software
  17  *    without specific prior written permission.
  18  * 
  19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29  * SUCH DAMAGE.
  30  */
  31 
  32 #include <config.h>
  33 
  34 #include <sys/types.h>
  35 #include <sys/param.h>
  36 #include <sys/socket.h>
  37 
  38 #include <netinet/in.h>
  39 
  40 #ifdef HAVE_NETINET6_IPSEC_H
  41 # include <netinet6/ipsec.h>
  42 #else
  43 # ifdef HAVE_NETIPSEC_IPSEC_H
  44 #  include <netipsec/ipsec.h>
  45 # else
  46 #  include <linux/ipsec.h>
  47 # endif
  48 #endif
  49 
  50 #include <assert.h>
  51 #include <stdlib.h>
  52 #include <stdio.h>
  53 #include <string.h>
  54 #include <errno.h>
  55 #include <netdb.h>
  56 #if TIME_WITH_SYS_TIME
  57 # include <sys/time.h>
  58 # include <time.h>
  59 #else
  60 # if HAVE_SYS_TIME_H
  61 #  include <sys/time.h>
  62 # else
  63 #  include <time.h>
  64 # endif
  65 #endif
  66 
  67 #include "racoon.h"
  68 
  69 #include "var.h"
  70 /* #include "vmbuf.h" */
  71 /* #include "misc.h" */
  72 #include "plog.h"
  73 #include "debug.h"
  74 
  75 /* #include "cfparse_proto.h" */
  76 #include "isakmp.h"
  77 #include "isakmp_impl.h"
  78 #include "isakmp_var.h"
  79 #include "ikev1_impl.h"
  80 #include "ipsec_doi.h"
  81 #include "dhgroup.h"
  82 #include "oakley.h"
  83 #include "remoteconf.h"
  84 /* #include "localconf.h" */
  85 #include "sockmisc.h"
  86 #include "handler.h"
  87 /* #include "policy.h" */
  88 #include "algorithm.h"
  89 /* #include "sainfo.h" */
  90 #include "proposal.h"
  91 #include "crypto_impl.h"
  92 #include "strnames.h"
  93 #include "gcmalloc.h"
  94 
  95 #ifdef ENABLE_NATT
  96 #include "ikev1_natt.h"
  97 #endif
  98 #ifdef HAVE_GSSAPI
  99 #include "gssapi.h"
 100 #endif
 101 
 102 #include "ike_conf.h"
 103 
 104 int verbose_proposal_check = 1;
 105 
 106 static rc_vchar_t *get_ph1approval (struct ph1handle *,
 107                                         struct prop_pair **);
 108 static struct isakmpsa *get_ph1approvalx (struct prop_pair *,
 109         struct isakmpsa *, struct isakmpsa *, rc_type);
 110 static void print_ph1mismatched (struct prop_pair *, struct isakmpsa *);
 111 static int t2isakmpsa (struct isakmp_pl_t *, struct isakmpsa *);
 112 static int cmp_aproppair_i (struct prop_pair *, struct prop_pair *);
 113 static struct prop_pair *get_ph2approval (struct ph2handle *,
 114         struct prop_pair **);
 115 static struct prop_pair *get_ph2approvalx (struct ph2handle *,
 116         struct prop_pair *);
 117 static void free_proppair0 (struct prop_pair *);
 118 
 119 static int get_transform
 120         (struct isakmp_pl_p *, struct prop_pair **, int *);
 121 static uint32_t ipsecdoi_set_ld (rc_vchar_t *);
 122 
 123 static int check_doi (uint32_t);
 124 static int check_situation (uint32_t);
 125 
 126 static int check_prot_main (int);
 127 static int check_prot_quick (int);
 128 static int (*check_protocol[]) (int) = {
 129         check_prot_main,        /* IPSECDOI_TYPE_PH1 */
 130         check_prot_quick,       /* IPSECDOI_TYPE_PH2 */
 131 };
 132 
 133 static int check_spi_size (int, int);
 134 
 135 static int check_trns_isakmp (int);
 136 static int check_trns_ah (int);
 137 static int check_trns_esp (int);
 138 static int check_trns_ipcomp (int);
 139 static int (*check_transform[]) (int) = {
 140         0,
 141         check_trns_isakmp,      /* IPSECDOI_PROTO_ISAKMP */
 142         check_trns_ah,          /* IPSECDOI_PROTO_IPSEC_AH */
 143         check_trns_esp,         /* IPSECDOI_PROTO_IPSEC_ESP */
 144         check_trns_ipcomp,      /* IPSECDOI_PROTO_IPCOMP */
 145 };
 146 
 147 static int check_attr_isakmp (struct isakmp_pl_t *);
 148 static int check_attr_ah (struct isakmp_pl_t *);
 149 static int check_attr_esp (struct isakmp_pl_t *);
 150 static int check_attr_ipsec (int, struct isakmp_pl_t *);
 151 static int check_attr_ipcomp (struct isakmp_pl_t *);
 152 static int (*check_attributes[]) (struct isakmp_pl_t *) = {
 153         0,
 154         check_attr_isakmp,      /* IPSECDOI_PROTO_ISAKMP */
 155         check_attr_ah,          /* IPSECDOI_PROTO_IPSEC_AH */
 156         check_attr_esp,         /* IPSECDOI_PROTO_IPSEC_ESP */
 157         check_attr_ipcomp,      /* IPSECDOI_PROTO_IPCOMP */
 158 };
 159 
 160 static int setph1prop (struct isakmpsa *, caddr_t);
 161 static int setph1trns (struct isakmpsa *, caddr_t);
 162 static int setph1attr (struct isakmpsa *, caddr_t);
 163 static rc_vchar_t *setph2proposal0 (const struct ph2handle *,
 164         const struct saprop *, const struct saproto *);
 165 
 166 #if 0
 167 static rc_vchar_t *getidval (int, rc_vchar_t *);
 168 #endif
 169 
 170 #ifdef HAVE_GSSAPI
 171 static struct isakmpsa *fixup_initiator_sa (struct isakmpsa *,
 172         struct isakmpsa *);
 173 #endif
 174 
 175 /*%%%*/
 176 /*
 177  * check phase 1 SA payload.
 178  * make new SA payload to be replyed not including general header.
 179  * the pointer to one of isakmpsa in proposal is set into iph1->approval.
 180  * OUT:
 181  *      positive: the pointer to new buffer of SA payload.
 182  *                network byte order.
 183  *      NULL    : error occurd.
 184  */
 185 int
 186 ipsecdoi_checkph1proposal(sa, iph1)
 187         rc_vchar_t *sa;
 188         struct ph1handle *iph1;
 189 {
 190         rc_vchar_t *newsa;              /* new SA payload approved. */
 191         struct prop_pair **pair;
 192 
 193         /* get proposal pair */
 194         pair = get_proppair(sa, IPSECDOI_TYPE_PH1);
 195         if (pair == NULL)
 196                 return -1;
 197 
 198         /* check and get one SA for use */
 199         newsa = get_ph1approval(iph1, pair);
 200         
 201         free_proppair(pair);
 202 
 203         if (newsa == NULL)
 204                 return -1;
 205 
 206         iph1->sa_ret = newsa;
 207 
 208         return 0;
 209 }
 210 
 211 /*
 212  * acceptable check for remote configuration.
 213  * return a new SA payload to be reply to peer.
 214  */
 215 static rc_vchar_t *
 216 get_ph1approval(iph1, pair)
 217         struct ph1handle *iph1;
 218         struct prop_pair **pair;
 219 {
 220         rc_vchar_t *newsa;
 221         struct isakmpsa *sa, tsa;
 222         struct prop_pair *s, *p;
 223         int prophlen;
 224         int i;
 225 
 226         if (iph1->approval) {
 227                 delisakmpsa(iph1->approval);
 228                 iph1->approval = NULL;
 229         }
 230 
 231         for (i = 0; i < MAXPROPPAIRLEN; i++) {
 232                 if (pair[i] == NULL)
 233                         continue;
 234                 for (s = pair[i]; s; s = s->next) {
 235                         prophlen = sizeof(struct isakmp_pl_p)
 236                                         + s->prop->spi_size;
 237                         /* compare proposal and select one */
 238                         for (p = s; p; p = p->tnext) {
 239                                 sa = get_ph1approvalx(p, iph1->proposal,
 240                                                       &tsa,
 241                                                       ikev1_proposal_check(iph1->rmconf));
 242                                 if (sa != NULL)
 243                                         goto found;
 244                         }
 245                 }
 246         }
 247 
 248         /*
 249          * if there is no suitable proposal, racoon complains about all of
 250          * mismatched items in those proposal.
 251          */
 252         if (verbose_proposal_check) {
 253                 for (i = 0; i < MAXPROPPAIRLEN; i++) {
 254                         if (pair[i] == NULL)
 255                                 continue;
 256                         for (s = pair[i]; s; s = s->next) {
 257                                 prophlen = sizeof(struct isakmp_pl_p)
 258                                                 + s->prop->spi_size;
 259                                 for (p = s; p; p = p->tnext) {
 260                                         print_ph1mismatched(p,
 261                                                             iph1->proposal);
 262                                 }
 263                         }
 264                 }
 265         }
 266         plog(PLOG_PROTOERR, PLOGLOC, NULL, "no suitable proposal found.\n");
 267 
 268         return NULL;
 269 
 270 found:
 271         plog(PLOG_DEBUG, PLOGLOC, NULL, "an acceptable proposal found.\n");
 272 
 273         /* check DH group settings */
 274         if (sa->dhgrp) {
 275                 if (sa->dhgrp->prime && sa->dhgrp->gen1) {
 276                         /* it's ok */
 277                         goto saok;
 278                 }
 279                 plog(PLOG_PROTOWARN, PLOGLOC, 0,
 280                         "invalid DH parameter found, use default.\n");
 281                 oakley_dhgrp_free(sa->dhgrp);
 282                 sa->dhgrp = NULL;
 283         }
 284 
 285         if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
 286                 racoon_free(sa);
 287                 return NULL;
 288         }
 289 
 290 saok:
 291 #ifdef HAVE_GSSAPI
 292         if (sa->gssid != NULL)
 293                 plog(PLOG_DEBUG, PLOGLOC, NULL, "gss id in new sa '%s'\n",
 294                     sa->gssid->v);
 295         if (iph1-> side == INITIATOR) {
 296                 if (iph1->proposal->gssid != NULL)
 297                         iph1->gi_i = rc_vdup(iph1->proposal->gssid);
 298                 if (tsa.gssid != NULL)
 299                         iph1->gi_r = rc_vdup(tsa.gssid);
 300                 iph1->approval = fixup_initiator_sa(sa, &tsa);
 301         } else {
 302                 if (tsa.gssid != NULL) {
 303                         iph1->gi_r = rc_vdup(tsa.gssid);
 304                         if (iph1->proposal->gssid != NULL)
 305                                 iph1->gi_i =
 306                                     rc_vdup(iph1->proposal->gssid);
 307                         else
 308                                 iph1->gi_i = gssapi_get_default_id(iph1);
 309                         if (sa->gssid == NULL && iph1->gi_i != NULL)
 310                                 sa->gssid = rc_vdup(iph1->gi_i);
 311                 }
 312                 iph1->approval = sa;
 313         }
 314         if (iph1->gi_i != NULL)
 315                 plog(PLOG_DEBUG, PLOGLOC, NULL, "GIi is %*s\n",
 316                     iph1->gi_i->l, iph1->gi_i->v);
 317         if (iph1->gi_r != NULL)
 318                 plog(PLOG_DEBUG, PLOGLOC, NULL, "GIr is %*s\n",
 319                     iph1->gi_r->l, iph1->gi_r->v);
 320 #else
 321         iph1->approval = sa;
 322 #endif
 323 
 324         newsa = get_sabyproppair(p, iph1);
 325         if (newsa == NULL && iph1->approval != NULL) {
 326                 delisakmpsa(iph1->approval);
 327                 iph1->approval = NULL;
 328         }
 329 
 330         return newsa;
 331 }
 332 
 333 /*
 334  * compare peer's single proposal and all of my proposal.
 335  * and select one if suiatable.
 336  * p       : one of peer's proposal.
 337  * proposal: my proposals.
 338  */
 339 static struct isakmpsa *
 340 get_ph1approvalx(p, proposal, sap, check_level)
 341         struct prop_pair *p;
 342         struct isakmpsa *proposal, *sap;
 343         rc_type check_level;
 344 {
 345         struct isakmp_pl_p *prop = p->prop;
 346         struct isakmp_pl_t *trns = p->trns;
 347         struct isakmpsa sa, *s, *tsap;
 348 
 349         plog(PLOG_DEBUG, PLOGLOC, NULL,
 350                 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
 351                 prop->p_no, s_ipsecdoi_proto(prop->proto_id),
 352                 prop->spi_size, prop->num_t);
 353 
 354         plog(PLOG_DEBUG, PLOGLOC, NULL,
 355                 "trns#=%d, trns-id=%s\n",
 356                 trns->t_no,
 357                 s_ipsecdoi_trns(prop->proto_id, trns->t_id));
 358 
 359         tsap = sap != NULL ? sap : &sa;
 360 
 361         memset(tsap, 0, sizeof(*tsap));
 362         if (t2isakmpsa(trns, tsap) < 0)
 363                 return NULL;
 364         for (s = proposal; s != NULL; s = s->next) {
 365                 int authmethod;
 366 
 367 #ifdef ENABLE_HYBRID
 368                 authmethod = switch_authmethod(s->authmethod);
 369 #else
 370                 authmethod = s->authmethod;
 371 #endif
 372                 plog(PLOG_DEBUG, PLOGLOC, NULL, "Compared: DB:Peer\n");
 373                 plog(PLOG_DEBUG, PLOGLOC, NULL, "(lifetime = %ld:%ld)\n",
 374                         (long)s->lifetime, (long)tsap->lifetime);
 375                 plog(PLOG_DEBUG, PLOGLOC, NULL, "(lifebyte = %zu:%zu)\n",
 376                         s->lifebyte, tsap->lifebyte);
 377                 plog(PLOG_DEBUG, PLOGLOC, NULL, "enctype = %s:%s\n",
 378                         s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
 379                                         s->enctype),
 380                         s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
 381                                         tsap->enctype));
 382                 plog(PLOG_DEBUG, PLOGLOC, NULL, "(encklen = %d:%d)\n",
 383                         s->encklen, tsap->encklen);
 384                 plog(PLOG_DEBUG, PLOGLOC, NULL, "hashtype = %s:%s\n",
 385                         s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
 386                                         s->hashtype),
 387                         s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
 388                                         tsap->hashtype));
 389                 plog(PLOG_DEBUG, PLOGLOC, NULL, "authmethod = %s:%s\n",
 390                         s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
 391                                         authmethod),
 392                         s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
 393                                         tsap->authmethod));
 394                 plog(PLOG_DEBUG, PLOGLOC, NULL, "dh_group = %s:%s\n",
 395                         s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
 396                                         s->dh_group),
 397                         s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
 398                                         tsap->dh_group));
 399 #if 0
 400                 /* XXX to be considered ? */
 401                 if (tsap->lifebyte > s->lifebyte) ;
 402 #endif
 403                 /*
 404                  * if responder side and peer's key length in proposal
 405                  * is bigger than mine, it might be accepted.
 406                  */
 407                 if(tsap->enctype == s->enctype &&
 408                     tsap->authmethod == authmethod &&
 409                     tsap->hashtype == s->hashtype &&
 410                     tsap->dh_group == s->dh_group &&
 411                     tsap->encklen == s->encklen) {
 412                         switch(check_level) {
 413                         case RCT_PCT_OBEY:
 414                                 goto found;
 415                                 break;
 416 
 417                         case RCT_PCT_STRICT:
 418                                 if ((s->lifetime != 0 && 
 419                                      tsap->lifetime > s->lifetime) ||
 420                                     (s->lifebyte != 0 &&
 421                                      tsap->lifebyte > s->lifebyte))
 422                                         continue;
 423                                 goto found;
 424                                 break;
 425 
 426                         case RCT_PCT_CLAIM:
 427                                 if (s->lifetime == 0 ||
 428                                     tsap->lifetime < s->lifetime)
 429                                         s->lifetime = tsap->lifetime;
 430                                 if (s->lifebyte == 0 ||
 431                                     tsap->lifebyte < s->lifebyte)
 432                                         s->lifebyte = tsap->lifebyte;
 433                                 goto found;
 434                                 break;
 435 
 436                         case RCT_PCT_EXACT:
 437                                 if ((tsap->lifetime != s->lifetime) ||
 438                                     (tsap->lifebyte != s->lifebyte))
 439                                         continue;
 440                                 goto found;
 441                                 break;
 442 
 443                         default:
 444                                 plog(PLOG_PROTOERR, PLOGLOC, NULL, 
 445                                     "Unexpected proposal_check value\n");
 446                                 continue;
 447                                 break;
 448                         }
 449                 }
 450         }
 451 
 452 found:
 453         if (tsap->dhgrp != NULL) {
 454                 oakley_dhgrp_free(tsap->dhgrp);
 455                 tsap->dhgrp = NULL;
 456         }
 457 
 458         if ((s = dupisakmpsa(s)) != NULL) {
 459                 switch(check_level) {
 460                 case RCT_PCT_OBEY:
 461                         s->lifetime = tsap->lifetime;
 462                         s->lifebyte = tsap->lifebyte;
 463                         break;
 464 
 465                 case RCT_PCT_STRICT:
 466                         s->lifetime = tsap->lifetime;
 467                         s->lifebyte = tsap->lifebyte;
 468                         break;
 469 
 470                 case RCT_PCT_CLAIM:
 471                         if (tsap->lifetime < s->lifetime)
 472                                 s->lifetime = tsap->lifetime;
 473                         if (tsap->lifebyte < s->lifebyte)
 474                                 s->lifebyte = tsap->lifebyte;
 475                         break;
 476 
 477                 default:
 478                         break;
 479                 }
 480         }
 481 
 482         return s;
 483 }
 484 
 485 /*
 486  * print all of items in peer's proposal which are mismatched to my proposal.
 487  * p       : one of peer's proposal.
 488  * proposal: my proposals.
 489  */
 490 static void
 491 print_ph1mismatched(p, proposal)
 492         struct prop_pair *p;
 493         struct isakmpsa *proposal;
 494 {
 495         struct isakmpsa sa, *s;
 496 
 497         memset(&sa, 0, sizeof(sa));
 498         if (t2isakmpsa(p->trns, &sa) < 0)
 499                 return;
 500         for (s = proposal; s ; s = s->next) {
 501                 if (sa.enctype != s->enctype) {
 502                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 503                                 "rejected enctype: "
 504                                 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
 505                                 "%s:%s\n",
 506                                 s->prop_no, s->trns_no,
 507                                 p->prop->p_no, p->trns->t_no,
 508                                 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
 509                                         s->enctype),
 510                                 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
 511                                         sa.enctype));
 512                 }
 513                 if (sa.authmethod != s->authmethod) {
 514                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 515                                 "rejected authmethod: "
 516                                 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
 517                                 "%s:%s\n",
 518                                 s->prop_no, s->trns_no,
 519                                 p->prop->p_no, p->trns->t_no,
 520                                 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
 521                                         s->authmethod),
 522                                 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
 523                                         sa.authmethod));
 524                 }
 525                 if (sa.hashtype != s->hashtype) {
 526                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 527                                 "rejected hashtype: "
 528                                 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
 529                                 "%s:%s\n",
 530                                 s->prop_no, s->trns_no,
 531                                 p->prop->p_no, p->trns->t_no,
 532                                 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
 533                                         s->hashtype),
 534                                 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
 535                                         sa.hashtype));
 536                 }
 537                 if (sa.dh_group != s->dh_group) {
 538                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 539                                 "rejected dh_group: "
 540                                 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
 541                                 "%s:%s\n",
 542                                 s->prop_no, s->trns_no,
 543                                 p->prop->p_no, p->trns->t_no,
 544                                 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
 545                                         s->dh_group),
 546                                 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
 547                                         sa.dh_group));
 548                 }
 549         }
 550 
 551         if (sa.dhgrp != NULL)
 552                 oakley_dhgrp_free(sa.dhgrp);
 553 }
 554 
 555 /*
 556  * get ISAKMP data attributes
 557  */
 558 static int
 559 t2isakmpsa(trns, sa)
 560         struct isakmp_pl_t *trns;
 561         struct isakmpsa *sa;
 562 {
 563         struct isakmp_data *d, *prev;
 564         int flag, type;
 565         int error = -1;
 566         int life_t;
 567         int keylen = 0;
 568         rc_vchar_t *val = NULL;
 569         int len, tlen;
 570         unsigned char *p;
 571 
 572         tlen = get_uint16(&trns->h.len) - sizeof(*trns);
 573         prev = (struct isakmp_data *)NULL;
 574         d = (struct isakmp_data *)(trns + 1);
 575 
 576         /* default */
 577         life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
 578         sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
 579         sa->lifebyte = 0;
 580         sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
 581         if (!sa->dhgrp)
 582                 goto err;
 583 
 584         while (tlen > 0) {
 585 
 586                 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
 587                 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
 588 
 589                 plog(PLOG_DEBUG, PLOGLOC, NULL,
 590                         "type=%s, flag=0x%04x, lorv=%s\n",
 591                         s_oakley_attr(type), flag,
 592                         s_oakley_attr_v(type, get_uint16(&d->lorv)));
 593 
 594                 /* get variable-sized item */
 595                 switch (type) {
 596                 case OAKLEY_ATTR_GRP_PI:
 597                 case OAKLEY_ATTR_GRP_GEN_ONE:
 598                 case OAKLEY_ATTR_GRP_GEN_TWO:
 599                 case OAKLEY_ATTR_GRP_CURVE_A:
 600                 case OAKLEY_ATTR_GRP_CURVE_B:
 601                 case OAKLEY_ATTR_SA_LD:
 602                 case OAKLEY_ATTR_GRP_ORDER:
 603                         if (flag) {     /*TV*/
 604                                 len = 2;
 605                                 p = (unsigned char *)&d->lorv;
 606                         } else {        /*TLV*/
 607                                 len = get_uint16(&d->lorv);
 608                                 p = (unsigned char *)(d + 1);
 609                         }
 610                         val = rc_vmalloc(len);
 611                         if (!val)
 612                                 return -1;
 613                         memcpy(val->v, p, len);
 614                         break;
 615 
 616                 default:
 617                         break;
 618                 }
 619 
 620                 switch (type) {
 621                 case OAKLEY_ATTR_ENC_ALG:
 622                         sa->enctype = get_uint16(&d->lorv);
 623                         break;
 624 
 625                 case OAKLEY_ATTR_HASH_ALG:
 626                         sa->hashtype = get_uint16(&d->lorv);
 627                         break;
 628 
 629                 case OAKLEY_ATTR_AUTH_METHOD:
 630                         sa->authmethod = get_uint16(&d->lorv);
 631                         break;
 632 
 633                 case OAKLEY_ATTR_GRP_DESC:
 634                         sa->dh_group = get_uint16(&d->lorv);
 635                         break;
 636 
 637                 case OAKLEY_ATTR_GRP_TYPE:
 638                 {
 639                         int type = get_uint16(&d->lorv);
 640                         if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
 641                                 sa->dhgrp->type = type;
 642                         else
 643                                 return -1;
 644                         break;
 645                 }
 646                 case OAKLEY_ATTR_GRP_PI:
 647                         sa->dhgrp->prime = val;
 648                         break;
 649 
 650                 case OAKLEY_ATTR_GRP_GEN_ONE:
 651                         rc_vfree(val);
 652                         if (!flag)
 653                                 sa->dhgrp->gen1 = get_uint16(&d->lorv);
 654                         else {
 655                                 int len = get_uint16(&d->lorv);
 656                                 sa->dhgrp->gen1 = 0;
 657                                 if (len > 4)
 658                                         return -1;
 659                                 memcpy(&sa->dhgrp->gen1, d + 1, len);
 660                                 sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
 661                         }
 662                         break;
 663 
 664                 case OAKLEY_ATTR_GRP_GEN_TWO:
 665                         rc_vfree(val);
 666                         if (!flag)
 667                                 sa->dhgrp->gen2 = get_uint16(&d->lorv);
 668                         else {
 669                                 int len = get_uint16(&d->lorv);
 670                                 sa->dhgrp->gen2 = 0;
 671                                 if (len > 4)
 672                                         return -1;
 673                                 memcpy(&sa->dhgrp->gen2, d + 1, len);
 674                                 sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
 675                         }
 676                         break;
 677 
 678                 case OAKLEY_ATTR_GRP_CURVE_A:
 679                         sa->dhgrp->curve_a = val;
 680                         break;
 681 
 682                 case OAKLEY_ATTR_GRP_CURVE_B:
 683                         sa->dhgrp->curve_b = val;
 684                         break;
 685 
 686                 case OAKLEY_ATTR_SA_LD_TYPE:
 687                 {
 688                         int type = get_uint16(&d->lorv);
 689                         switch (type) {
 690                         case OAKLEY_ATTR_SA_LD_TYPE_SEC:
 691                         case OAKLEY_ATTR_SA_LD_TYPE_KB:
 692                                 life_t = type;
 693                                 break;
 694                         default:
 695                                 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
 696                                 break;
 697                         }
 698                         break;
 699                 }
 700                 case OAKLEY_ATTR_SA_LD:
 701                         if (!prev
 702                          || (get_uint16(&prev->type) & ~ISAKMP_GEN_MASK) !=
 703                                         OAKLEY_ATTR_SA_LD_TYPE) {
 704                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 705                                     "life duration must follow ltype\n");
 706                                 break;
 707                         }
 708 
 709                         switch (life_t) {
 710                         case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
 711                                 sa->lifetime = ipsecdoi_set_ld(val);
 712                                 rc_vfree(val);
 713                                 if (sa->lifetime == 0) {
 714                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 715                                                 "invalid life duration.\n");
 716                                         goto err;
 717                                 }
 718                                 break;
 719                         case IPSECDOI_ATTR_SA_LD_TYPE_KB:
 720                                 sa->lifebyte = ipsecdoi_set_ld(val);
 721                                 rc_vfree(val);
 722                                 if (sa->lifetime == 0) {
 723                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 724                                                 "invalid life duration.\n");
 725                                         goto err;
 726                                 }
 727                                 break;
 728                         default:
 729                                 rc_vfree(val);
 730                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 731                                         "invalid life type: %d\n", life_t);
 732                                 goto err;
 733                         }
 734                         break;
 735 
 736                 case OAKLEY_ATTR_KEY_LEN:
 737                 {
 738                         int len = get_uint16(&d->lorv);
 739                         if (len % 8 != 0) {
 740                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 741                                         "keylen %d: not multiple of 8\n",
 742                                         len);
 743                                 goto err;
 744                         }
 745                         sa->encklen = (uint16_t)len;
 746                         keylen++;
 747                         break;
 748                 }
 749                 case OAKLEY_ATTR_PRF:
 750                 case OAKLEY_ATTR_FIELD_SIZE:
 751                         /* unsupported */
 752                         break;
 753 
 754                 case OAKLEY_ATTR_GRP_ORDER:
 755                         sa->dhgrp->order = val;
 756                         break;
 757 #ifdef HAVE_GSSAPI
 758                 case OAKLEY_ATTR_GSS_ID:
 759                 {
 760                         int len = get_uint16(&d->lorv);
 761 
 762                         sa->gssid = rc_vmalloc(len);
 763                         memcpy(sa->gssid->v, d + 1, len);
 764                         plog(PLOG_DEBUG, PLOGLOC, NULL,
 765                             "received gss id '%s' (len %d)\n", sa->gssid->v,
 766                             sa->gssid->l);
 767                         break;
 768                 }
 769 #endif
 770 
 771                 default:
 772                         break;
 773                 }
 774 
 775                 prev = d;
 776                 if (flag) {
 777                         tlen -= sizeof(*d);
 778                         d = (struct isakmp_data *)((char *)d + sizeof(*d));
 779                 } else {
 780                         tlen -= (sizeof(*d) + get_uint16(&d->lorv));
 781                         d = (struct isakmp_data *)((char *)d + sizeof(*d) + get_uint16(&d->lorv));
 782                 }
 783         }
 784 
 785         /* key length must not be specified on some algorithms */
 786         if (keylen) {
 787                 if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
 788 #ifdef HAVE_OPENSSL_IDEA_H
 789                  || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
 790 #endif
 791                  || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
 792                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 793                                 "keylen must not be specified "
 794                                 "for encryption algorithm %d\n",
 795                                 sa->enctype);
 796                         return -1;
 797                 }
 798         }
 799 
 800         return 0;
 801 err:
 802         return error;
 803 }
 804 
 805 /*%%%*/
 806 /*
 807  * check phase 2 SA payload and select single proposal.
 808  * make new SA payload to be replyed not including general header.
 809  * This function is called by responder only.
 810  * OUT:
 811  *      0: succeed.
 812  *      -1: error occured.
 813  */
 814 int
 815 ipsecdoi_selectph2proposal(iph2)
 816         struct ph2handle *iph2;
 817 {
 818         struct prop_pair **pair;
 819         struct prop_pair *ret;
 820 
 821         /* get proposal pair */
 822         pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
 823         if (pair == NULL)
 824                 return -1;
 825 
 826         /* check and select a proposal. */
 827         ret = get_ph2approval(iph2, pair);
 828         free_proppair(pair);
 829         if (ret == NULL)
 830                 return -1;
 831 
 832         /* make a SA to be replayed. */
 833         /* SPI must be updated later. */
 834         iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
 835         free_proppair0(ret);
 836         if (iph2->sa_ret == NULL)
 837                 return -1;
 838 
 839         return 0;
 840 }
 841 
 842 /*
 843  * check phase 2 SA payload returned from responder.
 844  * This function is called by initiator only.
 845  * OUT:
 846  *      0: valid.
 847  *      -1: invalid.
 848  */
 849 int
 850 ipsecdoi_checkph2proposal(iph2)
 851         struct ph2handle *iph2;
 852 {
 853         struct prop_pair **rpair = NULL, **spair = NULL;
 854         struct prop_pair *p;
 855         rc_vchar_t      *old_sa;
 856         int i, n, num;
 857         int error = -1;
 858 
 859         /* get proposal pair of SA sent. */
 860         spair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
 861         if (spair == NULL) {
 862                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 863                         "failed to get prop pair.\n");
 864                 goto end;
 865         }
 866 
 867         /* XXX should check the number of transform */
 868 
 869         /* get proposal pair of SA replyed */
 870         rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
 871         if (rpair == NULL) {
 872                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 873                         "failed to get prop pair.\n");
 874                 goto end;
 875         }
 876 
 877         /* check proposal is only one ? */
 878         n = 0;
 879         num = 0;
 880         for (i = 0; i < MAXPROPPAIRLEN; i++) {
 881                 if (rpair[i]) {
 882                         n = i;
 883                         num++;
 884                 }
 885         }
 886         if (num == 0) {
 887                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 888                         "no proposal received.\n");
 889                 goto end;
 890         }
 891         if (num != 1) {
 892                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 893                         "some proposals received.\n");
 894                 goto end;
 895         }
 896 
 897         if (spair[n] == NULL) {
 898                 plog(PLOG_PROTOWARN, PLOGLOC, 0,
 899                         "invalid proposal number:%d received.\n", i);
 900         }
 901         
 902 
 903         if (rpair[n]->tnext != NULL) {
 904                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 905                         "multi transforms replyed.\n");
 906                 goto end;
 907         }
 908 
 909         if (cmp_aproppair_i(rpair[n], spair[n])) {
 910                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 911                         "proposal mismathed.\n");
 912                 goto end;
 913         }
 914 
 915         /*
 916          * check and select a proposal.
 917          * ensure that there is no modification of the proposal by
 918          * cmp_aproppair_i()
 919          */
 920         p = get_ph2approval(iph2, rpair);
 921         if (p == NULL)
 922                 goto end;
 923 
 924         /* make a SA to be replayed. */
 925         old_sa = iph2->sa_ret;       /* since p->prop points inside iph2->sa_ret */
 926         iph2->sa_ret = get_sabyproppair(p, iph2->ph1);
 927         rc_vfree(old_sa);
 928         free_proppair0(p);
 929         if (iph2->sa_ret == NULL)
 930                 goto end;
 931 
 932         error = 0;
 933 
 934 end:
 935         if (rpair)
 936                 free_proppair(rpair);
 937         if (spair)
 938                 free_proppair(spair);
 939 
 940         return error;
 941 }
 942 
 943 /*
 944  * compare two prop_pair which is assumed to have same proposal number.
 945  * the case of bundle or single SA, NOT multi transforms.
 946  * a: a proposal that is multi protocols and single transform, usually replyed.
 947  * b: a proposal that is multi protocols and multi transform, usually sent.
 948  * NOTE: this function is for initiator.
 949  * OUT
 950  *      0: equal
 951  *      1: not equal
 952  * XXX cannot understand the comment!
 953  */
 954 static int
 955 cmp_aproppair_i(a, b)
 956         struct prop_pair *a, *b;
 957 {
 958         struct prop_pair *p, *q, *r;
 959         int len;
 960 
 961         for (p = a, q = b; p && q; p = p->next, q = q->next) {
 962                 for (r = q; r; r = r->tnext) {
 963                         /* compare trns */
 964                         if (p->trns->t_no == r->trns->t_no)
 965                                 break;
 966                 }
 967                 if (!r) {
 968                         /* no suitable transform found */
 969                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 970                                 "no suitable transform found.\n");
 971                         return -1;
 972                 }
 973 
 974                 /* compare prop */
 975                 if (p->prop->p_no != r->prop->p_no) {
 976                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
 977                                 "proposal #%d mismatched, "
 978                                 "expected #%d.\n",
 979                                 r->prop->p_no, p->prop->p_no);
 980                         /*FALLTHROUGH*/
 981                 }
 982 
 983                 if (p->prop->proto_id != r->prop->proto_id) {
 984                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 985                                 "proto_id mismathed: my:%d peer:%d\n",
 986                                 r->prop->proto_id, p->prop->proto_id);
 987                         return -1;
 988                 }
 989 
 990                 if (p->prop->spi_size != r->prop->spi_size) {
 991                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 992                                 "invalid spi size: %d.\n",
 993                                 p->prop->spi_size);
 994                         return -1;
 995                 }
 996 
 997                 /* check #of transforms */
 998                 if (p->prop->num_t != 1) {
 999                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
1000                                 "#of transform is %d, "
1001                                 "but expected 1.\n", p->prop->num_t);
1002                         /*FALLTHROUGH*/
1003                 }
1004 
1005                 if (p->trns->t_id != r->trns->t_id) {
1006                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
1007                                 "transform number has been modified.\n");
1008                         /*FALLTHROUGH*/
1009                 }
1010                 if (p->trns->reserved != r->trns->reserved) {
1011                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
1012                                 "reserved field should be zero.\n");
1013                         /*FALLTHROUGH*/
1014                 }
1015 
1016                 /* compare attribute */
1017                 len = get_uint16(&r->trns->h.len) - sizeof(*p->trns);
1018                 if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
1019                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
1020                                 "attribute has been modified.\n");
1021                         /*FALLTHROUGH*/
1022                 }
1023         }
1024         if ((p && !q) || (!p && q)) {
1025                 /* # of protocols mismatched */
1026                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1027                         "#of protocols mismatched.\n");
1028                 return -1;
1029         }
1030 
1031         return 0;
1032 }
1033 
1034 /*
1035  * acceptable check for policy configuration.
1036  * return a new SA payload to be reply to peer.
1037  */
1038 static struct prop_pair *
1039 get_ph2approval(iph2, pair)
1040         struct ph2handle *iph2;
1041         struct prop_pair **pair;
1042 {
1043         struct prop_pair *ret;
1044         int i;
1045 
1046         iph2->approval = NULL;
1047 
1048         plog(PLOG_DEBUG, PLOGLOC, NULL,
1049                 "begin compare proposals.\n");
1050 
1051         for (i = 0; i < MAXPROPPAIRLEN; i++) {
1052                 if (pair[i] == NULL)
1053                         continue;
1054                 plog(PLOG_DEBUG, PLOGLOC, NULL,
1055                         "pair[%d]: %p\n", i, pair[i]);
1056                 print_proppair(PLOG_DEBUG, pair[i]);;
1057 
1058                 /* compare proposal and select one */
1059                 ret = get_ph2approvalx(iph2, pair[i]);
1060                 if (ret != NULL) {
1061                         /* found */
1062                         return ret;
1063                 }
1064         }
1065 
1066         plog(PLOG_PROTOERR, PLOGLOC, NULL, "no suitable policy found.\n");
1067 
1068         return NULL;
1069 }
1070 
1071 /*
1072  * compare my proposal and peers just one proposal.
1073  * set a approval.
1074  */
1075 static struct prop_pair *
1076 get_ph2approvalx(iph2, pp)
1077         struct ph2handle *iph2;
1078         struct prop_pair *pp;
1079 {
1080         struct prop_pair *ret = NULL;
1081         struct saprop *pr0, *pr = NULL;
1082         struct saprop *q1, *q2;
1083 
1084         pr0 = aproppair2saprop(pp);
1085         if (pr0 == NULL)
1086                 return NULL;
1087 
1088         for (q1 = pr0; q1; q1 = q1->next) {
1089                 for (q2 = iph2->proposal; q2; q2 = q2->next) {
1090                         plog(PLOG_DEBUG, PLOGLOC, NULL,
1091                                 "peer's single bundle:\n");
1092                         printsaprop0(PLOG_DEBUG, q1);
1093                         plog(PLOG_DEBUG, PLOGLOC, NULL,
1094                                 "my single bundle:\n");
1095                         printsaprop0(PLOG_DEBUG, q2);
1096 
1097                         pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
1098                         if (pr != NULL)
1099                                 goto found;
1100 
1101                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1102                                 "not matched\n");
1103                 }
1104         }
1105         /* no proposal matching */
1106 err:
1107         flushsaprop(pr0);
1108         return NULL;
1109 
1110 found:
1111         flushsaprop(pr0);
1112         plog(PLOG_DEBUG, PLOGLOC, NULL, "matched\n");
1113         iph2->approval = pr;
1114 
1115     {
1116         struct saproto *sp;
1117         struct prop_pair *p, *n, *x;
1118 
1119         ret = NULL;
1120 
1121         for (p = pp; p; p = p->next) {
1122                 /*
1123                  * find a proposal with matching proto_id.
1124                  * we have analyzed validity already, in cmpsaprop_alloc().
1125                  */
1126                 for (sp = pr->head; sp; sp = sp->next) {
1127                         if (sp->proto_id == p->prop->proto_id)
1128                                 break;
1129                 }
1130                 if (!sp)
1131                         goto err;
1132                 if (sp->head->next)
1133                         goto err;       /* XXX */
1134 
1135                 for (x = p; x; x = x->tnext)
1136                         if (sp->head->trns_no == x->trns->t_no)
1137                                 break;
1138                 if (!x)
1139                         goto err;       /* XXX */
1140 
1141                 n = racoon_calloc(1, sizeof(struct prop_pair));
1142                 if (!n) {
1143                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1144                                 "failed to get buffer.\n");
1145                         goto err;
1146                 }
1147 
1148                 n->prop = x->prop;
1149                 n->trns = x->trns;
1150 
1151                 /* need to preserve the order */
1152                 for (x = ret; x && x->next; x = x->next)
1153                         ;
1154                 if (x && x->prop == n->prop) {
1155                         for (/*nothing*/; x && x->tnext; x = x->tnext)
1156                                 ;
1157                         x->tnext = n;
1158                 } else {
1159                         if (x)
1160                                 x->next = n;
1161                         else {
1162                                 ret = n;
1163                         }
1164                 }
1165 
1166                 /* #of transforms should be updated ? */
1167         }
1168     }
1169 
1170         return ret;
1171 }
1172 
1173 void
1174 free_proppair(pair)
1175         struct prop_pair **pair;
1176 {
1177         int i;
1178 
1179         for (i = 0; i < MAXPROPPAIRLEN; i++) {
1180                 free_proppair0(pair[i]);
1181                 pair[i] = NULL;
1182         }
1183         racoon_free(pair);
1184 }
1185 
1186 static void
1187 free_proppair0(pair)
1188         struct prop_pair *pair;
1189 {
1190         struct prop_pair *p, *q, *r, *s;
1191 
1192         for (p = pair; p; p = q) {
1193                 q = p->next;
1194                 for (r = p; r; r = s) {
1195                         s = r->tnext;
1196                         racoon_free(r);
1197                 }
1198         }
1199 }
1200 
1201 /*
1202  * get proposal pairs from SA payload.
1203  * tiny check for proposal payload.
1204  */
1205 struct prop_pair **
1206 get_proppair(sa, mode)
1207         rc_vchar_t *sa;
1208         int mode;
1209 {
1210         struct prop_pair **pair = NULL;
1211         int num_p = 0;                  /* number of proposal for use */
1212         int tlen;
1213         caddr_t bp;
1214         int i;
1215         struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
1216 
1217         plog(PLOG_DEBUG, PLOGLOC, NULL, "total SA len=%d\n", sa->l);
1218         plogdump(PLOG_DEBUG, PLOGLOC, 0, sa->v, sa->l);
1219 
1220         /* check SA payload size */
1221         if (sa->l < sizeof(*sab)) {
1222                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1223                         "Invalid SA length = %d.\n", sa->l);
1224                 return NULL;
1225         }
1226 
1227         /* check DOI */
1228         if (check_doi(get_uint32(&sab->doi)) < 0)
1229                 return NULL;
1230 
1231         /* check SITUATION */
1232         if (check_situation(get_uint32(&sab->sit)) < 0)
1233                 return NULL;
1234 
1235         pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
1236         if (pair == NULL) {
1237                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1238                         "failed to get buffer.\n");
1239                 return NULL;
1240         }
1241         memset(pair, 0, sizeof(pair));
1242 
1243         bp = (caddr_t)(sab + 1);
1244         tlen = sa->l - sizeof(*sab);
1245 
1246     {
1247         struct isakmp_pl_p *prop;
1248         int proplen;
1249         rc_vchar_t *pbuf = NULL;
1250         struct isakmp_parse_t *pa;
1251 
1252         pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
1253         if (pbuf == NULL)
1254                 goto bad;
1255 
1256         for (pa = (struct isakmp_parse_t *)pbuf->v;
1257              pa->type != ISAKMP_NPTYPE_NONE;
1258              pa++) {
1259                 /* check the value of next payload */
1260                 if (pa->type != ISAKMP_NPTYPE_P) {
1261                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1262                                 "Invalid payload type=%u\n", pa->type);
1263                         rc_vfree(pbuf);
1264                         goto bad;
1265                 }
1266 
1267                 prop = (struct isakmp_pl_p *)pa->ptr;
1268                 proplen = pa->len;
1269 
1270                 plog(PLOG_DEBUG, PLOGLOC, NULL,
1271                         "proposal #%u len=%d\n", prop->p_no, proplen);
1272 
1273                 if (proplen == 0) {
1274                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1275                                 "invalid proposal with length %d\n", proplen);
1276                         rc_vfree(pbuf);
1277                         goto bad;
1278                 }
1279 
1280                 /* check Protocol ID */
1281                 if (!check_protocol[mode]) {
1282                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1283                                 "unsupported mode %d\n", mode);
1284                         continue;
1285                 }
1286 
1287                 if (check_protocol[mode](prop->proto_id) < 0)
1288                         continue;
1289 
1290                 /* check SPI length when IKE. */
1291                 if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
1292                         continue;
1293 
1294                 /* get transform */
1295                 if (get_transform(prop, pair, &num_p) < 0) {
1296                         rc_vfree(pbuf);
1297                         goto bad;
1298                 }
1299         }
1300         rc_vfree(pbuf);
1301         pbuf = NULL;
1302     }
1303 
1304     {
1305         int notrans, nprop;
1306         struct prop_pair *p, *q;
1307 
1308         /* check for proposals with no transforms */
1309         for (i = 0; i < MAXPROPPAIRLEN; i++) {
1310                 if (!pair[i])
1311                         continue;
1312 
1313                 plog(PLOG_DEBUG, PLOGLOC, NULL, "pair %d:\n", i);
1314                 print_proppair(PLOG_DEBUG, pair[i]);
1315 
1316                 notrans = nprop = 0;
1317                 for (p = pair[i]; p; p = p->next) {
1318                         if (p->trns == NULL) {
1319                                 notrans++;
1320                                 break;
1321                         }
1322                         for (q = p; q; q = q->tnext)
1323                                 nprop++;
1324                 }
1325 
1326 #if 0
1327                 /*
1328                  * XXX at this moment, we cannot accept proposal group
1329                  * with multiple proposals.  this should be fixed.
1330                  */
1331                 if (pair[i]->next) {
1332                         plog(LLV_WARNING, PLOGLOC, NULL,
1333                                 "proposal #%u ignored "
1334                                 "(multiple proposal not supported)\n",
1335                                 pair[i]->prop->p_no);
1336                         notrans++;
1337                 }
1338 #endif
1339 
1340                 if (notrans) {
1341                         for (p = pair[i]; p; p = q) {
1342                                 q = p->next;
1343                                 racoon_free(p);
1344                         }
1345                         pair[i] = NULL;
1346                         num_p--;
1347                 } else {
1348                         plog(PLOG_DEBUG, PLOGLOC, NULL,
1349                                 "proposal #%u: %d transform\n",
1350                                 pair[i]->prop->p_no, nprop);
1351                 }
1352         }
1353     }
1354 
1355         /* bark if no proposal is found. */
1356         if (num_p <= 0) {
1357                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1358                         "no Proposal found.\n");
1359                 goto bad;
1360         }
1361 
1362         return pair;
1363 
1364   bad:
1365         if (pair)
1366                 racoon_free(pair);
1367         return NULL;
1368 }
1369 
1370 /*
1371  * check transform payload.
1372  * OUT:
1373  *      positive: return the pointer to the payload of valid transform.
1374  *      0       : No valid transform found.
1375  */
1376 static int
1377 get_transform(prop, pair, num_p)
1378         struct isakmp_pl_p *prop;
1379         struct prop_pair **pair;
1380         int *num_p;
1381 {
1382         int tlen; /* total length of all transform in a proposal */
1383         caddr_t bp;
1384         struct isakmp_pl_t *trns;
1385         int trnslen;
1386         rc_vchar_t *pbuf = NULL;
1387         struct isakmp_parse_t *pa;
1388         struct prop_pair *p = NULL, *q;
1389         int num_t;
1390 
1391         bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
1392         tlen = get_uint16(&prop->h.len)
1393                 - (sizeof(struct isakmp_pl_p) + prop->spi_size);
1394         pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
1395         if (pbuf == NULL)
1396                 return -1;
1397 
1398         /* check and get transform for use */
1399         num_t = 0;
1400         for (pa = (struct isakmp_parse_t *)pbuf->v;
1401              pa->type != ISAKMP_NPTYPE_NONE;
1402              pa++) {
1403 
1404                 num_t++;
1405 
1406                 /* check the value of next payload */
1407                 if (pa->type != ISAKMP_NPTYPE_T) {
1408                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1409                                 "Invalid payload type=%u\n", pa->type);
1410                         break;
1411                 }
1412 
1413                 trns = (struct isakmp_pl_t *)pa->ptr;
1414                 trnslen = pa->len;
1415 
1416                 plog(PLOG_DEBUG, PLOGLOC, NULL,
1417                         "transform #%u len=%u\n", trns->t_no, trnslen);
1418 
1419                 /* check transform ID */
1420                 if (prop->proto_id >= ARRAYLEN(check_transform)) {
1421                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
1422                                 "unsupported proto_id %u\n",
1423                                 prop->proto_id);
1424                         continue;
1425                 }
1426                 if (prop->proto_id >= ARRAYLEN(check_attributes)) {
1427                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
1428                                 "unsupported proto_id %u\n",
1429                                 prop->proto_id);
1430                         continue;
1431                 }
1432 
1433                 if (!check_transform[prop->proto_id]
1434                  || !check_attributes[prop->proto_id]) {
1435                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
1436                                 "unsupported proto_id %u\n",
1437                                 prop->proto_id);
1438                         continue;
1439                 }
1440                 if (check_transform[prop->proto_id](trns->t_id) < 0)
1441                         continue;
1442 
1443                 /* check data attributes */
1444                 if (check_attributes[prop->proto_id](trns) != 0)
1445                         continue;
1446 
1447                 p = racoon_calloc(1, sizeof(*p));
1448                 if (p == NULL) {
1449                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1450                                 "failed to get buffer.\n");
1451                         rc_vfree(pbuf);
1452                         return -1;
1453                 }
1454                 p->prop = prop;
1455                 p->trns = trns;
1456 
1457                 /* need to preserve the order */
1458                 for (q = pair[prop->p_no]; q && q->next; q = q->next)
1459                         ;
1460                 if (q && q->prop == p->prop) {
1461                         for (/*nothing*/; q && q->tnext; q = q->tnext)
1462                                 ;
1463                         q->tnext = p;
1464                 } else {
1465                         if (q)
1466                                 q->next = p;
1467                         else {
1468                                 pair[prop->p_no] = p;
1469                                 (*num_p)++;
1470                         }
1471                 }
1472         }
1473 
1474         rc_vfree(pbuf);
1475 
1476         return 0;
1477 }
1478 
1479 /*
1480  * make a new SA payload from prop_pair.
1481  * NOTE: this function make spi value clear.
1482  */
1483 rc_vchar_t *
1484 get_sabyproppair(pair, iph1)
1485         struct prop_pair *pair;
1486         struct ph1handle *iph1;
1487 {
1488         rc_vchar_t *newsa;
1489         int newtlen;
1490         uint8_t *np_p = NULL;
1491         struct prop_pair *p;
1492         int prophlen, trnslen;
1493         caddr_t bp;
1494 
1495         newtlen = sizeof(struct ipsecdoi_sa_b);
1496         for (p = pair; p; p = p->next) {
1497                 newtlen += (sizeof(struct isakmp_pl_p)
1498                                 + p->prop->spi_size
1499                                 + get_uint16(&p->trns->h.len));
1500         }
1501 
1502         newsa = rc_vmalloc(newtlen);
1503         if (newsa == NULL) {
1504                 plog(PLOG_PROTOERR, PLOGLOC, NULL, "failed to get newsa.\n");
1505                 return NULL;
1506         }
1507         bp = newsa->v;
1508 
1509         put_uint16(&((struct isakmp_gen *)bp)->len, newtlen);
1510 
1511         /* update some of values in SA header */
1512         put_uint32(&((struct ipsecdoi_sa_b *)bp)->doi, ikev1_doitype(iph1->rmconf));
1513         put_uint32(&((struct ipsecdoi_sa_b *)bp)->sit, ikev1_sittype(iph1->rmconf));
1514         bp += sizeof(struct ipsecdoi_sa_b);
1515 
1516         /* create proposal payloads */
1517         for (p = pair; p; p = p->next) {
1518                 prophlen = sizeof(struct isakmp_pl_p)
1519                                 + p->prop->spi_size;
1520                 trnslen = get_uint16(&p->trns->h.len);
1521 
1522                 if (np_p)
1523                         *np_p = ISAKMP_NPTYPE_P;
1524 
1525                 /* create proposal */
1526 
1527                 memcpy(bp, p->prop, prophlen);
1528                 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1529                 put_uint16(&((struct isakmp_pl_p *)bp)->h.len, prophlen + trnslen);
1530                 ((struct isakmp_pl_p *)bp)->num_t = 1;
1531                 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1532                 memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
1533                 bp += prophlen;
1534 
1535                 /* create transform */
1536                 memcpy(bp, p->trns, trnslen);
1537                 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1538                 put_uint16(&((struct isakmp_pl_t *)bp)->h.len, trnslen);
1539                 bp += trnslen;
1540         }
1541 
1542         return newsa;
1543 }
1544 
1545 /*
1546  * update responder's spi
1547  */
1548 int
1549 ipsecdoi_updatespi(iph2)
1550         struct ph2handle *iph2;
1551 {
1552         struct prop_pair **pair, *p;
1553         struct saprop *pp;
1554         struct saproto *pr;
1555         int i;
1556         int error = -1;
1557         uint8_t *spi;
1558 
1559         pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
1560         if (pair == NULL)
1561                 return -1;
1562         for (i = 0; i < MAXPROPPAIRLEN; i++) {
1563                 if (pair[i])
1564                         break;
1565         }
1566         if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
1567                 /* multiple transform must be filtered by selectph2proposal.*/
1568                 goto end;
1569         }
1570 
1571         pp = iph2->approval;
1572 
1573         /* create proposal payloads */
1574         for (p = pair[i]; p; p = p->next) {
1575                 /*
1576                  * find a proposal/transform with matching proto_id/t_id.
1577                  * we have analyzed validity already, in cmpsaprop_alloc().
1578                  */
1579                 for (pr = pp->head; pr; pr = pr->next) {
1580                         if (p->prop->proto_id == pr->proto_id &&
1581                             p->trns->t_id == pr->head->trns_id) {
1582                                 break;
1583                         }
1584                 }
1585                 if (!pr)
1586                         goto end;
1587 
1588                 /*
1589                  * XXX SPI bits are left-filled, for use with IPComp.
1590                  * we should be switching to variable-length spi field...
1591                  */
1592                 spi = (uint8_t *)&pr->spi;
1593                 spi += sizeof(pr->spi);
1594                 spi -= pr->spisize;
1595                 memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
1596         }
1597 
1598         error = 0;
1599 end:
1600         free_proppair(pair);
1601         return error;
1602 }
1603 
1604 /*
1605  * make a new SA payload from prop_pair.
1606  */
1607 rc_vchar_t *
1608 get_sabysaprop(pp0, sa0)
1609         struct saprop *pp0;
1610         rc_vchar_t *sa0;
1611 {
1612         struct prop_pair **pair;
1613         rc_vchar_t *newsa = NULL;
1614         int newtlen;
1615         uint8_t *np_p = NULL;
1616         struct prop_pair *p = NULL;
1617         struct saprop *pp;
1618         struct saproto *pr;
1619         struct satrns *tr;
1620         int prophlen, trnslen;
1621         caddr_t bp;
1622         int error = -1;
1623 
1624         /* get proposal pair */
1625         pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
1626         if (pair == NULL)
1627                 return NULL;
1628 
1629         newtlen = sizeof(struct ipsecdoi_sa_b);
1630         for (pp = pp0; pp; pp = pp->next) {
1631 
1632                 if (pair[pp->prop_no] == NULL)
1633                         goto out;
1634 
1635                 for (pr = pp->head; pr; pr = pr->next) {
1636                         newtlen += (sizeof(struct isakmp_pl_p)
1637                                 + pr->spisize);
1638 
1639                         for (tr = pr->head; tr; tr = tr->next) {
1640                                 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1641                                         if (tr->trns_no == p->trns->t_no)
1642                                                 break;
1643                                 }
1644                                 if (p == NULL)
1645                                         goto out;
1646 
1647                                 newtlen += get_uint16(&p->trns->h.len);
1648                         }
1649                 }
1650         }
1651 
1652         newsa = rc_vmalloc(newtlen);
1653         if (newsa == NULL) {
1654                 plog(PLOG_PROTOERR, PLOGLOC, NULL, "failed to get newsa.\n");
1655                 goto out;
1656         }
1657         bp = newsa->v;
1658 
1659         /* some of values of SA must be updated in the out of this function */
1660         put_uint16(&((struct isakmp_gen *)bp)->len, newtlen);
1661         bp += sizeof(struct ipsecdoi_sa_b);
1662 
1663         /* create proposal payloads */
1664         for (pp = pp0; pp; pp = pp->next) {
1665 
1666                 for (pr = pp->head; pr; pr = pr->next) {
1667                         prophlen = sizeof(struct isakmp_pl_p)
1668                                         + p->prop->spi_size;
1669 
1670                         for (tr = pr->head; tr; tr = tr->next) {
1671                                 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1672                                         if (tr->trns_no == p->trns->t_no)
1673                                                 break;
1674                                 }
1675                                 if (p == NULL)
1676                                         goto out;
1677 
1678                                 trnslen = get_uint16(&p->trns->h.len);
1679 
1680                                 if (np_p)
1681                                         *np_p = ISAKMP_NPTYPE_P;
1682 
1683                                 /* create proposal */
1684 
1685                                 memcpy(bp, p->prop, prophlen);
1686                                 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1687                                 put_uint16(&((struct isakmp_pl_p *)bp)->h.len, prophlen + trnslen);
1688                                 ((struct isakmp_pl_p *)bp)->num_t = 1;
1689                                 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1690                                 bp += prophlen;
1691 
1692                                 /* create transform */
1693                                 memcpy(bp, p->trns, trnslen);
1694                                 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1695                                 put_uint16(&((struct isakmp_pl_t *)bp)->h.len, trnslen);
1696                                 bp += trnslen;
1697                         }
1698                 }
1699         }
1700 
1701         error = 0;
1702   out:
1703         if (pair != NULL)
1704                 racoon_free(pair);
1705 
1706         if (error != 0) {
1707                 if (newsa)
1708                         rc_vfree(newsa);
1709                 newsa = NULL;
1710         }
1711 
1712         return newsa;
1713 }
1714 
1715 /*
1716  * If some error happens then return 0.  Although 0 means that lifetime is zero,
1717  * such a value should not be accepted.
1718  * Also 0 of lifebyte should not be included in a packet although 0 means not
1719  * to care of it.
1720  */
1721 static uint32_t
1722 ipsecdoi_set_ld(buf)
1723         rc_vchar_t *buf;
1724 {
1725         uint32_t ld;
1726 
1727         if (buf == 0)
1728                 return 0;
1729 
1730         switch (buf->l) {
1731         case 2:
1732                 ld = get_uint16((uint16_t *)buf->v);
1733                 break;
1734         case 4:
1735                 ld = get_uint32((uint32_t *)buf->v);
1736                 break;
1737         default:
1738                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1739                         "length %d of life duration "
1740                         "isn't supported.\n", buf->l);
1741                 return 0;
1742         }
1743 
1744         return ld;
1745 }
1746 
1747 /*%%%*/
1748 /*
1749  * check DOI
1750  */
1751 static int
1752 check_doi(doi)
1753         uint32_t doi;
1754 {
1755         switch (doi) {
1756         case IPSEC_DOI:
1757                 return 0;
1758         default:
1759                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1760                         "invalid value of DOI 0x%08x.\n", doi);
1761                 return -1;
1762         }
1763         /* NOT REACHED */
1764 }
1765 
1766 /*
1767  * check situation
1768  */
1769 static int
1770 check_situation(sit)
1771         uint32_t sit;
1772 {
1773         switch (sit) {
1774         case IPSECDOI_SIT_IDENTITY_ONLY:
1775                 return 0;
1776 
1777         case IPSECDOI_SIT_SECRECY:
1778         case IPSECDOI_SIT_INTEGRITY:
1779                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1780                         "situation 0x%08x unsupported yet.\n", sit);
1781                 return -1;
1782 
1783         default:
1784                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1785                         "invalid situation 0x%08x.\n", sit);
1786                 return -1;
1787         }
1788         /* NOT REACHED */
1789 }
1790 
1791 /*
1792  * check protocol id in main mode
1793  */
1794 static int
1795 check_prot_main(proto_id)
1796         int proto_id;
1797 {
1798         switch (proto_id) {
1799         case IPSECDOI_PROTO_ISAKMP:
1800                 return 0;
1801 
1802         default:
1803                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1804                         "Illegal protocol id=%u.\n", proto_id);
1805                 return -1;
1806         }
1807         /* NOT REACHED */
1808 }
1809 
1810 /*
1811  * check protocol id in quick mode
1812  */
1813 static int
1814 check_prot_quick(proto_id)
1815         int proto_id;
1816 {
1817         switch (proto_id) {
1818         case IPSECDOI_PROTO_IPSEC_AH:
1819         case IPSECDOI_PROTO_IPSEC_ESP:
1820                 return 0;
1821 
1822         case IPSECDOI_PROTO_IPCOMP:
1823                 return 0;
1824 
1825         default:
1826                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1827                         "invalid protocol id %d.\n", proto_id);
1828                 return -1;
1829         }
1830         /* NOT REACHED */
1831 }
1832 
1833 static int
1834 check_spi_size(proto_id, size)
1835         int proto_id, size;
1836 {
1837         switch (proto_id) {
1838         case IPSECDOI_PROTO_ISAKMP:
1839                 if (size != 0) {
1840                         /* WARNING */
1841                         plog(PLOG_DEBUG, PLOGLOC, NULL,
1842                                 "SPI size isn't zero, but IKE proposal.\n");
1843                 }
1844                 return 0;
1845 
1846         case IPSECDOI_PROTO_IPSEC_AH:
1847         case IPSECDOI_PROTO_IPSEC_ESP:
1848                 if (size != 4) {
1849                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1850                                 "invalid SPI size=%d for IPSEC proposal.\n",
1851                                 size);
1852                         return -1;
1853                 }
1854                 return 0;
1855 
1856         case IPSECDOI_PROTO_IPCOMP:
1857                 if (size != 2 && size != 4) {
1858                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1859                                 "invalid SPI size=%d for IPCOMP proposal.\n",
1860                                 size);
1861                         return -1;
1862                 }
1863                 return 0;
1864 
1865         default:
1866                 /* ??? */
1867                 return -1;
1868         }
1869         /* NOT REACHED */
1870 }
1871 
1872 /*
1873  * check transform ID in ISAKMP.
1874  */
1875 static int
1876 check_trns_isakmp(t_id)
1877         int t_id;
1878 {
1879         switch (t_id) {
1880         case IPSECDOI_KEY_IKE:
1881                 return 0;
1882         default:
1883                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1884                         "invalid transform-id=%u in proto_id=%u.\n",
1885                         t_id, IPSECDOI_KEY_IKE);
1886                 return -1;
1887         }
1888         /* NOT REACHED */
1889 }
1890 
1891 /*
1892  * check transform ID in AH.
1893  */
1894 static int
1895 check_trns_ah(t_id)
1896         int t_id;
1897 {
1898         switch (t_id) {
1899         case IPSECDOI_AH_MD5:
1900         case IPSECDOI_AH_SHA:
1901         case IPSECDOI_AH_SHA256:
1902         case IPSECDOI_AH_SHA384:
1903         case IPSECDOI_AH_SHA512:
1904                 return 0;
1905         case IPSECDOI_AH_DES:
1906                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1907                         "not support transform-id=%u in AH.\n", t_id);
1908                 return -1;
1909         default:
1910                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1911                         "invalid transform-id=%u in AH.\n", t_id);
1912                 return -1;
1913         }
1914         /* NOT REACHED */
1915 }
1916 
1917 /*
1918  * check transform ID in ESP.
1919  */
1920 static int
1921 check_trns_esp(t_id)
1922         int t_id;
1923 {
1924         switch (t_id) {
1925         case IPSECDOI_ESP_DES:
1926         case IPSECDOI_ESP_3DES:
1927         case IPSECDOI_ESP_NULL:
1928         case IPSECDOI_ESP_RC5:
1929         case IPSECDOI_ESP_CAST:
1930         case IPSECDOI_ESP_BLOWFISH:
1931         case IPSECDOI_ESP_AES:
1932         case IPSECDOI_ESP_TWOFISH:
1933                 return 0;
1934         case IPSECDOI_ESP_DES_IV32:
1935         case IPSECDOI_ESP_DES_IV64:
1936         case IPSECDOI_ESP_IDEA:
1937         case IPSECDOI_ESP_3IDEA:
1938         case IPSECDOI_ESP_RC4:
1939                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1940                         "not support transform-id=%u in ESP.\n", t_id);
1941                 return -1;
1942         default:
1943                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1944                         "invalid transform-id=%u in ESP.\n", t_id);
1945                 return -1;
1946         }
1947         /* NOT REACHED */
1948 }
1949 
1950 /*
1951  * check transform ID in IPCOMP.
1952  */
1953 static int
1954 check_trns_ipcomp(t_id)
1955         int t_id;
1956 {
1957         switch (t_id) {
1958         case IPSECDOI_IPCOMP_OUI:
1959         case IPSECDOI_IPCOMP_DEFLATE:
1960         case IPSECDOI_IPCOMP_LZS:
1961                 return 0;
1962         default:
1963                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1964                         "invalid transform-id=%u in IPCOMP.\n", t_id);
1965                 return -1;
1966         }
1967         /* NOT REACHED */
1968 }
1969 
1970 /*
1971  * check data attributes in IKE.
1972  */
1973 static int
1974 check_attr_isakmp(trns)
1975         struct isakmp_pl_t *trns;
1976 {
1977         struct isakmp_data *d;
1978         int tlen;
1979         int flag, type;
1980         uint16_t lorv;
1981 
1982         tlen = get_uint16(&trns->h.len) - sizeof(struct isakmp_pl_t);
1983         d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
1984 
1985         while (tlen > 0) {
1986                 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
1987                 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
1988                 lorv = get_uint16(&d->lorv);
1989 
1990                 plog(PLOG_DEBUG, PLOGLOC, NULL,
1991                         "type=%s, flag=0x%04x, lorv=%s\n",
1992                         s_oakley_attr(type), flag,
1993                         s_oakley_attr_v(type, lorv));
1994 
1995                 /*
1996                  * some of the attributes must be encoded in TV.
1997                  * see RFC2409 Appendix A "Attribute Classes".
1998                  */
1999                 switch (type) {
2000                 case OAKLEY_ATTR_ENC_ALG:
2001                 case OAKLEY_ATTR_HASH_ALG:
2002                 case OAKLEY_ATTR_AUTH_METHOD:
2003                 case OAKLEY_ATTR_GRP_DESC:
2004                 case OAKLEY_ATTR_GRP_TYPE:
2005                 case OAKLEY_ATTR_SA_LD_TYPE:
2006                 case OAKLEY_ATTR_PRF:
2007                 case OAKLEY_ATTR_KEY_LEN:
2008                 case OAKLEY_ATTR_FIELD_SIZE:
2009                         if (!flag) {    /* TLV*/
2010                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2011                                         "oakley attribute %d must be TV.\n",
2012                                         type);
2013                                 return -1;
2014                         }
2015                         break;
2016                 }
2017 
2018                 /* sanity check for TLV.  length must be specified. */
2019                 if (!flag && lorv == 0) {       /*TLV*/
2020                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2021                                 "invalid length %d for TLV attribute %d.\n",
2022                                 lorv, type);
2023                         return -1;
2024                 }
2025 
2026                 switch (type) {
2027                 case OAKLEY_ATTR_ENC_ALG:
2028                         if (!alg_oakley_encdef_ok(lorv)) {
2029                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2030                                         "invalied encryption algorithm=%d.\n",
2031                                         lorv);
2032                                 return -1;
2033                         }
2034                         break;
2035 
2036                 case OAKLEY_ATTR_HASH_ALG:
2037                         if (!alg_oakley_hashdef_ok(lorv)) {
2038                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2039                                         "invalied hash algorithm=%d.\n",
2040                                         lorv);
2041                                 return -1;
2042                         }
2043                         break;
2044 
2045                 case OAKLEY_ATTR_AUTH_METHOD:
2046                         switch (lorv) {
2047                         case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
2048                         case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2049                         case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
2050                                 break;
2051                         case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2052                         case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2053                         case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
2054                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2055                                         "auth method %d isn't supported.\n",
2056                                         lorv);
2057                                 return -1;
2058                         default:
2059                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2060                                         "invalid auth method %d.\n",
2061                                         lorv);
2062                                 return -1;
2063                         }
2064                         break;
2065 
2066                 case OAKLEY_ATTR_GRP_DESC:
2067                         if (!alg_oakley_dhdef_ok(lorv)) {
2068                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2069                                         "invalid DH group %d.\n",
2070                                         lorv);
2071                                 return -1;
2072                         }
2073                         break;
2074 
2075                 case OAKLEY_ATTR_GRP_TYPE:
2076                         switch (lorv) {
2077                         case OAKLEY_ATTR_GRP_TYPE_MODP:
2078                                 break;
2079                         default:
2080                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2081                                         "unsupported DH group type %d.\n",
2082                                         lorv);
2083                                 return -1;
2084                         }
2085                         break;
2086 
2087                 case OAKLEY_ATTR_GRP_PI:
2088                 case OAKLEY_ATTR_GRP_GEN_ONE:
2089                         /* sanity checks? */
2090                         break;
2091 
2092                 case OAKLEY_ATTR_GRP_GEN_TWO:
2093                 case OAKLEY_ATTR_GRP_CURVE_A:
2094                 case OAKLEY_ATTR_GRP_CURVE_B:
2095                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2096                                 "attr type=%u isn't supported.\n", type);
2097                         return -1;
2098 
2099                 case OAKLEY_ATTR_SA_LD_TYPE:
2100                         switch (lorv) {
2101                         case OAKLEY_ATTR_SA_LD_TYPE_SEC:
2102                         case OAKLEY_ATTR_SA_LD_TYPE_KB:
2103                                 break;
2104                         default:
2105                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2106                                         "invalid life type %d.\n", lorv);
2107                                 return -1;
2108                         }
2109                         break;
2110 
2111                 case OAKLEY_ATTR_SA_LD:
2112                         /* should check the value */
2113                         break;
2114 
2115                 case OAKLEY_ATTR_PRF:
2116                 case OAKLEY_ATTR_KEY_LEN:
2117                         break;
2118 
2119                 case OAKLEY_ATTR_FIELD_SIZE:
2120                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2121                                 "attr type=%u isn't supported.\n", type);
2122                         return -1;
2123 
2124                 case OAKLEY_ATTR_GRP_ORDER:
2125                         break;
2126 
2127                 case OAKLEY_ATTR_GSS_ID:
2128                         break;
2129 
2130                 default:
2131                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2132                                 "invalid attribute type %d.\n", type);
2133                         return -1;
2134                 }
2135 
2136                 if (flag) {
2137                         tlen -= sizeof(*d);
2138                         d = (struct isakmp_data *)((char *)d
2139                                 + sizeof(*d));
2140                 } else {
2141                         tlen -= (sizeof(*d) + lorv);
2142                         d = (struct isakmp_data *)((char *)d
2143                                 + sizeof(*d) + lorv);
2144                 }
2145         }
2146 
2147         return 0;
2148 }
2149 
2150 /*
2151  * check data attributes in IPSEC AH/ESP.
2152  */
2153 static int
2154 check_attr_ah(trns)
2155         struct isakmp_pl_t *trns;
2156 {
2157         return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2158 }
2159 
2160 static int
2161 check_attr_esp(trns)
2162         struct isakmp_pl_t *trns;
2163 {
2164         return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2165 }
2166 
2167 static int
2168 check_attr_ipsec(proto_id, trns)
2169         int proto_id;
2170         struct isakmp_pl_t *trns;
2171 {
2172         struct isakmp_data *d;
2173         int tlen;
2174         int flag, type = 0;
2175         uint16_t lorv;
2176         int attrseen[16];       /* XXX magic number */
2177 
2178         tlen = get_uint16(&trns->h.len) - sizeof(struct isakmp_pl_t);
2179         d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2180         memset(attrseen, 0, sizeof(attrseen));
2181 
2182         while (tlen > 0) {
2183                 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
2184                 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
2185                 lorv = get_uint16(&d->lorv);
2186 
2187                 plog(PLOG_DEBUG, PLOGLOC, NULL,
2188                         "type=%s, flag=0x%04x, lorv=%s\n",
2189                         s_ipsecdoi_attr(type), flag,
2190                         s_ipsecdoi_attr_v(type, lorv));
2191 
2192                 if (type < ARRAYLEN(attrseen))
2193                         attrseen[type]++;
2194 
2195                 switch (type) {
2196                 case IPSECDOI_ATTR_ENC_MODE:
2197                         if (! flag) {
2198                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2199                                         "must be TV when ENC_MODE.\n");
2200                                 return -1;
2201                         }
2202 
2203                         switch (lorv) {
2204                         case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2205                         case IPSECDOI_ATTR_ENC_MODE_TRNS:
2206                                 break;
2207 #ifdef ENABLE_NATT
2208                         case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2209                         case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2210                         case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2211                         case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2212                                 plog(PLOG_DEBUG, PLOGLOC, NULL,
2213                                      "UDP encapsulation requested\n");
2214                                 break;
2215 #endif
2216                         default:
2217                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2218                                         "invalid encryption mode=%u.\n",
2219                                         lorv);
2220                                 return -1;
2221                         }
2222                         break;
2223 
2224                 case IPSECDOI_ATTR_AUTH:
2225                         if (! flag) {
2226                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2227                                         "must be TV when AUTH.\n");
2228                                 return -1;
2229                         }
2230 
2231                         switch (lorv) {
2232                         case IPSECDOI_ATTR_AUTH_HMAC_MD5:
2233                                 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2234                                     trns->t_id != IPSECDOI_AH_MD5) {
2235 ahmismatch:
2236                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2237                                                 "auth algorithm %u conflicts "
2238                                                 "with transform %u.\n",
2239                                                 lorv, trns->t_id);
2240                                         return -1;
2241                                 }
2242                                 break;
2243                         case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
2244                                 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2245                                         if (trns->t_id != IPSECDOI_AH_SHA)
2246                                                 goto ahmismatch;
2247                                 }
2248                                 break;
2249                         case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
2250                                 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2251                                         if (trns->t_id != IPSECDOI_AH_SHA256)
2252                                                 goto ahmismatch;
2253                                 }       
2254                                 break;
2255                         case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
2256                                 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2257                                         if (trns->t_id != IPSECDOI_AH_SHA384)
2258                                                 goto ahmismatch;
2259                                 }
2260                                 break;
2261                         case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
2262                                 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2263                                         if (trns->t_id != IPSECDOI_AH_SHA512)
2264                                         goto ahmismatch;
2265                                 }
2266                                 break;
2267                         case IPSECDOI_ATTR_AUTH_DES_MAC:
2268                         case IPSECDOI_ATTR_AUTH_KPDK:
2269                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2270                                         "auth algorithm %u isn't supported.\n",
2271                                         lorv);
2272                                 return -1;
2273                         default:
2274                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2275                                         "invalid auth algorithm=%u.\n",
2276                                         lorv);
2277                                 return -1;
2278                         }
2279                         break;
2280 
2281                 case IPSECDOI_ATTR_SA_LD_TYPE:
2282                         if (! flag) {
2283                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2284                                         "must be TV when LD_TYPE.\n");
2285                                 return -1;
2286                         }
2287 
2288                         switch (lorv) {
2289                         case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2290                         case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2291                                 break;
2292                         default:
2293                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2294                                         "invalid life type %d.\n", lorv);
2295                                 return -1;
2296                         }
2297                         break;
2298 
2299                 case IPSECDOI_ATTR_SA_LD:
2300                         if (flag) {
2301                                 /* i.e. ISAKMP_GEN_TV */
2302                                 plog(PLOG_DEBUG, PLOGLOC, NULL,
2303                                         "life duration was in TLV.\n");
2304                         } else {
2305                                 /* i.e. ISAKMP_GEN_TLV */
2306                                 if (lorv == 0) {
2307                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2308                                                 "invalid length of LD\n");
2309                                         return -1;
2310                                 }
2311                         }
2312                         break;
2313 
2314                 case IPSECDOI_ATTR_GRP_DESC:
2315                         if (! flag) {
2316                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2317                                         "must be TV when GRP_DESC.\n");
2318                                 return -1;
2319                         }
2320 
2321                         if (!alg_oakley_dhdef_ok(lorv)) {
2322                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2323                                         "invalid group description=%u.\n",
2324                                         lorv);
2325                                 return -1;
2326                         }
2327                         break;
2328 
2329                 case IPSECDOI_ATTR_KEY_LENGTH:
2330                         if (! flag) {
2331                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2332                                         "must be TV when KEY_LENGTH.\n");
2333                                 return -1;
2334                         }
2335                         break;
2336 
2337                 case IPSECDOI_ATTR_KEY_ROUNDS:
2338                 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2339                 case IPSECDOI_ATTR_COMP_PRIVALG:
2340                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2341                                 "attr type=%u isn't supported.\n", type);
2342                         return -1;
2343 
2344                 default:
2345                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2346                                 "invalid attribute type %d.\n", type);
2347                         return -1;
2348                 }
2349 
2350                 if (flag) {
2351                         tlen -= sizeof(*d);
2352                         d = (struct isakmp_data *)((char *)d
2353                                 + sizeof(*d));
2354                 } else {
2355                         tlen -= (sizeof(*d) + lorv);
2356                         d = (struct isakmp_data *)((caddr_t)d
2357                                 + sizeof(*d) + lorv);
2358                 }
2359         }
2360 
2361         if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2362             !attrseen[IPSECDOI_ATTR_AUTH]) {
2363                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2364                         "attr AUTH must be present for AH.\n");
2365                 return -1;
2366         }
2367 
2368         if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
2369             trns->t_id == IPSECDOI_ESP_NULL &&
2370             !attrseen[IPSECDOI_ATTR_AUTH]) {
2371                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2372                     "attr AUTH must be present for ESP NULL encryption.\n");
2373                 return -1;
2374         }
2375 
2376         return 0;
2377 }
2378 
2379 static int
2380 check_attr_ipcomp(trns)
2381         struct isakmp_pl_t *trns;
2382 {
2383         struct isakmp_data *d;
2384         int tlen;
2385         int flag, type = 0;
2386         uint16_t lorv;
2387         int attrseen[16];       /* XXX magic number */
2388 
2389         tlen = get_uint16(&trns->h.len) - sizeof(struct isakmp_pl_t);
2390         d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2391         memset(attrseen, 0, sizeof(attrseen));
2392 
2393         while (tlen > 0) {
2394                 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
2395                 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
2396                 lorv = get_uint16(&d->lorv);
2397 
2398                 plog(PLOG_DEBUG, PLOGLOC, NULL,
2399                         "type=%d, flag=0x%04x, lorv=0x%04x\n",
2400                         type, flag, lorv);
2401 
2402                 if (type < ARRAYLEN(attrseen))
2403                         attrseen[type]++;
2404 
2405                 switch (type) {
2406                 case IPSECDOI_ATTR_ENC_MODE:
2407                         if (! flag) {
2408                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2409                                         "must be TV when ENC_MODE.\n");
2410                                 return -1;
2411                         }
2412 
2413                         switch (lorv) {
2414                         case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2415                         case IPSECDOI_ATTR_ENC_MODE_TRNS:
2416                                 break;
2417 #ifdef ENABLE_NATT
2418                         case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2419                         case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2420                         case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2421                         case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2422                                 plog(PLOG_DEBUG, PLOGLOC, NULL,
2423                                      "UDP encapsulation requested\n");
2424                                 break;
2425 #endif
2426                         default:
2427                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2428                                         "invalid encryption mode=%u.\n",
2429                                         lorv);
2430                                 return -1;
2431                         }
2432                         break;
2433 
2434                 case IPSECDOI_ATTR_SA_LD_TYPE:
2435                         if (! flag) {
2436                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2437                                         "must be TV when LD_TYPE.\n");
2438                                 return -1;
2439                         }
2440 
2441                         switch (lorv) {
2442                         case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2443                         case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2444                                 break;
2445                         default:
2446                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2447                                         "invalid life type %d.\n", lorv);
2448                                 return -1;
2449                         }
2450                         break;
2451 
2452                 case IPSECDOI_ATTR_SA_LD:
2453                         if (flag) {
2454                                 /* i.e. ISAKMP_GEN_TV */
2455                                 plog(PLOG_DEBUG, PLOGLOC, NULL,
2456                                         "life duration was in TLV.\n");
2457                         } else {
2458                                 /* i.e. ISAKMP_GEN_TLV */
2459                                 if (lorv == 0) {
2460                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2461                                                 "invalid length of LD\n");
2462                                         return -1;
2463                                 }
2464                         }
2465                         break;
2466 
2467                 case IPSECDOI_ATTR_GRP_DESC:
2468                         if (! flag) {
2469                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2470                                         "must be TV when GRP_DESC.\n");
2471                                 return -1;
2472                         }
2473 
2474                         if (!alg_oakley_dhdef_ok(lorv)) {
2475                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2476                                         "invalid group description=%u.\n",
2477                                         lorv);
2478                                 return -1;
2479                         }
2480                         break;
2481 
2482                 case IPSECDOI_ATTR_AUTH:
2483                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2484                                 "invalid attr type=%u.\n", type);
2485                         return -1;
2486 
2487                 case IPSECDOI_ATTR_KEY_LENGTH:
2488                 case IPSECDOI_ATTR_KEY_ROUNDS:
2489                 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2490                 case IPSECDOI_ATTR_COMP_PRIVALG:
2491                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2492                                 "attr type=%u isn't supported.\n", type);
2493                         return -1;
2494 
2495                 default:
2496                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2497                                 "invalid attribute type %d.\n", type);
2498                         return -1;
2499                 }
2500 
2501                 if (flag) {
2502                         tlen -= sizeof(*d);
2503                         d = (struct isakmp_data *)((char *)d
2504                                 + sizeof(*d));
2505                 } else {
2506                         tlen -= (sizeof(*d) + lorv);
2507                         d = (struct isakmp_data *)((caddr_t)d
2508                                 + sizeof(*d) + lorv);
2509                 }
2510         }
2511 
2512 #if 0
2513         if (proto_id == IPSECDOI_PROTO_IPCOMP &&
2514             !attrseen[IPSECDOI_ATTR_AUTH]) {
2515                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2516                         "attr AUTH must be present for AH.\n", type);
2517                 return -1;
2518         }
2519 #endif
2520 
2521         return 0;
2522 }
2523 
2524 /* %%% */
2525 /*
2526  * create phase1 proposal from remote configuration.
2527  * NOT INCLUDING isakmp general header of SA payload
2528  */
2529 rc_vchar_t *
2530 ipsecdoi_setph1proposal(props)
2531         struct isakmpsa *props;
2532 {
2533         rc_vchar_t *mysa;
2534         int sablen;
2535 
2536         /* count total size of SA minus isakmp general header */
2537         /* not including isakmp general header of SA payload */
2538         sablen = sizeof(struct ipsecdoi_sa_b);
2539         sablen += setph1prop(props, NULL);
2540 
2541         mysa = rc_vmalloc(sablen);
2542         if (mysa == NULL) {
2543                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2544                         "failed to allocate my sa buffer\n");
2545                 return NULL;
2546         }
2547 
2548         /* create SA payload */
2549         /* not including isakmp general header */
2550         put_uint32(&((struct ipsecdoi_sa_b *)mysa->v)->doi, ikev1_doitype(props->rmconf));
2551         put_uint32(&((struct ipsecdoi_sa_b *)mysa->v)->sit, ikev1_sittype(props->rmconf));
2552 
2553         (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
2554 
2555         return mysa;
2556 }
2557 
2558 static int
2559 setph1prop(props, buf)
2560         struct isakmpsa *props;
2561         caddr_t buf;
2562 {
2563         struct isakmp_pl_p *prop = NULL;
2564         struct isakmpsa *s = NULL;
2565         int proplen, trnslen;
2566         uint8_t *np_t; /* pointer next trns type in previous header */
2567         int trns_num;
2568         caddr_t p = buf;
2569 
2570         proplen = sizeof(*prop);
2571         if (buf) {
2572                 /* create proposal */
2573                 prop = (struct isakmp_pl_p *)p;
2574                 prop->h.np = ISAKMP_NPTYPE_NONE;
2575                 prop->p_no = props->prop_no;
2576                 prop->proto_id = IPSECDOI_PROTO_ISAKMP;
2577                 prop->spi_size = 0;
2578                 p += sizeof(*prop);
2579         }
2580 
2581         np_t = NULL;
2582         trns_num = 0;
2583 
2584         for (s = props; s != NULL; s = s->next) {
2585                 if (np_t)
2586                         *np_t = ISAKMP_NPTYPE_T;
2587 
2588                 trnslen = setph1trns(s, p);
2589                 proplen += trnslen;
2590                 if (buf) {
2591                         /* save buffer to pre-next payload */
2592                         np_t = &((struct isakmp_pl_t *)p)->h.np;
2593                         p += trnslen;
2594 
2595                         /* count up transform length */
2596                         trns_num++;
2597                 }
2598         }
2599 
2600         /* update proposal length */
2601         if (buf) {
2602                 put_uint16(&prop->h.len, proplen);
2603                 prop->num_t = trns_num;
2604         }
2605 
2606         return proplen;
2607 }
2608 
2609 static int
2610 setph1trns(sa, buf)
2611         struct isakmpsa *sa;
2612         caddr_t buf;
2613 {
2614         struct isakmp_pl_t *trns = NULL;
2615         int trnslen, attrlen;
2616         caddr_t p = buf;
2617 
2618         trnslen = sizeof(*trns);
2619         if (buf) {
2620                 /* create transform */
2621                 trns = (struct isakmp_pl_t *)p;
2622                 trns->h.np  = ISAKMP_NPTYPE_NONE;
2623                 trns->t_no  = sa->trns_no;
2624                 trns->t_id  = IPSECDOI_KEY_IKE;
2625                 p += sizeof(*trns);
2626         }
2627 
2628         attrlen = setph1attr(sa, p);
2629         trnslen += attrlen;
2630         if (buf)
2631                 p += attrlen;
2632 
2633         if (buf)
2634                 put_uint16(&trns->h.len, trnslen);
2635 
2636         return trnslen;
2637 }
2638 
2639 static int
2640 setph1attr(sa, buf)
2641         struct isakmpsa *sa;
2642         caddr_t buf;
2643 {
2644         caddr_t p = buf;
2645         int attrlen = 0;
2646 
2647         if (sa->lifetime) {
2648                 uint32_t lifetime = htonl((uint32_t)sa->lifetime);
2649 
2650                 attrlen += sizeof(struct isakmp_data)
2651                         + sizeof(struct isakmp_data);
2652                 if (sa->lifetime > 0xffff)
2653                         attrlen += sizeof(lifetime);
2654                 if (buf) {
2655                         p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2656                                                 OAKLEY_ATTR_SA_LD_TYPE_SEC);
2657                         if (sa->lifetime > 0xffff) {
2658                                 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2659                                                 (caddr_t)&lifetime,
2660                                                 sizeof(lifetime));
2661                         } else {
2662                                 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2663                                                         sa->lifetime);
2664                         }
2665                 }
2666         }
2667 
2668         if (sa->lifebyte) {
2669                 uint32_t lifebyte = htonl((uint32_t)sa->lifebyte);
2670                 
2671                 attrlen += sizeof(struct isakmp_data)
2672                         + sizeof(struct isakmp_data);
2673                 if (sa->lifebyte > 0xffff)
2674                         attrlen += sizeof(lifebyte);
2675                 if (buf) {
2676                         p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2677                                                 OAKLEY_ATTR_SA_LD_TYPE_KB);
2678                         if (sa->lifebyte > 0xffff) {
2679                                 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2680                                                         (caddr_t)&lifebyte,
2681                                                         sizeof(lifebyte));
2682                         } else {
2683                                 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2684                                                         sa->lifebyte);
2685                         }
2686                 }
2687         }
2688 
2689         if (sa->enctype) {
2690                 attrlen += sizeof(struct isakmp_data);
2691                 if (buf)
2692                         p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
2693         }
2694         if (sa->encklen) {
2695                 attrlen += sizeof(struct isakmp_data);
2696                 if (buf)
2697                         p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
2698         }
2699         if (sa->authmethod) {
2700                 attrlen += sizeof(struct isakmp_data);
2701                 if (buf)
2702                         p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, sa->authmethod);
2703         }
2704         if (sa->hashtype) {
2705                 attrlen += sizeof(struct isakmp_data);
2706                 if (buf)
2707                         p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
2708         }
2709         switch (sa->dh_group) {
2710         case OAKLEY_ATTR_GRP_DESC_MODP768:
2711         case OAKLEY_ATTR_GRP_DESC_MODP1024:
2712         case OAKLEY_ATTR_GRP_DESC_MODP1536:
2713         case OAKLEY_ATTR_GRP_DESC_MODP2048:
2714         case OAKLEY_ATTR_GRP_DESC_MODP3072:
2715         case OAKLEY_ATTR_GRP_DESC_MODP4096:
2716         case OAKLEY_ATTR_GRP_DESC_MODP6144:
2717         case OAKLEY_ATTR_GRP_DESC_MODP8192:
2718                 /* don't attach group type for known groups */
2719                 attrlen += sizeof(struct isakmp_data);
2720                 if (buf) {
2721                         p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
2722                                 sa->dh_group);
2723                 }
2724                 break;
2725         case OAKLEY_ATTR_GRP_DESC_EC2N155:
2726         case OAKLEY_ATTR_GRP_DESC_EC2N185:
2727                 /* don't attach group type for known groups */
2728                 attrlen += sizeof(struct isakmp_data);
2729                 if (buf) {
2730                         p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
2731                                 OAKLEY_ATTR_GRP_TYPE_EC2N);
2732                 }
2733                 break;
2734         case 0:
2735         default:
2736                 break;
2737         }
2738 
2739 #ifdef HAVE_GSSAPI
2740         if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
2741             sa->gssid != NULL) {
2742                 attrlen += sizeof(struct isakmp_data);
2743                 attrlen += sa->gssid->l;
2744                 if (buf) {
2745                         plog(PLOG_DEBUG, PLOGLOC, NULL, "gss id attr: len %d, "
2746                             "val '%s'\n", sa->gssid->l, sa->gssid->v);
2747                         p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2748                                 (caddr_t)sa->gssid->v, 
2749                                 sa->gssid->l);
2750                 }
2751         }
2752 #endif
2753 
2754         return attrlen;
2755 }
2756 
2757 static rc_vchar_t *
2758 setph2proposal0(iph2, pp, pr)
2759         const struct ph2handle *iph2;
2760         const struct saprop *pp;
2761         const struct saproto *pr;
2762 {
2763         rc_vchar_t *p;
2764         struct isakmp_pl_p *prop;
2765         struct isakmp_pl_t *trns;
2766         struct satrns *tr;
2767         int attrlen;
2768         size_t trnsoff;
2769         caddr_t x0, x;
2770         uint8_t *np_t; /* pointer next trns type in previous header */
2771         const uint8_t *spi;
2772 
2773         p = rc_vmalloc(sizeof(*prop) + sizeof(pr->spi));
2774         if (p == NULL)
2775                 return NULL;
2776 
2777         /* create proposal */
2778         prop = (struct isakmp_pl_p *)p->v;
2779         prop->h.np = ISAKMP_NPTYPE_NONE;
2780         prop->p_no = pp->prop_no;
2781         prop->proto_id = pr->proto_id;
2782         prop->num_t = 1;
2783 
2784         spi = (const uint8_t *)&pr->spi;
2785         switch (pr->proto_id) {
2786         case IPSECDOI_PROTO_IPCOMP:
2787                 /*
2788                  * draft-shacham-ippcp-rfc2393bis-05.txt:
2789                  * construct 16bit SPI (CPI).
2790                  * XXX we may need to provide a configuration option to
2791                  * generate 32bit SPI.  otherwise we cannot interoeprate
2792                  * with nodes that uses 32bit SPI, in case we are initiator.
2793                  */
2794                 prop->spi_size = sizeof(uint16_t);
2795                 spi += sizeof(pr->spi) - sizeof(uint16_t);
2796                 p->l -= sizeof(pr->spi);
2797                 p->l += sizeof(uint16_t);
2798                 break;
2799         default:
2800                 prop->spi_size = sizeof(pr->spi);
2801                 break;
2802         }
2803         memcpy(prop + 1, spi, prop->spi_size);
2804 
2805         /* create transform */
2806         trnsoff = sizeof(*prop) + prop->spi_size;
2807         np_t = NULL;
2808 
2809         for (tr = pr->head; tr; tr = tr->next) {
2810         
2811                 switch (pr->proto_id) {
2812                 case IPSECDOI_PROTO_IPSEC_ESP:
2813                         /*
2814                          * don't build a null encryption
2815                          * with no authentication transform.
2816                          */
2817                         if (tr->trns_id == IPSECDOI_ESP_NULL &&
2818                             tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
2819                                 continue;
2820                         break;
2821                 }
2822 
2823                 if (np_t) {
2824                         *np_t = ISAKMP_NPTYPE_T;
2825                         prop->num_t++;
2826                 }
2827 
2828                 /* get attribute length */
2829                 attrlen = 0;
2830                 if (pp->lifetime) {
2831                         attrlen += sizeof(struct isakmp_data)
2832                                 + sizeof(struct isakmp_data);
2833                         if (pp->lifetime > 0xffff)
2834                                 attrlen += sizeof(uint32_t);
2835                 }
2836                 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2837                         attrlen += sizeof(struct isakmp_data)
2838                                 + sizeof(struct isakmp_data);
2839                         if (pp->lifebyte > 0xffff)
2840                                 attrlen += sizeof(uint32_t);
2841                 }
2842                 attrlen += sizeof(struct isakmp_data);  /* enc mode */
2843                 if (tr->encklen)
2844                         attrlen += sizeof(struct isakmp_data);
2845 
2846                 switch (pr->proto_id) {
2847                 case IPSECDOI_PROTO_IPSEC_ESP:
2848                         /* non authentication mode ? */
2849                         if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2850                                 attrlen += sizeof(struct isakmp_data);
2851                         break;
2852                 case IPSECDOI_PROTO_IPSEC_AH:
2853                         if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
2854                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2855                                         "no authentication algorithm found "
2856                                         "but protocol is AH.\n");
2857                                 rc_vfree(p);
2858                                 return NULL;
2859                         }
2860                         attrlen += sizeof(struct isakmp_data);
2861                         break;
2862                 case IPSECDOI_PROTO_IPCOMP:
2863                         break;
2864                 default:
2865                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2866                                 "invalid protocol: %d\n", pr->proto_id);
2867                         rc_vfree(p);
2868                         return NULL;
2869                 }
2870 
2871                 if (alg_oakley_dhdef_ok(pp->pfs_group))
2872                         attrlen += sizeof(struct isakmp_data);
2873 
2874                 p = rc_vrealloc(p, p->l + sizeof(*trns) + attrlen);
2875                 if (p == NULL)
2876                         return NULL;
2877                 prop = (struct isakmp_pl_p *)p->v;
2878 
2879                 /* set transform's values */
2880                 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
2881                 trns->h.np  = ISAKMP_NPTYPE_NONE;
2882                 trns->t_no  = tr->trns_no;
2883                 trns->t_id  = tr->trns_id;
2884 
2885                 /* set attributes */
2886                 x = x0 = p->v + trnsoff + sizeof(*trns);
2887 
2888                 if (pp->lifetime) {
2889                         x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2890                                                 IPSECDOI_ATTR_SA_LD_TYPE_SEC);
2891                         if (pp->lifetime > 0xffff) {
2892                                 uint32_t v = htonl((uint32_t)pp->lifetime);
2893                                 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
2894                                                         (caddr_t)&v, sizeof(v));
2895                         } else {
2896                                 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
2897                                                         pp->lifetime);
2898                         }
2899                 }
2900 
2901                 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2902                         x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2903                                                 IPSECDOI_ATTR_SA_LD_TYPE_KB);
2904                         if (pp->lifebyte > 0xffff) {
2905                                 uint32_t v = htonl((uint32_t)pp->lifebyte);
2906                                 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
2907                                                         (caddr_t)&v, sizeof(v));
2908                         } else {
2909                                 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
2910                                                         pp->lifebyte);
2911                         }
2912                 }
2913 
2914                 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
2915 
2916                 if (tr->encklen)
2917                         x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
2918 
2919                 /* mandatory check has done above. */
2920                 if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2921                  || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
2922                         x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
2923 
2924                 if (alg_oakley_dhdef_ok(pp->pfs_group))
2925                         x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
2926                                 pp->pfs_group);
2927 
2928                 /* update length of this transform. */
2929                 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
2930                 put_uint16(&trns->h.len, sizeof(*trns) + attrlen);
2931 
2932                 /* save buffer to pre-next payload */
2933                 np_t = &trns->h.np;
2934 
2935                 trnsoff += (sizeof(*trns) + attrlen);
2936         }
2937 
2938         if (np_t == NULL) {
2939                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2940                         "no suitable proposal was created.\n");
2941                 return NULL;
2942         }
2943 
2944         /* update length of this protocol. */
2945         put_uint16(&prop->h.len, p->l);
2946 
2947         return p;
2948 }
2949 
2950 /*
2951  * create phase2 proposal from policy configuration.
2952  * NOT INCLUDING isakmp general header of SA payload.
2953  * This function is called by initiator only.
2954  */
2955 int
2956 ipsecdoi_setph2proposal(iph2)
2957         struct ph2handle *iph2;
2958 {
2959         struct saprop *proposal, *a;
2960         struct saproto *b = NULL;
2961         rc_vchar_t *q;
2962         struct ipsecdoi_sa_b *sab;
2963         struct isakmp_pl_p *prop;
2964         size_t propoff; /* for previous field of type of next payload. */
2965 
2966         proposal = iph2->proposal;
2967 
2968         iph2->sa = rc_vmalloc(sizeof(*sab));
2969         if (iph2->sa == NULL) {
2970                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2971                         "failed to allocate my sa buffer\n");
2972                 return -1;
2973         }
2974 
2975         /* create SA payload */
2976         sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
2977         put_uint32(&sab->doi, IPSEC_DOI);
2978         put_uint32(&sab->sit, IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */
2979 
2980         prop = NULL;
2981         propoff = 0;
2982         for (a = proposal; a; a = a->next) {
2983                 for (b = a->head; b; b = b->next) {
2984 #ifdef ENABLE_NATT
2985                         if (iph2->ph1->natt_flags & NAT_DETECTED) {
2986                           int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
2987                           plog (PLOG_INFO, PLOGLOC, NULL,
2988                                 "NAT detected -> UDP encapsulation "
2989                                 "(ENC_MODE %d->%d).\n",
2990                                 b->encmode,
2991                                 b->encmode+udp_diff);
2992                           /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
2993                           b->encmode += udp_diff;
2994                           b->udp_encap = 1;
2995                         }
2996 #endif
2997 
2998                         q = setph2proposal0(iph2, a, b);
2999                         if (q == NULL) {
3000                                 VPTRINIT(iph2->sa);
3001                                 return -1;
3002                         }
3003 
3004                         iph2->sa = rc_vrealloc(iph2->sa, iph2->sa->l + q->l);
3005                         if (iph2->sa == NULL) {
3006                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3007                                         "failed to allocate my sa buffer\n");
3008                                 if (q)
3009                                         rc_vfree(q);
3010                                 return -1;
3011                         }
3012                         memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
3013                         if (propoff != 0) {
3014                                 prop = (struct isakmp_pl_p *)(iph2->sa->v +
3015                                         propoff);
3016                                 prop->h.np = ISAKMP_NPTYPE_P;
3017                         }
3018                         propoff = iph2->sa->l - q->l;
3019 
3020                         rc_vfree(q);
3021                 }
3022         }
3023 
3024         return 0;
3025 }
3026 
3027 /*
3028  * return 1 if all of the given protocols are transport mode.
3029  */
3030 int
3031 ipsecdoi_transportmode(pp)
3032         struct saprop *pp;
3033 {
3034         struct saproto *pr = NULL;
3035 
3036         for (; pp; pp = pp->next) {
3037                 for (pr = pp->head; pr; pr = pr->next) {
3038                         if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
3039                                 return 0;
3040                 }
3041         }
3042 
3043         return 1;
3044 }
3045 
3046 #if 0
3047 int
3048 ipsecdoi_get_defaultlifetime()
3049 {
3050         return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3051 }
3052 #endif
3053 
3054 int
3055 ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
3056         int proto_id, enc, auth, comp;
3057 {
3058 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3059         switch (proto_id) {
3060         case IPSECDOI_PROTO_IPSEC_ESP:
3061                 if (enc == 0 || comp != 0) {
3062                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3063                                 "illegal algorithm defined "
3064                                 "ESP enc=%s auth=%s comp=%s.\n",
3065                                 TMPALGTYPE2STR(enc),
3066                                 TMPALGTYPE2STR(auth),
3067                                 TMPALGTYPE2STR(comp));
3068                         return -1;
3069                 }
3070                 break;
3071         case IPSECDOI_PROTO_IPSEC_AH:
3072                 if (enc != 0 || auth == 0 || comp != 0) {
3073                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3074                                 "illegal algorithm defined "
3075                                 "AH enc=%s auth=%s comp=%s.\n",
3076                                 TMPALGTYPE2STR(enc),
3077                                 TMPALGTYPE2STR(auth),
3078                                 TMPALGTYPE2STR(comp));
3079                         return -1;
3080                 }
3081                 break;
3082         case IPSECDOI_PROTO_IPCOMP:
3083                 if (enc != 0 || auth != 0 || comp == 0) {
3084                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3085                                 "illegal algorithm defined "
3086                                 "IPcomp enc=%s auth=%s comp=%s.\n",
3087                                 TMPALGTYPE2STR(enc),
3088                                 TMPALGTYPE2STR(auth),
3089                                 TMPALGTYPE2STR(comp));
3090                         return -1;
3091                 }
3092                 break;
3093         default:
3094                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3095                         "invalid ipsec protocol %d\n", proto_id);
3096                 return -1;
3097         }
3098 #undef TMPALGTYPE2STR
3099         return 0;
3100 }
3101 
3102 int
3103 ipproto2doi(proto)
3104         int proto;
3105 {
3106         switch (proto) {
3107         case IPPROTO_AH:
3108                 return IPSECDOI_PROTO_IPSEC_AH;
3109         case IPPROTO_ESP:
3110                 return IPSECDOI_PROTO_IPSEC_ESP;
3111         case IPPROTO_IPCOMP:
3112                 return IPSECDOI_PROTO_IPCOMP;
3113         }
3114         return -1;      /* XXX */
3115 }
3116 
3117 int
3118 doi2ipproto(proto)
3119         int proto;
3120 {
3121         switch (proto) {
3122         case IPSECDOI_PROTO_IPSEC_AH:
3123                 return IPPROTO_AH;
3124         case IPSECDOI_PROTO_IPSEC_ESP:
3125                 return IPPROTO_ESP;
3126         case IPSECDOI_PROTO_IPCOMP:
3127                 return IPPROTO_IPCOMP;
3128         }
3129         return -1;      /* XXX */
3130 }
3131 
3132 /*
3133  * check the following:
3134  * - In main mode with pre-shared key, only address type can be used.
3135  * - if proper type for phase 1 ?
3136  * - if phase 1 ID payload conformed RFC2407 4.6.2.
3137  *   (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3138  * - if ID payload sent from peer is equal to the ID expected by me.
3139  *
3140  * both of "id" and "id_p" should be ID payload without general header,
3141  */
3142 int
3143 ipsecdoi_checkid1(iph1)
3144         struct ph1handle *iph1;
3145 {
3146         struct ipsecdoi_id_b *id_b;
3147 #if 0
3148         struct sockaddr *sa;
3149         caddr_t sa1, sa2;
3150 #endif
3151 
3152         if (iph1->id_p == NULL) {
3153                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3154                         "invalid iph1 passed id_p == NULL\n");
3155                 return ISAKMP_INTERNAL_ERROR;
3156         }
3157         if (iph1->id_p->l < sizeof(*id_b)) {
3158                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3159                         "invalid value passed as \"ident\" (len=%lu)\n",
3160                         (u_long)iph1->id_p->l);
3161                 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3162         }
3163 
3164         id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
3165 
3166         /* In main mode with pre-shared key, only address type can be used. */
3167         if (iph1->etype == ISAKMP_ETYPE_IDENT &&
3168             iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
3169                  if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3170                   && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3171                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3172                                 "Expecting IP address type in main mode, "
3173                                 "but %s.\n", s_ipsecdoi_ident(id_b->type));
3174                         return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3175                 }
3176         }
3177 
3178         /* if proper type for phase 1 ? */
3179         switch (id_b->type) {
3180         case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3181         case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3182         case IPSECDOI_ID_IPV4_ADDR_RANGE:
3183         case IPSECDOI_ID_IPV6_ADDR_RANGE:
3184                 plog(PLOG_PROTOWARN, PLOGLOC, 0,
3185                      "peer ID type %s is not acceptable\n",
3186                      s_ipsecdoi_ident(id_b->type));
3187                 /*FALLTHROUGH*/
3188         }
3189 
3190         /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3191         if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
3192             id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3193 
3194                 if (id_b->proto_id == 0 && get_uint16(&id_b->port) != 0) {
3195                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
3196                                 "protocol ID and Port mismatched. "
3197                                 "proto_id:%d port:%d\n",
3198                                 id_b->proto_id, get_uint16(&id_b->port));
3199                         /*FALLTHROUGH*/
3200 
3201                 } else if (id_b->proto_id == IPPROTO_UDP) {
3202                         /*
3203                          * copmaring with expecting port.
3204                          * always permit if port is equal to PORT_ISAKMP
3205                          */
3206                         if (get_uint16(&id_b->port) != PORT_ISAKMP) {
3207 
3208                                 uint16_t port;
3209 
3210                                 switch (iph1->remote->sa_family) {
3211                                 case AF_INET:
3212                                         port = ((struct sockaddr_in *)iph1->remote)->sin_port;
3213                                         break;
3214 #ifdef INET6
3215                                 case AF_INET6:
3216                                         port = ((struct sockaddr_in6 *)iph1->remote)->sin6_port;
3217                                         break;
3218 #endif
3219                                 default:
3220                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3221                                                 "invalid family: %d\n",
3222                                                 iph1->remote->sa_family);
3223                                         return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3224                                 }
3225                                 if (get_uint16(&id_b->port) != port) {
3226                                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
3227                                                 "port %d expected, but %d\n",
3228                                                 port, get_uint16(&id_b->port));
3229                                         /*FALLTHROUGH*/
3230                                 }
3231                         }
3232                 }
3233         }
3234 
3235 #if 0
3236         /* compare with the ID if specified. */
3237         if (ikev1_peers_id(iph1->rmconf)) {
3238                 rc_type rc_id_type;
3239                 rc_vchar_t *id_data;
3240 
3241                 /* check the type of both IDs */
3242                 if (ikev1_compare_id(iph1->id_p, ikev1_peers_id(iph1->rmconf)) != 0) {
3243                         if (ikev1_verify_id(iph1->rmconf) == RCT_BOOL_ON) {
3244                                 plog(PLOG_PROTOERR, PLOGLOC, 0,
3245                                      "peer identifier does not match\n");
3246                                 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3247                         }
3248                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
3249                              "peer identifier does not match\n");
3250                 }
3251         }
3252 #endif
3253 
3254         return 0;
3255 }
3256 
3257 /*
3258  * create ID payload for phase 1 and set into iph1->id.
3259  * NOT INCLUDING isakmp general header.
3260  * see, RFC2407 4.6.2.1
3261  */
3262 int
3263 ipsecdoi_setid1(iph1)
3264         struct ph1handle *iph1;
3265 {
3266         struct rc_idlist *id;
3267         rc_vchar_t *id_data = 0;
3268         int id_type;
3269         struct ipsecdoi_id_b id_b;
3270         rc_vchar_t *ret;
3271 
3272         id = ikev1_my_id(iph1->rmconf);
3273         id_data = ike_identifier_data(id, &id_type);
3274         if (!id_data)
3275                 goto err;
3276 
3277         /* init */
3278         id_b.type = id_type;
3279         id_b.proto_id = 0;
3280         id_b.port = 0;
3281 
3282         ret = rc_vmalloc(sizeof(id_b) + id_data->l);
3283         if (ret == NULL)
3284                 goto err;
3285 
3286         memcpy(ret->v, &id_b, sizeof(id_b));
3287         memcpy(ret->v + sizeof(id_b), id_data->v, id_data->l);
3288 
3289         iph1->id = ret;
3290 
3291         plog(PLOG_DEBUG, PLOGLOC, NULL,
3292              "using ID type %s\n", s_ipsecdoi_ident(id_b.type));
3293         if (id_data)
3294                 rc_vfree(id_data);
3295         return 0;
3296 
3297 err:
3298         if (id_data)
3299                 rc_vfree(id_data);
3300         plog(PLOG_INTERR, PLOGLOC, NULL, "failed constructing my ID\n");
3301         return -1;
3302 }
3303 
3304 #if 0
3305 static rc_vchar_t *
3306 getidval(type, val)
3307         int type;
3308         rc_vchar_t *val;
3309 {
3310         rc_vchar_t *new = NULL;
3311 
3312         if (val)
3313                 new = rc_vdup(val);
3314         else if (lcconf->ident[type])
3315                 new = rc_vdup(lcconf->ident[type]);
3316 
3317         return new;
3318 }
3319 #endif
3320 
3321 #if 0
3322 /* it's only called by cfparse.y. */
3323 int
3324 set_identifier(vpp, type, value)
3325         rc_vchar_t **vpp, *value;
3326         int type;
3327 {
3328         rc_vchar_t *new = NULL;
3329 
3330         /* simply return if value is null. */
3331         if (!value)
3332                 return 0;
3333 
3334         switch (type) {
3335         case IDTYPE_FQDN:
3336         case IDTYPE_USERFQDN:
3337                 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3338                 new = rc_vmalloc(value->l - 1);
3339                 if (new == NULL)
3340                         return -1;
3341                 memcpy(new->v, value->v, new->l);
3342                 break;
3343         case IDTYPE_KEYID:
3344         {
3345                 FILE *fp;
3346                 char b[512];
3347                 int tlen, len;
3348 
3349                 fp = fopen(value->v, "r");
3350                 if (fp == NULL) {
3351                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3352                                 "can not open %s\n", value->v);
3353                         return -1;
3354                 }
3355                 tlen = 0;
3356                 while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
3357                         new = rc_vrealloc(new, tlen + len);
3358                         if (!new) {
3359                                 fclose(fp);
3360                                 return -1;
3361                         }
3362                         memcpy(new->v + tlen, b, len);
3363                         tlen += len;
3364                 }
3365                 break;
3366         }
3367         case IDTYPE_ADDRESS:
3368         {
3369                 struct sockaddr *sa;
3370 
3371                 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3372                 if (value->l == 0)
3373                         break;
3374 
3375                 sa = str2saddr(value->v, NULL);
3376                 if (sa == NULL) {
3377                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3378                                 "invalid ip address %s\n", value->v);
3379                         return -1;
3380                 }
3381 
3382                 new = rc_vmalloc(sa->sa_len);
3383                 if (new == NULL)
3384                         return -1;
3385                 memcpy(new->v, sa, new->l);
3386                 break;
3387         }
3388         case IDTYPE_ASN1DN:
3389                 new = eay_str2asn1dn(value->v, value->l - 1);
3390                 if (new == NULL)
3391                         return -1;
3392                 break;
3393         }
3394 
3395         *vpp = new;
3396 
3397         return 0;
3398 }
3399 #endif
3400 
3401 /*
3402  * create ID payload for phase 2, and set into iph2->id and id_p.  There are
3403  * NOT INCLUDING isakmp general header.
3404  * this function is for initiator.  responder will get to copy from payload.
3405  * responder ID type is always address type.
3406  * see, RFC2407 4.6.2.1
3407  */
3408 int
3409 ipsecdoi_setid2(iph2)
3410         struct ph2handle *iph2;
3411 {
3412         struct rcf_selector *sel;
3413         int proto;
3414 
3415         /* check there is phase 2 handler ? */
3416         sel = iph2->selector;
3417         assert(sel->src->type == RCT_ADDR_INET);
3418         assert(sel->dst->type == RCT_ADDR_INET);
3419         proto = sel->upper_layer_protocol;
3420         if (proto == RC_PROTO_ANY)
3421                 proto = 0;
3422 
3423         iph2->id = ipsecdoi_sockaddr2id(sel->src->a.ipaddr, sel->src->prefixlen, proto);
3424         if (iph2->id == NULL) {
3425                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3426                      "failed to create ID payload for %s\n",
3427                      rc_vmem2str(sel->sl_index));
3428                 return -1;
3429         }
3430         plog(PLOG_DEBUG, PLOGLOC, NULL, "use local ID type %s\n",
3431                 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
3432 
3433         /* remote side */
3434         iph2->id_p = ipsecdoi_sockaddr2id(sel->dst->a.ipaddr, sel->dst->prefixlen, proto);
3435         if (iph2->id_p == NULL) {
3436                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3437                      "failed to create ID payload for %s\n",
3438                      rc_vmem2str(sel->sl_index));
3439                 VPTRINIT(iph2->id);
3440                 return -1;
3441         }
3442         plog(PLOG_DEBUG, PLOGLOC, NULL,
3443                 "use remote ID type %s\n",
3444                 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
3445 
3446         return 0;
3447 }
3448 
3449 /*
3450  * set address type of ID.
3451  * NOT INCLUDING general header.
3452  */
3453 rc_vchar_t *
3454 ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
3455         struct sockaddr *saddr;
3456         unsigned int prefixlen;
3457         unsigned int ul_proto;
3458 {
3459         rc_vchar_t *new;
3460         int type, len1, len2;
3461         caddr_t sa;
3462         uint16_t port;
3463 
3464         /*
3465          * Q. When type is SUBNET, is it allowed to be ::1/128.
3466          * A. Yes. (consensus at bake-off)
3467          */
3468         switch (saddr->sa_family) {
3469         case AF_INET:
3470                 len1 = sizeof(struct in_addr);
3471                 if (prefixlen == (sizeof(struct in_addr) << 3)) {
3472                         type = IPSECDOI_ID_IPV4_ADDR;
3473                         len2 = 0;
3474                 } else {
3475                         type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
3476                         len2 = sizeof(struct in_addr);
3477                 }
3478                 sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
3479                 port = ((struct sockaddr_in *)(saddr))->sin_port;
3480                 break;
3481 #ifdef INET6
3482         case AF_INET6:
3483                 len1 = sizeof(struct in6_addr);
3484                 if (prefixlen == (sizeof(struct in6_addr) << 3)) {
3485                         type = IPSECDOI_ID_IPV6_ADDR;
3486                         len2 = 0;
3487                 } else {
3488                         type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
3489                         len2 = sizeof(struct in6_addr);
3490                 }
3491                 sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
3492                 port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
3493                 break;
3494 #endif
3495         default:
3496                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3497                         "invalid family: %d.\n", saddr->sa_family);
3498                 return NULL;
3499         }
3500 
3501         /* get ID buffer */
3502         new = rc_vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
3503         if (new == NULL) {
3504                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3505                         "failed to get ID buffer.\n");
3506                 return NULL;
3507         }
3508 
3509         memset(new->v, 0, new->l);
3510 
3511         /* set the part of header. */
3512         ((struct ipsecdoi_id_b *)new->v)->type = type;
3513 
3514         /* set ul_proto and port */
3515         /*
3516          * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
3517          * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
3518          */
3519         ((struct ipsecdoi_id_b *)new->v)->proto_id =
3520                 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
3521         ((struct ipsecdoi_id_b *)new->v)->port =
3522                 port == IPSEC_PORT_ANY ? 0 : port;
3523         memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
3524 
3525         /* set address */
3526 
3527         /* set prefix */
3528         if (len2) {
3529                 unsigned char *p = (unsigned char *)new->v + sizeof(struct ipsecdoi_id_b) + len1;
3530                 unsigned int bits = prefixlen;
3531 
3532                 while (bits >= 8) {
3533                         *p++ = 0xff;
3534                         bits -= 8;
3535                 }
3536 
3537                 if (bits > 0)
3538                         *p = ~((1 << (8 - bits)) - 1);
3539         }
3540 
3541         return new;
3542 }
3543 
3544 /*
3545  * create sockaddr structure from ID payload (buf).
3546  * buffers (saddr, prefixlen, ul_proto) must be allocated.
3547  * see, RFC2407 4.6.2.1
3548  */
3549 int
3550 ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
3551         rc_vchar_t *buf;
3552         struct sockaddr *saddr;
3553         uint8_t *prefixlen;
3554         uint16_t *ul_proto;
3555 {
3556         struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
3557         unsigned int plen = 0;
3558 
3559         /*
3560          * When a ID payload of subnet type with a IP address of full bit
3561          * masked, it has to be processed as host address.
3562          * e.g. below 2 type are same.
3563          *      type = ipv6 subnet, data = 2001::1/128
3564          *      type = ipv6 address, data = 2001::1
3565          */
3566         switch (id_b->type) {
3567         case IPSECDOI_ID_IPV4_ADDR:
3568         case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3569                 SET_SOCKADDR_LEN(saddr, sizeof(struct sockaddr_in));
3570                 saddr->sa_family = AF_INET;
3571                 ((struct sockaddr_in *)saddr)->sin_port =
3572                         (id_b->port == 0
3573                                 ? IPSEC_PORT_ANY
3574                                 : id_b->port);               /* see sockaddr2id() */
3575                 memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
3576                         buf->v + sizeof(*id_b), sizeof(struct in_addr));
3577                 break;
3578 #ifdef INET6
3579         case IPSECDOI_ID_IPV6_ADDR:
3580         case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3581                 SET_SOCKADDR_LEN(saddr, sizeof(struct sockaddr_in6));
3582                 saddr->sa_family = AF_INET6;
3583                 ((struct sockaddr_in6 *)saddr)->sin6_port =
3584                         (id_b->port == 0
3585                                 ? IPSEC_PORT_ANY
3586                                 : id_b->port);               /* see sockaddr2id() */
3587                 memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
3588                         buf->v + sizeof(*id_b), sizeof(struct in6_addr));
3589                 ((struct sockaddr_in6 *)saddr)->sin6_scope_id = 0;
3590                 break;
3591 #endif
3592         default:
3593                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3594                         "unsupported ID type %d\n", id_b->type);
3595                 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3596         }
3597 
3598         /* get prefix length */
3599         switch (id_b->type) {
3600         case IPSECDOI_ID_IPV4_ADDR:
3601                 plen = sizeof(struct in_addr) << 3;
3602                 break;
3603 #ifdef INET6
3604         case IPSECDOI_ID_IPV6_ADDR:
3605                 plen = sizeof(struct in6_addr) << 3;
3606                 break;
3607 #endif
3608         case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3609 #ifdef INET6
3610         case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3611 #endif
3612             {
3613                 unsigned char *p;
3614                 unsigned int max;
3615                 int alen = sizeof(struct in_addr);
3616 
3617                 switch (id_b->type) {
3618                 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3619                         alen = sizeof(struct in_addr);
3620                         break;
3621 #ifdef INET6
3622                 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3623                         alen = sizeof(struct in6_addr);
3624                         break;
3625 #endif
3626                 }
3627 
3628                 /* sanity check */
3629                 if (buf->l < alen)
3630                         return ISAKMP_INTERNAL_ERROR;
3631 
3632                 /* get subnet mask length */
3633                 plen = 0;
3634                 max = alen <<3;
3635 
3636                 p = (unsigned char *) buf->v
3637                         + sizeof(struct ipsecdoi_id_b)
3638                         + alen;
3639 
3640                 for (; *p == 0xff; p++) {
3641                         plen += 8;
3642                         if (plen >= max)
3643                                 break;
3644                 }
3645 
3646                 if (plen < max) {
3647                         unsigned int l = 0;
3648                         unsigned char b = ~(*p);
3649 
3650                         while (b) {
3651                                 b >>= 1;
3652                                 l++;
3653                         }
3654 
3655                         l = 8 - l;
3656                         plen += l;
3657                 }
3658             }
3659                 break;
3660         }
3661 
3662         *prefixlen = plen;
3663         *ul_proto = id_b->proto_id == 0
3664                                 ? IPSEC_ULPROTO_ANY
3665                                 : id_b->proto_id;    /* see sockaddr2id() */
3666 
3667         return 0;
3668 }
3669 
3670 /*
3671  * make printable string from ID payload except of general header.
3672  */
3673 const char *
3674 ipsecdoi_id2str(id)
3675         const rc_vchar_t *id;
3676 {
3677         static char buf[256];
3678 
3679         /* XXX */
3680         buf[0] = '\0';
3681 
3682         return buf;
3683 }
3684 
3685 /*
3686  * set IPsec data attributes into a proposal.
3687  * NOTE: MUST called per a transform.
3688  */
3689 int
3690 ipsecdoi_t2satrns(t, pp, pr, tr)
3691         struct isakmp_pl_t *t;
3692         struct saprop *pp;
3693         struct saproto *pr;
3694         struct satrns *tr;
3695 {
3696         struct isakmp_data *d, *prev;
3697         int flag, type;
3698         int error = -1;
3699         int life_t;
3700         int tlen;
3701 
3702         tr->trns_no = t->t_no;
3703         tr->trns_id = t->t_id;
3704 
3705         tlen = get_uint16(&t->h.len) - sizeof(*t);
3706         prev = (struct isakmp_data *)NULL;
3707         d = (struct isakmp_data *)(t + 1);
3708 
3709         /* default */
3710         life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
3711         pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3712         pp->lifebyte = 0;
3713         tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
3714 
3715         while (tlen > 0) {
3716 
3717                 type = get_uint16(&d->type) & ~ISAKMP_GEN_MASK;
3718                 flag = get_uint16(&d->type) & ISAKMP_GEN_MASK;
3719 
3720                 plog(PLOG_DEBUG, PLOGLOC, NULL,
3721                         "type=%s, flag=0x%04x, lorv=%s\n",
3722                         s_ipsecdoi_attr(type), flag,
3723                         s_ipsecdoi_attr_v(type, get_uint16(&d->lorv)));
3724 
3725                 switch (type) {
3726                 case IPSECDOI_ATTR_SA_LD_TYPE:
3727                 {
3728                         int type = get_uint16(&d->lorv);
3729                         switch (type) {
3730                         case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
3731                         case IPSECDOI_ATTR_SA_LD_TYPE_KB:
3732                                 life_t = type;
3733                                 break;
3734                         default:
3735                                 plog(PLOG_PROTOWARN, PLOGLOC, 0,
3736                                         "invalid life duration type. "
3737                                         "using default value.\n");
3738                                 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
3739                                 break;
3740                         }
3741                         break;
3742                 }
3743                 case IPSECDOI_ATTR_SA_LD:
3744                         if (prev == NULL
3745                          || (get_uint16(&prev->type) & ~ISAKMP_GEN_MASK) !=
3746                                         IPSECDOI_ATTR_SA_LD_TYPE) {
3747                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3748                                     "life duration must follow ltype\n");
3749                                 break;
3750                         }
3751 
3752                     {
3753                         uint32_t t;
3754                         rc_vchar_t *ld_buf = NULL;
3755 
3756                         if (flag) {
3757                                 /* i.e. ISAKMP_GEN_TV */
3758                                 ld_buf = rc_vmalloc(sizeof(d->lorv));
3759                                 if (ld_buf == NULL) {
3760                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3761                                             "failed to get LD buffer.\n");
3762                                         goto end;
3763                                 }
3764                                 memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
3765                         } else {
3766                                 int len = get_uint16(&d->lorv);
3767                                 /* i.e. ISAKMP_GEN_TLV */
3768                                 ld_buf = rc_vmalloc(len);
3769                                 if (ld_buf == NULL) {
3770                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3771                                             "failed to get LD buffer.\n");
3772                                         goto end;
3773                                 }
3774                                 memcpy(ld_buf->v, d + 1, len);
3775                         }
3776                         switch (life_t) {
3777                         case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
3778                                 t = ipsecdoi_set_ld(ld_buf);
3779                                 rc_vfree(ld_buf);
3780                                 if (t == 0) {
3781                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3782                                                 "invalid life duration.\n");
3783                                         goto end;
3784                                 }
3785                                 /* lifetime must be equal in a proposal. */
3786                                 if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
3787                                         pp->lifetime = t;
3788                                 else if (pp->lifetime != t) {
3789                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3790                                                 "lifetime mismatched "
3791                                                 "in a proposal, "
3792                                                 "prev:%ld curr:%lu.\n",
3793                                                 (long)pp->lifetime, (unsigned long)t);
3794                                         goto end;
3795                                 }
3796                                 break;
3797                         case IPSECDOI_ATTR_SA_LD_TYPE_KB:
3798                                 t = ipsecdoi_set_ld(ld_buf);
3799                                 rc_vfree(ld_buf);
3800                                 if (t == 0) {
3801                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3802                                                 "invalid life duration.\n");
3803                                         goto end;
3804                                 }
3805                                 /* lifebyte must be equal in a proposal. */
3806                                 if (pp->lifebyte == 0)
3807                                         pp->lifebyte = t;
3808                                 else if (pp->lifebyte != t) {
3809                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
3810                                                 "lifebyte mismatched "
3811                                                 "in a proposal, "
3812                                                 "prev:%ld curr:%lu.\n",
3813                                                 (long)pp->lifebyte, (unsigned long)t);
3814                                         goto end;
3815                                 }
3816                                 break;
3817                         default:
3818                                 rc_vfree(ld_buf);
3819                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3820                                         "invalid life type: %d\n", life_t);
3821                                 goto end;
3822                         }
3823                     }
3824                         break;
3825 
3826                 case IPSECDOI_ATTR_GRP_DESC:
3827                         /*
3828                          * RFC2407: 4.5 IPSEC Security Association Attributes
3829                          *   Specifies the Oakley Group to be used in a PFS QM
3830                          *   negotiation.  For a list of supported values, see
3831                          *   Appendix A of [IKE].
3832                          */
3833                         if (pp->pfs_group == 0)
3834                                 pp->pfs_group = get_uint16(&d->lorv);
3835                         else if (pp->pfs_group != get_uint16(&d->lorv)) {
3836                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3837                                         "pfs_group mismatched "
3838                                         "in a proposal.\n");
3839                                 goto end;
3840                         }
3841                         break;
3842 
3843                 case IPSECDOI_ATTR_ENC_MODE:
3844                         if (pr->encmode &&
3845                             pr->encmode != get_uint16(&d->lorv)) {
3846                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3847                                         "multiple encmode exist "
3848                                         "in a transform.\n");
3849                                 goto end;
3850                         }
3851                         pr->encmode = get_uint16(&d->lorv);
3852                         break;
3853 
3854                 case IPSECDOI_ATTR_AUTH:
3855                         if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
3856                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3857                                         "multiple authtype exist "
3858                                         "in a transform.\n");
3859                                 goto end;
3860                         }
3861                         tr->authtype = get_uint16(&d->lorv);
3862                         break;
3863 
3864                 case IPSECDOI_ATTR_KEY_LENGTH:
3865                         if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
3866                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3867                                         "key length defined but not ESP");
3868                                 goto end;
3869                         }
3870                         tr->encklen = get_uint16(&d->lorv);
3871                         break;
3872 
3873                 case IPSECDOI_ATTR_KEY_ROUNDS:
3874                 case IPSECDOI_ATTR_COMP_DICT_SIZE:
3875                 case IPSECDOI_ATTR_COMP_PRIVALG:
3876                 default:
3877                         break;
3878                 }
3879 
3880                 prev = d;
3881                 if (flag) {
3882                         tlen -= sizeof(*d);
3883                         d = (struct isakmp_data *)((char *)d + sizeof(*d));
3884                 } else {
3885                         tlen -= (sizeof(*d) + get_uint16(&d->lorv));
3886                         d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + get_uint16(&d->lorv));
3887                 }
3888         }
3889 
3890         error = 0;
3891 end:
3892         return error;
3893 }
3894 
3895 int
3896 ipsecdoi_authalg_rct2trnsid(rc_type alg)
3897 {
3898         switch (alg) {
3899         case RCT_ALG_HMAC_MD5:
3900                 return IPSECDOI_AH_MD5;
3901         case RCT_ALG_HMAC_SHA1:
3902                 return IPSECDOI_AH_SHA;
3903 #if 0
3904         case RCT_ALG_DES_MAC:
3905                 return IPSECDOI_AH_DES;
3906 #endif
3907         case RCT_ALG_KPDK_MD5:
3908                 return IPSECDOI_AH_MD5;
3909         case RCT_ALG_KPDK_SHA1:
3910                 return IPSECDOI_AH_SHA;
3911         default:
3912                 plog(PLOG_INTERR, PLOGLOC, 0,
3913                      "unsupported authentication algorithm for AH: %s\n",
3914                      rct2str(alg));
3915                 return -1;
3916         }
3917 }
3918 
3919 #if 0
3920 int
3921 ipsecdoi_authalg2trnsid(alg)
3922         int alg;
3923 {
3924         switch (alg) {
3925         case IPSECDOI_ATTR_AUTH_HMAC_MD5:
3926                 return IPSECDOI_AH_MD5;
3927         case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
3928                 return IPSECDOI_AH_SHA;
3929         case IPSECDOI_ATTR_AUTH_DES_MAC:
3930                 return IPSECDOI_AH_DES;
3931         case IPSECDOI_ATTR_AUTH_KPDK:
3932                 return IPSECDOI_AH_MD5; /* XXX */
3933         default:
3934                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
3935                         "invalid authentication algorithm:%d\n", alg);
3936         }
3937         return -1;
3938 }
3939 #endif
3940 
3941 #ifdef HAVE_GSSAPI
3942 struct isakmpsa *
3943 fixup_initiator_sa(match, received)
3944         struct isakmpsa *match, *received;
3945 {
3946         struct isakmpsa *newsa;
3947 
3948         if (received->gssid == NULL)
3949                 return match;
3950 
3951         newsa = newisakmpsa();
3952         memcpy(newsa, match, sizeof *newsa);
3953 
3954         if (match->dhgrp != NULL) {
3955                 newsa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
3956                 memcpy(newsa->dhgrp, match->dhgrp, sizeof (struct dhgroup));
3957         }
3958         newsa->next = NULL;
3959         newsa->rmconf = NULL;
3960 
3961         newsa->gssid = rc_vdup(received->gssid);
3962 
3963         return newsa;
3964 }
3965 #endif
3966 
3967 #if 0
3968 static int rm_idtype2doi[] = {
3969         IPSECDOI_ID_FQDN,
3970         IPSECDOI_ID_USER_FQDN,
3971         IPSECDOI_ID_KEY_ID,
3972         255,    /* it's type of "address"
3973                  * it expands into 4 types by another function. */
3974         IPSECDOI_ID_DER_ASN1_DN,
3975 };
3976 
3977 /*
3978  * convert idtype to DOI value.
3979  * OUT  255  : NG
3980  *      other: converted.
3981  */
3982 int
3983 idtype2doi(idtype)
3984         int idtype;
3985 {
3986         if (ARRAYLEN(rm_idtype2doi) > idtype)
3987                 return rm_idtype2doi[idtype];
3988         return 255;
3989 }
3990 
3991 int
3992 doi2idtype(doi)
3993         int doi;
3994 {
3995         switch(doi) {
3996         case IPSECDOI_ID_FQDN:
3997                 return(IDTYPE_FQDN);
3998         case IPSECDOI_ID_USER_FQDN:
3999                 return(IDTYPE_USERFQDN);
4000         case IPSECDOI_ID_KEY_ID:
4001                 return(IDTYPE_KEYID);
4002         case IPSECDOI_ID_DER_ASN1_DN:
4003                 return(IDTYPE_ASN1DN);
4004         case IPSECDOI_ID_IPV4_ADDR:
4005         case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4006         case IPSECDOI_ID_IPV6_ADDR:
4007         case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4008                 return(IDTYPE_ADDRESS);
4009         default:
4010                 plog(PLOG_PROTOWARN, PLOGLOC, 0,
4011                      "Improper idtype:%s\n",
4012                      s_ipsecdoi_ident(doi));
4013                 return(IDTYPE_ADDRESS); /* XXX */
4014         }
4015         /*NOTREACHED*/
4016 }
4017 #endif
4018