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