]> git.saurik.com Git - apple/ipsec.git/blame_incremental - ipsec-tools/racoon/ipsec_doi.c
ipsec-286.1.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / ipsec_doi.c
... / ...
CommitLineData
1/* $Id: ipsec_doi.c,v 1.26.2.16 2006/02/02 14:37:17 vanhu 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#ifndef HAVE_NETINET6_IPSEC
41#include <netinet/ipsec.h>
42#else
43#include <netinet6/ipsec.h>
44#endif
45
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49#include <errno.h>
50#include <netdb.h>
51#if TIME_WITH_SYS_TIME
52# include <sys/time.h>
53# include <time.h>
54#else
55# if HAVE_SYS_TIME_H
56# include <sys/time.h>
57# else
58# include <time.h>
59# endif
60#endif
61
62#include "var.h"
63#include "vmbuf.h"
64#include "misc.h"
65#include "plog.h"
66#include "debug.h"
67
68#include "cfparse_proto.h"
69#include "isakmp_var.h"
70#include "isakmp.h"
71#include "ipsec_doi.h"
72#include "oakley.h"
73#include "remoteconf.h"
74#include "localconf.h"
75#include "sockmisc.h"
76#include "handler.h"
77#include "policy.h"
78#include "algorithm.h"
79#include "sainfo.h"
80#include "proposal.h"
81#include "crypto_openssl.h"
82#include "crypto_cssm.h"
83#include "strnames.h"
84#include "gcmalloc.h"
85
86#ifdef ENABLE_NATT
87#include "nattraversal.h"
88#endif
89
90#ifdef ENABLE_HYBRID
91static int switch_authmethod(int);
92#endif
93
94int verbose_proposal_check = 1;
95
96static vchar_t *get_ph1approval (phase1_handle_t *, struct prop_pair **);
97void print_ph1mismatched (struct prop_pair *, struct isakmpsa *);
98static int t2isakmpsa (struct isakmp_pl_t *, struct isakmpsa *);
99static int cmp_aproppair_i (struct prop_pair *, struct prop_pair *);
100static struct prop_pair *get_ph2approval (phase2_handle_t *,
101 struct prop_pair **);
102static struct prop_pair *get_ph2approvalx (phase2_handle_t *,
103 struct prop_pair *);
104static void free_proppair0 (struct prop_pair *);
105
106static int get_transform (struct isakmp_pl_p *, struct prop_pair **, int *);
107static u_int32_t ipsecdoi_set_ld (vchar_t *);
108
109static int check_doi (u_int32_t);
110static int check_situation (u_int32_t);
111
112static int check_prot_main (int);
113static int check_prot_quick (int);
114static int (*check_protocol[]) (int) = {
115 check_prot_main, /* IPSECDOI_TYPE_PH1 */
116 check_prot_quick, /* IPSECDOI_TYPE_PH2 */
117 NULL, /* IPSECDOI_TYPE_IKEV2_PH1 */
118 NULL, /* IPSECDOI_TYPE_IKEV2_PH2 */
119};
120
121int check_spi_size (int, int);
122
123static int check_trns_isakmp (int);
124static int check_trns_ah (int);
125static int check_trns_esp (int);
126static int check_trns_ipcomp (int);
127static int (*check_transform[]) (int) = {
128 0,
129 check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */
130 check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */
131 check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
132 check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
133};
134
135static int check_attr_isakmp (struct isakmp_pl_t *);
136static int check_attr_ah (struct isakmp_pl_t *);
137static int check_attr_esp (struct isakmp_pl_t *);
138static int check_attr_ipsec (int, struct isakmp_pl_t *);
139static int check_attr_ipcomp (struct isakmp_pl_t *);
140static int (*check_attributes[]) (struct isakmp_pl_t *) = {
141 0,
142 check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */
143 check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */
144 check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
145 check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
146};
147
148int setph1prop (phase1_handle_t *, caddr_t);
149static int setph1trns (struct isakmpsa *, caddr_t);
150static int setph1attr (struct isakmpsa *, caddr_t);
151static vchar_t *setph2proposal0 (const phase2_handle_t *,
152 const struct saprop *, const struct saproto *);
153
154static vchar_t *getidval (int, vchar_t *);
155
156
157/*%%%*/
158/*
159 * check phase 1 SA payload.
160 * make new SA payload to be replyed not including general header.
161 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
162 * OUT:
163 * positive: the pointer to new buffer of SA payload.
164 * network byte order.
165 * NULL : error occurd.
166 */
167int
168ipsecdoi_checkph1proposal(sa, iph1)
169 vchar_t *sa;
170 phase1_handle_t *iph1;
171{
172 vchar_t *newsa; /* new SA payload approved. */
173 struct prop_pair **pair;
174
175 /* get proposal pair */
176 pair = get_proppair(sa, IPSECDOI_TYPE_PH1);
177 if (pair == NULL)
178 return -1;
179
180 /* check and get one SA for use */
181 newsa = get_ph1approval(iph1, pair);
182
183 free_proppair(pair);
184
185 if (newsa == NULL)
186 return -1;
187
188 iph1->sa_ret = newsa;
189
190 return 0;
191}
192
193/*
194 * acceptable check for remote configuration.
195 * return a new SA payload to be reply to peer.
196 */
197static vchar_t *
198get_ph1approval(iph1, pair)
199 phase1_handle_t *iph1;
200 struct prop_pair **pair;
201{
202 vchar_t *newsa;
203 struct isakmpsa *sa, tsa;
204 struct prop_pair *s, *p;
205 int prophlen;
206 int i;
207
208 if (iph1->approval) {
209 delisakmpsa(iph1->approval);
210 iph1->approval = NULL;
211 }
212
213 for (i = 0; i < MAXPROPPAIRLEN; i++) {
214 if (pair[i] == NULL)
215 continue;
216 for (s = pair[i]; s; s = s->next) {
217 prophlen =
218 sizeof(struct isakmp_pl_p) + s->prop->spi_size;
219
220 /* compare proposal and select one */
221 for (p = s; p; p = p->tnext) {
222 if ((sa = get_ph1approvalx(p,
223 iph1->rmconf->proposal, &tsa,
224 iph1->rmconf->pcheck_level)) != NULL)
225 goto found;
226 }
227 }
228 }
229
230 /*
231 * if there is no suitable proposal, racoon complains about all of
232 * mismatched items in those proposal.
233 */
234 if (verbose_proposal_check) {
235 for (i = 0; i < MAXPROPPAIRLEN; i++) {
236 if (pair[i] == NULL)
237 continue;
238 for (s = pair[i]; s; s = s->next) {
239 prophlen = sizeof(struct isakmp_pl_p)
240 + s->prop->spi_size;
241 for (p = s; p; p = p->tnext) {
242 print_ph1mismatched(p,
243 iph1->rmconf->proposal);
244 }
245 }
246 }
247 }
248 plog(ASL_LEVEL_ERR, "no suitable proposal found.\n");
249
250 return NULL;
251
252found:
253 plog(ASL_LEVEL_DEBUG, "an acceptable proposal found.\n");
254
255 /* check DH group settings */
256 if (sa->dhgrp) {
257 if (sa->dhgrp->prime && sa->dhgrp->gen1) {
258 /* it's ok */
259 goto saok;
260 }
261 plog(ASL_LEVEL_WARNING,
262 "invalid DH parameter found, use default.\n");
263 oakley_dhgrp_free(sa->dhgrp);
264 sa->dhgrp=NULL;
265 }
266
267 if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
268 sa->dhgrp = NULL;
269 racoon_free(sa);
270 return NULL;
271 }
272
273saok:
274 iph1->approval = sa;
275 if(iph1->approval) {
276 plog(ASL_LEVEL_DEBUG, "agreed on %s auth.\n",
277 s_oakley_attr_method(iph1->approval->authmethod));
278 }
279
280 newsa = get_sabyproppair(p, iph1);
281 if (newsa == NULL) {
282 delisakmpsa(iph1->approval);
283 iph1->approval = NULL;
284 }
285
286 return newsa;
287}
288
289/*
290 * compare peer's single proposal and all of my proposal.
291 * and select one if suiatable.
292 * p : one of peer's proposal.
293 * proposal: my proposals.
294 */
295struct isakmpsa *
296get_ph1approvalx(p, proposal, sap, check_level)
297 struct prop_pair *p;
298 struct isakmpsa *proposal, *sap;
299 int check_level;
300{
301 struct isakmp_pl_p *prop = p->prop;
302 struct isakmp_pl_t *trns = p->trns;
303 struct isakmpsa sa, *s, *tsap;
304 int authmethod;
305 int tsap_authmethod;
306
307 plog(ASL_LEVEL_DEBUG,
308 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
309 prop->p_no, s_ipsecdoi_proto(prop->proto_id),
310 prop->spi_size, prop->num_t);
311
312 plog(ASL_LEVEL_DEBUG,
313 "trns#=%d, trns-id=%s\n",
314 trns->t_no,
315 s_ipsecdoi_trns(prop->proto_id, trns->t_id));
316
317 tsap = sap != NULL ? sap : &sa;
318
319 memset(tsap, 0, sizeof(*tsap));
320 if (t2isakmpsa(trns, tsap) < 0)
321 return NULL;
322 for (s = proposal; s != NULL; s = s->next) {
323#ifdef ENABLE_HYBRID
324 authmethod = switch_authmethod(s->authmethod);
325 tsap_authmethod = switch_authmethod(tsap->authmethod);
326#else
327 authmethod = s->authmethod;
328 tsap_authmethod = tsap->authmethod;
329#endif
330 plog(ASL_LEVEL_DEBUG, "Compared: DB:Peer\n");
331 plog(ASL_LEVEL_DEBUG, "(version = %d:%d)\n",
332 s->version, tsap->version);
333 plog(ASL_LEVEL_DEBUG, "(lifetime = %ld:%ld)\n",
334 (long)s->lifetime, (long)tsap->lifetime);
335 plog(ASL_LEVEL_DEBUG, "(lifebyte = %zu:%zu)\n",
336 s->lifebyte, tsap->lifebyte);
337 plog(ASL_LEVEL_DEBUG, "enctype = %s:%s\n",
338 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
339 s->enctype),
340 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
341 tsap->enctype));
342 plog(ASL_LEVEL_DEBUG, "(encklen = %d:%d)\n",
343 s->encklen, tsap->encklen);
344 plog(ASL_LEVEL_DEBUG, "hashtype = %s:%s\n",
345 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
346 s->hashtype),
347 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
348 tsap->hashtype));
349 plog(ASL_LEVEL_DEBUG, "authmethod = %s:%s\n",
350 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
351 s->authmethod),
352 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
353 tsap->authmethod));
354 plog(ASL_LEVEL_DEBUG, "dh_group = %s:%s\n",
355 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
356 s->dh_group),
357 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
358 tsap->dh_group));
359#if 0
360 /* XXX to be considered ? */
361 if (tsap->lifebyte > s->lifebyte) ;
362#endif
363 /*
364 * if responder side and peer's key length in proposal
365 * is bigger than mine, it might be accepted.
366 */
367 if(tsap->enctype == s->enctype &&
368 (tsap->authmethod == authmethod || tsap_authmethod == authmethod) &&
369 tsap->hashtype == s->hashtype &&
370 tsap->dh_group == s->dh_group &&
371 tsap->encklen == s->encklen &&
372 tsap->version == s->version) {
373 switch(check_level) {
374 case PROP_CHECK_OBEY:
375 goto found;
376 break;
377
378 case PROP_CHECK_STRICT:
379 if ((tsap->lifetime > s->lifetime) ||
380 (tsap->lifebyte > s->lifebyte))
381 continue;
382 goto found;
383 break;
384
385 case PROP_CHECK_CLAIM:
386 if (tsap->lifetime < s->lifetime)
387 s->lifetime = tsap->lifetime;
388 if (tsap->lifebyte < s->lifebyte)
389 s->lifebyte = tsap->lifebyte;
390 goto found;
391 break;
392
393 case PROP_CHECK_EXACT:
394 if ((tsap->lifetime != s->lifetime) ||
395 (tsap->lifebyte != s->lifebyte))
396 continue;
397 goto found;
398 break;
399
400 default:
401 plog(ASL_LEVEL_ERR,
402 "Unexpected proposal_check value\n");
403 continue;
404 break;
405 }
406 }
407 }
408
409found:
410 if (tsap->dhgrp != NULL){
411 oakley_dhgrp_free(tsap->dhgrp);
412 tsap->dhgrp = NULL;
413 }
414
415 if ((s = dupisakmpsa(s)) != NULL) {
416 switch(check_level) {
417 case PROP_CHECK_OBEY:
418 s->lifetime = tsap->lifetime;
419 s->lifebyte = tsap->lifebyte;
420 break;
421
422 case PROP_CHECK_STRICT:
423 s->lifetime = tsap->lifetime;
424 s->lifebyte = tsap->lifebyte;
425 break;
426
427 case PROP_CHECK_CLAIM:
428 if (tsap->lifetime < s->lifetime)
429 s->lifetime = tsap->lifetime;
430 if (tsap->lifebyte < s->lifebyte)
431 s->lifebyte = tsap->lifebyte;
432 break;
433
434 default:
435 break;
436 }
437 // hack to get around cisco rekeys
438 if (tsap->authmethod != authmethod && tsap_authmethod == authmethod) {
439 s->authmethod = tsap->authmethod;
440 }
441 }
442 return s;
443}
444
445/*
446 * print all of items in peer's proposal which are mismatched to my proposal.
447 * p : one of peer's proposal.
448 * proposal: my proposals.
449 */
450void
451print_ph1mismatched(p, proposal)
452 struct prop_pair *p;
453 struct isakmpsa *proposal;
454{
455 struct isakmpsa sa, *s;
456
457 memset(&sa, 0, sizeof(sa));
458 if (t2isakmpsa(p->trns, &sa) < 0)
459 return;
460 for (s = proposal; s ; s = s->next) {
461 if (sa.enctype != s->enctype) {
462 plog(ASL_LEVEL_ERR,
463 "rejected enctype: "
464 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
465 "%s:%s\n",
466 s->prop_no, s->trns_no,
467 p->prop->p_no, p->trns->t_no,
468 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
469 s->enctype),
470 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
471 sa.enctype));
472 }
473 if (sa.authmethod != s->authmethod) {
474 plog(ASL_LEVEL_ERR,
475 "rejected authmethod: "
476 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
477 "%s:%s\n",
478 s->prop_no, s->trns_no,
479 p->prop->p_no, p->trns->t_no,
480 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
481 s->authmethod),
482 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
483 sa.authmethod));
484 }
485 if (sa.hashtype != s->hashtype) {
486 plog(ASL_LEVEL_ERR,
487 "rejected hashtype: "
488 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
489 "%s:%s\n",
490 s->prop_no, s->trns_no,
491 p->prop->p_no, p->trns->t_no,
492 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
493 s->hashtype),
494 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
495 sa.hashtype));
496 }
497 if (sa.prf != s->prf ||
498 sa.prfklen != s->prfklen) {
499 plog(ASL_LEVEL_ERR,
500 "rejected prf: "
501 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
502 "%s.%d:%s.%d\n",
503 s->prop_no, s->trns_no,
504 p->prop->p_no, p->trns->t_no,
505 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
506 s->prf),
507 s->prfklen,
508 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
509 sa.prf),
510 sa.prfklen);
511 }
512 if (sa.dh_group != s->dh_group) {
513 plog(ASL_LEVEL_ERR,
514 "rejected dh_group: "
515 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
516 "%s:%s\n",
517 s->prop_no, s->trns_no,
518 p->prop->p_no, p->trns->t_no,
519 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
520 s->dh_group),
521 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
522 sa.dh_group));
523 }
524 }
525
526 if (sa.dhgrp != NULL){
527 oakley_dhgrp_free(sa.dhgrp);
528 sa.dhgrp=NULL;
529 }
530}
531
532/*
533 * get ISAKMP data attributes
534 */
535static int
536t2isakmpsa(trns, sa)
537 struct isakmp_pl_t *trns;
538 struct isakmpsa *sa;
539{
540 struct isakmp_data *d, *prev;
541 int flag, type;
542 int error = -1;
543 int life_t;
544 int keylen = 0;
545 vchar_t *val = NULL;
546 int len, tlen;
547 u_char *p;
548
549 tlen = ntohs(trns->h.len) - sizeof(*trns);
550 prev = (struct isakmp_data *)NULL;
551 d = (struct isakmp_data *)(trns + 1);
552
553 /* default */
554 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
555 sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
556 sa->lifebyte = 0;
557 sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
558 if (!sa->dhgrp)
559 goto err;
560
561 while (tlen > 0) {
562
563 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
564 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
565
566 plog(ASL_LEVEL_DEBUG,
567 "type=%s, flag=0x%04x, lorv=%s\n",
568 s_oakley_attr(type), flag,
569 s_oakley_attr_v(type, ntohs(d->lorv)));
570
571 /* get variable-sized item */
572 switch (type) {
573 case OAKLEY_ATTR_GRP_PI:
574 case OAKLEY_ATTR_GRP_GEN_ONE:
575 case OAKLEY_ATTR_GRP_GEN_TWO:
576 case OAKLEY_ATTR_GRP_CURVE_A:
577 case OAKLEY_ATTR_GRP_CURVE_B:
578 case OAKLEY_ATTR_SA_LD:
579 case OAKLEY_ATTR_GRP_ORDER:
580 if (flag) { /*TV*/
581 len = 2;
582 p = (u_char *)&d->lorv;
583 } else { /*TLV*/
584 len = ntohs(d->lorv);
585 if (len > tlen) {
586 plog(ASL_LEVEL_ERR,
587 "invalid ISAKMP-SA attr, attr-len %d, overall-len %d\n",
588 len, tlen);
589 return -1;
590 }
591 p = (u_char *)(d + 1);
592 }
593 val = vmalloc(len);
594 if (!val)
595 return -1;
596 memcpy(val->v, p, len);
597 break;
598
599 default:
600 break;
601 }
602
603 switch (type) {
604 case OAKLEY_ATTR_ENC_ALG:
605 sa->enctype = (u_int16_t)ntohs(d->lorv);
606 break;
607
608 case OAKLEY_ATTR_HASH_ALG:
609 sa->hashtype = (u_int16_t)ntohs(d->lorv);
610 break;
611
612 case OAKLEY_ATTR_AUTH_METHOD:
613 sa->authmethod = ntohs(d->lorv);
614 break;
615
616 case OAKLEY_ATTR_GRP_DESC:
617 sa->dh_group = (u_int16_t)ntohs(d->lorv);
618 break;
619
620 case OAKLEY_ATTR_GRP_TYPE:
621 {
622 int type = (int)ntohs(d->lorv);
623 if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
624 sa->dhgrp->type = type;
625 else
626 return -1;
627 break;
628 }
629 case OAKLEY_ATTR_GRP_PI:
630 sa->dhgrp->prime = val;
631 break;
632
633 case OAKLEY_ATTR_GRP_GEN_ONE:
634 vfree(val);
635 if (!flag)
636 sa->dhgrp->gen1 = ntohs(d->lorv);
637 else {
638 int len = ntohs(d->lorv);
639 sa->dhgrp->gen1 = 0;
640 if (len > 4)
641 return -1;
642 memcpy(&sa->dhgrp->gen1, d + 1, len);
643 sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
644 }
645 break;
646
647 case OAKLEY_ATTR_GRP_GEN_TWO:
648 vfree(val);
649 if (!flag)
650 sa->dhgrp->gen2 = ntohs(d->lorv);
651 else {
652 int len = ntohs(d->lorv);
653 sa->dhgrp->gen2 = 0;
654 if (len > 4)
655 return -1;
656 memcpy(&sa->dhgrp->gen2, d + 1, len);
657 sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
658 }
659 break;
660
661 case OAKLEY_ATTR_GRP_CURVE_A:
662 sa->dhgrp->curve_a = val;
663 break;
664
665 case OAKLEY_ATTR_GRP_CURVE_B:
666 sa->dhgrp->curve_b = val;
667 break;
668
669 case OAKLEY_ATTR_SA_LD_TYPE:
670 {
671 int type = (int)ntohs(d->lorv);
672 switch (type) {
673 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
674 case OAKLEY_ATTR_SA_LD_TYPE_KB:
675 life_t = type;
676 break;
677 default:
678 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
679 break;
680 }
681 break;
682 }
683 case OAKLEY_ATTR_SA_LD:
684 if (!prev
685 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
686 OAKLEY_ATTR_SA_LD_TYPE) {
687 plog(ASL_LEVEL_ERR,
688 "life duration must follow ltype\n");
689 break;
690 }
691
692 switch (life_t) {
693 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
694 sa->lifetime = ipsecdoi_set_ld(val);
695 vfree(val);
696 if (sa->lifetime == 0) {
697 plog(ASL_LEVEL_ERR,
698 "invalid life duration.\n");
699 goto err;
700 }
701 break;
702 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
703 sa->lifebyte = ipsecdoi_set_ld(val);
704 vfree(val);
705 if (sa->lifebyte == 0) {
706 plog(ASL_LEVEL_ERR,
707 "invalid life duration.\n");
708 goto err;
709 }
710 break;
711 default:
712 vfree(val);
713 plog(ASL_LEVEL_ERR,
714 "invalid life type: %d\n", life_t);
715 goto err;
716 }
717 break;
718
719 case OAKLEY_ATTR_KEY_LEN:
720 {
721 int len = ntohs(d->lorv);
722 if (len % 8 != 0) {
723 plog(ASL_LEVEL_ERR,
724 "keylen %d: not multiple of 8\n",
725 len);
726 goto err;
727 }
728 sa->encklen = (u_int16_t)len;
729 keylen++;
730 break;
731 }
732 case OAKLEY_ATTR_PRF:
733 case OAKLEY_ATTR_FIELD_SIZE:
734 /* unsupported */
735 break;
736
737 case OAKLEY_ATTR_GRP_ORDER:
738 sa->dhgrp->order = val;
739 break;
740
741 default:
742 break;
743 }
744
745 prev = d;
746 if (flag) {
747 tlen -= sizeof(*d);
748 d = (struct isakmp_data *)((char *)d + sizeof(*d));
749 } else {
750 tlen -= (sizeof(*d) + ntohs(d->lorv));
751 d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
752 }
753 }
754
755 /* key length must not be specified on some algorithms */
756 if (keylen) {
757 if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
758 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
759 plog(ASL_LEVEL_ERR,
760 "keylen must not be specified "
761 "for encryption algorithm %d\n",
762 sa->enctype);
763 return -1;
764 }
765 }
766
767 return 0;
768err:
769 return error;
770}
771
772/*%%%*/
773/*
774 * check phase 2 SA payload and select single proposal.
775 * make new SA payload to be replyed not including general header.
776 * This function is called by responder only.
777 * OUT:
778 * 0: succeed.
779 * -1: error occured.
780 */
781int
782ipsecdoi_selectph2proposal(iph2)
783 phase2_handle_t *iph2;
784{
785 struct prop_pair **pair;
786 struct prop_pair *ret;
787
788 /* get proposal pair */
789 pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
790 if (pair == NULL)
791 return -1;
792
793 /* check and select a proposal. */
794 ret = get_ph2approval(iph2, pair);
795 free_proppair(pair);
796 if (ret == NULL)
797 return -1;
798
799 /* make a SA to be replayed. */
800 /* SPI must be updated later. */
801 iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
802 free_proppair0(ret);
803 if (iph2->sa_ret == NULL)
804 return -1;
805
806 return 0;
807}
808
809/*
810 * check phase 2 SA payload returned from responder.
811 * This function is called by initiator only.
812 * OUT:
813 * 0: valid.
814 * -1: invalid.
815 */
816int
817ipsecdoi_checkph2proposal(iph2)
818 phase2_handle_t *iph2;
819{
820 struct prop_pair **rpair = NULL, **spair = NULL;
821 struct prop_pair *p;
822 int i, n, num;
823 int error = -1;
824 vchar_t *sa_ret = NULL;
825
826 /* get proposal pair of SA sent. */
827 spair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
828 if (spair == NULL) {
829 plog(ASL_LEVEL_ERR,
830 "failed to get prop pair.\n");
831 goto end;
832 }
833
834 /* XXX should check the number of transform */
835
836 /* get proposal pair of SA replayed */
837 rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
838 if (rpair == NULL) {
839 plog(ASL_LEVEL_ERR,
840 "failed to get prop pair.\n");
841 goto end;
842 }
843
844 /* check proposal is only one ? */
845 n = 0;
846 num = 0;
847 for (i = 0; i < MAXPROPPAIRLEN; i++) {
848 if (rpair[i]) {
849 n = i;
850 num++;
851 }
852 }
853 if (num == 0) {
854 plog(ASL_LEVEL_ERR,
855 "no proposal received.\n");
856 goto end;
857 }
858 if (num != 1) {
859 plog(ASL_LEVEL_ERR,
860 "some proposals received.\n");
861 goto end;
862 }
863
864 if (spair[n] == NULL) {
865 plog(ASL_LEVEL_WARNING,
866 "invalid proposal number:%d received.\n", i);
867 }
868
869
870 if (rpair[n]->tnext != NULL) {
871 plog(ASL_LEVEL_ERR,
872 "multi transforms replyed.\n");
873 goto end;
874 }
875
876 if (cmp_aproppair_i(rpair[n], spair[n])) {
877 plog(ASL_LEVEL_ERR,
878 "proposal mismathed.\n");
879 goto end;
880 }
881
882 /*
883 * check and select a proposal.
884 * ensure that there is no modification of the proposal by
885 * cmp_aproppair_i()
886 */
887 p = get_ph2approval(iph2, rpair);
888 if (p == NULL)
889 goto end;
890
891 /* make a SA to be replayed. */
892 sa_ret = iph2->sa_ret;
893 iph2->sa_ret = get_sabyproppair(p, iph2->ph1);
894 free_proppair0(p);
895 if (iph2->sa_ret == NULL)
896 goto end;
897
898 error = 0;
899
900end:
901 if (rpair)
902 free_proppair(rpair);
903 if (spair)
904 free_proppair(spair);
905 if (sa_ret)
906 vfree(sa_ret);
907
908 return error;
909}
910
911/*
912 * compare two prop_pair which is assumed to have same proposal number.
913 * the case of bundle or single SA, NOT multi transforms.
914 * a: a proposal that is multi protocols and single transform, usually replyed.
915 * b: a proposal that is multi protocols and multi transform, usually sent.
916 * NOTE: this function is for initiator.
917 * OUT
918 * 0: equal
919 * 1: not equal
920 * XXX cannot understand the comment!
921 */
922static int
923cmp_aproppair_i(a, b)
924 struct prop_pair *a, *b;
925{
926 struct prop_pair *p, *q, *r;
927 int len;
928
929 for (p = a, q = b; p && q; p = p->next, q = q->next) {
930 for (r = q; r; r = r->tnext) {
931 /* compare trns */
932 if (p->trns->t_no == r->trns->t_no)
933 break;
934 }
935 if (!r) {
936 /* no suitable transform found */
937 plog(ASL_LEVEL_ERR,
938 "no suitable transform found.\n");
939 return -1;
940 }
941
942 /* compare prop */
943 if (p->prop->p_no != r->prop->p_no) {
944 plog(ASL_LEVEL_WARNING,
945 "proposal #%d mismatched, "
946 "expected #%d.\n",
947 r->prop->p_no, p->prop->p_no);
948 /*FALLTHROUGH*/
949 }
950
951 if (p->prop->proto_id != r->prop->proto_id) {
952 plog(ASL_LEVEL_ERR,
953 "proto_id mismathed: my:%d peer:%d\n",
954 r->prop->proto_id, p->prop->proto_id);
955 return -1;
956 }
957
958 if (p->prop->proto_id != r->prop->proto_id) {
959 plog(ASL_LEVEL_ERR,
960 "invalid spi size: %d.\n",
961 p->prop->proto_id);
962 return -1;
963 }
964
965 /* check #of transforms */
966 if (p->prop->num_t != 1) {
967 plog(ASL_LEVEL_WARNING,
968 "#of transform is %d, "
969 "but expected 1.\n", p->prop->num_t);
970 /*FALLTHROUGH*/
971 }
972
973 if (p->trns->t_id != r->trns->t_id) {
974 plog(ASL_LEVEL_WARNING,
975 "transform number has been modified.\n");
976 /*FALLTHROUGH*/
977 }
978 if (p->trns->reserved != r->trns->reserved) {
979 plog(ASL_LEVEL_WARNING,
980 "reserved field should be zero.\n");
981 /*FALLTHROUGH*/
982 }
983
984 /* compare attribute */
985 len = ntohs(r->trns->h.len) - sizeof(*p->trns);
986 if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
987 plog(ASL_LEVEL_WARNING,
988 "attribute has been modified.\n");
989 /*FALLTHROUGH*/
990 }
991 }
992 if ((p && !q) || (!p && q)) {
993 /* # of protocols mismatched */
994 plog(ASL_LEVEL_ERR,
995 "#of protocols mismatched.\n");
996 return -1;
997 }
998
999 return 0;
1000}
1001
1002/*
1003 * acceptable check for policy configuration.
1004 * return a new SA payload to be reply to peer.
1005 */
1006static struct prop_pair *
1007get_ph2approval(iph2, pair)
1008 phase2_handle_t *iph2;
1009 struct prop_pair **pair;
1010{
1011 struct prop_pair *ret;
1012 int i;
1013
1014 iph2->approval = NULL;
1015
1016 plog(ASL_LEVEL_DEBUG,
1017 "begin compare proposals.\n");
1018
1019 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1020 if (pair[i] == NULL)
1021 continue;
1022 plog(ASL_LEVEL_DEBUG,
1023 "pair[%d]: %p\n", i, pair[i]);
1024 print_proppair(ASL_LEVEL_DEBUG, pair[i]);;
1025
1026 /* compare proposal and select one */
1027 ret = get_ph2approvalx(iph2, pair[i]);
1028 if (ret != NULL) {
1029 /* found */
1030 return ret;
1031 }
1032 }
1033
1034 plog(ASL_LEVEL_ERR, "no suitable policy found.\n");
1035
1036 return NULL;
1037}
1038
1039/*
1040 * compare my proposal and peers just one proposal.
1041 * set a approval.
1042 */
1043static struct prop_pair *
1044get_ph2approvalx(iph2, pp)
1045 phase2_handle_t *iph2;
1046 struct prop_pair *pp;
1047{
1048 struct prop_pair *ret = NULL;
1049 struct saprop *pr0, *pr = NULL;
1050 struct saprop *q1, *q2;
1051
1052 pr0 = aproppair2saprop(pp);
1053 if (pr0 == NULL)
1054 return NULL;
1055
1056 for (q1 = pr0; q1; q1 = q1->next) {
1057 for (q2 = iph2->proposal; q2; q2 = q2->next) {
1058 plog(ASL_LEVEL_DEBUG,
1059 "peer's single bundle:\n");
1060 printsaprop0(ASL_LEVEL_DEBUG, q1);
1061 plog(ASL_LEVEL_DEBUG,
1062 "my single bundle:\n");
1063 printsaprop0(ASL_LEVEL_DEBUG, q2);
1064
1065 pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
1066 if (pr != NULL)
1067 goto found;
1068
1069 plog(ASL_LEVEL_ERR,
1070 "not matched\n");
1071 }
1072 }
1073 /* no proposal matching */
1074err:
1075 if (pr0 != NULL) {
1076 flushsaprop(pr0);
1077 pr0 = NULL;
1078 }
1079 return NULL;
1080
1081found:
1082 if (pr0 != NULL) {
1083 flushsaprop(pr0);
1084 pr0 = NULL;
1085 }
1086 plog(ASL_LEVEL_DEBUG, "matched\n");
1087 iph2->approval = pr;
1088
1089 {
1090 struct saproto *sp;
1091 struct prop_pair *p, *x;
1092 struct prop_pair *n = NULL;
1093
1094 ret = NULL;
1095
1096 for (p = pp; p; p = p->next) {
1097 /*
1098 * find a proposal with matching proto_id.
1099 * we have analyzed validity already, in cmpsaprop_alloc().
1100 */
1101 for (sp = pr->head; sp; sp = sp->next) {
1102 if (sp->proto_id == p->prop->proto_id)
1103 break;
1104 }
1105 if (!sp)
1106 goto err;
1107 if (sp->head->next)
1108 goto err; /* XXX */
1109
1110 for (x = p; x; x = x->tnext)
1111 if (sp->head->trns_no == x->trns->t_no)
1112 break;
1113 if (!x)
1114 goto err; /* XXX */
1115
1116 n = racoon_calloc(1, sizeof(struct prop_pair));
1117 if (n == NULL) {
1118 plog(ASL_LEVEL_ERR,
1119 "failed to get buffer.\n");
1120 goto err;
1121 }
1122
1123 n->prop = x->prop;
1124 n->trns = x->trns;
1125
1126 /* need to preserve the order */
1127 for (x = ret; x && x->next; x = x->next)
1128 ;
1129 if (x && x->prop == n->prop) {
1130 for (/*nothing*/; x && x->tnext; x = x->tnext)
1131 ;
1132 x->tnext = n;
1133 } else {
1134 if (x)
1135 x->next = n;
1136 else {
1137 ret = n;
1138 }
1139 }
1140
1141 /* #of transforms should be updated ? */
1142 }
1143 }
1144
1145 return ret;
1146}
1147
1148void
1149free_proppair(pair)
1150 struct prop_pair **pair;
1151{
1152 int i;
1153
1154 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1155 free_proppair0(pair[i]);
1156 pair[i] = NULL;
1157 }
1158 racoon_free(pair);
1159}
1160
1161static void
1162free_proppair0(pair)
1163 struct prop_pair *pair;
1164{
1165 struct prop_pair *p, *q, *r, *s;
1166
1167 p = pair;
1168 while (p) {
1169 q = p->next;
1170 r = p;
1171 while (r) {
1172 s = r->tnext;
1173 racoon_free(r);
1174 r = s;
1175 }
1176 p = q;
1177 }
1178}
1179
1180/*
1181 * get proposal pairs from SA payload.
1182 * tiny check for proposal payload.
1183 */
1184struct prop_pair **
1185get_proppair(sa, mode)
1186 vchar_t *sa;
1187 int mode;
1188{
1189 struct prop_pair **pair = NULL;
1190 int num_p = 0; /* number of proposal for use */
1191 int tlen;
1192 caddr_t bp;
1193 int i;
1194
1195 //plogdump(ASL_LEVEL_DEBUG, sa->v, sa->l, "total SA len=%zu\n", sa->l);
1196
1197 if (mode == IPSECDOI_TYPE_PH1 || mode == IPSECDOI_TYPE_PH2) {
1198 // IKEv1
1199 struct ipsecdoi_sa_b *sab = ALIGNED_CAST(__typeof__(sab))sa->v;
1200
1201
1202 /* check SA payload size */
1203 if (sa->l < sizeof(*sab)) {
1204 plog(ASL_LEVEL_ERR,
1205 "Invalid SA length = %zu.\n", sa->l);
1206 goto bad;
1207 }
1208
1209 /* check DOI */
1210 if (check_doi(ntohl(sab->doi)) < 0)
1211 goto bad;
1212
1213 /* check SITUATION */
1214 if (check_situation(ntohl(sab->sit)) < 0)
1215 goto bad;
1216
1217 bp = (caddr_t)(sab + 1);
1218 tlen = sa->l - sizeof(*sab);
1219 } else {
1220 bp = (__typeof__(bp))sa->v;
1221 tlen = sa->l;
1222 }
1223
1224 pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
1225 if (pair == NULL) {
1226 plog(ASL_LEVEL_ERR,
1227 "failed to get buffer.\n");
1228 goto bad;
1229 }
1230
1231 {
1232 struct isakmp_pl_p *prop;
1233 int proplen;
1234 vchar_t *pbuf = NULL;
1235 struct isakmp_parse_t *pa;
1236
1237 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
1238 if (pbuf == NULL)
1239 goto bad;
1240
1241 for (pa = ALIGNED_CAST(struct isakmp_parse_t *)pbuf->v;
1242 pa->type != ISAKMP_NPTYPE_NONE;
1243 pa++) {
1244 /* check the value of next payload */
1245 if (pa->type != ISAKMP_NPTYPE_P) {
1246 plog(ASL_LEVEL_ERR,
1247 "Invalid payload type=%u\n", pa->type);
1248 vfree(pbuf);
1249 goto bad;
1250 }
1251
1252 prop = (struct isakmp_pl_p *)pa->ptr;
1253 proplen = pa->len;
1254
1255 plog(ASL_LEVEL_DEBUG,
1256 "proposal #%u len=%d\n", prop->p_no, proplen);
1257
1258 if (proplen == 0) {
1259 plog(ASL_LEVEL_ERR,
1260 "invalid proposal with length %d\n", proplen);
1261 vfree(pbuf);
1262 goto bad;
1263 }
1264
1265 /* check Protocol ID */
1266 if (!check_protocol[mode]) {
1267 plog(ASL_LEVEL_ERR,
1268 "unsupported mode %d\n", mode);
1269 continue;
1270 }
1271
1272 if (check_protocol[mode](prop->proto_id) < 0)
1273 continue;
1274
1275 /* check SPI length when IKE. */
1276 if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
1277 continue;
1278
1279 /* get transform */
1280 if (get_transform(prop, pair, &num_p) < 0) {
1281 vfree(pbuf);
1282 goto bad;
1283 }
1284 }
1285 vfree(pbuf);
1286 pbuf = NULL;
1287 }
1288
1289 {
1290 int notrans, nprop;
1291 struct prop_pair *p, *q;
1292
1293 /* check for proposals with no transforms */
1294 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1295 if (!pair[i])
1296 continue;
1297
1298 plog(ASL_LEVEL_DEBUG, "pair %d:\n", i);
1299 print_proppair(ASL_LEVEL_DEBUG, pair[i]);
1300
1301 notrans = nprop = 0;
1302 for (p = pair[i]; p; p = p->next) {
1303 if (p->trns == NULL) {
1304 notrans++;
1305 break;
1306 }
1307 for (q = p; q; q = q->tnext)
1308 nprop++;
1309 }
1310
1311#if 0
1312 /*
1313 * XXX at this moment, we cannot accept proposal group
1314 * with multiple proposals. this should be fixed.
1315 */
1316 if (pair[i]->next) {
1317 plog(ASL_LEVEL_WARNING,
1318 "proposal #%u ignored "
1319 "(multiple proposal not supported)\n",
1320 pair[i]->prop->p_no);
1321 notrans++;
1322 }
1323#endif
1324
1325 if (notrans) {
1326 for (p = pair[i]; p; p = q) {
1327 q = p->next;
1328 racoon_free(p);
1329 }
1330 pair[i] = NULL;
1331 num_p--;
1332 } else {
1333 plog(ASL_LEVEL_DEBUG,
1334 "proposal #%u: %d transform\n",
1335 pair[i]->prop->p_no, nprop);
1336 }
1337 }
1338 }
1339
1340 /* bark if no proposal is found. */
1341 if (num_p <= 0) {
1342 plog(ASL_LEVEL_ERR,
1343 "no Proposal found.\n");
1344 goto bad;
1345 }
1346
1347 return pair;
1348bad:
1349 if (pair != NULL)
1350 racoon_free(pair);
1351 return NULL;
1352}
1353
1354/*
1355 * check transform payload.
1356 * OUT:
1357 * positive: return the pointer to the payload of valid transform.
1358 * 0 : No valid transform found.
1359 */
1360static int
1361get_transform(prop, pair, num_p)
1362 struct isakmp_pl_p *prop;
1363 struct prop_pair **pair;
1364 int *num_p;
1365{
1366 int tlen; /* total length of all transform in a proposal */
1367 caddr_t bp;
1368 struct isakmp_pl_t *trns;
1369 int trnslen;
1370 vchar_t *pbuf = NULL;
1371 struct isakmp_parse_t *pa;
1372 struct prop_pair *p = NULL, *q;
1373 int num_t;
1374
1375 bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
1376 tlen = ntohs(prop->h.len)
1377 - (sizeof(struct isakmp_pl_p) + prop->spi_size);
1378 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
1379 if (pbuf == NULL)
1380 return -1;
1381
1382 /* check and get transform for use */
1383 num_t = 0;
1384 for (pa = ALIGNED_CAST(struct isakmp_parse_t *)pbuf->v;
1385 pa->type != ISAKMP_NPTYPE_NONE;
1386 pa++) {
1387
1388 num_t++;
1389
1390 /* check the value of next payload */
1391 if (pa->type != ISAKMP_NPTYPE_T) {
1392 plog(ASL_LEVEL_ERR,
1393 "Invalid payload type=%u\n", pa->type);
1394 break;
1395 }
1396
1397 trns = (struct isakmp_pl_t *)pa->ptr;
1398 trnslen = pa->len;
1399
1400 plog(ASL_LEVEL_DEBUG,
1401 "transform #%u len=%u\n", trns->t_no, trnslen);
1402
1403 /* check transform ID */
1404 if (prop->proto_id >= ARRAYLEN(check_transform)) {
1405 plog(ASL_LEVEL_WARNING,
1406 "unsupported proto_id %u\n",
1407 prop->proto_id);
1408 continue;
1409 }
1410 if (prop->proto_id >= ARRAYLEN(check_attributes)) {
1411 plog(ASL_LEVEL_WARNING,
1412 "unsupported proto_id %u\n",
1413 prop->proto_id);
1414 continue;
1415 }
1416
1417 if (!check_transform[prop->proto_id]
1418 || !check_attributes[prop->proto_id]) {
1419 plog(ASL_LEVEL_WARNING,
1420 "unsupported proto_id %u\n",
1421 prop->proto_id);
1422 continue;
1423 }
1424 if (check_transform[prop->proto_id](trns->t_id) < 0)
1425 continue;
1426
1427 /* check data attributes */
1428 if (check_attributes[prop->proto_id](trns) != 0)
1429 continue;
1430
1431 p = racoon_calloc(1, sizeof(*p));
1432 if (p == NULL) {
1433 plog(ASL_LEVEL_ERR,
1434 "failed to get buffer.\n");
1435 vfree(pbuf);
1436 return -1;
1437 }
1438 p->prop = prop;
1439 p->trns = trns;
1440
1441 /* need to preserve the order */
1442 for (q = pair[prop->p_no]; q && q->next; q = q->next)
1443 ;
1444 if (q && q->prop == p->prop) {
1445 for (/*nothing*/; q && q->tnext; q = q->tnext)
1446 ;
1447 q->tnext = p;
1448 } else {
1449 if (q)
1450 q->next = p;
1451 else {
1452 pair[prop->p_no] = p;
1453 (*num_p)++;
1454 }
1455 }
1456 }
1457
1458 vfree(pbuf);
1459
1460 return 0;
1461}
1462
1463/*
1464 * make a new SA payload from prop_pair.
1465 * NOTE: this function clears the spi value.
1466 */
1467vchar_t *
1468get_sabyproppair(pair, iph1)
1469 struct prop_pair *pair;
1470 phase1_handle_t *iph1;
1471{
1472 vchar_t *newsa;
1473 int newtlen;
1474 u_int8_t *np_p = NULL;
1475 struct prop_pair *p;
1476 int prophlen, trnslen;
1477 caddr_t bp;
1478
1479 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
1480 newtlen = sizeof(struct ipsecdoi_sa_b);
1481 } else {
1482 newtlen = 0;
1483 }
1484 for (p = pair; p; p = p->next) {
1485 newtlen += sizeof(struct isakmp_pl_p);
1486 newtlen += p->prop->spi_size;
1487 newtlen += ntohs(p->trns->h.len);
1488 }
1489
1490 newsa = vmalloc(newtlen);
1491 if (newsa == NULL) {
1492 plog(ASL_LEVEL_ERR, "failed to get newsa.\n");
1493 return NULL;
1494 }
1495 bp = newsa->v;
1496
1497 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1498
1499 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
1500 /* update some of values in SA header */
1501 (ALIGNED_CAST(struct ipsecdoi_sa_b *)bp)->doi = htonl(iph1->rmconf->doitype);
1502 (ALIGNED_CAST(struct ipsecdoi_sa_b *)bp)->sit = htonl(iph1->rmconf->sittype);
1503 bp += sizeof(struct ipsecdoi_sa_b);
1504 }
1505
1506 /* create proposal payloads */
1507 for (p = pair; p; p = p->next) {
1508 prophlen = sizeof(struct isakmp_pl_p)
1509 + p->prop->spi_size;
1510 trnslen = ntohs(p->trns->h.len);
1511
1512 if (np_p)
1513 *np_p = ISAKMP_NPTYPE_P;
1514
1515 /* create proposal */
1516
1517 memcpy(bp, p->prop, prophlen);
1518 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1519 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1520 ((struct isakmp_pl_p *)bp)->num_t = 1;
1521 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1522 memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
1523 bp += prophlen;
1524
1525 /* create transform */
1526 memcpy(bp, p->trns, trnslen);
1527 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1528 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1529 bp += trnslen;
1530 }
1531
1532 return newsa;
1533}
1534
1535/*
1536 * update responder's spi
1537 */
1538int
1539ipsecdoi_updatespi(iph2)
1540 phase2_handle_t *iph2;
1541{
1542 struct prop_pair **pair, *p;
1543 struct saprop *pp;
1544 struct saproto *pr;
1545 int i;
1546 int error = -1;
1547 u_int8_t *spi;
1548
1549 pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
1550 if (pair == NULL)
1551 return -1;
1552 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1553 if (pair[i])
1554 break;
1555 }
1556 if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
1557 /* multiple transform must be filtered by selectph2proposal.*/
1558 goto end;
1559 }
1560
1561 pp = iph2->approval;
1562
1563 /* create proposal payloads */
1564 for (p = pair[i]; p; p = p->next) {
1565 /*
1566 * find a proposal/transform with matching proto_id/t_id.
1567 * we have analyzed validity already, in cmpsaprop_alloc().
1568 */
1569 for (pr = pp->head; pr; pr = pr->next) {
1570 if (p->prop->proto_id == pr->proto_id &&
1571 p->trns->t_id == pr->head->trns_id) {
1572 break;
1573 }
1574 }
1575 if (!pr)
1576 goto end;
1577
1578 /*
1579 * XXX SPI bits are left-filled, for use with IPComp.
1580 * we should be switching to variable-length spi field...
1581 */
1582 spi = (u_int8_t *)&pr->spi;
1583 spi += sizeof(pr->spi);
1584 spi -= pr->spisize;
1585 memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
1586 }
1587
1588 error = 0;
1589end:
1590 free_proppair(pair);
1591 return error;
1592}
1593
1594/*
1595 * make a new SA payload from prop_pair.
1596 */
1597vchar_t *
1598get_sabysaprop(pp0, sa0)
1599 struct saprop *pp0;
1600 vchar_t *sa0;
1601{
1602 struct prop_pair **pair = NULL;
1603 vchar_t *newsa = NULL;
1604 int newtlen;
1605 u_int8_t *np_p = NULL;
1606 struct prop_pair *p = NULL;
1607 struct saprop *pp;
1608 struct saproto *pr;
1609 struct satrns *tr;
1610 int prophlen, trnslen;
1611 caddr_t bp;
1612 int error = -1;
1613
1614 /* get proposal pair */
1615 pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
1616 if (pair == NULL)
1617 goto out;
1618
1619 newtlen = sizeof(struct ipsecdoi_sa_b);
1620 for (pp = pp0; pp; pp = pp->next) {
1621
1622 if (pair[pp->prop_no] == NULL)
1623 goto out;
1624
1625 for (pr = pp->head; pr; pr = pr->next) {
1626 newtlen += (sizeof(struct isakmp_pl_p)
1627 + pr->spisize);
1628
1629 for (tr = pr->head; tr; tr = tr->next) {
1630 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1631 if (tr->trns_no == p->trns->t_no)
1632 break;
1633 }
1634 if (p == NULL)
1635 goto out;
1636
1637 newtlen += ntohs(p->trns->h.len);
1638 }
1639 }
1640 }
1641
1642 newsa = vmalloc(newtlen);
1643 if (newsa == NULL) {
1644 plog(ASL_LEVEL_ERR, "failed to get newsa.\n");
1645 goto out;
1646 }
1647 bp = newsa->v;
1648
1649 /* some of values of SA must be updated in the out of this function */
1650 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1651 bp += sizeof(struct ipsecdoi_sa_b);
1652
1653 /* create proposal payloads */
1654 for (pp = pp0; pp; pp = pp->next) {
1655
1656 for (pr = pp->head; pr; pr = pr->next) {
1657 prophlen = sizeof(struct isakmp_pl_p)
1658 + p->prop->spi_size;
1659
1660 for (tr = pr->head; tr; tr = tr->next) {
1661 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1662 if (tr->trns_no == p->trns->t_no)
1663 break;
1664 }
1665 if (p == NULL)
1666 goto out;
1667
1668 trnslen = ntohs(p->trns->h.len);
1669
1670 if (np_p)
1671 *np_p = ISAKMP_NPTYPE_P;
1672
1673 /* create proposal */
1674
1675 memcpy(bp, p->prop, prophlen);
1676 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1677 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1678 ((struct isakmp_pl_p *)bp)->num_t = 1;
1679 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1680 bp += prophlen;
1681
1682 /* create transform */
1683 memcpy(bp, p->trns, trnslen);
1684 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1685 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1686 bp += trnslen;
1687 }
1688 }
1689 }
1690
1691 error = 0;
1692out:
1693 if (pair != NULL)
1694 racoon_free(pair);
1695
1696 if (error != 0) {
1697 if (newsa != NULL) {
1698 vfree(newsa);
1699 newsa = NULL;
1700 }
1701 }
1702
1703 return newsa;
1704}
1705
1706/*
1707 * If some error happens then return 0. Although 0 means that lifetime is zero,
1708 * such a value should not be accepted.
1709 * Also 0 of lifebyte should not be included in a packet although 0 means not
1710 * to care of it.
1711 */
1712static u_int32_t
1713ipsecdoi_set_ld(buf)
1714 vchar_t *buf;
1715{
1716 u_int32_t ld;
1717
1718 if (buf == 0)
1719 return 0;
1720
1721 switch (buf->l) {
1722 case 2:
1723 ld = ntohs(*ALIGNED_CAST(u_int16_t *)buf->v);
1724 break;
1725 case 4:
1726 ld = ntohl(*ALIGNED_CAST(u_int32_t *)buf->v);
1727 break;
1728 default:
1729 plog(ASL_LEVEL_ERR,
1730 "length %zu of life duration "
1731 "isn't supported.\n", buf->l);
1732 return 0;
1733 }
1734
1735 return ld;
1736}
1737
1738/*%%%*/
1739/*
1740 * check DOI
1741 */
1742static int
1743check_doi(doi)
1744 u_int32_t doi;
1745{
1746 switch (doi) {
1747 case IPSEC_DOI:
1748 return 0;
1749 default:
1750 plog(ASL_LEVEL_ERR,
1751 "invalid value of DOI 0x%08x.\n", doi);
1752 return -1;
1753 }
1754 /* NOT REACHED */
1755}
1756
1757/*
1758 * check situation
1759 */
1760static int
1761check_situation(sit)
1762 u_int32_t sit;
1763{
1764 switch (sit) {
1765 case IPSECDOI_SIT_IDENTITY_ONLY:
1766 return 0;
1767
1768 case IPSECDOI_SIT_SECRECY:
1769 case IPSECDOI_SIT_INTEGRITY:
1770 plog(ASL_LEVEL_ERR,
1771 "situation 0x%08x unsupported yet.\n", sit);
1772 return -1;
1773
1774 default:
1775 plog(ASL_LEVEL_ERR,
1776 "invalid situation 0x%08x.\n", sit);
1777 return -1;
1778 }
1779 /* NOT REACHED */
1780}
1781
1782/*
1783 * check protocol id in main mode
1784 */
1785static int
1786check_prot_main(proto_id)
1787 int proto_id;
1788{
1789 switch (proto_id) {
1790 case IPSECDOI_PROTO_ISAKMP:
1791 return 0;
1792
1793 default:
1794 plog(ASL_LEVEL_ERR,
1795 "Illegal protocol id=%u.\n", proto_id);
1796 return -1;
1797 }
1798 /* NOT REACHED */
1799}
1800
1801/*
1802 * check protocol id in quick mode
1803 */
1804static int
1805check_prot_quick(proto_id)
1806 int proto_id;
1807{
1808 switch (proto_id) {
1809 case IPSECDOI_PROTO_IPSEC_AH:
1810 case IPSECDOI_PROTO_IPSEC_ESP:
1811 return 0;
1812
1813 case IPSECDOI_PROTO_IPCOMP:
1814 return 0;
1815
1816 default:
1817 plog(ASL_LEVEL_ERR,
1818 "invalid protocol id %d.\n", proto_id);
1819 return -1;
1820 }
1821 /* NOT REACHED */
1822}
1823
1824int
1825check_spi_size(proto_id, size)
1826 int proto_id, size;
1827{
1828 switch (proto_id) {
1829 case IPSECDOI_PROTO_ISAKMP:
1830 if (size != 0) {
1831 /* WARNING */
1832 plog(ASL_LEVEL_WARNING,
1833 "SPI size isn't zero, but IKE proposal.\n");
1834 }
1835 return 0;
1836
1837 case IPSECDOI_PROTO_IPSEC_AH:
1838 case IPSECDOI_PROTO_IPSEC_ESP:
1839 if (size != 4) {
1840 plog(ASL_LEVEL_ERR,
1841 "invalid SPI size=%d for IPSEC proposal.\n",
1842 size);
1843 return -1;
1844 }
1845 return 0;
1846
1847 case IPSECDOI_PROTO_IPCOMP:
1848 if (size != 2 && size != 4) {
1849 plog(ASL_LEVEL_ERR,
1850 "invalid SPI size=%d for IPCOMP proposal.\n",
1851 size);
1852 return -1;
1853 }
1854 return 0;
1855
1856 default:
1857 /* ??? */
1858 return -1;
1859 }
1860 /* NOT REACHED */
1861}
1862
1863/*
1864 * check transform ID in ISAKMP.
1865 */
1866static int
1867check_trns_isakmp(t_id)
1868 int t_id;
1869{
1870 switch (t_id) {
1871 case IPSECDOI_KEY_IKE:
1872 return 0;
1873 default:
1874 plog(ASL_LEVEL_ERR,
1875 "invalid transform-id=%u in proto_id=%u.\n",
1876 t_id, IPSECDOI_KEY_IKE);
1877 return -1;
1878 }
1879 /* NOT REACHED */
1880}
1881
1882/*
1883 * check transform ID in AH.
1884 */
1885static int
1886check_trns_ah(t_id)
1887 int t_id;
1888{
1889 switch (t_id) {
1890 case IPSECDOI_AH_MD5:
1891 case IPSECDOI_AH_SHA:
1892 case IPSECDOI_AH_SHA256:
1893 case IPSECDOI_AH_SHA384:
1894 case IPSECDOI_AH_SHA512:
1895 return 0;
1896 case IPSECDOI_AH_DES:
1897 plog(ASL_LEVEL_ERR,
1898 "not support transform-id=%u in AH.\n", t_id);
1899 return -1;
1900 default:
1901 plog(ASL_LEVEL_ERR,
1902 "invalid transform-id=%u in AH.\n", t_id);
1903 return -1;
1904 }
1905 /* NOT REACHED */
1906}
1907
1908/*
1909 * check transform ID in ESP.
1910 */
1911static int
1912check_trns_esp(t_id)
1913 int t_id;
1914{
1915 switch (t_id) {
1916 case IPSECDOI_ESP_DES:
1917 case IPSECDOI_ESP_3DES:
1918 case IPSECDOI_ESP_NULL:
1919 case IPSECDOI_ESP_RC5:
1920 case IPSECDOI_ESP_CAST:
1921 case IPSECDOI_ESP_BLOWFISH:
1922 case IPSECDOI_ESP_AES:
1923 case IPSECDOI_ESP_TWOFISH:
1924 return 0;
1925 case IPSECDOI_ESP_DES_IV32:
1926 case IPSECDOI_ESP_DES_IV64:
1927 case IPSECDOI_ESP_IDEA:
1928 case IPSECDOI_ESP_3IDEA:
1929 case IPSECDOI_ESP_RC4:
1930 plog(ASL_LEVEL_ERR,
1931 "not support transform-id=%u in ESP.\n", t_id);
1932 return -1;
1933 default:
1934 plog(ASL_LEVEL_ERR,
1935 "invalid transform-id=%u in ESP.\n", t_id);
1936 return -1;
1937 }
1938 /* NOT REACHED */
1939}
1940
1941/*
1942 * check transform ID in IPCOMP.
1943 */
1944static int
1945check_trns_ipcomp(t_id)
1946 int t_id;
1947{
1948 switch (t_id) {
1949 case IPSECDOI_IPCOMP_OUI:
1950 case IPSECDOI_IPCOMP_DEFLATE:
1951 case IPSECDOI_IPCOMP_LZS:
1952 return 0;
1953 default:
1954 plog(ASL_LEVEL_ERR,
1955 "invalid transform-id=%u in IPCOMP.\n", t_id);
1956 return -1;
1957 }
1958 /* NOT REACHED */
1959}
1960
1961/*
1962 * check data attributes in IKE.
1963 */
1964static int
1965check_attr_isakmp(trns)
1966 struct isakmp_pl_t *trns;
1967{
1968 struct isakmp_data *d;
1969 int tlen;
1970 int flag, type;
1971 u_int16_t lorv;
1972
1973 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
1974 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
1975
1976 while (tlen > 0) {
1977 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
1978 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
1979 lorv = ntohs(d->lorv);
1980
1981 plog(ASL_LEVEL_DEBUG,
1982 "type=%s, flag=0x%04x, lorv=%s\n",
1983 s_oakley_attr(type), flag,
1984 s_oakley_attr_v(type, lorv));
1985
1986 /*
1987 * some of the attributes must be encoded in TV.
1988 * see RFC2409 Appendix A "Attribute Classes".
1989 */
1990 switch (type) {
1991 case OAKLEY_ATTR_ENC_ALG:
1992 case OAKLEY_ATTR_HASH_ALG:
1993 case OAKLEY_ATTR_AUTH_METHOD:
1994 case OAKLEY_ATTR_GRP_DESC:
1995 case OAKLEY_ATTR_GRP_TYPE:
1996 case OAKLEY_ATTR_SA_LD_TYPE:
1997 case OAKLEY_ATTR_PRF:
1998 case OAKLEY_ATTR_KEY_LEN:
1999 case OAKLEY_ATTR_FIELD_SIZE:
2000 if (!flag) { /* TLV*/
2001 plog(ASL_LEVEL_ERR,
2002 "oakley attribute %d must be TV.\n",
2003 type);
2004 return -1;
2005 }
2006 break;
2007 }
2008
2009 /* sanity check for TLV. length must be specified. */
2010 if (!flag && lorv == 0) { /*TLV*/
2011 plog(ASL_LEVEL_ERR,
2012 "invalid length %d for TLV attribute %d.\n",
2013 lorv, type);
2014 return -1;
2015 }
2016
2017 switch (type) {
2018 case OAKLEY_ATTR_ENC_ALG:
2019 if (!alg_oakley_encdef_ok(lorv)) {
2020 plog(ASL_LEVEL_ERR,
2021 "invalied encryption algorithm=%d.\n",
2022 lorv);
2023 return -1;
2024 }
2025 break;
2026
2027 case OAKLEY_ATTR_HASH_ALG:
2028 if (!alg_oakley_hashdef_ok(lorv)) {
2029 plog(ASL_LEVEL_ERR,
2030 "invalied hash algorithm=%d.\n",
2031 lorv);
2032 return -1;
2033 }
2034 break;
2035
2036 case OAKLEY_ATTR_AUTH_METHOD:
2037 switch (lorv) {
2038 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
2039 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2040#ifdef ENABLE_HYBRID
2041 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
2042 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2043#if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
2044 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
2045#endif
2046 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
2047#endif
2048 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
2049 break;
2050 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2051#ifdef ENABLE_HYBRID
2052 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
2053 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
2054 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
2055 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
2056 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
2057 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
2058 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
2059 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
2060 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
2061 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
2062#endif
2063 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2064 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
2065 plog(ASL_LEVEL_ERR,
2066 "auth method %s isn't supported.\n",
2067 s_oakley_attr_method(lorv));
2068 return -1;
2069 default:
2070 plog(ASL_LEVEL_ERR,
2071 "invalid auth method %d.\n",
2072 lorv);
2073 return -1;
2074 }
2075 break;
2076
2077 case OAKLEY_ATTR_GRP_DESC:
2078 if (!alg_oakley_dhdef_ok(lorv)) {
2079 plog(ASL_LEVEL_ERR,
2080 "invalid DH group %d.\n",
2081 lorv);
2082 return -1;
2083 }
2084 break;
2085
2086 case OAKLEY_ATTR_GRP_TYPE:
2087 switch (lorv) {
2088 case OAKLEY_ATTR_GRP_TYPE_MODP:
2089 break;
2090 default:
2091 plog(ASL_LEVEL_ERR,
2092 "unsupported DH group type %d.\n",
2093 lorv);
2094 return -1;
2095 }
2096 break;
2097
2098 case OAKLEY_ATTR_GRP_PI:
2099 case OAKLEY_ATTR_GRP_GEN_ONE:
2100 /* sanity checks? */
2101 break;
2102
2103 case OAKLEY_ATTR_GRP_GEN_TWO:
2104 case OAKLEY_ATTR_GRP_CURVE_A:
2105 case OAKLEY_ATTR_GRP_CURVE_B:
2106 plog(ASL_LEVEL_ERR,
2107 "attr type=%u isn't supported.\n", type);
2108 return -1;
2109
2110 case OAKLEY_ATTR_SA_LD_TYPE:
2111 switch (lorv) {
2112 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
2113 case OAKLEY_ATTR_SA_LD_TYPE_KB:
2114 break;
2115 default:
2116 plog(ASL_LEVEL_ERR,
2117 "invalid life type %d.\n", lorv);
2118 return -1;
2119 }
2120 break;
2121
2122 case OAKLEY_ATTR_SA_LD:
2123 /* should check the value */
2124 break;
2125
2126 case OAKLEY_ATTR_PRF:
2127 case OAKLEY_ATTR_KEY_LEN:
2128 break;
2129
2130 case OAKLEY_ATTR_FIELD_SIZE:
2131 plog(ASL_LEVEL_ERR,
2132 "attr type=%u isn't supported.\n", type);
2133 return -1;
2134
2135 case OAKLEY_ATTR_GRP_ORDER:
2136 break;
2137
2138 case OAKLEY_ATTR_GSS_ID:
2139 break;
2140
2141 default:
2142 plog(ASL_LEVEL_ERR,
2143 "invalid attribute type %d.\n", type);
2144 return -1;
2145 }
2146
2147 if (flag) {
2148 tlen -= sizeof(*d);
2149 d = (struct isakmp_data *)((char *)d
2150 + sizeof(*d));
2151 } else {
2152 tlen -= (sizeof(*d) + lorv);
2153 d = (struct isakmp_data *)((char *)d
2154 + sizeof(*d) + lorv);
2155 }
2156 }
2157
2158 return 0;
2159}
2160
2161/*
2162 * check data attributes in IPSEC AH/ESP.
2163 */
2164static int
2165check_attr_ah(trns)
2166 struct isakmp_pl_t *trns;
2167{
2168 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2169}
2170
2171static int
2172check_attr_esp(trns)
2173 struct isakmp_pl_t *trns;
2174{
2175 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2176}
2177
2178static int
2179check_attr_ipsec(proto_id, trns)
2180 int proto_id;
2181 struct isakmp_pl_t *trns;
2182{
2183 struct isakmp_data *d;
2184 int tlen;
2185 int flag, type = 0;
2186 u_int16_t lorv;
2187 int attrseen[16]; /* XXX magic number */
2188
2189 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2190 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2191 memset(attrseen, 0, sizeof(attrseen));
2192
2193 while (tlen > 0) {
2194 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2195 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2196 lorv = ntohs(d->lorv);
2197
2198 plog(ASL_LEVEL_DEBUG,
2199 "type=%s, flag=0x%04x, lorv=%s\n",
2200 s_ipsecdoi_attr(type), flag,
2201 s_ipsecdoi_attr_v(type, lorv));
2202
2203 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2204 attrseen[type]++;
2205
2206 switch (type) {
2207 case IPSECDOI_ATTR_ENC_MODE:
2208 if (! flag) {
2209 plog(ASL_LEVEL_ERR,
2210 "must be TV when ENC_MODE.\n");
2211 return -1;
2212 }
2213
2214 switch (lorv) {
2215 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2216 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2217 break;
2218#ifdef ENABLE_NATT
2219 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2220 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2221 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2222 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2223 plog(ASL_LEVEL_DEBUG,
2224 "UDP encapsulation requested\n");
2225 break;
2226#endif
2227 default:
2228 plog(ASL_LEVEL_ERR,
2229 "invalid encryption mode=%u.\n",
2230 lorv);
2231 return -1;
2232 }
2233 break;
2234
2235 case IPSECDOI_ATTR_AUTH:
2236 if (! flag) {
2237 plog(ASL_LEVEL_ERR,
2238 "must be TV when AUTH.\n");
2239 return -1;
2240 }
2241
2242 switch (lorv) {
2243 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
2244 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2245 trns->t_id != IPSECDOI_AH_MD5) {
2246ahmismatch:
2247 plog(ASL_LEVEL_ERR,
2248 "auth algorithm %u conflicts "
2249 "with transform %u.\n",
2250 lorv, trns->t_id);
2251 return -1;
2252 }
2253 break;
2254 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
2255 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2256 if (trns->t_id != IPSECDOI_AH_SHA)
2257 goto ahmismatch;
2258 }
2259 break;
2260 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
2261 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2262 if (trns->t_id != IPSECDOI_AH_SHA256)
2263 goto ahmismatch;
2264 }
2265 break;
2266 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
2267 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2268 if (trns->t_id != IPSECDOI_AH_SHA384)
2269 goto ahmismatch;
2270 }
2271 break;
2272 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
2273 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2274 if (trns->t_id != IPSECDOI_AH_SHA512)
2275 goto ahmismatch;
2276 }
2277 break;
2278 case IPSECDOI_ATTR_AUTH_DES_MAC:
2279 case IPSECDOI_ATTR_AUTH_KPDK:
2280 plog(ASL_LEVEL_ERR,
2281 "auth algorithm %u isn't supported.\n",
2282 lorv);
2283 return -1;
2284 default:
2285 plog(ASL_LEVEL_ERR,
2286 "invalid auth algorithm=%u.\n",
2287 lorv);
2288 return -1;
2289 }
2290 break;
2291
2292 case IPSECDOI_ATTR_SA_LD_TYPE:
2293 if (! flag) {
2294 plog(ASL_LEVEL_ERR,
2295 "must be TV when LD_TYPE.\n");
2296 return -1;
2297 }
2298
2299 switch (lorv) {
2300 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2301 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2302 break;
2303 default:
2304 plog(ASL_LEVEL_ERR,
2305 "invalid life type %d.\n", lorv);
2306 return -1;
2307 }
2308 break;
2309
2310 case IPSECDOI_ATTR_SA_LD:
2311 if (flag) {
2312 /* i.e. ISAKMP_GEN_TV */
2313 plog(ASL_LEVEL_DEBUG,
2314 "life duration was in TLV.\n");
2315 } else {
2316 /* i.e. ISAKMP_GEN_TLV */
2317 if (lorv == 0) {
2318 plog(ASL_LEVEL_ERR,
2319 "invalid length of LD\n");
2320 return -1;
2321 }
2322 }
2323 break;
2324
2325 case IPSECDOI_ATTR_GRP_DESC:
2326 if (! flag) {
2327 plog(ASL_LEVEL_ERR,
2328 "must be TV when GRP_DESC.\n");
2329 return -1;
2330 }
2331
2332 if (!alg_oakley_dhdef_ok(lorv)) {
2333 plog(ASL_LEVEL_ERR,
2334 "invalid group description=%u.\n",
2335 lorv);
2336 return -1;
2337 }
2338 break;
2339
2340 case IPSECDOI_ATTR_KEY_LENGTH:
2341 if (! flag) {
2342 plog(ASL_LEVEL_ERR,
2343 "must be TV when KEY_LENGTH.\n");
2344 return -1;
2345 }
2346 break;
2347
2348 case IPSECDOI_ATTR_KEY_ROUNDS:
2349 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2350 case IPSECDOI_ATTR_COMP_PRIVALG:
2351 plog(ASL_LEVEL_ERR,
2352 "attr type=%u isn't supported.\n", type);
2353 return -1;
2354
2355 default:
2356 plog(ASL_LEVEL_ERR,
2357 "invalid attribute type %d.\n", type);
2358 return -1;
2359 }
2360
2361 if (flag) {
2362 tlen -= sizeof(*d);
2363 d = (struct isakmp_data *)((char *)d
2364 + sizeof(*d));
2365 } else {
2366 tlen -= (sizeof(*d) + lorv);
2367 d = (struct isakmp_data *)((caddr_t)d
2368 + sizeof(*d) + lorv);
2369 }
2370 }
2371
2372 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2373 !attrseen[IPSECDOI_ATTR_AUTH]) {
2374 plog(ASL_LEVEL_ERR,
2375 "attr AUTH must be present for AH.\n");
2376 return -1;
2377 }
2378
2379 if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
2380 trns->t_id == IPSECDOI_ESP_NULL &&
2381 !attrseen[IPSECDOI_ATTR_AUTH]) {
2382 plog(ASL_LEVEL_ERR,
2383 "attr AUTH must be present for ESP NULL encryption.\n");
2384 return -1;
2385 }
2386
2387 return 0;
2388}
2389
2390static int
2391check_attr_ipcomp(trns)
2392 struct isakmp_pl_t *trns;
2393{
2394 struct isakmp_data *d;
2395 int tlen;
2396 int flag, type = 0;
2397 u_int16_t lorv;
2398 int attrseen[16]; /* XXX magic number */
2399
2400 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2401 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2402 memset(attrseen, 0, sizeof(attrseen));
2403
2404 while (tlen > 0) {
2405 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2406 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2407 lorv = ntohs(d->lorv);
2408
2409 plog(ASL_LEVEL_DEBUG,
2410 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2411 type, flag, lorv);
2412
2413 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2414 attrseen[type]++;
2415
2416 switch (type) {
2417 case IPSECDOI_ATTR_ENC_MODE:
2418 if (! flag) {
2419 plog(ASL_LEVEL_ERR,
2420 "must be TV when ENC_MODE.\n");
2421 return -1;
2422 }
2423
2424 switch (lorv) {
2425 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2426 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2427 break;
2428#ifdef ENABLE_NATT
2429 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2430 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2431 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2432 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2433 plog(ASL_LEVEL_DEBUG,
2434 "UDP encapsulation requested\n");
2435 break;
2436#endif
2437 default:
2438 plog(ASL_LEVEL_ERR,
2439 "invalid encryption mode=%u.\n",
2440 lorv);
2441 return -1;
2442 }
2443 break;
2444
2445 case IPSECDOI_ATTR_SA_LD_TYPE:
2446 if (! flag) {
2447 plog(ASL_LEVEL_ERR,
2448 "must be TV when LD_TYPE.\n");
2449 return -1;
2450 }
2451
2452 switch (lorv) {
2453 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2454 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2455 break;
2456 default:
2457 plog(ASL_LEVEL_ERR,
2458 "invalid life type %d.\n", lorv);
2459 return -1;
2460 }
2461 break;
2462
2463 case IPSECDOI_ATTR_SA_LD:
2464 if (flag) {
2465 /* i.e. ISAKMP_GEN_TV */
2466 plog(ASL_LEVEL_DEBUG,
2467 "life duration was in TLV.\n");
2468 } else {
2469 /* i.e. ISAKMP_GEN_TLV */
2470 if (lorv == 0) {
2471 plog(ASL_LEVEL_ERR,
2472 "invalid length of LD\n");
2473 return -1;
2474 }
2475 }
2476 break;
2477
2478 case IPSECDOI_ATTR_GRP_DESC:
2479 if (! flag) {
2480 plog(ASL_LEVEL_ERR,
2481 "must be TV when GRP_DESC.\n");
2482 return -1;
2483 }
2484
2485 if (!alg_oakley_dhdef_ok(lorv)) {
2486 plog(ASL_LEVEL_ERR,
2487 "invalid group description=%u.\n",
2488 lorv);
2489 return -1;
2490 }
2491 break;
2492
2493 case IPSECDOI_ATTR_AUTH:
2494 plog(ASL_LEVEL_ERR,
2495 "invalid attr type=%u.\n", type);
2496 return -1;
2497
2498 case IPSECDOI_ATTR_KEY_LENGTH:
2499 case IPSECDOI_ATTR_KEY_ROUNDS:
2500 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2501 case IPSECDOI_ATTR_COMP_PRIVALG:
2502 plog(ASL_LEVEL_ERR,
2503 "attr type=%u isn't supported.\n", type);
2504 return -1;
2505
2506 default:
2507 plog(ASL_LEVEL_ERR,
2508 "invalid attribute type %d.\n", type);
2509 return -1;
2510 }
2511
2512 if (flag) {
2513 tlen -= sizeof(*d);
2514 d = (struct isakmp_data *)((char *)d
2515 + sizeof(*d));
2516 } else {
2517 tlen -= (sizeof(*d) + lorv);
2518 d = (struct isakmp_data *)((caddr_t)d
2519 + sizeof(*d) + lorv);
2520 }
2521 }
2522
2523#if 0
2524 if (proto_id == IPSECDOI_PROTO_IPCOMP &&
2525 !attrseen[IPSECDOI_ATTR_AUTH]) {
2526 plog(ASL_LEVEL_ERR,
2527 "attr AUTH must be present for AH.\n", type);
2528 return -1;
2529 }
2530#endif
2531
2532 return 0;
2533}
2534
2535/* %%% */
2536/*
2537 * create phase1 proposal from remote configuration.
2538 * NOT INCLUDING isakmp general header of SA payload
2539 */
2540vchar_t *
2541ipsecdoi_setph1proposal (phase1_handle_t *iph1)
2542{
2543 vchar_t *mysa;
2544 int sablen;
2545
2546 if (!iph1) return NULL;
2547
2548 struct isakmpsa *props = iph1->rmconf->proposal;
2549 unsigned int version = iph1->version;
2550
2551 /* count total size of SA minus isakmp general header */
2552 /* not including isakmp general header of SA payload */
2553 if (version == ISAKMP_VERSION_NUMBER_IKEV1) {
2554 sablen = sizeof(struct ipsecdoi_sa_b);
2555 } else {
2556 sablen = 0;
2557 }
2558 sablen += setph1prop(iph1, NULL);
2559
2560 mysa = vmalloc(sablen);
2561 if (mysa == NULL) {
2562 plog(ASL_LEVEL_ERR,
2563 "failed to allocate my sa buffer\n");
2564 return NULL;
2565 }
2566
2567 /* create SA payload */
2568 if (version == ISAKMP_VERSION_NUMBER_IKEV1) {
2569 /* not including isakmp general header */
2570 (ALIGNED_CAST(struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(props->rmconf->doitype);
2571 (ALIGNED_CAST(struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(props->rmconf->sittype);
2572
2573 (void)setph1prop(iph1, mysa->v + sizeof(struct ipsecdoi_sa_b));
2574 }
2575
2576 return mysa;
2577}
2578
2579int
2580setph1prop (phase1_handle_t *iph1,
2581 caddr_t buf)
2582{
2583 struct isakmpsa *props = iph1->rmconf->proposal;
2584
2585 struct isakmp_pl_p *prop = NULL;
2586 struct isakmpsa *s = NULL;
2587 int proplen, trnslen;
2588 u_int8_t *np_t; /* pointer next trns type in previous header */
2589 int trns_num;
2590 caddr_t p = buf;
2591 int spi_size = 0;
2592
2593 proplen = sizeof(*prop) + spi_size;
2594 if (buf) {
2595 /* create proposal */
2596 prop = (struct isakmp_pl_p *)p;
2597 prop->h.np = ISAKMP_NPTYPE_NONE;
2598 prop->h.reserved = 0;
2599 prop->p_no = props->prop_no;
2600 prop->proto_id = IPSECDOI_PROTO_ISAKMP;
2601 prop->spi_size = spi_size;
2602 p += sizeof(*prop);
2603 }
2604
2605 np_t = NULL;
2606 trns_num = 0;
2607
2608 for (s = props; s != NULL; s = s->next) {
2609 {
2610 if (np_t)
2611 *np_t = ISAKMP_NPTYPE_T;
2612
2613 trnslen = setph1trns(s, p);
2614 proplen += trnslen;
2615 if (buf) {
2616 /* save buffer to pre-next payload */
2617 np_t = &((struct isakmp_pl_t *)p)->h.np;
2618 p += trnslen;
2619
2620 /* count up transform length */
2621 trns_num++;
2622 }
2623 }
2624 }
2625
2626 /* update proposal length */
2627 if (buf) {
2628 prop->h.len = htons(proplen);
2629 prop->num_t = trns_num;
2630 }
2631
2632 return proplen;
2633}
2634
2635static int
2636setph1trns (struct isakmpsa *sa,
2637 caddr_t buf)
2638{
2639 struct isakmp_pl_t *trns = NULL;
2640 int trnslen, attrlen;
2641 caddr_t p = buf;
2642
2643 trnslen = sizeof(*trns);
2644 if (buf) {
2645 /* create transform */
2646 trns = (struct isakmp_pl_t *)p;
2647 trns->h.np = ISAKMP_NPTYPE_NONE;
2648 trns->t_no = sa->trns_no;
2649 trns->t_id = IPSECDOI_KEY_IKE;
2650 p += sizeof(*trns);
2651 }
2652
2653 attrlen = setph1attr(sa, p);
2654 trnslen += attrlen;
2655 if (buf)
2656 p += attrlen;
2657
2658 if (buf)
2659 trns->h.len = htons(trnslen);
2660
2661 return trnslen;
2662}
2663
2664static int
2665setph1attr (struct isakmpsa *sa,
2666 caddr_t buf)
2667{
2668 caddr_t p = buf;
2669 int attrlen = 0;
2670
2671 if (sa->lifetime) {
2672 u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
2673
2674 attrlen += sizeof(struct isakmp_data)
2675 + sizeof(struct isakmp_data);
2676 if (sa->lifetime > 0xffff)
2677 attrlen += sizeof(lifetime);
2678 if (buf) {
2679 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2680 OAKLEY_ATTR_SA_LD_TYPE_SEC);
2681 if (sa->lifetime > 0xffff) {
2682 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2683 (caddr_t)&lifetime,
2684 sizeof(lifetime));
2685 } else {
2686 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2687 sa->lifetime);
2688 }
2689 }
2690 }
2691
2692 if (sa->lifebyte) {
2693 u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
2694
2695 attrlen += sizeof(struct isakmp_data)
2696 + sizeof(struct isakmp_data);
2697 if (sa->lifebyte > 0xffff)
2698 attrlen += sizeof(lifebyte);
2699 if (buf) {
2700 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2701 OAKLEY_ATTR_SA_LD_TYPE_KB);
2702 if (sa->lifebyte > 0xffff) {
2703 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2704 (caddr_t)&lifebyte,
2705 sizeof(lifebyte));
2706 } else {
2707 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2708 sa->lifebyte);
2709 }
2710 }
2711 }
2712
2713 if (sa->enctype) {
2714 attrlen += sizeof(struct isakmp_data);
2715 if (buf)
2716 p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
2717 }
2718 if (sa->encklen) {
2719 attrlen += sizeof(struct isakmp_data);
2720 if (buf)
2721 p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
2722 }
2723 if (sa->authmethod) {
2724 int authmethod;
2725
2726#ifdef ENABLE_HYBRID
2727 authmethod = switch_authmethod(sa->authmethod);
2728#else
2729 authmethod = sa->authmethod;
2730#endif
2731 attrlen += sizeof(struct isakmp_data);
2732 if (buf)
2733 p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
2734 }
2735 if (sa->hashtype) {
2736 attrlen += sizeof(struct isakmp_data);
2737 if (buf)
2738 p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
2739 }
2740 switch (sa->dh_group) {
2741 case OAKLEY_ATTR_GRP_DESC_MODP768:
2742 case OAKLEY_ATTR_GRP_DESC_MODP1024:
2743 case OAKLEY_ATTR_GRP_DESC_MODP1536:
2744 case OAKLEY_ATTR_GRP_DESC_MODP2048:
2745 case OAKLEY_ATTR_GRP_DESC_MODP3072:
2746 case OAKLEY_ATTR_GRP_DESC_MODP4096:
2747 case OAKLEY_ATTR_GRP_DESC_MODP6144:
2748 case OAKLEY_ATTR_GRP_DESC_MODP8192:
2749 /* don't attach group type for known groups */
2750 attrlen += sizeof(struct isakmp_data);
2751 if (buf) {
2752 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
2753 sa->dh_group);
2754 }
2755 break;
2756 case OAKLEY_ATTR_GRP_DESC_EC2N155:
2757 case OAKLEY_ATTR_GRP_DESC_EC2N185:
2758 /* don't attach group type for known groups */
2759 attrlen += sizeof(struct isakmp_data);
2760 if (buf) {
2761 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
2762 OAKLEY_ATTR_GRP_TYPE_EC2N);
2763 }
2764 break;
2765 case 0:
2766 default:
2767 break;
2768 }
2769
2770 return attrlen;
2771}
2772
2773static vchar_t *
2774setph2proposal0(iph2, pp, pr)
2775 const phase2_handle_t *iph2;
2776 const struct saprop *pp;
2777 const struct saproto *pr;
2778{
2779 vchar_t *p;
2780 struct isakmp_pl_p *prop;
2781 struct isakmp_pl_t *trns;
2782 struct satrns *tr;
2783 int attrlen;
2784 size_t trnsoff;
2785 caddr_t x0, x;
2786 u_int8_t *np_t; /* pointer next trns type in previous header */
2787 const u_int8_t *spi;
2788
2789 p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
2790 if (p == NULL)
2791 return NULL;
2792
2793 /* create proposal */
2794 prop = (struct isakmp_pl_p *)p->v;
2795 prop->h.np = ISAKMP_NPTYPE_NONE;
2796 prop->p_no = pp->prop_no;
2797 prop->proto_id = pr->proto_id;
2798 prop->num_t = 1;
2799
2800 spi = (const u_int8_t *)&pr->spi;
2801 switch (pr->proto_id) {
2802 case IPSECDOI_PROTO_IPCOMP:
2803 /*
2804 * draft-shacham-ippcp-rfc2393bis-05.txt:
2805 * construct 16bit SPI (CPI).
2806 * XXX we may need to provide a configuration option to
2807 * generate 32bit SPI. otherwise we cannot interoeprate
2808 * with nodes that uses 32bit SPI, in case we are initiator.
2809 */
2810 prop->spi_size = sizeof(u_int16_t);
2811 spi += sizeof(pr->spi) - sizeof(u_int16_t);
2812 p->l -= sizeof(pr->spi);
2813 p->l += sizeof(u_int16_t);
2814 break;
2815 default:
2816 prop->spi_size = sizeof(pr->spi);
2817 break;
2818 }
2819 memcpy(prop + 1, spi, prop->spi_size);
2820
2821 /* create transform */
2822 trnsoff = sizeof(*prop) + prop->spi_size;
2823 np_t = NULL;
2824
2825 for (tr = pr->head; tr; tr = tr->next) {
2826
2827 switch (pr->proto_id) {
2828 case IPSECDOI_PROTO_IPSEC_ESP:
2829 /*
2830 * don't build a null encryption
2831 * with no authentication transform.
2832 */
2833 if (tr->trns_id == IPSECDOI_ESP_NULL &&
2834 tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
2835 continue;
2836 break;
2837 }
2838
2839 if (np_t) {
2840 *np_t = ISAKMP_NPTYPE_T;
2841 prop->num_t++;
2842 }
2843
2844 /* get attribute length */
2845 attrlen = 0;
2846 if (pp->lifetime) {
2847 attrlen += sizeof(struct isakmp_data)
2848 + sizeof(struct isakmp_data);
2849 if (pp->lifetime > 0xffff)
2850 attrlen += sizeof(u_int32_t);
2851 }
2852 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2853 attrlen += sizeof(struct isakmp_data)
2854 + sizeof(struct isakmp_data);
2855 if (pp->lifebyte > 0xffff)
2856 attrlen += sizeof(u_int32_t);
2857 }
2858 attrlen += sizeof(struct isakmp_data); /* enc mode */
2859 if (tr->encklen)
2860 attrlen += sizeof(struct isakmp_data);
2861
2862 switch (pr->proto_id) {
2863 case IPSECDOI_PROTO_IPSEC_ESP:
2864 /* non authentication mode ? */
2865 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2866 attrlen += sizeof(struct isakmp_data);
2867 break;
2868 case IPSECDOI_PROTO_IPSEC_AH:
2869 if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
2870 plog(ASL_LEVEL_ERR,
2871 "no authentication algorithm found "
2872 "but protocol is AH.\n");
2873 vfree(p);
2874 return NULL;
2875 }
2876 attrlen += sizeof(struct isakmp_data);
2877 break;
2878 case IPSECDOI_PROTO_IPCOMP:
2879 break;
2880 default:
2881 plog(ASL_LEVEL_ERR,
2882 "invalid protocol: %d\n", pr->proto_id);
2883 vfree(p);
2884 return NULL;
2885 }
2886
2887 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
2888 attrlen += sizeof(struct isakmp_data);
2889
2890 p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
2891 if (p == NULL)
2892 return NULL;
2893 prop = (struct isakmp_pl_p *)p->v;
2894
2895 /* set transform's values */
2896 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
2897 trns->h.np = ISAKMP_NPTYPE_NONE;
2898 trns->t_no = tr->trns_no;
2899 trns->t_id = tr->trns_id;
2900
2901 /* set attributes */
2902 x = x0 = p->v + trnsoff + sizeof(*trns);
2903
2904 if (pp->lifetime) {
2905 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2906 IPSECDOI_ATTR_SA_LD_TYPE_SEC);
2907 if (pp->lifetime > 0xffff) {
2908 u_int32_t v = htonl((u_int32_t)pp->lifetime);
2909 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
2910 (caddr_t)&v, sizeof(v));
2911 } else {
2912 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
2913 pp->lifetime);
2914 }
2915 }
2916
2917 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
2918 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
2919 IPSECDOI_ATTR_SA_LD_TYPE_KB);
2920 if (pp->lifebyte > 0xffff) {
2921 u_int32_t v = htonl((u_int32_t)pp->lifebyte);
2922 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
2923 (caddr_t)&v, sizeof(v));
2924 } else {
2925 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
2926 pp->lifebyte);
2927 }
2928 }
2929
2930 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
2931
2932 if (tr->encklen)
2933 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
2934
2935 /* mandatory check has done above. */
2936 if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
2937 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
2938 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
2939
2940 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
2941 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
2942 iph2->sainfo->pfs_group);
2943
2944 /* update length of this transform. */
2945 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
2946 trns->h.len = htons(sizeof(*trns) + attrlen);
2947
2948 /* save buffer to pre-next payload */
2949 np_t = &trns->h.np;
2950
2951 trnsoff += (sizeof(*trns) + attrlen);
2952 }
2953
2954 if (np_t == NULL) {
2955 plog(ASL_LEVEL_ERR,
2956 "no suitable proposal was created.\n");
2957 return NULL;
2958 }
2959
2960 /* update length of this protocol. */
2961 prop->h.len = htons(p->l);
2962
2963 return p;
2964}
2965
2966/*
2967 * create phase2 proposal from policy configuration.
2968 * NOT INCLUDING isakmp general header of SA payload.
2969 * This function is called by initiator only.
2970 */
2971int
2972ipsecdoi_setph2proposal(phase2_handle_t *iph2, int return_sa)
2973{
2974 struct saprop *proposal, *a;
2975 struct saproto *b = NULL;
2976 vchar_t *q, *sa = NULL;
2977 struct isakmp_pl_p *prop;
2978 size_t propoff; /* for previous field of type of next payload. */
2979
2980 if (return_sa)
2981 proposal = iph2->approval;
2982 else
2983 proposal = iph2->proposal;
2984
2985 if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) {
2986 struct ipsecdoi_sa_b *sab;
2987
2988 sa = vmalloc(sizeof(*sab));
2989 if (sa == NULL) {
2990 plog(ASL_LEVEL_ERR,
2991 "failed to allocate my sa buffer\n");
2992 return -1;
2993 }
2994
2995 /* create SA payload */
2996 sab = ALIGNED_CAST(struct ipsecdoi_sa_b *)sa->v;
2997 sab->doi = htonl(IPSEC_DOI);
2998 sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */
2999
3000 }
3001
3002 prop = NULL;
3003 propoff = 0;
3004 for (a = proposal; a; a = a->next) {
3005 for (b = a->head; b; b = b->next) {
3006 if (b->proto_id == IPSECDOI_PROTO_IPCOMP) {
3007 // skip this - not specified in the SA
3008 // Need to set this in iph2 ???
3009 continue;
3010 }
3011 // IKEv1 sends encode mode in SA - uses diferent codes when NATT being used
3012#ifdef ENABLE_NATT
3013 if (iph2->ph1->natt_flags & NAT_DETECTED) {
3014 plog (ASL_LEVEL_INFO, "NAT detected -> UDP encapsulation\n");
3015 b->udp_encap = 1;
3016 if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) {
3017 int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
3018 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3019 b->encmode += udp_diff;
3020 }
3021 }
3022#endif
3023 switch (iph2->version) {
3024 case ISAKMP_VERSION_NUMBER_IKEV1:
3025 q = setph2proposal0(iph2, a, b);
3026 break;
3027 default:
3028 plog(ASL_LEVEL_ERR, "Invalid IKE version detected\n");
3029 q = NULL;
3030 break;
3031 }
3032 if (q == NULL) {
3033 VPTRINIT(sa);
3034 return -1;
3035 }
3036 if (sa != NULL)
3037 sa = vrealloc(sa, sa->l + q->l);
3038 else
3039 sa = vmalloc(q->l);
3040
3041 if (sa == NULL) {
3042 plog(ASL_LEVEL_ERR,
3043 "failed to allocate my sa buffer\n");
3044 if (q)
3045 vfree(q);
3046 return -1;
3047 }
3048 memcpy(sa->v + sa->l - q->l, q->v, q->l);
3049 if (propoff != 0) {
3050 prop = (struct isakmp_pl_p *)(sa->v +
3051 propoff);
3052 if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1)
3053 prop->h.np = ISAKMP_NPTYPE_P;
3054 }
3055 propoff = sa->l - q->l;
3056
3057 vfree(q);
3058 }
3059 }
3060 if (return_sa)
3061 iph2->sa_ret = sa;
3062 else
3063 iph2->sa = sa;
3064 return 0;
3065}
3066
3067/*
3068 * return 1 if all of the given protocols are tunnel mode.
3069 */
3070int
3071ipsecdoi_tunnelmode(iph2)
3072 phase2_handle_t *iph2;
3073{
3074 struct saprop *pp;
3075 struct saproto *pr = NULL;
3076
3077 for (pp = iph2->proposal; pp; pp = pp->next) {
3078 for (pr = pp->head; pr; pr = pr->next) {
3079 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TUNNEL &&
3080 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC &&
3081 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT)
3082 return 0;
3083 }
3084 }
3085
3086 return 1;
3087}
3088
3089/*
3090 * return 1 if any of the given protocols are transport mode.
3091 */
3092int
3093ipsecdoi_any_transportmode(pp)
3094struct saprop *pp;
3095{
3096 struct saproto *pr = NULL;
3097
3098 for (; pp; pp = pp->next) {
3099 for (pr = pp->head; pr; pr = pr->next) {
3100 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TRNS ||
3101 pr->encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC ||
3102 pr->encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
3103 return 1;
3104 }
3105 }
3106
3107 return 0;
3108}
3109
3110/*
3111 * return 1 if all of the given protocols are transport mode.
3112 */
3113int
3114ipsecdoi_transportmode(pp)
3115 struct saprop *pp;
3116{
3117 struct saproto *pr = NULL;
3118
3119 for (; pp; pp = pp->next) {
3120 for (pr = pp->head; pr; pr = pr->next) {
3121 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
3122 return 0;
3123 }
3124 }
3125
3126 return 1;
3127}
3128
3129int
3130ipsecdoi_get_defaultlifetime()
3131{
3132 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3133}
3134
3135int
3136ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
3137 int proto_id, enc, auth, comp;
3138{
3139#define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3140 switch (proto_id) {
3141 case IPSECDOI_PROTO_IPSEC_ESP:
3142 if (enc == 0 || comp != 0) {
3143 plog(ASL_LEVEL_ERR,
3144 "illegal algorithm defined "
3145 "ESP enc=%s auth=%s comp=%s.\n",
3146 TMPALGTYPE2STR(enc),
3147 TMPALGTYPE2STR(auth),
3148 TMPALGTYPE2STR(comp));
3149 return -1;
3150 }
3151 break;
3152 case IPSECDOI_PROTO_IPSEC_AH:
3153 if (enc != 0 || auth == 0 || comp != 0) {
3154 plog(ASL_LEVEL_ERR,
3155 "illegal algorithm defined "
3156 "AH enc=%s auth=%s comp=%s.\n",
3157 TMPALGTYPE2STR(enc),
3158 TMPALGTYPE2STR(auth),
3159 TMPALGTYPE2STR(comp));
3160 return -1;
3161 }
3162 break;
3163 case IPSECDOI_PROTO_IPCOMP:
3164 if (enc != 0 || auth != 0 || comp == 0) {
3165 plog(ASL_LEVEL_ERR,
3166 "illegal algorithm defined "
3167 "IPcomp enc=%s auth=%s comp=%s.\n",
3168 TMPALGTYPE2STR(enc),
3169 TMPALGTYPE2STR(auth),
3170 TMPALGTYPE2STR(comp));
3171 return -1;
3172 }
3173 break;
3174 default:
3175 plog(ASL_LEVEL_ERR,
3176 "invalid ipsec protocol %d\n", proto_id);
3177 return -1;
3178 }
3179#undef TMPALGTYPE2STR
3180 return 0;
3181}
3182
3183int
3184ipproto2doi(proto)
3185 int proto;
3186{
3187 switch (proto) {
3188 case IPPROTO_AH:
3189 return IPSECDOI_PROTO_IPSEC_AH;
3190 case IPPROTO_ESP:
3191 return IPSECDOI_PROTO_IPSEC_ESP;
3192 case IPPROTO_IPCOMP:
3193 return IPSECDOI_PROTO_IPCOMP;
3194 }
3195 return -1; /* XXX */
3196}
3197
3198int
3199doi2ipproto(proto)
3200 int proto;
3201{
3202 switch (proto) {
3203 case IPSECDOI_PROTO_IPSEC_AH:
3204 return IPPROTO_AH;
3205 case IPSECDOI_PROTO_IPSEC_ESP:
3206 return IPPROTO_ESP;
3207 case IPSECDOI_PROTO_IPCOMP:
3208 return IPPROTO_IPCOMP;
3209 }
3210 return -1; /* XXX */
3211}
3212
3213/*
3214 * Check if a subnet id is valid for comparison
3215 * with an address id ( address length mask )
3216 * and compare them
3217 * Return value
3218 * = 0 for match
3219 * = 1 for mismatch
3220 */
3221
3222int
3223ipsecdoi_subnetisaddr_v4( subnet, address )
3224 const vchar_t *subnet;
3225 const vchar_t *address;
3226{
3227 struct in_addr *mask;
3228
3229 if (address->l != sizeof(struct in_addr))
3230 return 1;
3231
3232 if (subnet->l != (sizeof(struct in_addr)*2))
3233 return 1;
3234
3235 mask = ALIGNED_CAST(struct in_addr*)(subnet->v + sizeof(struct in_addr));
3236
3237 if (mask->s_addr!=0xffffffff)
3238 return 1;
3239
3240 return memcmp(subnet->v,address->v,address->l);
3241}
3242
3243#ifdef INET6
3244
3245int
3246ipsecdoi_subnetisaddr_v6( subnet, address )
3247 const vchar_t *subnet;
3248 const vchar_t *address;
3249{
3250 struct in6_addr *mask;
3251 int i;
3252
3253 if (address->l != sizeof(struct in6_addr))
3254 return 1;
3255
3256 if (subnet->l != (sizeof(struct in6_addr)*2))
3257 return 1;
3258
3259 mask = ALIGNED_CAST(struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
3260
3261 for (i=0; i<16; i++)
3262 if(mask->s6_addr[i]!=0xff)
3263 return 1;
3264
3265 return memcmp(subnet->v,address->v,address->l);
3266}
3267
3268#endif
3269
3270#ifdef NOT_USED
3271/*
3272 * Check and Compare two IDs
3273 * - specify 0 for exact if wildcards are allowed
3274 * Return value
3275 * = 0 for match
3276 * = 1 for misatch
3277 * = -1 for integrity error
3278 */
3279
3280int
3281ipsecdoi_chkcmpids( idt, ids, exact )
3282 const vchar_t *idt; /* id cmp target */
3283 const vchar_t *ids; /* id cmp source */
3284 int exact;
3285{
3286 struct ipsecdoi_id_b *id_bt;
3287 struct ipsecdoi_id_b *id_bs;
3288 vchar_t ident_t;
3289 vchar_t ident_s;
3290 int result;
3291
3292 /* handle wildcard IDs */
3293
3294 if (idt == NULL || ids == NULL)
3295 {
3296 if( !exact )
3297 {
3298 plog(ASL_LEVEL_DEBUG,
3299 "check and compare ids : values matched (ANONYMOUS)\n" );
3300 return 0;
3301 }
3302 else
3303 {
3304 plog(ASL_LEVEL_DEBUG,
3305 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3306 return -1;
3307 }
3308 }
3309
3310 /* make sure the ids are of the same type */
3311
3312 id_bt = (struct ipsecdoi_id_b *) idt->v;
3313 id_bs = (struct ipsecdoi_id_b *) ids->v;
3314
3315 ident_t.v = idt->v + sizeof(*id_bt);
3316 ident_t.l = idt->l - sizeof(*id_bt);
3317 ident_s.v = ids->v + sizeof(*id_bs);
3318 ident_s.l = ids->l - sizeof(*id_bs);
3319
3320 if (id_bs->type != id_bt->type)
3321 {
3322 /*
3323 * special exception for comparing
3324 * address to subnet id types when
3325 * the netmask is address length
3326 */
3327
3328 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
3329 (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
3330 result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
3331 goto cmpid_result;
3332 }
3333
3334 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
3335 (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
3336 result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
3337 goto cmpid_result;
3338 }
3339
3340#ifdef INET6
3341 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
3342 (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
3343 result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
3344 goto cmpid_result;
3345 }
3346
3347 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
3348 (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
3349 result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
3350 goto cmpid_result;
3351 }
3352#endif
3353 plog(ASL_LEVEL_DEBUG,
3354 "check and compare ids : id type mismatch %s != %s\n",
3355 s_ipsecdoi_ident(id_bs->type),
3356 s_ipsecdoi_ident(id_bt->type));
3357
3358 return 1;
3359 }
3360
3361 if(id_bs->proto_id != id_bt->proto_id){
3362 plog(ASL_LEVEL_DEBUG,
3363 "check and compare ids : proto_id mismatch %d != %d\n",
3364 id_bs->proto_id, id_bt->proto_id);
3365
3366 return 1;
3367 }
3368
3369 /* compare the ID data. */
3370
3371 switch (id_bt->type) {
3372 case IPSECDOI_ID_DER_ASN1_DN:
3373 case IPSECDOI_ID_DER_ASN1_GN:
3374 /* compare asn1 ids */
3375 result = eay_cmp_asn1dn(&ident_t, &ident_s);
3376 goto cmpid_result;
3377
3378 case IPSECDOI_ID_IPV4_ADDR:
3379 /* validate lengths */
3380 if ((ident_t.l != sizeof(struct in_addr))||
3381 (ident_s.l != sizeof(struct in_addr)))
3382 goto cmpid_invalid;
3383 break;
3384
3385 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3386 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3387 /* validate lengths */
3388 if ((ident_t.l != (sizeof(struct in_addr)*2))||
3389 (ident_s.l != (sizeof(struct in_addr)*2)))
3390 goto cmpid_invalid;
3391 break;
3392
3393#ifdef INET6
3394 case IPSECDOI_ID_IPV6_ADDR:
3395 /* validate lengths */
3396 if ((ident_t.l != sizeof(struct in6_addr))||
3397 (ident_s.l != sizeof(struct in6_addr)))
3398 goto cmpid_invalid;
3399 break;
3400
3401 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3402 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3403 /* validate lengths */
3404 if ((ident_t.l != (sizeof(struct in6_addr)*2))||
3405 (ident_s.l != (sizeof(struct in6_addr)*2)))
3406 goto cmpid_invalid;
3407 break;
3408#endif
3409 case IPSECDOI_ID_FQDN:
3410 case IPSECDOI_ID_USER_FQDN:
3411 case IPSECDOI_ID_KEY_ID:
3412 break;
3413
3414 default:
3415 plog(ASL_LEVEL_ERR,
3416 "Unhandled id type %i specified for comparison\n",
3417 id_bt->type);
3418 return -1;
3419 }
3420
3421 /* validate matching data and length */
3422 if (ident_t.l == ident_s.l)
3423 result = memcmp(ident_t.v,ident_s.v,ident_t.l);
3424 else
3425 result = 1;
3426
3427cmpid_result:
3428
3429 /* debug level output */
3430 if(loglevel >= ASL_LEVEL_DEBUG) {
3431 char *idstrt = ipsecdoi_id2str(idt);
3432 char *idstrs = ipsecdoi_id2str(ids);
3433
3434 if (!result)
3435 plog(ASL_LEVEL_DEBUG,
3436 "check and compare ids : values matched (%s)\n",
3437 s_ipsecdoi_ident(id_bs->type) );
3438 else
3439 plog(ASL_LEVEL_DEBUG,
3440 "check and compare ids : value mismatch (%s)\n",
3441 s_ipsecdoi_ident(id_bs->type));
3442
3443 plog(ASL_LEVEL_DEBUG, "cmpid target: \'%s\'\n", idstrt );
3444 plog(ASL_LEVEL_DEBUG, "cmpid source: \'%s\'\n", idstrs );
3445
3446 racoon_free(idstrs);
3447 racoon_free(idstrt);
3448 }
3449
3450 /* return result */
3451 if( !result )
3452 return 0;
3453 else
3454 return 1;
3455
3456cmpid_invalid:
3457
3458 /* id integrity error */
3459 plog(ASL_LEVEL_DEBUG, "check and compare ids : %s integrity error\n",
3460 s_ipsecdoi_ident(id_bs->type));
3461 plog(ASL_LEVEL_DEBUG, "cmpid target: length = \'%zu\'\n", ident_t.l );
3462 plog(ASL_LEVEL_DEBUG, "cmpid source: length = \'%zu\'\n", ident_s.l );
3463
3464 return -1;
3465}
3466#endif
3467
3468/*
3469 * check the following:
3470 * - In main mode with pre-shared key, only address type can be used.
3471 * - if proper type for phase 1 ?
3472 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3473 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3474 * - if ID payload sent from peer is equal to the ID expected by me.
3475 *
3476 * both of "id" and "id_p" should be ID payload without general header,
3477 */
3478int
3479ipsecdoi_checkid1(iph1)
3480 phase1_handle_t *iph1;
3481{
3482 struct ipsecdoi_id_b *id_b;
3483 struct sockaddr_storage *sa;
3484 caddr_t sa1, sa2;
3485
3486 if (iph1->id_p == NULL) {
3487 plog(ASL_LEVEL_ERR,
3488 "invalid iph1 passed id_p == NULL\n");
3489 return ISAKMP_INTERNAL_ERROR;
3490 }
3491 if (iph1->id_p->l < sizeof(*id_b)) {
3492 plog(ASL_LEVEL_ERR,
3493 "invalid value passed as \"ident\" (len=%lu)\n",
3494 (u_long)iph1->id_p->l);
3495 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3496 }
3497
3498 id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v;
3499
3500 /* In main mode with pre-shared key, only address type can be used.
3501 * If NAT Traversal being used and peer is behind nat and
3502 * natt version = 02 - allow non-address ID type.
3503 */
3504 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1
3505 && iph1->etype == ISAKMP_ETYPE_IDENT
3506 && iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY
3507#ifdef ENABLE_NATT
3508 && (iph1->natt_flags & NAT_DETECTED_PEER) == 0
3509#endif
3510 ) {
3511 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3512 && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3513 plog(ASL_LEVEL_ERR,
3514 "Expecting IP address type in main mode, "
3515 "but %s.\n", s_ipsecdoi_ident(id_b->type));
3516 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3517 }
3518 }
3519
3520 /* if proper type for phase 1 ? */
3521 switch (id_b->type) {
3522 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3523 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3524 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3525 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3526 plog(ASL_LEVEL_WARNING,
3527 "such ID type %s is not proper.\n",
3528 s_ipsecdoi_ident(id_b->type));
3529 /*FALLTHROUGH*/
3530 }
3531
3532 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3533 if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
3534 id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3535
3536 if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
3537 plog(ASL_LEVEL_WARNING,
3538 "protocol ID and Port mismatched. "
3539 "proto_id:%d port:%d\n",
3540 id_b->proto_id, ntohs(id_b->port));
3541 /*FALLTHROUGH*/
3542
3543 } else if (id_b->proto_id == IPPROTO_UDP) {
3544 /*
3545 * copmaring with expected port.
3546 * always permit if port is equal to PORT_ISAKMP
3547 */
3548 if (ntohs(id_b->port) != PORT_ISAKMP) {
3549
3550 u_int16_t port;
3551
3552 switch (iph1->remote->ss_family) {
3553 case AF_INET:
3554 port = ((struct sockaddr_in *)iph1->remote)->sin_port;
3555 break;
3556#ifdef INET6
3557 case AF_INET6:
3558 port = ((struct sockaddr_in6 *)iph1->remote)->sin6_port;
3559 break;
3560#endif
3561 default:
3562 plog(ASL_LEVEL_ERR,
3563 "invalid family: %d\n",
3564 iph1->remote->ss_family);
3565 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3566 }
3567 if (ntohs(id_b->port) != port) {
3568 plog(ASL_LEVEL_WARNING,
3569 "port %d expected, but %d\n",
3570 port, ntohs(id_b->port));
3571 /*FALLTHROUGH*/
3572 }
3573 }
3574 }
3575 }
3576
3577 /* compare with the ID if specified. */
3578 if (genlist_next(iph1->rmconf->idvl_p, 0)) {
3579 vchar_t *ident0 = NULL;
3580#ifdef HAVE_OPENSSL
3581 vchar_t ident;
3582#endif
3583 struct idspec *id;
3584 struct genlist_entry *gpb;
3585
3586 for (id = genlist_next (iph1->rmconf->idvl_p, &gpb); id; id = genlist_next (0, &gpb)) {
3587 /* check the type of both IDs */
3588 if (id->idtype != doi2idtype(id_b->type))
3589 continue; /* ID type mismatch */
3590 if (id->id == 0)
3591 goto matched;
3592
3593 /* compare defined ID with the ID sent by peer. */
3594 if (ident0 != NULL)
3595 vfree(ident0);
3596 ident0 = getidval(id->idtype, id->id);
3597
3598 switch (id->idtype) {
3599 case IDTYPE_ASN1DN:
3600#ifdef HAVE_OPENSSL
3601 ident.v = iph1->id_p->v + sizeof(*id_b);
3602 ident.l = iph1->id_p->l - sizeof(*id_b);
3603 if (eay_cmp_asn1dn(ident0, &ident) == 0)
3604 goto matched;
3605#else
3606 plog(ASL_LEVEL_WARNING, "ASN1DN ID matching not implemented - passed.\n");
3607 goto matched; //%%%%%% hack for now until we have code to do this.
3608#endif
3609 break;
3610 case IDTYPE_ADDRESS:
3611 sa = ALIGNED_CAST(struct sockaddr_storage *)ident0->v;
3612 sa2 = (caddr_t)(id_b + 1);
3613 switch (sa->ss_family) {
3614 case AF_INET:
3615 if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
3616 continue; /* ID value mismatch */
3617 sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr;
3618 if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
3619 goto matched;
3620 break;
3621#ifdef INET6
3622 case AF_INET6:
3623 if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
3624 continue; /* ID value mismatch */
3625 sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr;
3626 if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
3627 goto matched;
3628 break;
3629#endif
3630 default:
3631 break;
3632 }
3633 break;
3634 default:
3635 if (memcmp(ident0->v, id_b + 1, ident0->l) == 0)
3636 goto matched;
3637 break;
3638 }
3639 }
3640 if (ident0 != NULL) {
3641 vfree(ident0);
3642 ident0 = NULL;
3643 }
3644 plog(ASL_LEVEL_DEBUG, "No ID match.\n");
3645 if (iph1->rmconf->verify_identifier)
3646 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3647matched: /* ID value match */
3648 if (ident0 != NULL)
3649 vfree(ident0);
3650 }
3651
3652 return 0;
3653}
3654
3655/* HACK!!! - temporary until this prototype gets moved */
3656extern CFDataRef SecCertificateCopySubjectSequence( SecCertificateRef certificate);
3657
3658/*
3659 * create ID payload for phase 1 and set into iph1->id.
3660 * NOT INCLUDING isakmp general header.
3661 * see, RFC2407 4.6.2.1
3662 */
3663int
3664ipsecdoi_setid1(iph1)
3665 phase1_handle_t *iph1;
3666{
3667 vchar_t *ret = NULL;
3668 struct ipsecdoi_id_b id_b;
3669 vchar_t *ident = NULL;
3670 struct sockaddr_storage *ipid = NULL;
3671
3672 /* init */
3673 bzero(&id_b, sizeof(id_b));
3674 ident = NULL;
3675 switch (iph1->rmconf->idvtype) {
3676 case IDTYPE_FQDN:
3677 id_b.type = IPSECDOI_ID_FQDN;
3678 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3679 break;
3680 case IDTYPE_USERFQDN:
3681 id_b.type = IPSECDOI_ID_USER_FQDN;
3682 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3683 break;
3684 case IDTYPE_KEYID:
3685 case IDTYPE_KEYIDUSE:
3686 id_b.type = IPSECDOI_ID_KEY_ID;
3687 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3688 break;
3689 case IDTYPE_ASN1DN:
3690 id_b.type = IPSECDOI_ID_DER_ASN1_DN;
3691 if (iph1->rmconf->idv) {
3692 /* XXX it must be encoded to asn1dn. */
3693 ident = vdup(iph1->rmconf->idv);
3694 } else {
3695 if (oakley_getmycert(iph1) < 0) {
3696 plog(ASL_LEVEL_ERR,
3697 "failed to get own CERT.\n");
3698 goto err;
3699 }
3700
3701 SecCertificateRef certificate;
3702 CFDataRef subject;
3703 UInt8* namePtr;
3704 int len;
3705
3706 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(&iph1->cert->cert);
3707 if (certificate == NULL) {
3708 plog(ASL_LEVEL_ERR,
3709 "failed to get SecCertificateRef\n");
3710 break;
3711 }
3712 subject = crypto_cssm_CopySubjectSequence(certificate);
3713 if (subject == NULL) {
3714 plog(ASL_LEVEL_ERR,
3715 "failed to get subjectName\n");
3716 CFRelease(certificate);
3717 break;
3718 }
3719 len = CFDataGetLength(subject);
3720 namePtr = (UInt8*)CFDataGetBytePtr(subject);
3721 ident = vmalloc(len);
3722 if (ident == NULL) {
3723 plog(ASL_LEVEL_ERR,
3724 "failed to get subjectName\n");
3725 CFRelease(certificate);
3726 CFRelease(subject);
3727 break;
3728 }
3729 memcpy(ident->v, namePtr, len);
3730 CFRelease(certificate);
3731 CFRelease(subject);
3732 }
3733 break;
3734 case IDTYPE_ADDRESS:
3735 /*
3736 * if the value of the id type was set by the configuration
3737 * file, then use it. otherwise the value is get from local
3738 * ip address by using ike negotiation.
3739 */
3740 if (iph1->rmconf->idv)
3741 ipid = ALIGNED_CAST(struct sockaddr_storage *)iph1->rmconf->idv->v;
3742 /*FALLTHROUGH*/
3743 default:
3744 {
3745 int l;
3746 caddr_t p;
3747
3748 if (ipid == NULL)
3749 ipid = iph1->local;
3750
3751 /* use IP address */
3752 switch (ipid->ss_family) {
3753 case AF_INET:
3754 id_b.type = IPSECDOI_ID_IPV4_ADDR;
3755 l = sizeof(struct in_addr);
3756 p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
3757 break;
3758#ifdef INET6
3759 case AF_INET6:
3760 id_b.type = IPSECDOI_ID_IPV6_ADDR;
3761 l = sizeof(struct in6_addr);
3762 p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
3763 break;
3764#endif
3765 default:
3766 plog(ASL_LEVEL_ERR,
3767 "invalid address family.\n");
3768 goto err;
3769 }
3770 if(iph1->version == ISAKMP_VERSION_NUMBER_IKEV1){
3771 id_b.proto_id = IPPROTO_UDP;
3772 id_b.port = htons(PORT_ISAKMP);
3773
3774 }
3775 ident = vmalloc(l);
3776 if (!ident) {
3777 plog(ASL_LEVEL_ERR,
3778 "failed to get ID buffer.\n");
3779 return 0;
3780 }
3781 memcpy(ident->v, p, ident->l);
3782 }
3783 }
3784 if (!ident) {
3785 plog(ASL_LEVEL_ERR,
3786 "failed to get ID buffer.\n");
3787 return 0;
3788 }
3789
3790 ret = vmalloc(sizeof(id_b) + ident->l);
3791 if (ret == NULL) {
3792 plog(ASL_LEVEL_ERR,
3793 "failed to get ID buffer.\n");
3794 goto err;
3795 }
3796
3797 memcpy(ret->v, &id_b, sizeof(id_b));
3798 memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
3799
3800 iph1->id = ret;
3801
3802 plogdump(ASL_LEVEL_DEBUG, iph1->id->v, iph1->id->l, "use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
3803 if (ident)
3804 vfree(ident);
3805 return 0;
3806
3807err:
3808 if (ident)
3809 vfree(ident);
3810 plog(ASL_LEVEL_ERR, "failed get my ID\n");
3811 return -1;
3812}
3813
3814static vchar_t *
3815getidval(type, val)
3816 int type;
3817 vchar_t *val;
3818{
3819 vchar_t *new = NULL;
3820
3821 if (val)
3822 new = vdup(val);
3823 else if (lcconf->ident[type])
3824 new = vdup(lcconf->ident[type]);
3825
3826 return new;
3827}
3828
3829/* it's only called by cfparse.y. */
3830int
3831set_identifier(vpp, type, value)
3832 vchar_t **vpp, *value;
3833 int type;
3834{
3835 return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
3836}
3837
3838int
3839set_identifier_qual(vpp, type, value, qual)
3840 vchar_t **vpp, *value;
3841 int type;
3842 int qual;
3843{
3844 vchar_t *new = NULL;
3845
3846 /* simply return if value is null. */
3847 if (!value){
3848 if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
3849 plog(ASL_LEVEL_ERR,
3850 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3851 return -1;
3852 }
3853 return 0;
3854 }
3855
3856 switch (type) {
3857 case IDTYPE_FQDN:
3858 case IDTYPE_USERFQDN:
3859 if(value->l <= 1){
3860 plog(ASL_LEVEL_ERR,
3861 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3862 return -1;
3863 }
3864 case IDTYPE_KEYIDUSE:
3865#ifdef ENABLE_HYBRID
3866 case IDTYPE_LOGIN:
3867#endif
3868 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3869 new = vmalloc(value->l - 1);
3870 if (new == NULL)
3871 return -1;
3872 memcpy(new->v, value->v, new->l);
3873 break;
3874 case IDTYPE_KEYID:
3875 /*
3876 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3877 * to use a file for backward compatibility sake.
3878 */
3879 switch(qual) {
3880 case IDQUAL_FILE:
3881 case IDQUAL_UNSPEC: {
3882 FILE *fp;
3883 char b[512];
3884 int tlen, len;
3885
3886 fp = fopen(value->v, "r");
3887 if (fp == NULL) {
3888 plog(ASL_LEVEL_ERR,
3889 "can not open %s\n", value->v);
3890 return -1;
3891 }
3892 tlen = 0;
3893 while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
3894 new = vrealloc(new, tlen + len);
3895 if (!new) {
3896 fclose(fp);
3897 return -1;
3898 }
3899 memcpy(new->v + tlen, b, len);
3900 tlen += len;
3901 }
3902 fclose(fp);
3903 break;
3904 }
3905
3906 case IDQUAL_TAG:
3907 new = vmalloc(value->l - 1);
3908 if (new == NULL) {
3909 plog(ASL_LEVEL_ERR,
3910 "can not allocate memory");
3911 return -1;
3912 }
3913 memcpy(new->v, value->v, new->l);
3914 break;
3915
3916 default:
3917 plog(ASL_LEVEL_ERR,
3918 "unknown qualifier");
3919 return -1;
3920 }
3921 break;
3922
3923 case IDTYPE_ADDRESS: {
3924 struct sockaddr_storage *sa;
3925
3926 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3927 if (value->l == 0)
3928 break;
3929
3930 sa = str2saddr(value->v, NULL);
3931 if (sa == NULL) {
3932 plog(ASL_LEVEL_ERR,
3933 "invalid ip address %s\n", value->v);
3934 return -1;
3935 }
3936
3937 new = vmalloc(sysdep_sa_len((struct sockaddr *)sa));
3938 if (new == NULL) {
3939 racoon_free(sa);
3940 return -1;
3941 }
3942 memcpy(new->v, sa, new->l);
3943 racoon_free(sa);
3944 break;
3945 }
3946 case IDTYPE_ASN1DN:
3947 plog(ASL_LEVEL_DEBUG, "Setting ID type ASN1DN from string not supported\n");
3948 return -1;
3949
3950 break;
3951 }
3952
3953 *vpp = new;
3954
3955 return 0;
3956}
3957
3958/*
3959 * create ID payload for phase 2, and set into iph2->id and id_p. There are
3960 * NOT INCLUDING isakmp general header.
3961 * this function is for initiator. responder will get to copy from payload.
3962 * responder ID type is always address type.
3963 * see, RFC2407 4.6.2.1
3964 */
3965int
3966ipsecdoi_setid2(iph2)
3967 phase2_handle_t *iph2;
3968{
3969 struct secpolicy *sp;
3970
3971 /* check there is phase 2 handler ? */
3972 sp = getspbyspid(iph2->spid);
3973 if (sp == NULL) {
3974 plog(ASL_LEVEL_ERR,
3975 "no policy found for spid:%u.\n", iph2->spid);
3976 return -1;
3977 }
3978
3979 iph2->id = ipsecdoi_sockaddr2id(&sp->spidx.src,
3980 sp->spidx.prefs, sp->spidx.ul_proto);
3981 if (iph2->id == NULL) {
3982 plog(ASL_LEVEL_ERR,
3983 "failed to get ID for %s\n",
3984 spidx2str(&sp->spidx));
3985 return -1;
3986 }
3987#ifdef ENABLE_NATT
3988 if (((ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id->v)->type == IPSECDOI_ID_IPV4_ADDR ||
3989 (ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id->v)->type == IPSECDOI_ID_IPV4_ADDR_SUBNET) &&
3990 iph2->side == RESPONDER &&
3991 iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED_ME) &&
3992 lcconf->ext_nat_id) {
3993 vfree(iph2->id);
3994 if (!(iph2->id = vdup(lcconf->ext_nat_id))) {
3995 return -1;
3996 }
3997 }
3998#endif
3999 plogdump(ASL_LEVEL_DEBUG, iph2->id->v, iph2->id->l, "use local ID type %s\n",
4000 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id->v)->type));
4001
4002 /* remote side */
4003 iph2->id_p = ipsecdoi_sockaddr2id(&sp->spidx.dst,
4004 sp->spidx.prefd, sp->spidx.ul_proto);
4005 if (iph2->id_p == NULL) {
4006 plog(ASL_LEVEL_ERR,
4007 "failed to get ID for %s\n",
4008 spidx2str(&sp->spidx));
4009 VPTRINIT(iph2->id);
4010 return -1;
4011 }
4012 plogdump(ASL_LEVEL_DEBUG, iph2->id->v, iph2->id->l, "use remote ID type %s\n",
4013 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id_p->v)->type));
4014
4015 return 0;
4016}
4017
4018/*
4019 * set address type of ID.
4020 * NOT INCLUDING general header.
4021 */
4022vchar_t *
4023ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
4024 struct sockaddr_storage *saddr;
4025 u_int prefixlen;
4026 u_int ul_proto;
4027{
4028 vchar_t *new;
4029 int type, len1, len2;
4030 caddr_t sa;
4031 u_short port;
4032
4033 /*
4034 * Q. When type is SUBNET, is it allowed to be ::1/128.
4035 * A. Yes. (consensus at bake-off)
4036 */
4037 switch (saddr->ss_family) {
4038 case AF_INET:
4039 len1 = sizeof(struct in_addr);
4040 if (prefixlen == (sizeof(struct in_addr) << 3)) {
4041 type = IPSECDOI_ID_IPV4_ADDR;
4042 len2 = 0;
4043 } else {
4044 type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
4045 len2 = sizeof(struct in_addr);
4046 }
4047 sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
4048 port = ((struct sockaddr_in *)(saddr))->sin_port;
4049 break;
4050#ifdef INET6
4051 case AF_INET6:
4052 len1 = sizeof(struct in6_addr);
4053 if (prefixlen == (sizeof(struct in6_addr) << 3)) {
4054 type = IPSECDOI_ID_IPV6_ADDR;
4055 len2 = 0;
4056 } else {
4057 type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
4058 len2 = sizeof(struct in6_addr);
4059 }
4060 sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
4061 port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
4062 break;
4063#endif
4064 default:
4065 plog(ASL_LEVEL_ERR,
4066 "invalid family: %d.\n", saddr->ss_family);
4067 return NULL;
4068 }
4069
4070 /* get ID buffer */
4071 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4072 if (new == NULL) {
4073 plog(ASL_LEVEL_ERR,
4074 "failed to get ID buffer.\n");
4075 return NULL;
4076 }
4077
4078 memset(new->v, 0, new->l);
4079
4080 /* set the part of header. */
4081 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->type = type;
4082
4083 /* set ul_proto and port */
4084 /*
4085 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4086 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4087 */
4088 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->proto_id =
4089 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4090 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->port =
4091 port == IPSEC_PORT_ANY ? 0 : port;
4092 memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
4093
4094 /* set address */
4095
4096 /* set prefix */
4097 if (len2) {
4098 u_char *p = (unsigned char *) new->v +
4099 sizeof(struct ipsecdoi_id_b) + len1;
4100 u_int bits = prefixlen;
4101
4102 while (bits >= 8) {
4103 *p++ = 0xff;
4104 bits -= 8;
4105 }
4106
4107 if (bits > 0)
4108 *p = ~((1 << (8 - bits)) - 1);
4109 }
4110
4111 return new;
4112}
4113
4114vchar_t *
4115ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
4116 struct sockaddr_storage *laddr, *haddr;
4117 u_int ul_proto;
4118{
4119 vchar_t *new;
4120 int type, len1, len2;
4121 u_short port;
4122
4123 if (laddr->ss_family != haddr->ss_family) {
4124 plog(ASL_LEVEL_ERR, "Address family mismatch\n");
4125 return NULL;
4126 }
4127
4128 switch (laddr->ss_family) {
4129 case AF_INET:
4130 type = IPSECDOI_ID_IPV4_ADDR_RANGE;
4131 len1 = sizeof(struct in_addr);
4132 len2 = sizeof(struct in_addr);
4133 break;
4134#ifdef INET6
4135 case AF_INET6:
4136 type = IPSECDOI_ID_IPV6_ADDR_RANGE;
4137 len1 = sizeof(struct in6_addr);
4138 len2 = sizeof(struct in6_addr);
4139 break;
4140#endif
4141 default:
4142 plog(ASL_LEVEL_ERR,
4143 "invalid family: %d.\n", laddr->ss_family);
4144 return NULL;
4145 }
4146
4147 /* get ID buffer */
4148 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4149 if (new == NULL) {
4150 plog(ASL_LEVEL_ERR,
4151 "failed to get ID buffer.\n");
4152 return NULL;
4153 }
4154
4155 memset(new->v, 0, new->l);
4156 /* set the part of header. */
4157 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->type = type;
4158
4159 /* set ul_proto and port */
4160 /*
4161 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4162 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4163 */
4164 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->proto_id =
4165 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4166 port = ((struct sockaddr_in *)(laddr))->sin_port;
4167 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->port =
4168 port == IPSEC_PORT_ANY ? 0 : port;
4169 memcpy(new->v + sizeof(struct ipsecdoi_id_b),
4170 (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
4171 len1);
4172 memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
4173 (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
4174 len2);
4175 return new;
4176}
4177
4178
4179/*
4180 * create sockaddr_storage structure from ID payload (buf).
4181 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4182 * see, RFC2407 4.6.2.1
4183 */
4184int
4185ipsecdoi_id2sockaddr(vchar_t *buf,
4186 struct sockaddr_storage *saddr,
4187 u_int8_t *prefixlen,
4188 u_int16_t *ul_proto,
4189 int version)
4190{
4191 struct ipsecdoi_id_b *id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)buf->v;
4192 u_int plen = 0;
4193
4194 /*
4195 * When a ID payload of subnet type with a IP address of full bit
4196 * masked, it has to be processed as host address.
4197 * e.g. below 2 type are same.
4198 * type = ipv6 subnet, data = 2001::1/128
4199 * type = ipv6 address, data = 2001::1
4200 */
4201 switch (id_b->type) {
4202 case IPSECDOI_ID_IPV4_ADDR:
4203 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4204 saddr->ss_len = sizeof(struct sockaddr_in);
4205 saddr->ss_family = AF_INET;
4206 ((struct sockaddr_in *)saddr)->sin_port =
4207 (id_b->port == 0
4208 ? IPSEC_PORT_ANY
4209 : id_b->port); /* see sockaddr2id() */
4210 memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
4211 buf->v + sizeof(*id_b), sizeof(struct in_addr));
4212 break;
4213#ifdef INET6
4214 case IPSECDOI_ID_IPV6_ADDR:
4215 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4216 saddr->ss_len = sizeof(struct sockaddr_in6);
4217 saddr->ss_family = AF_INET6;
4218 ((struct sockaddr_in6 *)saddr)->sin6_port =
4219 (id_b->port == 0
4220 ? IPSEC_PORT_ANY
4221 : id_b->port); /* see sockaddr2id() */
4222 memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
4223 buf->v + sizeof(*id_b), sizeof(struct in6_addr));
4224 break;
4225#endif
4226 default:
4227 plog(ASL_LEVEL_ERR,
4228 "unsupported ID type %d\n", id_b->type);
4229 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
4230 }
4231
4232 /* get prefix length */
4233 switch (id_b->type) {
4234 case IPSECDOI_ID_IPV4_ADDR:
4235 plen = sizeof(struct in_addr) << 3;
4236 break;
4237#ifdef INET6
4238 case IPSECDOI_ID_IPV6_ADDR:
4239 plen = sizeof(struct in6_addr) << 3;
4240 break;
4241#endif
4242 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4243#ifdef INET6
4244 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4245#endif
4246 {
4247 u_char *p;
4248 u_int max;
4249 int alen = sizeof(struct in_addr);
4250
4251 switch (id_b->type) {
4252 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4253 alen = sizeof(struct in_addr);
4254 break;
4255#ifdef INET6
4256 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4257 alen = sizeof(struct in6_addr);
4258 break;
4259#endif
4260 }
4261
4262 /* sanity check */
4263 if (buf->l < alen)
4264 return ISAKMP_INTERNAL_ERROR;
4265
4266 /* get subnet mask length */
4267 plen = 0;
4268 max = alen <<3;
4269
4270 p = (unsigned char *) buf->v
4271 + sizeof(struct ipsecdoi_id_b)
4272 + alen;
4273
4274 for (; *p == 0xff; p++) {
4275 plen += 8;
4276 if (plen >= max)
4277 break;
4278 }
4279
4280 if (plen < max) {
4281 u_int l = 0;
4282 u_char b = ~(*p);
4283
4284 while (b) {
4285 b >>= 1;
4286 l++;
4287 }
4288
4289 l = 8 - l;
4290 plen += l;
4291 }
4292 }
4293 break;
4294 }
4295
4296 *prefixlen = plen;
4297 if (version == ISAKMP_VERSION_NUMBER_IKEV1) {
4298 *ul_proto = id_b->proto_id == 0 ? IPSEC_ULPROTO_ANY : id_b->proto_id; /* see sockaddr2id() */
4299 }
4300
4301 return 0;
4302}
4303
4304/*
4305 * make printable string from ID payload except of general header.
4306 */
4307char *
4308ipsecdoi_id2str(id)
4309 const vchar_t *id;
4310{
4311#define BUFLEN 512
4312 char * ret = NULL;
4313 int len = 0;
4314 char *dat;
4315 static char buf[BUFLEN];
4316 struct ipsecdoi_id_b *id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)id->v;
4317 struct sockaddr_storage saddr;
4318 u_int plen = 0;
4319
4320 bzero(&saddr, sizeof(saddr));
4321
4322 switch (id_b->type) {
4323 case IPSECDOI_ID_IPV4_ADDR:
4324 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4325 case IPSECDOI_ID_IPV4_ADDR_RANGE:
4326
4327 saddr.ss_len = sizeof(struct sockaddr_in);
4328 saddr.ss_family = AF_INET;
4329 ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
4330 memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
4331 id->v + sizeof(*id_b), sizeof(struct in_addr));
4332 break;
4333#ifdef INET6
4334 case IPSECDOI_ID_IPV6_ADDR:
4335 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4336 case IPSECDOI_ID_IPV6_ADDR_RANGE:
4337 saddr.ss_len = sizeof(struct sockaddr_in6);
4338 saddr.ss_family = AF_INET6;
4339 ((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
4340 memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
4341 id->v + sizeof(*id_b), sizeof(struct in6_addr));
4342 ((struct sockaddr_in6 *)&saddr)->sin6_scope_id =
4343 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&saddr)->sin6_addr)
4344 ? (ALIGNED_CAST(struct sockaddr_in6 *)id_b)->sin6_scope_id
4345 : 0);
4346 break;
4347#endif
4348 }
4349
4350 switch (id_b->type) {
4351 case IPSECDOI_ID_IPV4_ADDR:
4352#ifdef INET6
4353 case IPSECDOI_ID_IPV6_ADDR:
4354#endif
4355 len = snprintf( buf, sizeof(buf), "%s", saddrwop2str((struct sockaddr *)&saddr));
4356 break;
4357
4358 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4359#ifdef INET6
4360 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4361#endif
4362 {
4363 u_char *p;
4364 u_int max;
4365 int alen = sizeof(struct in_addr);
4366
4367 switch (id_b->type) {
4368 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4369 alen = sizeof(struct in_addr);
4370 break;
4371#ifdef INET6
4372 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4373 alen = sizeof(struct in6_addr);
4374 break;
4375#endif
4376 }
4377
4378 /* sanity check */
4379 if (id->l < alen) {
4380 len = 0;
4381 break;
4382 }
4383
4384 /* get subnet mask length */
4385 plen = 0;
4386 max = alen <<3;
4387
4388 p = (unsigned char *) id->v
4389 + sizeof(struct ipsecdoi_id_b)
4390 + alen;
4391
4392 for (; *p == 0xff; p++) {
4393 plen += 8;
4394 if (plen >= max)
4395 break;
4396 }
4397
4398 if (plen < max) {
4399 u_int l = 0;
4400 u_char b = ~(*p);
4401
4402 while (b) {
4403 b >>= 1;
4404 l++;
4405 }
4406
4407 l = 8 - l;
4408 plen += l;
4409 }
4410
4411 len = snprintf( buf, sizeof(buf), "%s/%i", saddrwop2str((struct sockaddr *)&saddr), plen);
4412 }
4413 break;
4414
4415 case IPSECDOI_ID_IPV4_ADDR_RANGE:
4416
4417 len = snprintf( buf, sizeof(buf), "%s-", saddrwop2str((struct sockaddr *)&saddr));
4418
4419 saddr.ss_len = sizeof(struct sockaddr_in);
4420 saddr.ss_family = AF_INET;
4421 ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
4422 memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
4423 id->v + sizeof(*id_b) + sizeof(struct in_addr),
4424 sizeof(struct in_addr));
4425
4426 if (len >= 0) {
4427 len += snprintf( buf + len, sizeof(buf) - len, "%s", saddrwop2str((struct sockaddr *)&saddr));
4428 }
4429
4430 break;
4431
4432#ifdef INET6
4433 case IPSECDOI_ID_IPV6_ADDR_RANGE:
4434
4435 len = snprintf( buf, sizeof(buf), "%s-", saddrwop2str((struct sockaddr *)&saddr));
4436
4437 saddr.ss_len = sizeof(struct sockaddr_in6);
4438 saddr.ss_family = AF_INET6;
4439 ((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
4440 memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
4441 id->v + sizeof(*id_b) + sizeof(struct in6_addr),
4442 sizeof(struct in6_addr));
4443 ((struct sockaddr_in6 *)&saddr)->sin6_scope_id =
4444 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&saddr)->sin6_addr)
4445 ? (ALIGNED_CAST(struct sockaddr_in6 *)id_b)->sin6_scope_id
4446 : 0);
4447
4448 if (len >= 0) {
4449 len += snprintf( buf + len, sizeof(buf) - len, "%s", saddrwop2str((struct sockaddr *)&saddr));
4450 }
4451
4452 break;
4453#endif
4454
4455 case IPSECDOI_ID_FQDN:
4456 case IPSECDOI_ID_USER_FQDN:
4457 len = id->l - sizeof(*id_b);
4458 if (len > BUFLEN)
4459 len = BUFLEN;
4460 memcpy(buf, id->v + sizeof(*id_b), len);
4461 break;
4462
4463 case IPSECDOI_ID_DER_ASN1_DN:
4464 case IPSECDOI_ID_DER_ASN1_GN:
4465 {
4466#ifdef HAVE_OPENSSL
4467 X509_NAME *xn = NULL;
4468#endif
4469
4470 dat = id->v + sizeof(*id_b);
4471 len = id->l - sizeof(*id_b);
4472#ifdef HAVE_OPENSSL
4473 if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
4474 BIO *bio = BIO_new(BIO_s_mem());
4475 X509_NAME_print_ex(bio, xn, 0, 0);
4476 len = BIO_get_mem_data(bio, &dat);
4477 if (len > BUFLEN)
4478 len = BUFLEN;
4479 memcpy(buf,dat,len);
4480 BIO_free(bio);
4481 X509_NAME_free(xn);
4482 } else
4483#endif
4484 {
4485
4486 plog(ASL_LEVEL_ERR,
4487 "unable to extract asn1dn from id\n");
4488
4489 len = snprintf(buf, sizeof(buf), "<ASN1-DN>");
4490 }
4491
4492 break;
4493 }
4494
4495 /* currently unhandled id types */
4496 case IPSECDOI_ID_KEY_ID:
4497 len = snprintf( buf, sizeof(buf), "<KEY-ID>");
4498 break;
4499
4500 default:
4501 plog(ASL_LEVEL_ERR,
4502 "unknown ID type %d\n", id_b->type);
4503 }
4504
4505 if (!len)
4506 len = snprintf( buf, sizeof(buf), "<?>");
4507
4508 ret = racoon_malloc(len+1);
4509 if (ret != NULL) {
4510 memcpy(ret,buf,len);
4511 ret[len]=0;
4512 }
4513
4514 return ret;
4515}
4516
4517/*
4518 * set IPsec data attributes into a proposal.
4519 * NOTE: MUST called per a transform.
4520 */
4521int
4522ipsecdoi_t2satrns(t, pp, pr, tr)
4523 struct isakmp_pl_t *t;
4524 struct saprop *pp;
4525 struct saproto *pr;
4526 struct satrns *tr;
4527{
4528 struct isakmp_data *d, *prev;
4529 int flag, type;
4530 int error = -1;
4531 int life_t;
4532 int tlen;
4533
4534 tr->trns_no = t->t_no;
4535 tr->trns_id = t->t_id;
4536
4537 tlen = ntohs(t->h.len) - sizeof(*t);
4538 prev = (struct isakmp_data *)NULL;
4539 d = (struct isakmp_data *)(t + 1);
4540
4541 /* default */
4542 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4543 pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
4544 pp->lifebyte = 0;
4545 tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
4546
4547 while (tlen > 0) {
4548
4549 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
4550 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
4551
4552 plog(ASL_LEVEL_DEBUG,
4553 "type=%s, flag=0x%04x, lorv=%s\n",
4554 s_ipsecdoi_attr(type), flag,
4555 s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
4556
4557 switch (type) {
4558 case IPSECDOI_ATTR_SA_LD_TYPE:
4559 {
4560 int type = ntohs(d->lorv);
4561 switch (type) {
4562 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4563 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4564 life_t = type;
4565 break;
4566 default:
4567 plog(ASL_LEVEL_WARNING,
4568 "invalid life duration type. "
4569 "use default\n");
4570 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4571 break;
4572 }
4573 break;
4574 }
4575 case IPSECDOI_ATTR_SA_LD:
4576 if (prev == NULL
4577 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
4578 IPSECDOI_ATTR_SA_LD_TYPE) {
4579 plog(ASL_LEVEL_ERR,
4580 "life duration must follow ltype\n");
4581 break;
4582 }
4583
4584 {
4585 u_int32_t t;
4586 vchar_t *ld_buf = NULL;
4587
4588 if (flag) {
4589 /* i.e. ISAKMP_GEN_TV */
4590 ld_buf = vmalloc(sizeof(d->lorv));
4591 if (ld_buf == NULL) {
4592 plog(ASL_LEVEL_ERR,
4593 "failed to get LD buffer.\n");
4594 goto end;
4595 }
4596 memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
4597 } else {
4598 int len = ntohs(d->lorv);
4599 /* i.e. ISAKMP_GEN_TLV */
4600 ld_buf = vmalloc(len);
4601 if (ld_buf == NULL) {
4602 plog(ASL_LEVEL_ERR,
4603 "failed to get LD buffer.\n");
4604 goto end;
4605 }
4606 memcpy(ld_buf->v, d + 1, len);
4607 }
4608 switch (life_t) {
4609 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4610 t = ipsecdoi_set_ld(ld_buf);
4611 vfree(ld_buf);
4612 if (t == 0) {
4613 plog(ASL_LEVEL_ERR,
4614 "invalid life duration.\n");
4615 goto end;
4616 }
4617 /* lifetime must be equal in a proposal. */
4618 if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
4619 pp->lifetime = t;
4620 else if (pp->lifetime != t) {
4621 plog(ASL_LEVEL_ERR,
4622 "lifetime mismatched "
4623 "in a proposal, "
4624 "prev:%ld curr:%u.\n",
4625 (long)pp->lifetime, t);
4626 goto end;
4627 }
4628 break;
4629 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4630 t = ipsecdoi_set_ld(ld_buf);
4631 vfree(ld_buf);
4632 if (t == 0) {
4633 plog(ASL_LEVEL_ERR,
4634 "invalid life duration.\n");
4635 goto end;
4636 }
4637 /* lifebyte must be equal in a proposal. */
4638 if (pp->lifebyte == 0)
4639 pp->lifebyte = t;
4640 else if (pp->lifebyte != t) {
4641 plog(ASL_LEVEL_ERR,
4642 "lifebyte mismatched "
4643 "in a proposal, "
4644 "prev:%d curr:%u.\n",
4645 pp->lifebyte, t);
4646 goto end;
4647 }
4648 break;
4649 default:
4650 vfree(ld_buf);
4651 plog(ASL_LEVEL_ERR,
4652 "invalid life type: %d\n", life_t);
4653 goto end;
4654 }
4655 }
4656 break;
4657
4658 case IPSECDOI_ATTR_GRP_DESC:
4659 /*
4660 * RFC2407: 4.5 IPSEC Security Association Attributes
4661 * Specifies the Oakley Group to be used in a PFS QM
4662 * negotiation. For a list of supported values, see
4663 * Appendix A of [IKE].
4664 */
4665 if (pp->pfs_group == 0)
4666 pp->pfs_group = (u_int16_t)ntohs(d->lorv);
4667 else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
4668 plog(ASL_LEVEL_ERR,
4669 "pfs_group mismatched "
4670 "in a proposal.\n");
4671 goto end;
4672 }
4673 break;
4674
4675 case IPSECDOI_ATTR_ENC_MODE:
4676 if (pr->encmode &&
4677 pr->encmode != (u_int16_t)ntohs(d->lorv)) {
4678 plog(ASL_LEVEL_ERR,
4679 "multiple encmode exist "
4680 "in a transform.\n");
4681 goto end;
4682 }
4683 pr->encmode = (u_int16_t)ntohs(d->lorv);
4684 break;
4685
4686 case IPSECDOI_ATTR_AUTH:
4687 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
4688 plog(ASL_LEVEL_ERR,
4689 "multiple authtype exist "
4690 "in a transform.\n");
4691 goto end;
4692 }
4693 tr->authtype = (u_int16_t)ntohs(d->lorv);
4694 break;
4695
4696 case IPSECDOI_ATTR_KEY_LENGTH:
4697 if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
4698 plog(ASL_LEVEL_ERR,
4699 "key length defined but not ESP");
4700 goto end;
4701 }
4702 tr->encklen = ntohs(d->lorv);
4703 break;
4704
4705 case IPSECDOI_ATTR_KEY_ROUNDS:
4706 case IPSECDOI_ATTR_COMP_DICT_SIZE:
4707 case IPSECDOI_ATTR_COMP_PRIVALG:
4708 default:
4709 break;
4710 }
4711
4712 prev = d;
4713 if (flag) {
4714 tlen -= sizeof(*d);
4715 d = (struct isakmp_data *)((char *)d + sizeof(*d));
4716 } else {
4717 tlen -= (sizeof(*d) + ntohs(d->lorv));
4718 d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
4719 }
4720 }
4721
4722 error = 0;
4723end:
4724 return error;
4725}
4726
4727int
4728ipsecdoi_authalg2trnsid(alg)
4729 int alg;
4730{
4731 switch (alg) {
4732 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
4733 return IPSECDOI_AH_MD5;
4734 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
4735 return IPSECDOI_AH_SHA;
4736 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
4737 return IPSECDOI_AH_SHA256;
4738 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
4739 return IPSECDOI_AH_SHA384;
4740 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
4741 return IPSECDOI_AH_SHA512;
4742 case IPSECDOI_ATTR_AUTH_DES_MAC:
4743 return IPSECDOI_AH_DES;
4744 case IPSECDOI_ATTR_AUTH_KPDK:
4745 return IPSECDOI_AH_MD5; /* XXX */
4746 default:
4747 plog(ASL_LEVEL_ERR,
4748 "invalid authentication algorithm:%d\n", alg);
4749 }
4750 return -1;
4751}
4752
4753static int rm_idtype2doi[] = {
4754 255, /* IDTYPE_UNDEFINED, 0 */
4755 IPSECDOI_ID_FQDN, /* IDTYPE_FQDN, 1 */
4756 IPSECDOI_ID_USER_FQDN, /* IDTYPE_USERFQDN, 2 */
4757 IPSECDOI_ID_KEY_ID, /* IDTYPE_KEYID, 3 */
4758 255, /* IDTYPE_ADDRESS, 4
4759 * it expands into 4 types by another function. */
4760 IPSECDOI_ID_DER_ASN1_DN, /* IDTYPE_ASN1DN, 5 */
4761};
4762
4763/*
4764 * convert idtype to DOI value.
4765 * OUT 255 : NG
4766 * other: converted.
4767 */
4768int
4769idtype2doi(idtype)
4770 int idtype;
4771{
4772 if (ARRAYLEN(rm_idtype2doi) > idtype)
4773 return rm_idtype2doi[idtype];
4774 return 255;
4775}
4776
4777int
4778doi2idtype(doi)
4779 int doi;
4780{
4781 switch(doi) {
4782 case IPSECDOI_ID_FQDN:
4783 return(IDTYPE_FQDN);
4784 case IPSECDOI_ID_USER_FQDN:
4785 return(IDTYPE_USERFQDN);
4786 case IPSECDOI_ID_KEY_ID:
4787 return(IDTYPE_KEYID);
4788 case IPSECDOI_ID_DER_ASN1_DN:
4789 return(IDTYPE_ASN1DN);
4790 case IPSECDOI_ID_IPV4_ADDR:
4791 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4792 case IPSECDOI_ID_IPV6_ADDR:
4793 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4794 return(IDTYPE_ADDRESS);
4795 default:
4796 plog(ASL_LEVEL_WARNING,
4797 "Inproper idtype:%s in this function.\n",
4798 s_ipsecdoi_ident(doi));
4799 return(IDTYPE_ADDRESS); /* XXX */
4800 }
4801 /*NOTREACHED*/
4802}
4803
4804#ifdef ENABLE_HYBRID
4805static int
4806switch_authmethod(authmethod)
4807 int authmethod;
4808{
4809 switch(authmethod) {
4810 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
4811 authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
4812 break;
4813 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
4814 authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
4815 break;
4816 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
4817 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
4818 break;
4819 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
4820 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
4821 break;
4822 /* Those are not implemented */
4823 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
4824 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
4825 break;
4826 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
4827 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
4828 break;
4829 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
4830 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
4831 break;
4832 default:
4833 break;
4834 }
4835
4836 return authmethod;
4837}
4838#endif