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 #if defined(ANDROID_CHANGES)
1322 memset(pair, 0, MAXPROPPAIRLEN * sizeof(*pair));
1323 #else
1324 memset(pair, 0, sizeof(pair));
1325 #endif
1326
1327 bp = (caddr_t)(sab + 1);
1328 tlen = sa->l - sizeof(*sab);
1329
1330 {
1331 struct isakmp_pl_p *prop;
1332 int proplen;
1333 vchar_t *pbuf = NULL;
1334 struct isakmp_parse_t *pa;
1335
1336 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
1337 if (pbuf == NULL)
1338 goto bad;
1339
1340 for (pa = (struct isakmp_parse_t *)pbuf->v;
1341 pa->type != ISAKMP_NPTYPE_NONE;
1342 pa++) {
1343 /* check the value of next payload */
1344 if (pa->type != ISAKMP_NPTYPE_P) {
1345 plog(LLV_ERROR, LOCATION, NULL,
1346 "Invalid payload type=%u\n", pa->type);
1347 vfree(pbuf);
1348 goto bad;
1349 }
1350
1351 prop = (struct isakmp_pl_p *)pa->ptr;
1352 proplen = pa->len;
1353
1354 plog(LLV_DEBUG, LOCATION, NULL,
1355 "proposal #%u len=%d\n", prop->p_no, proplen);
1356
1357 if (proplen == 0) {
1358 plog(LLV_ERROR, LOCATION, NULL,
1359 "invalid proposal with length %d\n", proplen);
1360 vfree(pbuf);
1361 goto bad;
1362 }
1363
1364 /* check Protocol ID */
1365 if (!check_protocol[mode]) {
1366 plog(LLV_ERROR, LOCATION, NULL,
1367 "unsupported mode %d\n", mode);
1368 continue;
1369 }
1370
1371 if (check_protocol[mode](prop->proto_id) < 0)
1372 continue;
1373
1374 /* check SPI length when IKE. */
1375 if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
1376 continue;
1377
1378 /* get transform */
1379 if (get_transform(prop, pair, &num_p) < 0) {
1380 vfree(pbuf);
1381 goto bad;
1382 }
1383 }
1384 vfree(pbuf);
1385 pbuf = NULL;
1386 }
1387
1388 {
1389 int notrans, nprop;
1390 struct prop_pair *p, *q;
1391
1392 /* check for proposals with no transforms */
1393 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1394 if (!pair[i])
1395 continue;
1396
1397 plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
1398 print_proppair(LLV_DEBUG, pair[i]);
1399
1400 notrans = nprop = 0;
1401 for (p = pair[i]; p; p = p->next) {
1402 if (p->trns == NULL) {
1403 notrans++;
1404 break;
1405 }
1406 for (q = p; q; q = q->tnext)
1407 nprop++;
1408 }
1409
1410 #if 0
1411 /*
1412 * XXX at this moment, we cannot accept proposal group
1413 * with multiple proposals. this should be fixed.
1414 */
1415 if (pair[i]->next) {
1416 plog(LLV_WARNING, LOCATION, NULL,
1417 "proposal #%u ignored "
1418 "(multiple proposal not supported)\n",
1419 pair[i]->prop->p_no);
1420 notrans++;
1421 }
1422 #endif
1423
1424 if (notrans) {
1425 for (p = pair[i]; p; p = q) {
1426 q = p->next;
1427 racoon_free(p);
1428 }
1429 pair[i] = NULL;
1430 num_p--;
1431 } else {
1432 plog(LLV_DEBUG, LOCATION, NULL,
1433 "proposal #%u: %d transform\n",
1434 pair[i]->prop->p_no, nprop);
1435 }
1436 }
1437 }
1438
1439 /* bark if no proposal is found. */
1440 if (num_p <= 0) {
1441 plog(LLV_ERROR, LOCATION, NULL,
1442 "no Proposal found.\n");
1443 goto bad;
1444 }
1445
1446 return pair;
1447 bad:
1448 if (pair != NULL)
1449 racoon_free(pair);
1450 return NULL;
1451 }
1452
1453 /*
1454 * check transform payload.
1455 * OUT:
1456 * positive: return the pointer to the payload of valid transform.
1457 * 0 : No valid transform found.
1458 */
1459 static int
get_transform(prop,pair,num_p)1460 get_transform(prop, pair, num_p)
1461 struct isakmp_pl_p *prop;
1462 struct prop_pair **pair;
1463 int *num_p;
1464 {
1465 int tlen; /* total length of all transform in a proposal */
1466 caddr_t bp;
1467 struct isakmp_pl_t *trns;
1468 int trnslen;
1469 vchar_t *pbuf = NULL;
1470 struct isakmp_parse_t *pa;
1471 struct prop_pair *p = NULL, *q;
1472 int num_t;
1473
1474 bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
1475 tlen = ntohs(prop->h.len)
1476 - (sizeof(struct isakmp_pl_p) + prop->spi_size);
1477 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
1478 if (pbuf == NULL)
1479 return -1;
1480
1481 /* check and get transform for use */
1482 num_t = 0;
1483 for (pa = (struct isakmp_parse_t *)pbuf->v;
1484 pa->type != ISAKMP_NPTYPE_NONE;
1485 pa++) {
1486
1487 num_t++;
1488
1489 /* check the value of next payload */
1490 if (pa->type != ISAKMP_NPTYPE_T) {
1491 plog(LLV_ERROR, LOCATION, NULL,
1492 "Invalid payload type=%u\n", pa->type);
1493 break;
1494 }
1495
1496 trns = (struct isakmp_pl_t *)pa->ptr;
1497 trnslen = pa->len;
1498
1499 plog(LLV_DEBUG, LOCATION, NULL,
1500 "transform #%u len=%u\n", trns->t_no, trnslen);
1501
1502 /* check transform ID */
1503 if (prop->proto_id >= ARRAYLEN(check_transform)) {
1504 plog(LLV_WARNING, LOCATION, NULL,
1505 "unsupported proto_id %u\n",
1506 prop->proto_id);
1507 continue;
1508 }
1509 if (prop->proto_id >= ARRAYLEN(check_attributes)) {
1510 plog(LLV_WARNING, LOCATION, NULL,
1511 "unsupported proto_id %u\n",
1512 prop->proto_id);
1513 continue;
1514 }
1515
1516 if (!check_transform[prop->proto_id]
1517 || !check_attributes[prop->proto_id]) {
1518 plog(LLV_WARNING, LOCATION, NULL,
1519 "unsupported proto_id %u\n",
1520 prop->proto_id);
1521 continue;
1522 }
1523 if (check_transform[prop->proto_id](trns->t_id) < 0)
1524 continue;
1525
1526 /* check data attributes */
1527 if (check_attributes[prop->proto_id](trns) != 0)
1528 continue;
1529
1530 p = racoon_calloc(1, sizeof(*p));
1531 if (p == NULL) {
1532 plog(LLV_ERROR, LOCATION, NULL,
1533 "failed to get buffer.\n");
1534 vfree(pbuf);
1535 return -1;
1536 }
1537 p->prop = prop;
1538 p->trns = trns;
1539
1540 /* need to preserve the order */
1541 for (q = pair[prop->p_no]; q && q->next; q = q->next)
1542 ;
1543 if (q && q->prop == p->prop) {
1544 for (/*nothing*/; q && q->tnext; q = q->tnext)
1545 ;
1546 q->tnext = p;
1547 } else {
1548 if (q)
1549 q->next = p;
1550 else {
1551 pair[prop->p_no] = p;
1552 (*num_p)++;
1553 }
1554 }
1555 }
1556
1557 vfree(pbuf);
1558
1559 return 0;
1560 }
1561
1562 /*
1563 * make a new SA payload from prop_pair.
1564 * NOTE: this function make spi value clear.
1565 */
1566 vchar_t *
get_sabyproppair(pair,iph1)1567 get_sabyproppair(pair, iph1)
1568 struct prop_pair *pair;
1569 struct ph1handle *iph1;
1570 {
1571 vchar_t *newsa;
1572 int newtlen;
1573 u_int8_t *np_p = NULL;
1574 struct prop_pair *p;
1575 int prophlen, trnslen;
1576 caddr_t bp;
1577
1578 newtlen = sizeof(struct ipsecdoi_sa_b);
1579 for (p = pair; p; p = p->next) {
1580 newtlen += sizeof(struct isakmp_pl_p);
1581 newtlen += p->prop->spi_size;
1582 newtlen += ntohs(p->trns->h.len);
1583 }
1584
1585 newsa = vmalloc(newtlen);
1586 if (newsa == NULL) {
1587 plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1588 return NULL;
1589 }
1590 bp = newsa->v;
1591
1592 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1593
1594 /* update some of values in SA header */
1595 ((struct ipsecdoi_sa_b *)bp)->doi = htonl(iph1->rmconf->doitype);
1596 ((struct ipsecdoi_sa_b *)bp)->sit = htonl(iph1->rmconf->sittype);
1597 bp += sizeof(struct ipsecdoi_sa_b);
1598
1599 /* create proposal payloads */
1600 for (p = pair; p; p = p->next) {
1601 prophlen = sizeof(struct isakmp_pl_p)
1602 + p->prop->spi_size;
1603 trnslen = ntohs(p->trns->h.len);
1604
1605 if (np_p)
1606 *np_p = ISAKMP_NPTYPE_P;
1607
1608 /* create proposal */
1609
1610 memcpy(bp, p->prop, prophlen);
1611 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1612 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1613 ((struct isakmp_pl_p *)bp)->num_t = 1;
1614 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1615 memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
1616 bp += prophlen;
1617
1618 /* create transform */
1619 memcpy(bp, p->trns, trnslen);
1620 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1621 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1622 bp += trnslen;
1623 }
1624
1625 return newsa;
1626 }
1627
1628 /*
1629 * update responder's spi
1630 */
1631 int
ipsecdoi_updatespi(iph2)1632 ipsecdoi_updatespi(iph2)
1633 struct ph2handle *iph2;
1634 {
1635 struct prop_pair **pair, *p;
1636 struct saprop *pp;
1637 struct saproto *pr;
1638 int i;
1639 int error = -1;
1640 u_int8_t *spi;
1641
1642 pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
1643 if (pair == NULL)
1644 return -1;
1645 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1646 if (pair[i])
1647 break;
1648 }
1649 if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
1650 /* multiple transform must be filtered by selectph2proposal.*/
1651 goto end;
1652 }
1653
1654 pp = iph2->approval;
1655
1656 /* create proposal payloads */
1657 for (p = pair[i]; p; p = p->next) {
1658 /*
1659 * find a proposal/transform with matching proto_id/t_id.
1660 * we have analyzed validity already, in cmpsaprop_alloc().
1661 */
1662 for (pr = pp->head; pr; pr = pr->next) {
1663 if (p->prop->proto_id == pr->proto_id &&
1664 p->trns->t_id == pr->head->trns_id) {
1665 break;
1666 }
1667 }
1668 if (!pr)
1669 goto end;
1670
1671 /*
1672 * XXX SPI bits are left-filled, for use with IPComp.
1673 * we should be switching to variable-length spi field...
1674 */
1675 spi = (u_int8_t *)&pr->spi;
1676 spi += sizeof(pr->spi);
1677 spi -= pr->spisize;
1678 memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
1679 }
1680
1681 error = 0;
1682 end:
1683 free_proppair(pair);
1684 return error;
1685 }
1686
1687 /*
1688 * make a new SA payload from prop_pair.
1689 */
1690 vchar_t *
get_sabysaprop(pp0,sa0)1691 get_sabysaprop(pp0, sa0)
1692 struct saprop *pp0;
1693 vchar_t *sa0;
1694 {
1695 struct prop_pair **pair = NULL;
1696 vchar_t *newsa = NULL;
1697 int newtlen;
1698 u_int8_t *np_p = NULL;
1699 struct prop_pair *p = NULL;
1700 struct saprop *pp;
1701 struct saproto *pr;
1702 struct satrns *tr;
1703 int prophlen, trnslen;
1704 caddr_t bp;
1705 int error = -1;
1706
1707 /* get proposal pair */
1708 pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
1709 if (pair == NULL)
1710 goto out;
1711
1712 newtlen = sizeof(struct ipsecdoi_sa_b);
1713 for (pp = pp0; pp; pp = pp->next) {
1714
1715 if (pair[pp->prop_no] == NULL)
1716 goto out;
1717
1718 for (pr = pp->head; pr; pr = pr->next) {
1719 newtlen += (sizeof(struct isakmp_pl_p)
1720 + pr->spisize);
1721
1722 for (tr = pr->head; tr; tr = tr->next) {
1723 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1724 if (tr->trns_no == p->trns->t_no)
1725 break;
1726 }
1727 if (p == NULL)
1728 goto out;
1729
1730 newtlen += ntohs(p->trns->h.len);
1731 }
1732 }
1733 }
1734
1735 newsa = vmalloc(newtlen);
1736 if (newsa == NULL) {
1737 plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1738 goto out;
1739 }
1740 bp = newsa->v;
1741
1742 /* some of values of SA must be updated in the out of this function */
1743 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1744 bp += sizeof(struct ipsecdoi_sa_b);
1745
1746 /* create proposal payloads */
1747 for (pp = pp0; pp; pp = pp->next) {
1748
1749 for (pr = pp->head; pr; pr = pr->next) {
1750 prophlen = sizeof(struct isakmp_pl_p)
1751 + p->prop->spi_size;
1752
1753 for (tr = pr->head; tr; tr = tr->next) {
1754 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1755 if (tr->trns_no == p->trns->t_no)
1756 break;
1757 }
1758 if (p == NULL)
1759 goto out;
1760
1761 trnslen = ntohs(p->trns->h.len);
1762
1763 if (np_p)
1764 *np_p = ISAKMP_NPTYPE_P;
1765
1766 /* create proposal */
1767
1768 memcpy(bp, p->prop, prophlen);
1769 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1770 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1771 ((struct isakmp_pl_p *)bp)->num_t = 1;
1772 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1773 bp += prophlen;
1774
1775 /* create transform */
1776 memcpy(bp, p->trns, trnslen);
1777 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1778 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1779 bp += trnslen;
1780 }
1781 }
1782 }
1783
1784 error = 0;
1785 out:
1786 if (pair != NULL)
1787 racoon_free(pair);
1788
1789 if (error != 0) {
1790 if (newsa != NULL) {
1791 vfree(newsa);
1792 newsa = NULL;
1793 }
1794 }
1795
1796 return newsa;
1797 }
1798
1799 /*
1800 * If some error happens then return 0. Although 0 means that lifetime is zero,
1801 * such a value should not be accepted.
1802 * Also 0 of lifebyte should not be included in a packet although 0 means not
1803 * to care of it.
1804 */
1805 static u_int32_t
ipsecdoi_set_ld(buf)1806 ipsecdoi_set_ld(buf)
1807 vchar_t *buf;
1808 {
1809 u_int32_t ld;
1810
1811 if (buf == 0)
1812 return 0;
1813
1814 switch (buf->l) {
1815 case 2:
1816 ld = ntohs(*(u_int16_t *)buf->v);
1817 break;
1818 case 4:
1819 ld = ntohl(*(u_int32_t *)buf->v);
1820 break;
1821 default:
1822 plog(LLV_ERROR, LOCATION, NULL,
1823 "length %zu of life duration "
1824 "isn't supported.\n", buf->l);
1825 return 0;
1826 }
1827
1828 return ld;
1829 }
1830
1831 /*%%%*/
1832 /*
1833 * check DOI
1834 */
1835 static int
check_doi(doi)1836 check_doi(doi)
1837 u_int32_t doi;
1838 {
1839 switch (doi) {
1840 case IPSEC_DOI:
1841 return 0;
1842 default:
1843 plog(LLV_ERROR, LOCATION, NULL,
1844 "invalid value of DOI 0x%08x.\n", doi);
1845 return -1;
1846 }
1847 /* NOT REACHED */
1848 }
1849
1850 /*
1851 * check situation
1852 */
1853 static int
check_situation(sit)1854 check_situation(sit)
1855 u_int32_t sit;
1856 {
1857 switch (sit) {
1858 case IPSECDOI_SIT_IDENTITY_ONLY:
1859 return 0;
1860
1861 case IPSECDOI_SIT_SECRECY:
1862 case IPSECDOI_SIT_INTEGRITY:
1863 plog(LLV_ERROR, LOCATION, NULL,
1864 "situation 0x%08x unsupported yet.\n", sit);
1865 return -1;
1866
1867 default:
1868 plog(LLV_ERROR, LOCATION, NULL,
1869 "invalid situation 0x%08x.\n", sit);
1870 return -1;
1871 }
1872 /* NOT REACHED */
1873 }
1874
1875 /*
1876 * check protocol id in main mode
1877 */
1878 static int
check_prot_main(proto_id)1879 check_prot_main(proto_id)
1880 int proto_id;
1881 {
1882 switch (proto_id) {
1883 case IPSECDOI_PROTO_ISAKMP:
1884 return 0;
1885
1886 default:
1887 plog(LLV_ERROR, LOCATION, NULL,
1888 "Illegal protocol id=%u.\n", proto_id);
1889 return -1;
1890 }
1891 /* NOT REACHED */
1892 }
1893
1894 /*
1895 * check protocol id in quick mode
1896 */
1897 static int
check_prot_quick(proto_id)1898 check_prot_quick(proto_id)
1899 int proto_id;
1900 {
1901 switch (proto_id) {
1902 case IPSECDOI_PROTO_IPSEC_AH:
1903 case IPSECDOI_PROTO_IPSEC_ESP:
1904 return 0;
1905
1906 case IPSECDOI_PROTO_IPCOMP:
1907 return 0;
1908
1909 default:
1910 plog(LLV_ERROR, LOCATION, NULL,
1911 "invalid protocol id %d.\n", proto_id);
1912 return -1;
1913 }
1914 /* NOT REACHED */
1915 }
1916
1917 static int
check_spi_size(proto_id,size)1918 check_spi_size(proto_id, size)
1919 int proto_id, size;
1920 {
1921 switch (proto_id) {
1922 case IPSECDOI_PROTO_ISAKMP:
1923 if (size != 0) {
1924 /* WARNING */
1925 plog(LLV_WARNING, LOCATION, NULL,
1926 "SPI size isn't zero, but IKE proposal.\n");
1927 }
1928 return 0;
1929
1930 case IPSECDOI_PROTO_IPSEC_AH:
1931 case IPSECDOI_PROTO_IPSEC_ESP:
1932 if (size != 4) {
1933 plog(LLV_ERROR, LOCATION, NULL,
1934 "invalid SPI size=%d for IPSEC proposal.\n",
1935 size);
1936 return -1;
1937 }
1938 return 0;
1939
1940 case IPSECDOI_PROTO_IPCOMP:
1941 if (size != 2 && size != 4) {
1942 plog(LLV_ERROR, LOCATION, NULL,
1943 "invalid SPI size=%d for IPCOMP proposal.\n",
1944 size);
1945 return -1;
1946 }
1947 return 0;
1948
1949 default:
1950 /* ??? */
1951 return -1;
1952 }
1953 /* NOT REACHED */
1954 }
1955
1956 /*
1957 * check transform ID in ISAKMP.
1958 */
1959 static int
check_trns_isakmp(t_id)1960 check_trns_isakmp(t_id)
1961 int t_id;
1962 {
1963 switch (t_id) {
1964 case IPSECDOI_KEY_IKE:
1965 return 0;
1966 default:
1967 plog(LLV_ERROR, LOCATION, NULL,
1968 "invalid transform-id=%u in proto_id=%u.\n",
1969 t_id, IPSECDOI_KEY_IKE);
1970 return -1;
1971 }
1972 /* NOT REACHED */
1973 }
1974
1975 /*
1976 * check transform ID in AH.
1977 */
1978 static int
check_trns_ah(t_id)1979 check_trns_ah(t_id)
1980 int t_id;
1981 {
1982 switch (t_id) {
1983 case IPSECDOI_AH_MD5:
1984 case IPSECDOI_AH_SHA:
1985 case IPSECDOI_AH_SHA256:
1986 case IPSECDOI_AH_SHA384:
1987 case IPSECDOI_AH_SHA512:
1988 return 0;
1989 case IPSECDOI_AH_DES:
1990 plog(LLV_ERROR, LOCATION, NULL,
1991 "not support transform-id=%u in AH.\n", t_id);
1992 return -1;
1993 default:
1994 plog(LLV_ERROR, LOCATION, NULL,
1995 "invalid transform-id=%u in AH.\n", t_id);
1996 return -1;
1997 }
1998 /* NOT REACHED */
1999 }
2000
2001 /*
2002 * check transform ID in ESP.
2003 */
2004 static int
check_trns_esp(t_id)2005 check_trns_esp(t_id)
2006 int t_id;
2007 {
2008 switch (t_id) {
2009 case IPSECDOI_ESP_DES:
2010 case IPSECDOI_ESP_3DES:
2011 case IPSECDOI_ESP_NULL:
2012 case IPSECDOI_ESP_RC5:
2013 case IPSECDOI_ESP_CAST:
2014 case IPSECDOI_ESP_BLOWFISH:
2015 case IPSECDOI_ESP_AES:
2016 case IPSECDOI_ESP_TWOFISH:
2017 case IPSECDOI_ESP_CAMELLIA:
2018 return 0;
2019 case IPSECDOI_ESP_DES_IV32:
2020 case IPSECDOI_ESP_DES_IV64:
2021 case IPSECDOI_ESP_IDEA:
2022 case IPSECDOI_ESP_3IDEA:
2023 case IPSECDOI_ESP_RC4:
2024 plog(LLV_ERROR, LOCATION, NULL,
2025 "not support transform-id=%u in ESP.\n", t_id);
2026 return -1;
2027 default:
2028 plog(LLV_ERROR, LOCATION, NULL,
2029 "invalid transform-id=%u in ESP.\n", t_id);
2030 return -1;
2031 }
2032 /* NOT REACHED */
2033 }
2034
2035 /*
2036 * check transform ID in IPCOMP.
2037 */
2038 static int
check_trns_ipcomp(t_id)2039 check_trns_ipcomp(t_id)
2040 int t_id;
2041 {
2042 switch (t_id) {
2043 case IPSECDOI_IPCOMP_OUI:
2044 case IPSECDOI_IPCOMP_DEFLATE:
2045 case IPSECDOI_IPCOMP_LZS:
2046 return 0;
2047 default:
2048 plog(LLV_ERROR, LOCATION, NULL,
2049 "invalid transform-id=%u in IPCOMP.\n", t_id);
2050 return -1;
2051 }
2052 /* NOT REACHED */
2053 }
2054
2055 /*
2056 * check data attributes in IKE.
2057 */
2058 static int
check_attr_isakmp(trns)2059 check_attr_isakmp(trns)
2060 struct isakmp_pl_t *trns;
2061 {
2062 struct isakmp_data *d;
2063 int tlen;
2064 int flag, type;
2065 u_int16_t lorv;
2066
2067 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2068 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2069
2070 while (tlen > 0) {
2071 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2072 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2073 lorv = ntohs(d->lorv);
2074
2075 plog(LLV_DEBUG, LOCATION, NULL,
2076 "type=%s, flag=0x%04x, lorv=%s\n",
2077 s_oakley_attr(type), flag,
2078 s_oakley_attr_v(type, lorv));
2079
2080 /*
2081 * some of the attributes must be encoded in TV.
2082 * see RFC2409 Appendix A "Attribute Classes".
2083 */
2084 switch (type) {
2085 case OAKLEY_ATTR_ENC_ALG:
2086 case OAKLEY_ATTR_HASH_ALG:
2087 case OAKLEY_ATTR_AUTH_METHOD:
2088 case OAKLEY_ATTR_GRP_DESC:
2089 case OAKLEY_ATTR_GRP_TYPE:
2090 case OAKLEY_ATTR_SA_LD_TYPE:
2091 case OAKLEY_ATTR_PRF:
2092 case OAKLEY_ATTR_KEY_LEN:
2093 case OAKLEY_ATTR_FIELD_SIZE:
2094 if (!flag) { /* TLV*/
2095 plog(LLV_ERROR, LOCATION, NULL,
2096 "oakley attribute %d must be TV.\n",
2097 type);
2098 return -1;
2099 }
2100 break;
2101 }
2102
2103 /* sanity check for TLV. length must be specified. */
2104 if (!flag && lorv == 0) { /*TLV*/
2105 plog(LLV_ERROR, LOCATION, NULL,
2106 "invalid length %d for TLV attribute %d.\n",
2107 lorv, type);
2108 return -1;
2109 }
2110
2111 switch (type) {
2112 case OAKLEY_ATTR_ENC_ALG:
2113 if (!alg_oakley_encdef_ok(lorv)) {
2114 plog(LLV_ERROR, LOCATION, NULL,
2115 "invalied encryption algorithm=%d.\n",
2116 lorv);
2117 return -1;
2118 }
2119 break;
2120
2121 case OAKLEY_ATTR_HASH_ALG:
2122 if (!alg_oakley_hashdef_ok(lorv)) {
2123 plog(LLV_ERROR, LOCATION, NULL,
2124 "invalied hash algorithm=%d.\n",
2125 lorv);
2126 return -1;
2127 }
2128 break;
2129
2130 case OAKLEY_ATTR_AUTH_METHOD:
2131 switch (lorv) {
2132 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
2133 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2134 #ifdef ENABLE_HYBRID
2135 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
2136 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2137 #if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
2138 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
2139 #endif
2140 #endif
2141 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
2142 break;
2143 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2144 #ifdef ENABLE_HYBRID
2145 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
2146 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
2147 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
2148 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
2149 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
2150 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
2151 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
2152 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
2153 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
2154 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
2155 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
2156 #endif
2157 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2158 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
2159 plog(LLV_ERROR, LOCATION, NULL,
2160 "auth method %s isn't supported.\n",
2161 s_oakley_attr_method(lorv));
2162 return -1;
2163 default:
2164 plog(LLV_ERROR, LOCATION, NULL,
2165 "invalid auth method %d.\n",
2166 lorv);
2167 return -1;
2168 }
2169 break;
2170
2171 case OAKLEY_ATTR_GRP_DESC:
2172 if (!alg_oakley_dhdef_ok(lorv)) {
2173 plog(LLV_ERROR, LOCATION, NULL,
2174 "invalid DH group %d.\n",
2175 lorv);
2176 return -1;
2177 }
2178 break;
2179
2180 case OAKLEY_ATTR_GRP_TYPE:
2181 switch (lorv) {
2182 case OAKLEY_ATTR_GRP_TYPE_MODP:
2183 break;
2184 default:
2185 plog(LLV_ERROR, LOCATION, NULL,
2186 "unsupported DH group type %d.\n",
2187 lorv);
2188 return -1;
2189 }
2190 break;
2191
2192 case OAKLEY_ATTR_GRP_PI:
2193 case OAKLEY_ATTR_GRP_GEN_ONE:
2194 /* sanity checks? */
2195 break;
2196
2197 case OAKLEY_ATTR_GRP_GEN_TWO:
2198 case OAKLEY_ATTR_GRP_CURVE_A:
2199 case OAKLEY_ATTR_GRP_CURVE_B:
2200 plog(LLV_ERROR, LOCATION, NULL,
2201 "attr type=%u isn't supported.\n", type);
2202 return -1;
2203
2204 case OAKLEY_ATTR_SA_LD_TYPE:
2205 switch (lorv) {
2206 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
2207 case OAKLEY_ATTR_SA_LD_TYPE_KB:
2208 break;
2209 default:
2210 plog(LLV_ERROR, LOCATION, NULL,
2211 "invalid life type %d.\n", lorv);
2212 return -1;
2213 }
2214 break;
2215
2216 case OAKLEY_ATTR_SA_LD:
2217 /* should check the value */
2218 break;
2219
2220 case OAKLEY_ATTR_PRF:
2221 case OAKLEY_ATTR_KEY_LEN:
2222 break;
2223
2224 case OAKLEY_ATTR_FIELD_SIZE:
2225 plog(LLV_ERROR, LOCATION, NULL,
2226 "attr type=%u isn't supported.\n", type);
2227 return -1;
2228
2229 case OAKLEY_ATTR_GRP_ORDER:
2230 break;
2231
2232 case OAKLEY_ATTR_GSS_ID:
2233 break;
2234
2235 default:
2236 plog(LLV_ERROR, LOCATION, NULL,
2237 "invalid attribute type %d.\n", type);
2238 return -1;
2239 }
2240
2241 if (flag) {
2242 tlen -= sizeof(*d);
2243 d = (struct isakmp_data *)((char *)d
2244 + sizeof(*d));
2245 } else {
2246 tlen -= (sizeof(*d) + lorv);
2247 d = (struct isakmp_data *)((char *)d
2248 + sizeof(*d) + lorv);
2249 }
2250 }
2251
2252 return 0;
2253 }
2254
2255 /*
2256 * check data attributes in IPSEC AH/ESP.
2257 */
2258 static int
check_attr_ah(trns)2259 check_attr_ah(trns)
2260 struct isakmp_pl_t *trns;
2261 {
2262 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2263 }
2264
2265 static int
check_attr_esp(trns)2266 check_attr_esp(trns)
2267 struct isakmp_pl_t *trns;
2268 {
2269 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2270 }
2271
2272 static int
check_attr_ipsec(proto_id,trns)2273 check_attr_ipsec(proto_id, trns)
2274 int proto_id;
2275 struct isakmp_pl_t *trns;
2276 {
2277 struct isakmp_data *d;
2278 int tlen;
2279 int flag, type = 0;
2280 u_int16_t lorv;
2281 int attrseen[16]; /* XXX magic number */
2282
2283 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2284 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2285 memset(attrseen, 0, sizeof(attrseen));
2286
2287 while (tlen > 0) {
2288 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2289 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2290 lorv = ntohs(d->lorv);
2291
2292 plog(LLV_DEBUG, LOCATION, NULL,
2293 "type=%s, flag=0x%04x, lorv=%s\n",
2294 s_ipsecdoi_attr(type), flag,
2295 s_ipsecdoi_attr_v(type, lorv));
2296
2297 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2298 attrseen[type]++;
2299
2300 switch (type) {
2301 case IPSECDOI_ATTR_ENC_MODE:
2302 if (! flag) {
2303 plog(LLV_ERROR, LOCATION, NULL,
2304 "must be TV when ENC_MODE.\n");
2305 return -1;
2306 }
2307
2308 switch (lorv) {
2309 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2310 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2311 break;
2312 #ifdef ENABLE_NATT
2313 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2314 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2315 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2316 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2317 plog(LLV_DEBUG, LOCATION, NULL,
2318 "UDP encapsulation requested\n");
2319 break;
2320 #endif
2321 default:
2322 plog(LLV_ERROR, LOCATION, NULL,
2323 "invalid encryption mode=%u.\n",
2324 lorv);
2325 return -1;
2326 }
2327 break;
2328
2329 case IPSECDOI_ATTR_AUTH:
2330 if (! flag) {
2331 plog(LLV_ERROR, LOCATION, NULL,
2332 "must be TV when AUTH.\n");
2333 return -1;
2334 }
2335
2336 switch (lorv) {
2337 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
2338 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2339 trns->t_id != IPSECDOI_AH_MD5) {
2340 ahmismatch:
2341 plog(LLV_ERROR, LOCATION, NULL,
2342 "auth algorithm %u conflicts "
2343 "with transform %u.\n",
2344 lorv, trns->t_id);
2345 return -1;
2346 }
2347 break;
2348 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
2349 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2350 if (trns->t_id != IPSECDOI_AH_SHA)
2351 goto ahmismatch;
2352 }
2353 break;
2354 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
2355 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2356 if (trns->t_id != IPSECDOI_AH_SHA256)
2357 goto ahmismatch;
2358 }
2359 break;
2360 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
2361 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2362 if (trns->t_id != IPSECDOI_AH_SHA384)
2363 goto ahmismatch;
2364 }
2365 break;
2366 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
2367 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2368 if (trns->t_id != IPSECDOI_AH_SHA512)
2369 goto ahmismatch;
2370 }
2371 break;
2372 case IPSECDOI_ATTR_AUTH_DES_MAC:
2373 case IPSECDOI_ATTR_AUTH_KPDK:
2374 plog(LLV_ERROR, LOCATION, NULL,
2375 "auth algorithm %u isn't supported.\n",
2376 lorv);
2377 return -1;
2378 default:
2379 plog(LLV_ERROR, LOCATION, NULL,
2380 "invalid auth algorithm=%u.\n",
2381 lorv);
2382 return -1;
2383 }
2384 break;
2385
2386 case IPSECDOI_ATTR_SA_LD_TYPE:
2387 if (! flag) {
2388 plog(LLV_ERROR, LOCATION, NULL,
2389 "must be TV when LD_TYPE.\n");
2390 return -1;
2391 }
2392
2393 switch (lorv) {
2394 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2395 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2396 break;
2397 default:
2398 plog(LLV_ERROR, LOCATION, NULL,
2399 "invalid life type %d.\n", lorv);
2400 return -1;
2401 }
2402 break;
2403
2404 case IPSECDOI_ATTR_SA_LD:
2405 if (flag) {
2406 /* i.e. ISAKMP_GEN_TV */
2407 plog(LLV_DEBUG, LOCATION, NULL,
2408 "life duration was in TLV.\n");
2409 } else {
2410 /* i.e. ISAKMP_GEN_TLV */
2411 if (lorv == 0) {
2412 plog(LLV_ERROR, LOCATION, NULL,
2413 "invalid length of LD\n");
2414 return -1;
2415 }
2416 }
2417 break;
2418
2419 case IPSECDOI_ATTR_GRP_DESC:
2420 if (! flag) {
2421 plog(LLV_ERROR, LOCATION, NULL,
2422 "must be TV when GRP_DESC.\n");
2423 return -1;
2424 }
2425
2426 if (!alg_oakley_dhdef_ok(lorv)) {
2427 plog(LLV_ERROR, LOCATION, NULL,
2428 "invalid group description=%u.\n",
2429 lorv);
2430 return -1;
2431 }
2432 break;
2433
2434 case IPSECDOI_ATTR_KEY_LENGTH:
2435 if (! flag) {
2436 plog(LLV_ERROR, LOCATION, NULL,
2437 "must be TV when KEY_LENGTH.\n");
2438 return -1;
2439 }
2440 break;
2441
2442 #ifdef HAVE_SECCTX
2443 case IPSECDOI_ATTR_SECCTX:
2444 if (flag) {
2445 plog(LLV_ERROR, LOCATION, NULL,
2446 "SECCTX must be in TLV.\n");
2447 return -1;
2448 }
2449 break;
2450 #endif
2451
2452 case IPSECDOI_ATTR_KEY_ROUNDS:
2453 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2454 case IPSECDOI_ATTR_COMP_PRIVALG:
2455 plog(LLV_ERROR, LOCATION, NULL,
2456 "attr type=%u isn't supported.\n", type);
2457 return -1;
2458
2459 default:
2460 plog(LLV_ERROR, LOCATION, NULL,
2461 "invalid attribute type %d.\n", type);
2462 return -1;
2463 }
2464
2465 if (flag) {
2466 tlen -= sizeof(*d);
2467 d = (struct isakmp_data *)((char *)d
2468 + sizeof(*d));
2469 } else {
2470 tlen -= (sizeof(*d) + lorv);
2471 d = (struct isakmp_data *)((caddr_t)d
2472 + sizeof(*d) + lorv);
2473 }
2474 }
2475
2476 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2477 !attrseen[IPSECDOI_ATTR_AUTH]) {
2478 plog(LLV_ERROR, LOCATION, NULL,
2479 "attr AUTH must be present for AH.\n");
2480 return -1;
2481 }
2482
2483 if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
2484 trns->t_id == IPSECDOI_ESP_NULL &&
2485 !attrseen[IPSECDOI_ATTR_AUTH]) {
2486 plog(LLV_ERROR, LOCATION, NULL,
2487 "attr AUTH must be present for ESP NULL encryption.\n");
2488 return -1;
2489 }
2490
2491 return 0;
2492 }
2493
2494 static int
check_attr_ipcomp(trns)2495 check_attr_ipcomp(trns)
2496 struct isakmp_pl_t *trns;
2497 {
2498 struct isakmp_data *d;
2499 int tlen;
2500 int flag, type = 0;
2501 u_int16_t lorv;
2502 int attrseen[16]; /* XXX magic number */
2503
2504 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2505 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2506 memset(attrseen, 0, sizeof(attrseen));
2507
2508 while (tlen > 0) {
2509 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2510 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2511 lorv = ntohs(d->lorv);
2512
2513 plog(LLV_DEBUG, LOCATION, NULL,
2514 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2515 type, flag, lorv);
2516
2517 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2518 attrseen[type]++;
2519
2520 switch (type) {
2521 case IPSECDOI_ATTR_ENC_MODE:
2522 if (! flag) {
2523 plog(LLV_ERROR, LOCATION, NULL,
2524 "must be TV when ENC_MODE.\n");
2525 return -1;
2526 }
2527
2528 switch (lorv) {
2529 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2530 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2531 break;
2532 #ifdef ENABLE_NATT
2533 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2534 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2535 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2536 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2537 plog(LLV_DEBUG, LOCATION, NULL,
2538 "UDP encapsulation requested\n");
2539 break;
2540 #endif
2541 default:
2542 plog(LLV_ERROR, LOCATION, NULL,
2543 "invalid encryption mode=%u.\n",
2544 lorv);
2545 return -1;
2546 }
2547 break;
2548
2549 case IPSECDOI_ATTR_SA_LD_TYPE:
2550 if (! flag) {
2551 plog(LLV_ERROR, LOCATION, NULL,
2552 "must be TV when LD_TYPE.\n");
2553 return -1;
2554 }
2555
2556 switch (lorv) {
2557 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2558 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2559 break;
2560 default:
2561 plog(LLV_ERROR, LOCATION, NULL,
2562 "invalid life type %d.\n", lorv);
2563 return -1;
2564 }
2565 break;
2566
2567 case IPSECDOI_ATTR_SA_LD:
2568 if (flag) {
2569 /* i.e. ISAKMP_GEN_TV */
2570 plog(LLV_DEBUG, LOCATION, NULL,
2571 "life duration was in TLV.\n");
2572 } else {
2573 /* i.e. ISAKMP_GEN_TLV */
2574 if (lorv == 0) {
2575 plog(LLV_ERROR, LOCATION, NULL,
2576 "invalid length of LD\n");
2577 return -1;
2578 }
2579 }
2580 break;
2581
2582 case IPSECDOI_ATTR_GRP_DESC:
2583 if (! flag) {
2584 plog(LLV_ERROR, LOCATION, NULL,
2585 "must be TV when GRP_DESC.\n");
2586 return -1;
2587 }
2588
2589 if (!alg_oakley_dhdef_ok(lorv)) {
2590 plog(LLV_ERROR, LOCATION, NULL,
2591 "invalid group description=%u.\n",
2592 lorv);
2593 return -1;
2594 }
2595 break;
2596
2597 case IPSECDOI_ATTR_AUTH:
2598 plog(LLV_ERROR, LOCATION, NULL,
2599 "invalid attr type=%u.\n", type);
2600 return -1;
2601
2602 case IPSECDOI_ATTR_KEY_LENGTH:
2603 case IPSECDOI_ATTR_KEY_ROUNDS:
2604 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2605 case IPSECDOI_ATTR_COMP_PRIVALG:
2606 plog(LLV_ERROR, LOCATION, NULL,
2607 "attr type=%u isn't supported.\n", type);
2608 return -1;
2609
2610 default:
2611 plog(LLV_ERROR, LOCATION, NULL,
2612 "invalid attribute type %d.\n", type);
2613 return -1;
2614 }
2615
2616 if (flag) {
2617 tlen -= sizeof(*d);
2618 d = (struct isakmp_data *)((char *)d
2619 + sizeof(*d));
2620 } else {
2621 tlen -= (sizeof(*d) + lorv);
2622 d = (struct isakmp_data *)((caddr_t)d
2623 + sizeof(*d) + lorv);
2624 }
2625 }
2626
2627 #if 0
2628 if (proto_id == IPSECDOI_PROTO_IPCOMP &&
2629 !attrseen[IPSECDOI_ATTR_AUTH]) {
2630 plog(LLV_ERROR, LOCATION, NULL,
2631 "attr AUTH must be present for AH.\n", type);
2632 return -1;
2633 }
2634 #endif
2635
2636 return 0;
2637 }
2638
2639 /* %%% */
2640 /*
2641 * create phase1 proposal from remote configuration.
2642 * NOT INCLUDING isakmp general header of SA payload
2643 */
2644 vchar_t *
ipsecdoi_setph1proposal(props)2645 ipsecdoi_setph1proposal(props)
2646 struct isakmpsa *props;
2647 {
2648 vchar_t *mysa;
2649 int sablen;
2650
2651 /* count total size of SA minus isakmp general header */
2652 /* not including isakmp general header of SA payload */
2653 sablen = sizeof(struct ipsecdoi_sa_b);
2654 sablen += setph1prop(props, NULL);
2655
2656 mysa = vmalloc(sablen);
2657 if (mysa == NULL) {
2658 plog(LLV_ERROR, LOCATION, NULL,
2659 "failed to allocate my sa buffer\n");
2660 return NULL;
2661 }
2662
2663 /* create SA payload */
2664 /* not including isakmp general header */
2665 ((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(props->rmconf->doitype);
2666 ((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(props->rmconf->sittype);
2667
2668 (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
2669
2670 return mysa;
2671 }
2672
2673 static int
setph1prop(props,buf)2674 setph1prop(props, buf)
2675 struct isakmpsa *props;
2676 caddr_t buf;
2677 {
2678 struct isakmp_pl_p *prop = NULL;
2679 struct isakmpsa *s = NULL;
2680 int proplen, trnslen;
2681 u_int8_t *np_t; /* pointer next trns type in previous header */
2682 int trns_num;
2683 caddr_t p = buf;
2684
2685 proplen = sizeof(*prop);
2686 if (buf) {
2687 /* create proposal */
2688 prop = (struct isakmp_pl_p *)p;
2689 prop->h.np = ISAKMP_NPTYPE_NONE;
2690 prop->p_no = props->prop_no;
2691 prop->proto_id = IPSECDOI_PROTO_ISAKMP;
2692 prop->spi_size = 0;
2693 p += sizeof(*prop);
2694 }
2695
2696 np_t = NULL;
2697 trns_num = 0;
2698
2699 for (s = props; s != NULL; s = s->next) {
2700 if (np_t)
2701 *np_t = ISAKMP_NPTYPE_T;
2702
2703 trnslen = setph1trns(s, p);
2704 proplen += trnslen;
2705 if (buf) {
2706 /* save buffer to pre-next payload */
2707 np_t = &((struct isakmp_pl_t *)p)->h.np;
2708 p += trnslen;
2709
2710 /* count up transform length */
2711 trns_num++;
2712 }
2713 }
2714
2715 /* update proposal length */
2716 if (buf) {
2717 prop->h.len = htons(proplen);
2718 prop->num_t = trns_num;
2719 }
2720
2721 return proplen;
2722 }
2723
2724 static int
setph1trns(sa,buf)2725 setph1trns(sa, buf)
2726 struct isakmpsa *sa;
2727 caddr_t buf;
2728 {
2729 struct isakmp_pl_t *trns = NULL;
2730 int trnslen, attrlen;
2731 caddr_t p = buf;
2732
2733 trnslen = sizeof(*trns);
2734 if (buf) {
2735 /* create transform */
2736 trns = (struct isakmp_pl_t *)p;
2737 trns->h.np = ISAKMP_NPTYPE_NONE;
2738 trns->t_no = sa->trns_no;
2739 trns->t_id = IPSECDOI_KEY_IKE;
2740 p += sizeof(*trns);
2741 }
2742
2743 attrlen = setph1attr(sa, p);
2744 trnslen += attrlen;
2745 if (buf)
2746 p += attrlen;
2747
2748 if (buf)
2749 trns->h.len = htons(trnslen);
2750
2751 return trnslen;
2752 }
2753
2754 static int
setph1attr(sa,buf)2755 setph1attr(sa, buf)
2756 struct isakmpsa *sa;
2757 caddr_t buf;
2758 {
2759 caddr_t p = buf;
2760 int attrlen = 0;
2761
2762 if (sa->lifetime) {
2763 u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
2764
2765 attrlen += sizeof(struct isakmp_data)
2766 + sizeof(struct isakmp_data);
2767 if (sa->lifetime > 0xffff)
2768 attrlen += sizeof(lifetime);
2769 if (buf) {
2770 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2771 OAKLEY_ATTR_SA_LD_TYPE_SEC);
2772 if (sa->lifetime > 0xffff) {
2773 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2774 (caddr_t)&lifetime,
2775 sizeof(lifetime));
2776 } else {
2777 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2778 sa->lifetime);
2779 }
2780 }
2781 }
2782
2783 if (sa->lifebyte) {
2784 u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
2785
2786 attrlen += sizeof(struct isakmp_data)
2787 + sizeof(struct isakmp_data);
2788 if (sa->lifebyte > 0xffff)
2789 attrlen += sizeof(lifebyte);
2790 if (buf) {
2791 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2792 OAKLEY_ATTR_SA_LD_TYPE_KB);
2793 if (sa->lifebyte > 0xffff) {
2794 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2795 (caddr_t)&lifebyte,
2796 sizeof(lifebyte));
2797 } else {
2798 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2799 sa->lifebyte);
2800 }
2801 }
2802 }
2803
2804 if (sa->enctype) {
2805 attrlen += sizeof(struct isakmp_data);
2806 if (buf)
2807 p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
2808 }
2809 if (sa->encklen) {
2810 attrlen += sizeof(struct isakmp_data);
2811 if (buf)
2812 p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
2813 }
2814 if (sa->authmethod) {
2815 int authmethod;
2816
2817 #ifdef ENABLE_HYBRID
2818 authmethod = switch_authmethod(sa->authmethod);
2819 #else
2820 authmethod = sa->authmethod;
2821 #endif
2822 attrlen += sizeof(struct isakmp_data);
2823 if (buf)
2824 p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
2825 }
2826 if (sa->hashtype) {
2827 attrlen += sizeof(struct isakmp_data);
2828 if (buf)
2829 p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
2830 }
2831 switch (sa->dh_group) {
2832 case OAKLEY_ATTR_GRP_DESC_MODP768:
2833 case OAKLEY_ATTR_GRP_DESC_MODP1024:
2834 case OAKLEY_ATTR_GRP_DESC_MODP1536:
2835 case OAKLEY_ATTR_GRP_DESC_MODP2048:
2836 case OAKLEY_ATTR_GRP_DESC_MODP3072:
2837 case OAKLEY_ATTR_GRP_DESC_MODP4096:
2838 case OAKLEY_ATTR_GRP_DESC_MODP6144:
2839 case OAKLEY_ATTR_GRP_DESC_MODP8192:
2840 /* don't attach group type for known groups */
2841 attrlen += sizeof(struct isakmp_data);
2842 if (buf) {
2843 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
2844 sa->dh_group);
2845 }
2846 break;
2847 case OAKLEY_ATTR_GRP_DESC_EC2N155:
2848 case OAKLEY_ATTR_GRP_DESC_EC2N185:
2849 /* don't attach group type for known groups */
2850 attrlen += sizeof(struct isakmp_data);
2851 if (buf) {
2852 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
2853 OAKLEY_ATTR_GRP_TYPE_EC2N);
2854 }
2855 break;
2856 case 0:
2857 default:
2858 break;
2859 }
2860
2861 #ifdef HAVE_GSSAPI
2862 if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
2863 sa->gssid != NULL) {
2864 attrlen += sizeof(struct isakmp_data);
2865 /*
2866 * Older versions of racoon just placed the ISO-Latin-1
2867 * string on the wire directly. Check to see if we are
2868 * configured to be compatible with this behavior. Otherwise,
2869 * we encode the GSS ID as UTF-16LE for Windows 2000
2870 * compatibility, which requires twice the number of octets.
2871 */
2872 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
2873 attrlen += sa->gssid->l;
2874 else
2875 attrlen += sa->gssid->l * 2;
2876 if (buf) {
2877 plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
2878 "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
2879 sa->gssid->v);
2880 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
2881 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2882 (caddr_t)sa->gssid->v,
2883 sa->gssid->l);
2884 } else {
2885 size_t dstleft = sa->gssid->l * 2;
2886 size_t srcleft = sa->gssid->l;
2887 const char *src = (const char *)sa->gssid->v;
2888 char *odst, *dst = racoon_malloc(dstleft);
2889 iconv_t cd;
2890 size_t rv;
2891
2892 cd = iconv_open("utf-16le", "latin1");
2893 if (cd == (iconv_t) -1) {
2894 plog(LLV_ERROR, LOCATION, NULL,
2895 "unable to initialize "
2896 "latin1 -> utf-16le "
2897 "converstion descriptor: %s\n",
2898 strerror(errno));
2899 attrlen -= sa->gssid->l * 2;
2900 goto gssid_done;
2901 }
2902 odst = dst;
2903 rv = iconv(cd, (__iconv_const char **)&src,
2904 &srcleft, &dst, &dstleft);
2905 if (rv != 0) {
2906 if (rv == -1) {
2907 plog(LLV_ERROR, LOCATION, NULL,
2908 "unable to convert GSS ID "
2909 "from latin1 -> utf-16le: "
2910 "%s\n", strerror(errno));
2911 } else {
2912 /* should never happen */
2913 plog(LLV_ERROR, LOCATION, NULL,
2914 "%zd character%s in GSS ID "
2915 "cannot be represented "
2916 "in utf-16le\n",
2917 rv, rv == 1 ? "" : "s");
2918 }
2919 (void) iconv_close(cd);
2920 attrlen -= sa->gssid->l * 2;
2921 goto gssid_done;
2922 }
2923 (void) iconv_close(cd);
2924
2925 /* XXX Check srcleft and dstleft? */
2926
2927 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2928 odst, sa->gssid->l * 2);
2929
2930 racoon_free(odst);
2931 }
2932 }
2933 }
2934 gssid_done:
2935 #endif /* HAVE_GSSAPI */
2936
2937 return attrlen;
2938 }
2939
2940 static vchar_t *
setph2proposal0(iph2,pp,pr)2941 setph2proposal0(iph2, pp, pr)
2942 const struct ph2handle *iph2;
2943 const struct saprop *pp;
2944 const struct saproto *pr;
2945 {
2946 vchar_t *p;
2947 struct isakmp_pl_p *prop;
2948 struct isakmp_pl_t *trns;
2949 struct satrns *tr;
2950 int attrlen;
2951 size_t trnsoff;
2952 caddr_t x0, x;
2953 u_int8_t *np_t; /* pointer next trns type in previous header */
2954 const u_int8_t *spi;
2955 #ifdef HAVE_SECCTX
2956 int truectxlen = 0;
2957 #endif
2958
2959 p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
2960 if (p == NULL)
2961 return NULL;
2962
2963 /* create proposal */
2964 prop = (struct isakmp_pl_p *)p->v;
2965 prop->h.np = ISAKMP_NPTYPE_NONE;
2966 prop->p_no = pp->prop_no;
2967 prop->proto_id = pr->proto_id;
2968 prop->num_t = 1;
2969
2970 spi = (const u_int8_t *)&pr->spi;
2971 switch (pr->proto_id) {
2972 case IPSECDOI_PROTO_IPCOMP:
2973 /*
2974 * draft-shacham-ippcp-rfc2393bis-05.txt:
2975 * construct 16bit SPI (CPI).
2976 * XXX we may need to provide a configuration option to
2977 * generate 32bit SPI. otherwise we cannot interoeprate
2978 * with nodes that uses 32bit SPI, in case we are initiator.
2979 */
2980 prop->spi_size = sizeof(u_int16_t);
2981 spi += sizeof(pr->spi) - sizeof(u_int16_t);
2982 p->l -= sizeof(pr->spi);
2983 p->l += sizeof(u_int16_t);
2984 break;
2985 default:
2986 prop->spi_size = sizeof(pr->spi);
2987 break;
2988 }
2989 memcpy(prop + 1, spi, prop->spi_size);
2990
2991 /* create transform */
2992 trnsoff = sizeof(*prop) + prop->spi_size;
2993 np_t = NULL;
2994
2995 for (tr = pr->head; tr; tr = tr->next) {
2996
2997 switch (pr->proto_id) {
2998 case IPSECDOI_PROTO_IPSEC_ESP:
2999 /*
3000 * don't build a null encryption
3001 * with no authentication transform.
3002 */
3003 if (tr->trns_id == IPSECDOI_ESP_NULL &&
3004 tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
3005 continue;
3006 break;
3007 }
3008
3009 if (np_t) {
3010 *np_t = ISAKMP_NPTYPE_T;
3011 prop->num_t++;
3012 }
3013
3014 /* get attribute length */
3015 attrlen = 0;
3016 if (pp->lifetime) {
3017 attrlen += sizeof(struct isakmp_data)
3018 + sizeof(struct isakmp_data);
3019 if (pp->lifetime > 0xffff)
3020 attrlen += sizeof(u_int32_t);
3021 }
3022 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
3023 attrlen += sizeof(struct isakmp_data)
3024 + sizeof(struct isakmp_data);
3025 if (pp->lifebyte > 0xffff)
3026 attrlen += sizeof(u_int32_t);
3027 }
3028 attrlen += sizeof(struct isakmp_data); /* enc mode */
3029 if (tr->encklen)
3030 attrlen += sizeof(struct isakmp_data);
3031
3032 switch (pr->proto_id) {
3033 case IPSECDOI_PROTO_IPSEC_ESP:
3034 /* non authentication mode ? */
3035 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
3036 attrlen += sizeof(struct isakmp_data);
3037 break;
3038 case IPSECDOI_PROTO_IPSEC_AH:
3039 if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
3040 plog(LLV_ERROR, LOCATION, NULL,
3041 "no authentication algorithm found "
3042 "but protocol is AH.\n");
3043 vfree(p);
3044 return NULL;
3045 }
3046 attrlen += sizeof(struct isakmp_data);
3047 break;
3048 case IPSECDOI_PROTO_IPCOMP:
3049 break;
3050 default:
3051 plog(LLV_ERROR, LOCATION, NULL,
3052 "invalid protocol: %d\n", pr->proto_id);
3053 vfree(p);
3054 return NULL;
3055 }
3056
3057 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
3058 attrlen += sizeof(struct isakmp_data);
3059
3060 #ifdef HAVE_SECCTX
3061 /* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
3062 * The string may be smaller than MAX_CTXSTR_SIZ.
3063 */
3064 if (*pp->sctx.ctx_str) {
3065 truectxlen = sizeof(struct security_ctx) -
3066 (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen);
3067 attrlen += sizeof(struct isakmp_data) + truectxlen;
3068 }
3069 #endif /* HAVE_SECCTX */
3070
3071 p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
3072 if (p == NULL)
3073 return NULL;
3074 prop = (struct isakmp_pl_p *)p->v;
3075
3076 /* set transform's values */
3077 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
3078 trns->h.np = ISAKMP_NPTYPE_NONE;
3079 trns->t_no = tr->trns_no;
3080 trns->t_id = tr->trns_id;
3081
3082 /* set attributes */
3083 x = x0 = p->v + trnsoff + sizeof(*trns);
3084
3085 if (pp->lifetime) {
3086 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
3087 IPSECDOI_ATTR_SA_LD_TYPE_SEC);
3088 if (pp->lifetime > 0xffff) {
3089 u_int32_t v = htonl((u_int32_t)pp->lifetime);
3090 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
3091 (caddr_t)&v, sizeof(v));
3092 } else {
3093 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
3094 pp->lifetime);
3095 }
3096 }
3097
3098 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
3099 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
3100 IPSECDOI_ATTR_SA_LD_TYPE_KB);
3101 if (pp->lifebyte > 0xffff) {
3102 u_int32_t v = htonl((u_int32_t)pp->lifebyte);
3103 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
3104 (caddr_t)&v, sizeof(v));
3105 } else {
3106 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
3107 pp->lifebyte);
3108 }
3109 }
3110
3111 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
3112
3113 if (tr->encklen)
3114 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
3115
3116 /* mandatory check has done above. */
3117 if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
3118 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
3119 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
3120
3121 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
3122 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
3123 iph2->sainfo->pfs_group);
3124
3125 #ifdef HAVE_SECCTX
3126 if (*pp->sctx.ctx_str) {
3127 struct security_ctx secctx;
3128 secctx = pp->sctx;
3129 secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
3130 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
3131 (caddr_t)&secctx, truectxlen);
3132 }
3133 #endif
3134 /* update length of this transform. */
3135 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
3136 trns->h.len = htons(sizeof(*trns) + attrlen);
3137
3138 /* save buffer to pre-next payload */
3139 np_t = &trns->h.np;
3140
3141 trnsoff += (sizeof(*trns) + attrlen);
3142 }
3143
3144 if (np_t == NULL) {
3145 plog(LLV_ERROR, LOCATION, NULL,
3146 "no suitable proposal was created.\n");
3147 return NULL;
3148 }
3149
3150 /* update length of this protocol. */
3151 prop->h.len = htons(p->l);
3152
3153 return p;
3154 }
3155
3156 /*
3157 * create phase2 proposal from policy configuration.
3158 * NOT INCLUDING isakmp general header of SA payload.
3159 * This function is called by initiator only.
3160 */
3161 int
ipsecdoi_setph2proposal(iph2)3162 ipsecdoi_setph2proposal(iph2)
3163 struct ph2handle *iph2;
3164 {
3165 struct saprop *proposal, *a;
3166 struct saproto *b = NULL;
3167 vchar_t *q;
3168 struct ipsecdoi_sa_b *sab;
3169 struct isakmp_pl_p *prop;
3170 size_t propoff; /* for previous field of type of next payload. */
3171
3172 proposal = iph2->proposal;
3173
3174 iph2->sa = vmalloc(sizeof(*sab));
3175 if (iph2->sa == NULL) {
3176 plog(LLV_ERROR, LOCATION, NULL,
3177 "failed to allocate my sa buffer\n");
3178 return -1;
3179 }
3180
3181 /* create SA payload */
3182 sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
3183 sab->doi = htonl(IPSEC_DOI);
3184 sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */
3185
3186 prop = NULL;
3187 propoff = 0;
3188 for (a = proposal; a; a = a->next) {
3189 for (b = a->head; b; b = b->next) {
3190 #ifdef ENABLE_NATT
3191 if (iph2->ph1->natt_flags & NAT_DETECTED) {
3192 int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
3193 plog (LLV_INFO, LOCATION, NULL,
3194 "NAT detected -> UDP encapsulation "
3195 "(ENC_MODE %d->%d).\n",
3196 b->encmode,
3197 b->encmode+udp_diff);
3198 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3199 b->encmode += udp_diff;
3200 b->udp_encap = 1;
3201 }
3202 #endif
3203
3204 q = setph2proposal0(iph2, a, b);
3205 if (q == NULL) {
3206 VPTRINIT(iph2->sa);
3207 return -1;
3208 }
3209
3210 iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
3211 if (iph2->sa == NULL) {
3212 plog(LLV_ERROR, LOCATION, NULL,
3213 "failed to allocate my sa buffer\n");
3214 if (q)
3215 vfree(q);
3216 return -1;
3217 }
3218 memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
3219 if (propoff != 0) {
3220 prop = (struct isakmp_pl_p *)(iph2->sa->v +
3221 propoff);
3222 prop->h.np = ISAKMP_NPTYPE_P;
3223 }
3224 propoff = iph2->sa->l - q->l;
3225
3226 vfree(q);
3227 }
3228 }
3229
3230 return 0;
3231 }
3232
3233 /*
3234 * return 1 if all of the given protocols are transport mode.
3235 */
3236 int
ipsecdoi_transportmode(pp)3237 ipsecdoi_transportmode(pp)
3238 struct saprop *pp;
3239 {
3240 struct saproto *pr = NULL;
3241
3242 for (; pp; pp = pp->next) {
3243 for (pr = pp->head; pr; pr = pr->next) {
3244 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
3245 return 0;
3246 }
3247 }
3248
3249 return 1;
3250 }
3251
3252 int
ipsecdoi_get_defaultlifetime()3253 ipsecdoi_get_defaultlifetime()
3254 {
3255 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3256 }
3257
3258 int
ipsecdoi_checkalgtypes(proto_id,enc,auth,comp)3259 ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
3260 int proto_id, enc, auth, comp;
3261 {
3262 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3263 switch (proto_id) {
3264 case IPSECDOI_PROTO_IPSEC_ESP:
3265 if (enc == 0 || comp != 0) {
3266 plog(LLV_ERROR, LOCATION, NULL,
3267 "illegal algorithm defined "
3268 "ESP enc=%s auth=%s comp=%s.\n",
3269 TMPALGTYPE2STR(enc),
3270 TMPALGTYPE2STR(auth),
3271 TMPALGTYPE2STR(comp));
3272 return -1;
3273 }
3274 break;
3275 case IPSECDOI_PROTO_IPSEC_AH:
3276 if (enc != 0 || auth == 0 || comp != 0) {
3277 plog(LLV_ERROR, LOCATION, NULL,
3278 "illegal algorithm defined "
3279 "AH enc=%s auth=%s comp=%s.\n",
3280 TMPALGTYPE2STR(enc),
3281 TMPALGTYPE2STR(auth),
3282 TMPALGTYPE2STR(comp));
3283 return -1;
3284 }
3285 break;
3286 case IPSECDOI_PROTO_IPCOMP:
3287 if (enc != 0 || auth != 0 || comp == 0) {
3288 plog(LLV_ERROR, LOCATION, NULL,
3289 "illegal algorithm defined "
3290 "IPcomp enc=%s auth=%s comp=%s.\n",
3291 TMPALGTYPE2STR(enc),
3292 TMPALGTYPE2STR(auth),
3293 TMPALGTYPE2STR(comp));
3294 return -1;
3295 }
3296 break;
3297 default:
3298 plog(LLV_ERROR, LOCATION, NULL,
3299 "invalid ipsec protocol %d\n", proto_id);
3300 return -1;
3301 }
3302 #undef TMPALGTYPE2STR
3303 return 0;
3304 }
3305
3306 int
ipproto2doi(proto)3307 ipproto2doi(proto)
3308 int proto;
3309 {
3310 switch (proto) {
3311 case IPPROTO_AH:
3312 return IPSECDOI_PROTO_IPSEC_AH;
3313 case IPPROTO_ESP:
3314 return IPSECDOI_PROTO_IPSEC_ESP;
3315 case IPPROTO_IPCOMP:
3316 return IPSECDOI_PROTO_IPCOMP;
3317 }
3318 return -1; /* XXX */
3319 }
3320
3321 int
doi2ipproto(proto)3322 doi2ipproto(proto)
3323 int proto;
3324 {
3325 switch (proto) {
3326 case IPSECDOI_PROTO_IPSEC_AH:
3327 return IPPROTO_AH;
3328 case IPSECDOI_PROTO_IPSEC_ESP:
3329 return IPPROTO_ESP;
3330 case IPSECDOI_PROTO_IPCOMP:
3331 return IPPROTO_IPCOMP;
3332 }
3333 return -1; /* XXX */
3334 }
3335
3336 /*
3337 * Check if a subnet id is valid for comparison
3338 * with an address id ( address length mask )
3339 * and compare them
3340 * Return value
3341 * = 0 for match
3342 * = 1 for mismatch
3343 */
3344
3345 int
ipsecdoi_subnetisaddr_v4(subnet,address)3346 ipsecdoi_subnetisaddr_v4( subnet, address )
3347 const vchar_t *subnet;
3348 const vchar_t *address;
3349 {
3350 struct in_addr *mask;
3351
3352 if (address->l != sizeof(struct in_addr))
3353 return 1;
3354
3355 if (subnet->l != (sizeof(struct in_addr)*2))
3356 return 1;
3357
3358 mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
3359
3360 if (mask->s_addr!=0xffffffff)
3361 return 1;
3362
3363 return memcmp(subnet->v,address->v,address->l);
3364 }
3365
3366 #ifdef INET6
3367
3368 int
ipsecdoi_subnetisaddr_v6(subnet,address)3369 ipsecdoi_subnetisaddr_v6( subnet, address )
3370 const vchar_t *subnet;
3371 const vchar_t *address;
3372 {
3373 struct in6_addr *mask;
3374 int i;
3375
3376 if (address->l != sizeof(struct in6_addr))
3377 return 1;
3378
3379 if (subnet->l != (sizeof(struct in6_addr)*2))
3380 return 1;
3381
3382 mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
3383
3384 for (i=0; i<16; i++)
3385 if(mask->s6_addr[i]!=0xff)
3386 return 1;
3387
3388 return memcmp(subnet->v,address->v,address->l);
3389 }
3390
3391 #endif
3392
3393 /*
3394 * Check and Compare two IDs
3395 * - specify 0 for exact if wildcards are allowed
3396 * Return value
3397 * = 0 for match
3398 * = 1 for misatch
3399 * = -1 for integrity error
3400 */
3401
3402 int
ipsecdoi_chkcmpids(idt,ids,exact)3403 ipsecdoi_chkcmpids( idt, ids, exact )
3404 const vchar_t *idt; /* id cmp target */
3405 const vchar_t *ids; /* id cmp source */
3406 int exact;
3407 {
3408 struct ipsecdoi_id_b *id_bt;
3409 struct ipsecdoi_id_b *id_bs;
3410 vchar_t ident_t;
3411 vchar_t ident_s;
3412 int result;
3413
3414 /* handle wildcard IDs */
3415
3416 if (idt == NULL || ids == NULL)
3417 {
3418 if( !exact )
3419 {
3420 plog(LLV_DEBUG, LOCATION, NULL,
3421 "check and compare ids : values matched (ANONYMOUS)\n" );
3422 return 0;
3423 }
3424 else
3425 {
3426 plog(LLV_DEBUG, LOCATION, NULL,
3427 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3428 return -1;
3429 }
3430 }
3431
3432 /* make sure the ids are of the same type */
3433
3434 id_bt = (struct ipsecdoi_id_b *) idt->v;
3435 id_bs = (struct ipsecdoi_id_b *) ids->v;
3436
3437 ident_t.v = idt->v + sizeof(*id_bt);
3438 ident_t.l = idt->l - sizeof(*id_bt);
3439 ident_s.v = ids->v + sizeof(*id_bs);
3440 ident_s.l = ids->l - sizeof(*id_bs);
3441
3442 if (id_bs->type != id_bt->type)
3443 {
3444 /*
3445 * special exception for comparing
3446 * address to subnet id types when
3447 * the netmask is address length
3448 */
3449
3450 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
3451 (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
3452 result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
3453 goto cmpid_result;
3454 }
3455
3456 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
3457 (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
3458 result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
3459 goto cmpid_result;
3460 }
3461
3462 #ifdef INET6
3463 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
3464 (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
3465 result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
3466 goto cmpid_result;
3467 }
3468
3469 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
3470 (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
3471 result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
3472 goto cmpid_result;
3473 }
3474 #endif
3475 plog(LLV_DEBUG, LOCATION, NULL,
3476 "check and compare ids : id type mismatch %s != %s\n",
3477 s_ipsecdoi_ident(id_bs->type),
3478 s_ipsecdoi_ident(id_bt->type));
3479
3480 return 1;
3481 }
3482
3483 if(id_bs->proto_id != id_bt->proto_id){
3484 plog(LLV_DEBUG, LOCATION, NULL,
3485 "check and compare ids : proto_id mismatch %d != %d\n",
3486 id_bs->proto_id, id_bt->proto_id);
3487
3488 return 1;
3489 }
3490
3491 /* compare the ID data. */
3492
3493 switch (id_bt->type) {
3494 case IPSECDOI_ID_DER_ASN1_DN:
3495 case IPSECDOI_ID_DER_ASN1_GN:
3496 /* compare asn1 ids */
3497 result = eay_cmp_asn1dn(&ident_t, &ident_s);
3498 goto cmpid_result;
3499
3500 case IPSECDOI_ID_IPV4_ADDR:
3501 /* validate lengths */
3502 if ((ident_t.l != sizeof(struct in_addr))||
3503 (ident_s.l != sizeof(struct in_addr)))
3504 goto cmpid_invalid;
3505 break;
3506
3507 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3508 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3509 /* validate lengths */
3510 if ((ident_t.l != (sizeof(struct in_addr)*2))||
3511 (ident_s.l != (sizeof(struct in_addr)*2)))
3512 goto cmpid_invalid;
3513 break;
3514
3515 #ifdef INET6
3516 case IPSECDOI_ID_IPV6_ADDR:
3517 /* validate lengths */
3518 if ((ident_t.l != sizeof(struct in6_addr))||
3519 (ident_s.l != sizeof(struct in6_addr)))
3520 goto cmpid_invalid;
3521 break;
3522
3523 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3524 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3525 /* validate lengths */
3526 if ((ident_t.l != (sizeof(struct in6_addr)*2))||
3527 (ident_s.l != (sizeof(struct in6_addr)*2)))
3528 goto cmpid_invalid;
3529 break;
3530 #endif
3531 case IPSECDOI_ID_FQDN:
3532 case IPSECDOI_ID_USER_FQDN:
3533 case IPSECDOI_ID_KEY_ID:
3534 break;
3535
3536 default:
3537 plog(LLV_ERROR, LOCATION, NULL,
3538 "Unhandled id type %i specified for comparison\n",
3539 id_bt->type);
3540 return -1;
3541 }
3542
3543 /* validate matching data and length */
3544 if (ident_t.l == ident_s.l)
3545 result = memcmp(ident_t.v,ident_s.v,ident_t.l);
3546 else
3547 result = 1;
3548
3549 cmpid_result:
3550
3551 /* debug level output */
3552 if(loglevel >= LLV_DEBUG) {
3553 char *idstrt = ipsecdoi_id2str(idt);
3554 char *idstrs = ipsecdoi_id2str(ids);
3555
3556 if (!result)
3557 plog(LLV_DEBUG, LOCATION, NULL,
3558 "check and compare ids : values matched (%s)\n",
3559 s_ipsecdoi_ident(id_bs->type) );
3560 else
3561 plog(LLV_DEBUG, LOCATION, NULL,
3562 "check and compare ids : value mismatch (%s)\n",
3563 s_ipsecdoi_ident(id_bs->type));
3564
3565 plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
3566 plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
3567
3568 racoon_free(idstrs);
3569 racoon_free(idstrt);
3570 }
3571
3572 /* return result */
3573 if( !result )
3574 return 0;
3575 else
3576 return 1;
3577
3578 cmpid_invalid:
3579
3580 /* id integrity error */
3581 plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
3582 s_ipsecdoi_ident(id_bs->type));
3583 plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
3584 plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
3585
3586 return -1;
3587 }
3588
3589 /*
3590 * check the following:
3591 * - In main mode with pre-shared key, only address type can be used.
3592 * - if proper type for phase 1 ?
3593 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3594 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3595 * - if ID payload sent from peer is equal to the ID expected by me.
3596 *
3597 * both of "id" and "id_p" should be ID payload without general header,
3598 */
3599 int
ipsecdoi_checkid1(iph1)3600 ipsecdoi_checkid1(iph1)
3601 struct ph1handle *iph1;
3602 {
3603 struct ipsecdoi_id_b *id_b;
3604 struct sockaddr *sa;
3605 caddr_t sa1, sa2;
3606
3607 if (iph1->id_p == NULL) {
3608 plog(LLV_ERROR, LOCATION, NULL,
3609 "invalid iph1 passed id_p == NULL\n");
3610 return ISAKMP_INTERNAL_ERROR;
3611 }
3612 if (iph1->id_p->l < sizeof(*id_b)) {
3613 plog(LLV_ERROR, LOCATION, NULL,
3614 "invalid value passed as \"ident\" (len=%lu)\n",
3615 (u_long)iph1->id_p->l);
3616 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3617 }
3618
3619 id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
3620
3621 #ifndef ANDROID_PATCHED
3622 /* In main mode with pre-shared key, only address type can be used. */
3623 if (iph1->etype == ISAKMP_ETYPE_IDENT &&
3624 iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
3625 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3626 && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3627 plog(LLV_ERROR, LOCATION, NULL,
3628 "Expecting IP address type in main mode, "
3629 "but %s.\n", s_ipsecdoi_ident(id_b->type));
3630 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3631 }
3632 }
3633 #endif
3634
3635 /* if proper type for phase 1 ? */
3636 switch (id_b->type) {
3637 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3638 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3639 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3640 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3641 plog(LLV_WARNING, LOCATION, NULL,
3642 "such ID type %s is not proper.\n",
3643 s_ipsecdoi_ident(id_b->type));
3644 /*FALLTHROUGH*/
3645 }
3646
3647 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
3648 if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
3649 id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3650
3651 if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
3652 plog(LLV_WARNING, LOCATION, NULL,
3653 "protocol ID and Port mismatched. "
3654 "proto_id:%d port:%d\n",
3655 id_b->proto_id, ntohs(id_b->port));
3656 /*FALLTHROUGH*/
3657
3658 } else if (id_b->proto_id == IPPROTO_UDP) {
3659 /*
3660 * copmaring with expecting port.
3661 * always permit if port is equal to PORT_ISAKMP
3662 */
3663 if (ntohs(id_b->port) != PORT_ISAKMP) {
3664 u_int16_t port;
3665
3666 port = extract_port(iph1->remote);
3667 if (ntohs(id_b->port) != port) {
3668 plog(LLV_WARNING, LOCATION, NULL,
3669 "port %d expected, but %d\n",
3670 port, ntohs(id_b->port));
3671 /*FALLTHROUGH*/
3672 }
3673 }
3674 }
3675 }
3676
3677 /* compare with the ID if specified. */
3678 if (genlist_next(iph1->rmconf->idvl_p, 0)) {
3679 vchar_t *ident0 = NULL;
3680 vchar_t ident;
3681 struct idspec *id;
3682 struct genlist_entry *gpb;
3683
3684 for (id = genlist_next (iph1->rmconf->idvl_p, &gpb); id; id = genlist_next (0, &gpb)) {
3685 /* check the type of both IDs */
3686 if (id->idtype != doi2idtype(id_b->type))
3687 continue; /* ID type mismatch */
3688 if (id->id == 0)
3689 goto matched;
3690
3691 /* compare defined ID with the ID sent by peer. */
3692 if (ident0 != NULL)
3693 vfree(ident0);
3694 ident0 = getidval(id->idtype, id->id);
3695
3696 switch (id->idtype) {
3697 case IDTYPE_ASN1DN:
3698 ident.v = iph1->id_p->v + sizeof(*id_b);
3699 ident.l = iph1->id_p->l - sizeof(*id_b);
3700 if (eay_cmp_asn1dn(ident0, &ident) == 0)
3701 goto matched;
3702 break;
3703 case IDTYPE_ADDRESS:
3704 sa = (struct sockaddr *)ident0->v;
3705 sa2 = (caddr_t)(id_b + 1);
3706 switch (sa->sa_family) {
3707 case AF_INET:
3708 if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
3709 continue; /* ID value mismatch */
3710 sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr;
3711 if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
3712 goto matched;
3713 break;
3714 #ifdef INET6
3715 case AF_INET6:
3716 if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
3717 continue; /* ID value mismatch */
3718 sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr;
3719 if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
3720 goto matched;
3721 break;
3722 #endif
3723 default:
3724 break;
3725 }
3726 break;
3727 default:
3728 if (memcmp(ident0->v, id_b + 1, ident0->l) == 0)
3729 goto matched;
3730 break;
3731 }
3732 }
3733 if (ident0 != NULL) {
3734 vfree(ident0);
3735 ident0 = NULL;
3736 }
3737 plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n");
3738 if (iph1->rmconf->verify_identifier)
3739 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3740 matched: /* ID value match */
3741 if (ident0 != NULL)
3742 vfree(ident0);
3743 }
3744
3745 return 0;
3746 }
3747
3748 /*
3749 * create ID payload for phase 1 and set into iph1->id.
3750 * NOT INCLUDING isakmp general header.
3751 * see, RFC2407 4.6.2.1
3752 */
3753 int
ipsecdoi_setid1(iph1)3754 ipsecdoi_setid1(iph1)
3755 struct ph1handle *iph1;
3756 {
3757 vchar_t *ret = NULL;
3758 struct ipsecdoi_id_b id_b;
3759 vchar_t *ident = NULL;
3760 struct sockaddr *ipid = NULL;
3761
3762 /* init */
3763 id_b.proto_id = 0;
3764 id_b.port = 0;
3765 ident = NULL;
3766
3767 switch (iph1->rmconf->idvtype) {
3768 case IDTYPE_FQDN:
3769 id_b.type = IPSECDOI_ID_FQDN;
3770 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3771 break;
3772 case IDTYPE_USERFQDN:
3773 id_b.type = IPSECDOI_ID_USER_FQDN;
3774 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3775 break;
3776 case IDTYPE_KEYID:
3777 id_b.type = IPSECDOI_ID_KEY_ID;
3778 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3779 break;
3780 case IDTYPE_ASN1DN:
3781 id_b.type = IPSECDOI_ID_DER_ASN1_DN;
3782 if (iph1->rmconf->idv) {
3783 /* XXX it must be encoded to asn1dn. */
3784 ident = vdup(iph1->rmconf->idv);
3785 } else {
3786 if (oakley_getmycert(iph1) < 0) {
3787 plog(LLV_ERROR, LOCATION, NULL,
3788 "failed to get own CERT.\n");
3789 goto err;
3790 }
3791 ident = eay_get_x509asn1subjectname(&iph1->cert->cert);
3792 }
3793 break;
3794 case IDTYPE_ADDRESS:
3795 /*
3796 * if the value of the id type was set by the configuration
3797 * file, then use it. otherwise the value is get from local
3798 * ip address by using ike negotiation.
3799 */
3800 if (iph1->rmconf->idv)
3801 ipid = (struct sockaddr *)iph1->rmconf->idv->v;
3802 /*FALLTHROUGH*/
3803 default:
3804 {
3805 int l;
3806 caddr_t p;
3807
3808 if (ipid == NULL)
3809 ipid = iph1->local;
3810
3811 /* use IP address */
3812 switch (ipid->sa_family) {
3813 case AF_INET:
3814 id_b.type = IPSECDOI_ID_IPV4_ADDR;
3815 l = sizeof(struct in_addr);
3816 p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
3817 break;
3818 #ifdef INET6
3819 case AF_INET6:
3820 id_b.type = IPSECDOI_ID_IPV6_ADDR;
3821 l = sizeof(struct in6_addr);
3822 p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
3823 break;
3824 #endif
3825 default:
3826 plog(LLV_ERROR, LOCATION, NULL,
3827 "invalid address family.\n");
3828 goto err;
3829 }
3830 id_b.proto_id = IPPROTO_UDP;
3831 id_b.port = htons(PORT_ISAKMP);
3832 ident = vmalloc(l);
3833 if (!ident) {
3834 plog(LLV_ERROR, LOCATION, NULL,
3835 "failed to get ID buffer.\n");
3836 return 0;
3837 }
3838 memcpy(ident->v, p, ident->l);
3839 }
3840 }
3841 if (!ident) {
3842 plog(LLV_ERROR, LOCATION, NULL,
3843 "failed to get ID buffer.\n");
3844 return 0;
3845 }
3846
3847 ret = vmalloc(sizeof(id_b) + ident->l);
3848 if (ret == NULL) {
3849 plog(LLV_ERROR, LOCATION, NULL,
3850 "failed to get ID buffer.\n");
3851 goto err;
3852 }
3853
3854 memcpy(ret->v, &id_b, sizeof(id_b));
3855 memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
3856
3857 iph1->id = ret;
3858
3859 plog(LLV_DEBUG, LOCATION, NULL,
3860 "use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
3861 if (ident)
3862 vfree(ident);
3863 return 0;
3864
3865 err:
3866 if (ident)
3867 vfree(ident);
3868 plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
3869 return -1;
3870 }
3871
3872 static vchar_t *
getidval(type,val)3873 getidval(type, val)
3874 int type;
3875 vchar_t *val;
3876 {
3877 vchar_t *new = NULL;
3878
3879 if (val)
3880 new = vdup(val);
3881 else if (lcconf->ident[type])
3882 new = vdup(lcconf->ident[type]);
3883
3884 return new;
3885 }
3886
3887 /* it's only called by cfparse.y. */
3888 int
set_identifier(vpp,type,value)3889 set_identifier(vpp, type, value)
3890 vchar_t **vpp, *value;
3891 int type;
3892 {
3893 return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
3894 }
3895
3896 int
set_identifier_qual(vpp,type,value,qual)3897 set_identifier_qual(vpp, type, value, qual)
3898 vchar_t **vpp, *value;
3899 int type;
3900 int qual;
3901 {
3902 vchar_t *new = NULL;
3903
3904 /* simply return if value is null. */
3905 if (!value){
3906 if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
3907 plog(LLV_ERROR, LOCATION, NULL,
3908 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3909 return -1;
3910 }
3911 return 0;
3912 }
3913
3914 switch (type) {
3915 case IDTYPE_FQDN:
3916 case IDTYPE_USERFQDN:
3917 if(value->l <= 1){
3918 plog(LLV_ERROR, LOCATION, NULL,
3919 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3920 return -1;
3921 }
3922 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3923 new = vmalloc(value->l - 1);
3924 if (new == NULL)
3925 return -1;
3926 memcpy(new->v, value->v, new->l);
3927 break;
3928 case IDTYPE_KEYID:
3929 /*
3930 * If no qualifier is specified: IDQUAL_UNSPEC. It means
3931 * to use a file for backward compatibility sake.
3932 */
3933 switch(qual) {
3934 case IDQUAL_FILE:
3935 case IDQUAL_UNSPEC: {
3936 FILE *fp;
3937 char b[512];
3938 int tlen, len;
3939
3940 fp = fopen(value->v, "r");
3941 if (fp == NULL) {
3942 plog(LLV_ERROR, LOCATION, NULL,
3943 "can not open %s\n", value->v);
3944 return -1;
3945 }
3946 tlen = 0;
3947 while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
3948 new = vrealloc(new, tlen + len);
3949 if (!new) {
3950 fclose(fp);
3951 return -1;
3952 }
3953 memcpy(new->v + tlen, b, len);
3954 tlen += len;
3955 }
3956 break;
3957 }
3958
3959 case IDQUAL_TAG:
3960 new = vmalloc(value->l - 1);
3961 if (new == NULL) {
3962 plog(LLV_ERROR, LOCATION, NULL,
3963 "can not allocate memory");
3964 return -1;
3965 }
3966 memcpy(new->v, value->v, new->l);
3967 break;
3968
3969 default:
3970 plog(LLV_ERROR, LOCATION, NULL,
3971 "unknown qualifier");
3972 return -1;
3973 }
3974 break;
3975
3976 case IDTYPE_ADDRESS: {
3977 struct sockaddr *sa;
3978
3979 /* length is adjusted since QUOTEDSTRING teminates NULL. */
3980 if (value->l == 0)
3981 break;
3982
3983 sa = str2saddr(value->v, NULL);
3984 if (sa == NULL) {
3985 plog(LLV_ERROR, LOCATION, NULL,
3986 "invalid ip address %s\n", value->v);
3987 return -1;
3988 }
3989
3990 new = vmalloc(sysdep_sa_len(sa));
3991 if (new == NULL) {
3992 racoon_free(sa);
3993 return -1;
3994 }
3995 memcpy(new->v, sa, new->l);
3996 racoon_free(sa);
3997 break;
3998 }
3999 case IDTYPE_ASN1DN:
4000 if (value->v[0] == '~')
4001 /* Hex-encoded ASN1 strings */
4002 new = eay_hex2asn1dn(value->v + 1, - 1);
4003 else
4004 /* DN encoded strings */
4005 new = eay_str2asn1dn(value->v, value->l - 1);
4006
4007 if (new == NULL)
4008 return -1;
4009
4010 if (loglevel >= LLV_DEBUG) {
4011 X509_NAME *xn;
4012 BIO *bio;
4013 unsigned char *ptr = (unsigned char *) new->v, *buf;
4014 size_t len;
4015 #if defined(ANDROID_CHANGES)
4016 char *bio_contents;
4017 #else
4018 char save;
4019 #endif
4020
4021 xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
4022 bio = BIO_new(BIO_s_mem());
4023
4024 X509_NAME_print_ex(bio, xn, 0, 0);
4025 #if defined(ANDROID_CHANGES)
4026 BIO_write(bio, "\x00", 1);
4027 BIO_get_mem_data(bio, &bio_contents);
4028 plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", bio_contents);
4029 #else
4030 len = BIO_get_mem_data(bio, &ptr);
4031 save = ptr[len];
4032 ptr[len] = 0;
4033 plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
4034 ptr[len] = save;
4035 #endif
4036 X509_NAME_free(xn);
4037 BIO_free(bio);
4038 }
4039
4040 break;
4041 }
4042
4043 *vpp = new;
4044
4045 return 0;
4046 }
4047
4048 /*
4049 * create ID payload for phase 2, and set into iph2->id and id_p. There are
4050 * NOT INCLUDING isakmp general header.
4051 * this function is for initiator. responder will get to copy from payload.
4052 * responder ID type is always address type.
4053 * see, RFC2407 4.6.2.1
4054 */
4055 int
ipsecdoi_setid2(iph2)4056 ipsecdoi_setid2(iph2)
4057 struct ph2handle *iph2;
4058 {
4059 struct secpolicy *sp;
4060
4061 /* check there is phase 2 handler ? */
4062 sp = getspbyspid(iph2->spid);
4063 if (sp == NULL) {
4064 plog(LLV_ERROR, LOCATION, NULL,
4065 "no policy found for spid:%u.\n", iph2->spid);
4066 return -1;
4067 }
4068
4069 iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
4070 sp->spidx.prefs, sp->spidx.ul_proto);
4071 if (iph2->id == NULL) {
4072 plog(LLV_ERROR, LOCATION, NULL,
4073 "failed to get ID for %s\n",
4074 spidx2str(&sp->spidx));
4075 return -1;
4076 }
4077 plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
4078 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
4079
4080 /* remote side */
4081 iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
4082 sp->spidx.prefd, sp->spidx.ul_proto);
4083 if (iph2->id_p == NULL) {
4084 plog(LLV_ERROR, LOCATION, NULL,
4085 "failed to get ID for %s\n",
4086 spidx2str(&sp->spidx));
4087 VPTRINIT(iph2->id);
4088 return -1;
4089 }
4090 plog(LLV_DEBUG, LOCATION, NULL,
4091 "use remote ID type %s\n",
4092 s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
4093
4094 return 0;
4095 }
4096
4097 /*
4098 * set address type of ID.
4099 * NOT INCLUDING general header.
4100 */
4101 vchar_t *
ipsecdoi_sockaddr2id(saddr,prefixlen,ul_proto)4102 ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
4103 struct sockaddr *saddr;
4104 u_int prefixlen;
4105 u_int ul_proto;
4106 {
4107 vchar_t *new;
4108 int type, len1, len2;
4109 caddr_t sa;
4110 u_short port;
4111
4112 /*
4113 * Q. When type is SUBNET, is it allowed to be ::1/128.
4114 * A. Yes. (consensus at bake-off)
4115 */
4116 switch (saddr->sa_family) {
4117 case AF_INET:
4118 len1 = sizeof(struct in_addr);
4119 if (prefixlen == (sizeof(struct in_addr) << 3)) {
4120 type = IPSECDOI_ID_IPV4_ADDR;
4121 len2 = 0;
4122 } else {
4123 type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
4124 len2 = sizeof(struct in_addr);
4125 }
4126 sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
4127 port = ((struct sockaddr_in *)(saddr))->sin_port;
4128 break;
4129 #ifdef INET6
4130 case AF_INET6:
4131 len1 = sizeof(struct in6_addr);
4132 if (prefixlen == (sizeof(struct in6_addr) << 3)) {
4133 type = IPSECDOI_ID_IPV6_ADDR;
4134 len2 = 0;
4135 } else {
4136 type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
4137 len2 = sizeof(struct in6_addr);
4138 }
4139 sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
4140 port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
4141 break;
4142 #endif
4143 default:
4144 plog(LLV_ERROR, LOCATION, NULL,
4145 "invalid family: %d.\n", saddr->sa_family);
4146 return NULL;
4147 }
4148
4149 /* get ID buffer */
4150 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4151 if (new == NULL) {
4152 plog(LLV_ERROR, LOCATION, NULL,
4153 "failed to get ID buffer.\n");
4154 return NULL;
4155 }
4156
4157 memset(new->v, 0, new->l);
4158
4159 /* set the part of header. */
4160 ((struct ipsecdoi_id_b *)new->v)->type = type;
4161
4162 /* set ul_proto and port */
4163 /*
4164 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4165 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4166 */
4167 ((struct ipsecdoi_id_b *)new->v)->proto_id =
4168 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4169 ((struct ipsecdoi_id_b *)new->v)->port =
4170 port == IPSEC_PORT_ANY ? 0 : port;
4171 memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
4172
4173 /* set address */
4174
4175 /* set prefix */
4176 if (len2) {
4177 u_char *p = (unsigned char *) new->v +
4178 sizeof(struct ipsecdoi_id_b) + len1;
4179 u_int bits = prefixlen;
4180
4181 while (bits >= 8) {
4182 *p++ = 0xff;
4183 bits -= 8;
4184 }
4185
4186 if (bits > 0)
4187 *p = ~((1 << (8 - bits)) - 1);
4188 }
4189
4190 return new;
4191 }
4192
4193 vchar_t *
ipsecdoi_sockrange2id(laddr,haddr,ul_proto)4194 ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
4195 struct sockaddr *laddr, *haddr;
4196 u_int ul_proto;
4197 {
4198 vchar_t *new;
4199 int type, len1, len2;
4200 u_short port;
4201
4202 if (laddr->sa_family != haddr->sa_family) {
4203 plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
4204 return NULL;
4205 }
4206
4207 switch (laddr->sa_family) {
4208 case AF_INET:
4209 type = IPSECDOI_ID_IPV4_ADDR_RANGE;
4210 len1 = sizeof(struct in_addr);
4211 len2 = sizeof(struct in_addr);
4212 break;
4213 #ifdef INET6
4214 case AF_INET6:
4215 type = IPSECDOI_ID_IPV6_ADDR_RANGE;
4216 len1 = sizeof(struct in6_addr);
4217 len2 = sizeof(struct in6_addr);
4218 break;
4219 #endif
4220 default:
4221 plog(LLV_ERROR, LOCATION, NULL,
4222 "invalid family: %d.\n", laddr->sa_family);
4223 return NULL;
4224 }
4225
4226 /* get ID buffer */
4227 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4228 if (new == NULL) {
4229 plog(LLV_ERROR, LOCATION, NULL,
4230 "failed to get ID buffer.\n");
4231 return NULL;
4232 }
4233
4234 memset(new->v, 0, new->l);
4235 /* set the part of header. */
4236 ((struct ipsecdoi_id_b *)new->v)->type = type;
4237
4238 /* set ul_proto and port */
4239 /*
4240 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4241 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4242 */
4243 ((struct ipsecdoi_id_b *)new->v)->proto_id =
4244 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4245 port = ((struct sockaddr_in *)(laddr))->sin_port;
4246 ((struct ipsecdoi_id_b *)new->v)->port =
4247 port == IPSEC_PORT_ANY ? 0 : port;
4248 memcpy(new->v + sizeof(struct ipsecdoi_id_b),
4249 (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
4250 len1);
4251 memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
4252 (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
4253 len2);
4254 return new;
4255 }
4256
4257
4258 /*
4259 * create sockaddr structure from ID payload (buf).
4260 * buffers (saddr, prefixlen, ul_proto) must be allocated.
4261 * see, RFC2407 4.6.2.1
4262 */
4263 int
ipsecdoi_id2sockaddr(buf,saddr,prefixlen,ul_proto)4264 ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
4265 vchar_t *buf;
4266 struct sockaddr *saddr;
4267 u_int8_t *prefixlen;
4268 u_int16_t *ul_proto;
4269 {
4270 struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
4271 u_int plen = 0;
4272
4273 /*
4274 * When a ID payload of subnet type with a IP address of full bit
4275 * masked, it has to be processed as host address.
4276 * e.g. below 2 type are same.
4277 * type = ipv6 subnet, data = 2001::1/128
4278 * type = ipv6 address, data = 2001::1
4279 */
4280 switch (id_b->type) {
4281 case IPSECDOI_ID_IPV4_ADDR:
4282 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4283 #ifndef __linux__
4284 saddr->sa_len = sizeof(struct sockaddr_in);
4285 #endif
4286 saddr->sa_family = AF_INET;
4287 ((struct sockaddr_in *)saddr)->sin_port =
4288 (id_b->port == 0
4289 ? IPSEC_PORT_ANY
4290 : id_b->port); /* see sockaddr2id() */
4291 memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
4292 buf->v + sizeof(*id_b), sizeof(struct in_addr));
4293 break;
4294 #ifdef INET6
4295 case IPSECDOI_ID_IPV6_ADDR:
4296 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4297 #ifndef __linux__
4298 saddr->sa_len = sizeof(struct sockaddr_in6);
4299 #endif
4300 saddr->sa_family = AF_INET6;
4301 ((struct sockaddr_in6 *)saddr)->sin6_port =
4302 (id_b->port == 0
4303 ? IPSEC_PORT_ANY
4304 : id_b->port); /* see sockaddr2id() */
4305 memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
4306 buf->v + sizeof(*id_b), sizeof(struct in6_addr));
4307 break;
4308 #endif
4309 default:
4310 plog(LLV_ERROR, LOCATION, NULL,
4311 "unsupported ID type %d\n", id_b->type);
4312 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
4313 }
4314
4315 /* get prefix length */
4316 switch (id_b->type) {
4317 case IPSECDOI_ID_IPV4_ADDR:
4318 plen = sizeof(struct in_addr) << 3;
4319 break;
4320 #ifdef INET6
4321 case IPSECDOI_ID_IPV6_ADDR:
4322 plen = sizeof(struct in6_addr) << 3;
4323 break;
4324 #endif
4325 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4326 #ifdef INET6
4327 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4328 #endif
4329 {
4330 u_char *p;
4331 u_int max;
4332 int alen = sizeof(struct in_addr);
4333
4334 switch (id_b->type) {
4335 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4336 alen = sizeof(struct in_addr);
4337 break;
4338 #ifdef INET6
4339 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4340 alen = sizeof(struct in6_addr);
4341 break;
4342 #endif
4343 }
4344
4345 /* sanity check */
4346 if (buf->l < alen)
4347 return ISAKMP_INTERNAL_ERROR;
4348
4349 /* get subnet mask length */
4350 plen = 0;
4351 max = alen <<3;
4352
4353 p = (unsigned char *) buf->v
4354 + sizeof(struct ipsecdoi_id_b)
4355 + alen;
4356
4357 for (; *p == 0xff; p++) {
4358 plen += 8;
4359 if (plen >= max)
4360 break;
4361 }
4362
4363 if (plen < max) {
4364 u_int l = 0;
4365 u_char b = ~(*p);
4366
4367 while (b) {
4368 b >>= 1;
4369 l++;
4370 }
4371
4372 l = 8 - l;
4373 plen += l;
4374 }
4375 }
4376 break;
4377 }
4378
4379 *prefixlen = plen;
4380 *ul_proto = id_b->proto_id == 0
4381 ? IPSEC_ULPROTO_ANY
4382 : id_b->proto_id; /* see sockaddr2id() */
4383
4384 return 0;
4385 }
4386
4387 /*
4388 * make printable string from ID payload except of general header.
4389 */
4390 char *
ipsecdoi_id2str(id)4391 ipsecdoi_id2str(id)
4392 const vchar_t *id;
4393 {
4394 #define BUFLEN 512
4395 char * ret = NULL;
4396 int len = 0;
4397 char *dat;
4398 static char buf[BUFLEN];
4399 struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
4400 struct sockaddr_storage saddr_storage;
4401 struct sockaddr *saddr;
4402 struct sockaddr_in *saddr_in;
4403 struct sockaddr_in6 *saddr_in6;
4404 u_int plen = 0;
4405
4406 saddr = (struct sockaddr *)&saddr_storage;
4407 saddr_in = (struct sockaddr_in *)&saddr_storage;
4408 saddr_in6 = (struct sockaddr_in6 *)&saddr_storage;
4409
4410
4411 switch (id_b->type) {
4412 case IPSECDOI_ID_IPV4_ADDR:
4413 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4414 case IPSECDOI_ID_IPV4_ADDR_RANGE:
4415
4416 #ifndef __linux__
4417 saddr->sa_len = sizeof(struct sockaddr_in);
4418 #endif
4419 saddr->sa_family = AF_INET;
4420
4421 saddr_in->sin_port = IPSEC_PORT_ANY;
4422 memcpy(&saddr_in->sin_addr,
4423 id->v + sizeof(*id_b), sizeof(struct in_addr));
4424 break;
4425 #ifdef INET6
4426 case IPSECDOI_ID_IPV6_ADDR:
4427 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4428 case IPSECDOI_ID_IPV6_ADDR_RANGE:
4429
4430 #ifndef __linux__
4431 saddr->sa_len = sizeof(struct sockaddr_in6);
4432 #endif
4433 saddr->sa_family = AF_INET6;
4434
4435 saddr_in6->sin6_port = IPSEC_PORT_ANY;
4436 memcpy(&saddr_in6->sin6_addr,
4437 id->v + sizeof(*id_b), sizeof(struct in6_addr));
4438 saddr_in6->sin6_scope_id =
4439 (IN6_IS_ADDR_LINKLOCAL(&saddr_in6->sin6_addr)
4440 ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4441 : 0);
4442 break;
4443 #endif
4444 }
4445
4446 switch (id_b->type) {
4447 case IPSECDOI_ID_IPV4_ADDR:
4448 #ifdef INET6
4449 case IPSECDOI_ID_IPV6_ADDR:
4450 #endif
4451 len = snprintf( buf, BUFLEN, "%s", saddrwop2str(saddr));
4452 break;
4453
4454 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4455 #ifdef INET6
4456 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4457 #endif
4458 {
4459 u_char *p;
4460 u_int max;
4461 int alen = sizeof(struct in_addr);
4462
4463 switch (id_b->type) {
4464 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4465 alen = sizeof(struct in_addr);
4466 break;
4467 #ifdef INET6
4468 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4469 alen = sizeof(struct in6_addr);
4470 break;
4471 #endif
4472 }
4473
4474 /* sanity check */
4475 if (id->l < alen) {
4476 len = 0;
4477 break;
4478 }
4479
4480 /* get subnet mask length */
4481 plen = 0;
4482 max = alen <<3;
4483
4484 p = (unsigned char *) id->v
4485 + sizeof(struct ipsecdoi_id_b)
4486 + alen;
4487
4488 for (; *p == 0xff; p++) {
4489 plen += 8;
4490 if (plen >= max)
4491 break;
4492 }
4493
4494 if (plen < max) {
4495 u_int l = 0;
4496 u_char b = ~(*p);
4497
4498 while (b) {
4499 b >>= 1;
4500 l++;
4501 }
4502
4503 l = 8 - l;
4504 plen += l;
4505 }
4506
4507 len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(saddr), plen);
4508 }
4509 break;
4510
4511 case IPSECDOI_ID_IPV4_ADDR_RANGE:
4512
4513 len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(saddr));
4514
4515 #ifndef __linux__
4516 saddr->sa_len = sizeof(struct sockaddr_in);
4517 #endif
4518 saddr->sa_family = AF_INET;
4519 saddr_in->sin_port = IPSEC_PORT_ANY;
4520 memcpy(&saddr_in->sin_addr,
4521 id->v + sizeof(*id_b) + sizeof(struct in_addr),
4522 sizeof(struct in_addr));
4523
4524 len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(saddr));
4525
4526 break;
4527
4528 #ifdef INET6
4529 case IPSECDOI_ID_IPV6_ADDR_RANGE:
4530
4531 len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(saddr));
4532
4533 #ifndef __linux__
4534 saddr->sa_len = sizeof(struct sockaddr_in6);
4535 #endif
4536 saddr->sa_family = AF_INET6;
4537 saddr_in6->sin6_port = IPSEC_PORT_ANY;
4538 memcpy(&saddr_in6->sin6_addr,
4539 id->v + sizeof(*id_b) + sizeof(struct in6_addr),
4540 sizeof(struct in6_addr));
4541 saddr_in6->sin6_scope_id =
4542 (IN6_IS_ADDR_LINKLOCAL(&saddr_in6->sin6_addr)
4543 ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
4544 : 0);
4545
4546 len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(saddr));
4547
4548 break;
4549 #endif
4550
4551 case IPSECDOI_ID_FQDN:
4552 case IPSECDOI_ID_USER_FQDN:
4553 len = id->l - sizeof(*id_b);
4554 if (len > BUFLEN)
4555 len = BUFLEN;
4556 memcpy(buf, id->v + sizeof(*id_b), len);
4557 break;
4558
4559 case IPSECDOI_ID_DER_ASN1_DN:
4560 case IPSECDOI_ID_DER_ASN1_GN:
4561 {
4562 X509_NAME *xn = NULL;
4563
4564 dat = id->v + sizeof(*id_b);
4565 len = id->l - sizeof(*id_b);
4566
4567 if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
4568 BIO *bio = BIO_new(BIO_s_mem());
4569 X509_NAME_print_ex(bio, xn, 0, 0);
4570 len = BIO_get_mem_data(bio, &dat);
4571 if (len > BUFLEN)
4572 len = BUFLEN;
4573 memcpy(buf,dat,len);
4574 BIO_free(bio);
4575 X509_NAME_free(xn);
4576 } else {
4577 plog(LLV_ERROR, LOCATION, NULL,
4578 "unable to extract asn1dn from id\n");
4579
4580 len = sprintf(buf, "<ASN1-DN>");
4581 }
4582
4583 break;
4584 }
4585
4586 /* currently unhandled id types */
4587 case IPSECDOI_ID_KEY_ID:
4588 len = sprintf( buf, "<KEY-ID>");
4589 break;
4590
4591 default:
4592 plog(LLV_ERROR, LOCATION, NULL,
4593 "unknown ID type %d\n", id_b->type);
4594 }
4595
4596 if (!len)
4597 len = sprintf( buf, "<?>");
4598
4599 ret = racoon_malloc(len+1);
4600 if (ret != NULL) {
4601 memcpy(ret,buf,len);
4602 ret[len]=0;
4603 }
4604
4605 return ret;
4606 }
4607
4608 /*
4609 * set IPsec data attributes into a proposal.
4610 * NOTE: MUST called per a transform.
4611 */
4612 int
ipsecdoi_t2satrns(t,pp,pr,tr)4613 ipsecdoi_t2satrns(t, pp, pr, tr)
4614 struct isakmp_pl_t *t;
4615 struct saprop *pp;
4616 struct saproto *pr;
4617 struct satrns *tr;
4618 {
4619 struct isakmp_data *d, *prev;
4620 int flag, type;
4621 int error = -1;
4622 int life_t;
4623 int tlen;
4624
4625 tr->trns_no = t->t_no;
4626 tr->trns_id = t->t_id;
4627
4628 tlen = ntohs(t->h.len) - sizeof(*t);
4629 prev = (struct isakmp_data *)NULL;
4630 d = (struct isakmp_data *)(t + 1);
4631
4632 /* default */
4633 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4634 pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
4635 pp->lifebyte = 0;
4636 tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
4637
4638 while (tlen > 0) {
4639
4640 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
4641 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
4642
4643 plog(LLV_DEBUG, LOCATION, NULL,
4644 "type=%s, flag=0x%04x, lorv=%s\n",
4645 s_ipsecdoi_attr(type), flag,
4646 s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
4647
4648 switch (type) {
4649 case IPSECDOI_ATTR_SA_LD_TYPE:
4650 {
4651 int type = ntohs(d->lorv);
4652 switch (type) {
4653 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4654 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4655 life_t = type;
4656 break;
4657 default:
4658 plog(LLV_WARNING, LOCATION, NULL,
4659 "invalid life duration type. "
4660 "use default\n");
4661 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4662 break;
4663 }
4664 break;
4665 }
4666 case IPSECDOI_ATTR_SA_LD:
4667 if (prev == NULL
4668 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
4669 IPSECDOI_ATTR_SA_LD_TYPE) {
4670 plog(LLV_ERROR, LOCATION, NULL,
4671 "life duration must follow ltype\n");
4672 break;
4673 }
4674
4675 {
4676 u_int32_t t;
4677 vchar_t *ld_buf = NULL;
4678
4679 if (flag) {
4680 /* i.e. ISAKMP_GEN_TV */
4681 ld_buf = vmalloc(sizeof(d->lorv));
4682 if (ld_buf == NULL) {
4683 plog(LLV_ERROR, LOCATION, NULL,
4684 "failed to get LD buffer.\n");
4685 goto end;
4686 }
4687 memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
4688 } else {
4689 int len = ntohs(d->lorv);
4690 /* i.e. ISAKMP_GEN_TLV */
4691 ld_buf = vmalloc(len);
4692 if (ld_buf == NULL) {
4693 plog(LLV_ERROR, LOCATION, NULL,
4694 "failed to get LD buffer.\n");
4695 goto end;
4696 }
4697 memcpy(ld_buf->v, d + 1, len);
4698 }
4699 switch (life_t) {
4700 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4701 t = ipsecdoi_set_ld(ld_buf);
4702 vfree(ld_buf);
4703 if (t == 0) {
4704 plog(LLV_ERROR, LOCATION, NULL,
4705 "invalid life duration.\n");
4706 goto end;
4707 }
4708 /* lifetime must be equal in a proposal. */
4709 if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
4710 pp->lifetime = t;
4711 else if (pp->lifetime != t) {
4712 plog(LLV_ERROR, LOCATION, NULL,
4713 "lifetime mismatched "
4714 "in a proposal, "
4715 "prev:%ld curr:%u.\n",
4716 (long)pp->lifetime, t);
4717 goto end;
4718 }
4719 break;
4720 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4721 t = ipsecdoi_set_ld(ld_buf);
4722 vfree(ld_buf);
4723 if (t == 0) {
4724 plog(LLV_ERROR, LOCATION, NULL,
4725 "invalid life duration.\n");
4726 goto end;
4727 }
4728 /* lifebyte must be equal in a proposal. */
4729 if (pp->lifebyte == 0)
4730 pp->lifebyte = t;
4731 else if (pp->lifebyte != t) {
4732 plog(LLV_ERROR, LOCATION, NULL,
4733 "lifebyte mismatched "
4734 "in a proposal, "
4735 "prev:%d curr:%u.\n",
4736 pp->lifebyte, t);
4737 goto end;
4738 }
4739 break;
4740 default:
4741 vfree(ld_buf);
4742 plog(LLV_ERROR, LOCATION, NULL,
4743 "invalid life type: %d\n", life_t);
4744 goto end;
4745 }
4746 }
4747 break;
4748
4749 case IPSECDOI_ATTR_GRP_DESC:
4750 /*
4751 * RFC2407: 4.5 IPSEC Security Association Attributes
4752 * Specifies the Oakley Group to be used in a PFS QM
4753 * negotiation. For a list of supported values, see
4754 * Appendix A of [IKE].
4755 */
4756 if (pp->pfs_group == 0)
4757 pp->pfs_group = (u_int16_t)ntohs(d->lorv);
4758 else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
4759 plog(LLV_ERROR, LOCATION, NULL,
4760 "pfs_group mismatched "
4761 "in a proposal.\n");
4762 goto end;
4763 }
4764 break;
4765
4766 case IPSECDOI_ATTR_ENC_MODE:
4767 if (pr->encmode &&
4768 pr->encmode != (u_int16_t)ntohs(d->lorv)) {
4769 plog(LLV_ERROR, LOCATION, NULL,
4770 "multiple encmode exist "
4771 "in a transform.\n");
4772 goto end;
4773 }
4774 pr->encmode = (u_int16_t)ntohs(d->lorv);
4775 break;
4776
4777 case IPSECDOI_ATTR_AUTH:
4778 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
4779 plog(LLV_ERROR, LOCATION, NULL,
4780 "multiple authtype exist "
4781 "in a transform.\n");
4782 goto end;
4783 }
4784 tr->authtype = (u_int16_t)ntohs(d->lorv);
4785 break;
4786
4787 case IPSECDOI_ATTR_KEY_LENGTH:
4788 if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
4789 plog(LLV_ERROR, LOCATION, NULL,
4790 "key length defined but not ESP");
4791 goto end;
4792 }
4793 tr->encklen = ntohs(d->lorv);
4794 break;
4795 #ifdef HAVE_SECCTX
4796 case IPSECDOI_ATTR_SECCTX:
4797 {
4798 int len = ntohs(d->lorv);
4799 memcpy(&pp->sctx, d + 1, len);
4800 pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
4801 break;
4802 }
4803 #endif /* HAVE_SECCTX */
4804 case IPSECDOI_ATTR_KEY_ROUNDS:
4805 case IPSECDOI_ATTR_COMP_DICT_SIZE:
4806 case IPSECDOI_ATTR_COMP_PRIVALG:
4807 default:
4808 break;
4809 }
4810
4811 prev = d;
4812 if (flag) {
4813 tlen -= sizeof(*d);
4814 d = (struct isakmp_data *)((char *)d + sizeof(*d));
4815 } else {
4816 tlen -= (sizeof(*d) + ntohs(d->lorv));
4817 d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
4818 }
4819 }
4820
4821 error = 0;
4822 end:
4823 return error;
4824 }
4825
4826 int
ipsecdoi_authalg2trnsid(alg)4827 ipsecdoi_authalg2trnsid(alg)
4828 int alg;
4829 {
4830 switch (alg) {
4831 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
4832 return IPSECDOI_AH_MD5;
4833 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
4834 return IPSECDOI_AH_SHA;
4835 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
4836 return IPSECDOI_AH_SHA256;
4837 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
4838 return IPSECDOI_AH_SHA384;
4839 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
4840 return IPSECDOI_AH_SHA512;
4841 case IPSECDOI_ATTR_AUTH_DES_MAC:
4842 return IPSECDOI_AH_DES;
4843 case IPSECDOI_ATTR_AUTH_KPDK:
4844 return IPSECDOI_AH_MD5; /* XXX */
4845 default:
4846 plog(LLV_ERROR, LOCATION, NULL,
4847 "invalid authentication algorithm:%d\n", alg);
4848 }
4849 return -1;
4850 }
4851
4852 #ifdef HAVE_GSSAPI
4853 struct isakmpsa *
fixup_initiator_sa(match,received)4854 fixup_initiator_sa(match, received)
4855 struct isakmpsa *match, *received;
4856 {
4857 if (received->gssid != NULL)
4858 match->gssid = vdup(received->gssid);
4859
4860 return match;
4861 }
4862 #endif
4863
4864 static int rm_idtype2doi[] = {
4865 255, /* IDTYPE_UNDEFINED, 0 */
4866 IPSECDOI_ID_FQDN, /* IDTYPE_FQDN, 1 */
4867 IPSECDOI_ID_USER_FQDN, /* IDTYPE_USERFQDN, 2 */
4868 IPSECDOI_ID_KEY_ID, /* IDTYPE_KEYID, 3 */
4869 255, /* IDTYPE_ADDRESS, 4
4870 * it expands into 4 types by another function. */
4871 IPSECDOI_ID_DER_ASN1_DN, /* IDTYPE_ASN1DN, 5 */
4872 };
4873
4874 /*
4875 * convert idtype to DOI value.
4876 * OUT 255 : NG
4877 * other: converted.
4878 */
4879 int
idtype2doi(idtype)4880 idtype2doi(idtype)
4881 int idtype;
4882 {
4883 if (ARRAYLEN(rm_idtype2doi) > idtype)
4884 return rm_idtype2doi[idtype];
4885 return 255;
4886 }
4887
4888 int
doi2idtype(doi)4889 doi2idtype(doi)
4890 int doi;
4891 {
4892 switch(doi) {
4893 case IPSECDOI_ID_FQDN:
4894 return(IDTYPE_FQDN);
4895 case IPSECDOI_ID_USER_FQDN:
4896 return(IDTYPE_USERFQDN);
4897 case IPSECDOI_ID_KEY_ID:
4898 return(IDTYPE_KEYID);
4899 case IPSECDOI_ID_DER_ASN1_DN:
4900 return(IDTYPE_ASN1DN);
4901 case IPSECDOI_ID_IPV4_ADDR:
4902 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4903 case IPSECDOI_ID_IPV6_ADDR:
4904 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4905 return(IDTYPE_ADDRESS);
4906 default:
4907 plog(LLV_WARNING, LOCATION, NULL,
4908 "Inproper idtype:%s in this function.\n",
4909 s_ipsecdoi_ident(doi));
4910 return(IDTYPE_ADDRESS); /* XXX */
4911 }
4912 /*NOTREACHED*/
4913 }
4914
4915 #ifdef ENABLE_HYBRID
4916 static int
switch_authmethod(authmethod)4917 switch_authmethod(authmethod)
4918 int authmethod;
4919 {
4920 switch(authmethod) {
4921 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
4922 authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
4923 break;
4924 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
4925 authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
4926 break;
4927 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
4928 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
4929 break;
4930 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
4931 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
4932 break;
4933 /* Those are not implemented */
4934 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
4935 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
4936 break;
4937 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
4938 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
4939 break;
4940 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
4941 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
4942 break;
4943 default:
4944 break;
4945 }
4946
4947 return authmethod;
4948 }
4949 #endif
4950