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