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