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