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