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