]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/ipsec_doi.c
ipsec-164.9.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"
85f41bec 82#include "crypto_cssm.h"
52b7d2ce
A
83#include "strnames.h"
84#include "gcmalloc.h"
85
86#ifdef ENABLE_NATT
87#include "nattraversal.h"
88#endif
89#ifdef ENABLE_HYBRID
90static int switch_authmethod(int);
91#endif
92
93#ifdef HAVE_GSSAPI
94#include <iconv.h>
95#include "gssapi.h"
96#ifdef HAVE_ICONV_2ND_CONST
97#define __iconv_const const
98#else
99#define __iconv_const
100#endif
101#endif
102
103int verbose_proposal_check = 1;
104
105static vchar_t *get_ph1approval __P((struct ph1handle *, struct prop_pair **));
106static struct isakmpsa *get_ph1approvalx __P((struct prop_pair *,
107 struct isakmpsa *, struct isakmpsa *, int));
108static void print_ph1mismatched __P((struct prop_pair *, struct isakmpsa *));
109static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *));
110static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *));
111static struct prop_pair *get_ph2approval __P((struct ph2handle *,
112 struct prop_pair **));
113static struct prop_pair *get_ph2approvalx __P((struct ph2handle *,
114 struct prop_pair *));
115static void free_proppair0 __P((struct prop_pair *));
116
117static int get_transform
118 __P((struct isakmp_pl_p *, struct prop_pair **, int *));
119static u_int32_t ipsecdoi_set_ld __P((vchar_t *));
120
121static int check_doi __P((u_int32_t));
122static int check_situation __P((u_int32_t));
123
124static int check_prot_main __P((int));
125static int check_prot_quick __P((int));
126static int (*check_protocol[]) __P((int)) = {
127 check_prot_main, /* IPSECDOI_TYPE_PH1 */
128 check_prot_quick, /* IPSECDOI_TYPE_PH2 */
129};
130
131static int check_spi_size __P((int, int));
132
133static int check_trns_isakmp __P((int));
134static int check_trns_ah __P((int));
135static int check_trns_esp __P((int));
136static int check_trns_ipcomp __P((int));
137static int (*check_transform[]) __P((int)) = {
138 0,
139 check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */
140 check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */
141 check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
142 check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
143};
144
145static int check_attr_isakmp __P((struct isakmp_pl_t *));
146static int check_attr_ah __P((struct isakmp_pl_t *));
147static int check_attr_esp __P((struct isakmp_pl_t *));
148static int check_attr_ipsec __P((int, struct isakmp_pl_t *));
149static int check_attr_ipcomp __P((struct isakmp_pl_t *));
150static int (*check_attributes[]) __P((struct isakmp_pl_t *)) = {
151 0,
152 check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */
153 check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */
154 check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
155 check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
156};
157
158static int setph1prop __P((struct isakmpsa *, caddr_t));
159static int setph1trns __P((struct isakmpsa *, caddr_t));
160static int setph1attr __P((struct isakmpsa *, caddr_t));
161static vchar_t *setph2proposal0 __P((const struct ph2handle *,
162 const struct saprop *, const struct saproto *));
163
164static vchar_t *getidval __P((int, vchar_t *));
165
166#ifdef HAVE_GSSAPI
167static struct isakmpsa *fixup_initiator_sa __P((struct isakmpsa *,
168 struct isakmpsa *));
169#endif
170
171/*%%%*/
172/*
173 * check phase 1 SA payload.
174 * make new SA payload to be replyed not including general header.
175 * the pointer to one of isakmpsa in proposal is set into iph1->approval.
176 * OUT:
177 * positive: the pointer to new buffer of SA payload.
178 * network byte order.
179 * NULL : error occurd.
180 */
181int
182ipsecdoi_checkph1proposal(sa, iph1)
183 vchar_t *sa;
184 struct ph1handle *iph1;
185{
186 vchar_t *newsa; /* new SA payload approved. */
187 struct prop_pair **pair;
188
189 /* get proposal pair */
190 pair = get_proppair(sa, IPSECDOI_TYPE_PH1);
191 if (pair == NULL)
192 return -1;
193
194 /* check and get one SA for use */
195 newsa = get_ph1approval(iph1, pair);
196
197 free_proppair(pair);
198
199 if (newsa == NULL)
200 return -1;
201
202 iph1->sa_ret = newsa;
203
204 return 0;
205}
206
207/*
208 * acceptable check for remote configuration.
209 * return a new SA payload to be reply to peer.
210 */
211static vchar_t *
212get_ph1approval(iph1, pair)
213 struct ph1handle *iph1;
214 struct prop_pair **pair;
215{
216 vchar_t *newsa;
217 struct isakmpsa *sa, tsa;
218 struct prop_pair *s, *p;
219 int prophlen;
220 int i;
221
222 if (iph1->approval) {
223 delisakmpsa(iph1->approval);
224 iph1->approval = NULL;
225 }
226
227 for (i = 0; i < MAXPROPPAIRLEN; i++) {
228 if (pair[i] == NULL)
229 continue;
230 for (s = pair[i]; s; s = s->next) {
231 prophlen =
232 sizeof(struct isakmp_pl_p) + s->prop->spi_size;
233
234 /* compare proposal and select one */
235 for (p = s; p; p = p->tnext) {
236 if ((sa = get_ph1approvalx(p,
237 iph1->rmconf->proposal, &tsa,
238 iph1->rmconf->pcheck_level)) != NULL)
239 goto found;
240 }
241 }
242 }
243
244 /*
245 * if there is no suitable proposal, racoon complains about all of
246 * mismatched items in those proposal.
247 */
248 if (verbose_proposal_check) {
249 for (i = 0; i < MAXPROPPAIRLEN; i++) {
250 if (pair[i] == NULL)
251 continue;
252 for (s = pair[i]; s; s = s->next) {
253 prophlen = sizeof(struct isakmp_pl_p)
254 + s->prop->spi_size;
255 for (p = s; p; p = p->tnext) {
256 print_ph1mismatched(p,
257 iph1->rmconf->proposal);
258 }
259 }
260 }
261 }
262 plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n");
263
264 return NULL;
265
266found:
267 plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n");
268
269 /* check DH group settings */
270 if (sa->dhgrp) {
271 if (sa->dhgrp->prime && sa->dhgrp->gen1) {
272 /* it's ok */
273 goto saok;
274 }
275 plog(LLV_WARNING, LOCATION, NULL,
276 "invalid DH parameter found, use default.\n");
277 oakley_dhgrp_free(sa->dhgrp);
d1e348cf 278 sa->dhgrp=NULL;
52b7d2ce
A
279 }
280
281 if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
282 sa->dhgrp = NULL;
d1e348cf 283 racoon_free(sa);
52b7d2ce
A
284 return NULL;
285 }
286
287saok:
288#ifdef HAVE_GSSAPI
289 if (sa->gssid != NULL)
290 plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
d1e348cf 291 (int)sa->gssid->l, sa->gssid->v);
52b7d2ce
A
292 if (iph1-> side == INITIATOR) {
293 if (iph1->rmconf->proposal->gssid != NULL)
294 iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
295 if (tsa.gssid != NULL)
296 iph1->gi_r = vdup(tsa.gssid);
297 iph1->approval = fixup_initiator_sa(sa, &tsa);
298 } else {
299 if (tsa.gssid != NULL) {
300 iph1->gi_r = vdup(tsa.gssid);
301 iph1->gi_i = gssapi_get_id(iph1);
302 if (sa->gssid == NULL && iph1->gi_i != NULL)
303 sa->gssid = vdup(iph1->gi_i);
304 }
305 iph1->approval = sa;
306 }
307 if (iph1->gi_i != NULL)
308 plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n",
d1e348cf 309 (int)iph1->gi_i->l, iph1->gi_i->v);
52b7d2ce
A
310 if (iph1->gi_r != NULL)
311 plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n",
d1e348cf 312 (int)iph1->gi_r->l, iph1->gi_r->v);
52b7d2ce
A
313#else
314 iph1->approval = sa;
315#endif
d1e348cf
A
316 if(iph1->approval) {
317 plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
318 s_oakley_attr_method(iph1->approval->authmethod));
319 }
52b7d2ce
A
320
321 newsa = get_sabyproppair(p, iph1);
322 if (newsa == NULL) {
323 delisakmpsa(iph1->approval);
324 iph1->approval = NULL;
325 }
326
327 return newsa;
328}
329
330/*
331 * compare peer's single proposal and all of my proposal.
332 * and select one if suiatable.
333 * p : one of peer's proposal.
334 * proposal: my proposals.
335 */
336static struct isakmpsa *
337get_ph1approvalx(p, proposal, sap, check_level)
338 struct prop_pair *p;
339 struct isakmpsa *proposal, *sap;
340 int check_level;
341{
342 struct isakmp_pl_p *prop = p->prop;
343 struct isakmp_pl_t *trns = p->trns;
344 struct isakmpsa sa, *s, *tsap;
345 int authmethod;
d1e348cf 346 int tsap_authmethod;
52b7d2ce
A
347
348 plog(LLV_DEBUG, LOCATION, NULL,
349 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
350 prop->p_no, s_ipsecdoi_proto(prop->proto_id),
351 prop->spi_size, prop->num_t);
352
353 plog(LLV_DEBUG, LOCATION, NULL,
354 "trns#=%d, trns-id=%s\n",
355 trns->t_no,
356 s_ipsecdoi_trns(prop->proto_id, trns->t_id));
357
358 tsap = sap != NULL ? sap : &sa;
359
360 memset(tsap, 0, sizeof(*tsap));
361 if (t2isakmpsa(trns, tsap) < 0)
362 return NULL;
363 for (s = proposal; s != NULL; s = s->next) {
364#ifdef ENABLE_HYBRID
365 authmethod = switch_authmethod(s->authmethod);
d1e348cf 366 tsap_authmethod = switch_authmethod(tsap->authmethod);
52b7d2ce
A
367#else
368 authmethod = s->authmethod;
d1e348cf 369 tsap_authmethod = tsap->authmethod;
52b7d2ce
A
370#endif
371 plog(LLV_DEBUG, LOCATION, NULL, "Compared: DB:Peer\n");
372 plog(LLV_DEBUG, LOCATION, NULL, "(lifetime = %ld:%ld)\n",
373 (long)s->lifetime, (long)tsap->lifetime);
374 plog(LLV_DEBUG, LOCATION, NULL, "(lifebyte = %zu:%zu)\n",
375 s->lifebyte, tsap->lifebyte);
376 plog(LLV_DEBUG, LOCATION, NULL, "enctype = %s:%s\n",
377 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
378 s->enctype),
379 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
380 tsap->enctype));
381 plog(LLV_DEBUG, LOCATION, NULL, "(encklen = %d:%d)\n",
382 s->encklen, tsap->encklen);
383 plog(LLV_DEBUG, LOCATION, NULL, "hashtype = %s:%s\n",
384 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
385 s->hashtype),
386 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
387 tsap->hashtype));
388 plog(LLV_DEBUG, LOCATION, NULL, "authmethod = %s:%s\n",
389 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
d1e348cf 390 s->authmethod),
52b7d2ce
A
391 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
392 tsap->authmethod));
393 plog(LLV_DEBUG, LOCATION, NULL, "dh_group = %s:%s\n",
394 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
395 s->dh_group),
396 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
397 tsap->dh_group));
398#if 0
399 /* XXX to be considered ? */
400 if (tsap->lifebyte > s->lifebyte) ;
401#endif
402 /*
403 * if responder side and peer's key length in proposal
404 * is bigger than mine, it might be accepted.
405 */
406 if(tsap->enctype == s->enctype &&
d1e348cf 407 (tsap->authmethod == authmethod || tsap_authmethod == authmethod) &&
52b7d2ce
A
408 tsap->hashtype == s->hashtype &&
409 tsap->dh_group == s->dh_group &&
410 tsap->encklen == s->encklen) {
411 switch(check_level) {
412 case PROP_CHECK_OBEY:
413 goto found;
414 break;
415
416 case PROP_CHECK_STRICT:
417 if ((tsap->lifetime > s->lifetime) ||
418 (tsap->lifebyte > s->lifebyte))
419 continue;
420 goto found;
421 break;
422
423 case PROP_CHECK_CLAIM:
424 if (tsap->lifetime < s->lifetime)
425 s->lifetime = tsap->lifetime;
426 if (tsap->lifebyte < s->lifebyte)
427 s->lifebyte = tsap->lifebyte;
428 goto found;
429 break;
430
431 case PROP_CHECK_EXACT:
432 if ((tsap->lifetime != s->lifetime) ||
433 (tsap->lifebyte != s->lifebyte))
434 continue;
435 goto found;
436 break;
437
438 default:
439 plog(LLV_ERROR, LOCATION, NULL,
440 "Unexpected proposal_check value\n");
441 continue;
442 break;
443 }
444 }
445 }
446
447found:
d1e348cf 448 if (tsap->dhgrp != NULL){
52b7d2ce 449 oakley_dhgrp_free(tsap->dhgrp);
d1e348cf
A
450 tsap->dhgrp = NULL;
451 }
52b7d2ce
A
452
453 if ((s = dupisakmpsa(s)) != NULL) {
454 switch(check_level) {
455 case PROP_CHECK_OBEY:
456 s->lifetime = tsap->lifetime;
457 s->lifebyte = tsap->lifebyte;
458 break;
459
460 case PROP_CHECK_STRICT:
461 s->lifetime = tsap->lifetime;
462 s->lifebyte = tsap->lifebyte;
463 break;
464
465 case PROP_CHECK_CLAIM:
466 if (tsap->lifetime < s->lifetime)
467 s->lifetime = tsap->lifetime;
468 if (tsap->lifebyte < s->lifebyte)
469 s->lifebyte = tsap->lifebyte;
470 break;
471
472 default:
473 break;
474 }
d1e348cf
A
475 // hack to get around cisco rekeys
476 if (tsap->authmethod != authmethod && tsap_authmethod == authmethod) {
477 s->authmethod = tsap->authmethod;
478 }
52b7d2ce 479 }
52b7d2ce
A
480 return s;
481}
482
483/*
484 * print all of items in peer's proposal which are mismatched to my proposal.
485 * p : one of peer's proposal.
486 * proposal: my proposals.
487 */
488static void
489print_ph1mismatched(p, proposal)
490 struct prop_pair *p;
491 struct isakmpsa *proposal;
492{
493 struct isakmpsa sa, *s;
494
495 memset(&sa, 0, sizeof(sa));
496 if (t2isakmpsa(p->trns, &sa) < 0)
497 return;
498 for (s = proposal; s ; s = s->next) {
499 if (sa.enctype != s->enctype) {
500 plog(LLV_ERROR, LOCATION, NULL,
501 "rejected enctype: "
502 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
503 "%s:%s\n",
504 s->prop_no, s->trns_no,
505 p->prop->p_no, p->trns->t_no,
506 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
507 s->enctype),
508 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
509 sa.enctype));
510 }
511 if (sa.authmethod != s->authmethod) {
512 plog(LLV_ERROR, LOCATION, NULL,
513 "rejected authmethod: "
514 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
515 "%s:%s\n",
516 s->prop_no, s->trns_no,
517 p->prop->p_no, p->trns->t_no,
518 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
519 s->authmethod),
520 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
521 sa.authmethod));
522 }
523 if (sa.hashtype != s->hashtype) {
524 plog(LLV_ERROR, LOCATION, NULL,
525 "rejected hashtype: "
526 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
527 "%s:%s\n",
528 s->prop_no, s->trns_no,
529 p->prop->p_no, p->trns->t_no,
530 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
531 s->hashtype),
532 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
533 sa.hashtype));
534 }
535 if (sa.dh_group != s->dh_group) {
536 plog(LLV_ERROR, LOCATION, NULL,
537 "rejected dh_group: "
538 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
539 "%s:%s\n",
540 s->prop_no, s->trns_no,
541 p->prop->p_no, p->trns->t_no,
542 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
543 s->dh_group),
544 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
545 sa.dh_group));
546 }
547 }
548
d1e348cf 549 if (sa.dhgrp != NULL){
52b7d2ce 550 oakley_dhgrp_free(sa.dhgrp);
d1e348cf
A
551 sa.dhgrp=NULL;
552 }
52b7d2ce
A
553}
554
555/*
556 * get ISAKMP data attributes
557 */
558static int
559t2isakmpsa(trns, sa)
560 struct isakmp_pl_t *trns;
561 struct isakmpsa *sa;
562{
563 struct isakmp_data *d, *prev;
564 int flag, type;
565 int error = -1;
566 int life_t;
567 int keylen = 0;
568 vchar_t *val = NULL;
569 int len, tlen;
570 u_char *p;
571
572 tlen = ntohs(trns->h.len) - sizeof(*trns);
573 prev = (struct isakmp_data *)NULL;
574 d = (struct isakmp_data *)(trns + 1);
575
576 /* default */
577 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
578 sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
579 sa->lifebyte = 0;
580 sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
581 if (!sa->dhgrp)
582 goto err;
583
584 while (tlen > 0) {
585
586 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
587 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
588
589 plog(LLV_DEBUG, LOCATION, NULL,
590 "type=%s, flag=0x%04x, lorv=%s\n",
591 s_oakley_attr(type), flag,
592 s_oakley_attr_v(type, ntohs(d->lorv)));
593
594 /* get variable-sized item */
595 switch (type) {
596 case OAKLEY_ATTR_GRP_PI:
597 case OAKLEY_ATTR_GRP_GEN_ONE:
598 case OAKLEY_ATTR_GRP_GEN_TWO:
599 case OAKLEY_ATTR_GRP_CURVE_A:
600 case OAKLEY_ATTR_GRP_CURVE_B:
601 case OAKLEY_ATTR_SA_LD:
602 case OAKLEY_ATTR_GRP_ORDER:
603 if (flag) { /*TV*/
604 len = 2;
605 p = (u_char *)&d->lorv;
606 } else { /*TLV*/
607 len = ntohs(d->lorv);
e8d9021d
A
608 if (len > tlen) {
609 plog(LLV_ERROR, LOCATION, NULL,
610 "invalid ISAKMP-SA attr, attr-len %d, overall-len %d\n",
611 len, tlen);
612 return -1;
613 }
52b7d2ce
A
614 p = (u_char *)(d + 1);
615 }
616 val = vmalloc(len);
617 if (!val)
618 return -1;
619 memcpy(val->v, p, len);
620 break;
621
622 default:
623 break;
624 }
625
626 switch (type) {
627 case OAKLEY_ATTR_ENC_ALG:
628 sa->enctype = (u_int16_t)ntohs(d->lorv);
629 break;
630
631 case OAKLEY_ATTR_HASH_ALG:
632 sa->hashtype = (u_int16_t)ntohs(d->lorv);
633 break;
634
635 case OAKLEY_ATTR_AUTH_METHOD:
636 sa->authmethod = ntohs(d->lorv);
637 break;
638
639 case OAKLEY_ATTR_GRP_DESC:
640 sa->dh_group = (u_int16_t)ntohs(d->lorv);
641 break;
642
643 case OAKLEY_ATTR_GRP_TYPE:
644 {
645 int type = (int)ntohs(d->lorv);
646 if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
647 sa->dhgrp->type = type;
648 else
649 return -1;
650 break;
651 }
652 case OAKLEY_ATTR_GRP_PI:
653 sa->dhgrp->prime = val;
654 break;
655
656 case OAKLEY_ATTR_GRP_GEN_ONE:
657 vfree(val);
658 if (!flag)
659 sa->dhgrp->gen1 = ntohs(d->lorv);
660 else {
661 int len = ntohs(d->lorv);
662 sa->dhgrp->gen1 = 0;
663 if (len > 4)
664 return -1;
665 memcpy(&sa->dhgrp->gen1, d + 1, len);
666 sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
667 }
668 break;
669
670 case OAKLEY_ATTR_GRP_GEN_TWO:
671 vfree(val);
672 if (!flag)
673 sa->dhgrp->gen2 = ntohs(d->lorv);
674 else {
675 int len = ntohs(d->lorv);
676 sa->dhgrp->gen2 = 0;
677 if (len > 4)
678 return -1;
679 memcpy(&sa->dhgrp->gen2, d + 1, len);
680 sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
681 }
682 break;
683
684 case OAKLEY_ATTR_GRP_CURVE_A:
685 sa->dhgrp->curve_a = val;
686 break;
687
688 case OAKLEY_ATTR_GRP_CURVE_B:
689 sa->dhgrp->curve_b = val;
690 break;
691
692 case OAKLEY_ATTR_SA_LD_TYPE:
693 {
694 int type = (int)ntohs(d->lorv);
695 switch (type) {
696 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
697 case OAKLEY_ATTR_SA_LD_TYPE_KB:
698 life_t = type;
699 break;
700 default:
701 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
702 break;
703 }
704 break;
705 }
706 case OAKLEY_ATTR_SA_LD:
707 if (!prev
708 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
709 OAKLEY_ATTR_SA_LD_TYPE) {
710 plog(LLV_ERROR, LOCATION, NULL,
711 "life duration must follow ltype\n");
712 break;
713 }
714
715 switch (life_t) {
716 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
717 sa->lifetime = ipsecdoi_set_ld(val);
718 vfree(val);
719 if (sa->lifetime == 0) {
720 plog(LLV_ERROR, LOCATION, NULL,
721 "invalid life duration.\n");
722 goto err;
723 }
724 break;
725 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
726 sa->lifebyte = ipsecdoi_set_ld(val);
727 vfree(val);
728 if (sa->lifebyte == 0) {
729 plog(LLV_ERROR, LOCATION, NULL,
730 "invalid life duration.\n");
731 goto err;
732 }
733 break;
734 default:
735 vfree(val);
736 plog(LLV_ERROR, LOCATION, NULL,
737 "invalid life type: %d\n", life_t);
738 goto err;
739 }
740 break;
741
742 case OAKLEY_ATTR_KEY_LEN:
743 {
744 int len = ntohs(d->lorv);
745 if (len % 8 != 0) {
746 plog(LLV_ERROR, LOCATION, NULL,
747 "keylen %d: not multiple of 8\n",
748 len);
749 goto err;
750 }
751 sa->encklen = (u_int16_t)len;
752 keylen++;
753 break;
754 }
755 case OAKLEY_ATTR_PRF:
756 case OAKLEY_ATTR_FIELD_SIZE:
757 /* unsupported */
758 break;
759
760 case OAKLEY_ATTR_GRP_ORDER:
761 sa->dhgrp->order = val;
762 break;
763#ifdef HAVE_GSSAPI
764 case OAKLEY_ATTR_GSS_ID:
765 {
d1e348cf
A
766 int error = -1;
767 iconv_t cd = (iconv_t) -1;
52b7d2ce
A
768 size_t srcleft, dstleft, rv;
769 __iconv_const char *src;
770 char *dst;
771 int len = ntohs(d->lorv);
772
773 /*
774 * Older verions of racoon just placed the
775 * ISO-Latin-1 string on the wire directly.
776 * Check to see if we are configured to be
777 * compatible with this behavior.
778 */
779 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
d1e348cf
A
780 if ((sa->gssid = vmalloc(len)) == NULL) {
781 plog(LLV_ERROR, LOCATION, NULL,
782 "failed to allocate memory\n");
783 goto out;
784 }
52b7d2ce
A
785 memcpy(sa->gssid->v, d + 1, len);
786 plog(LLV_DEBUG, LOCATION, NULL,
d1e348cf
A
787 "received old-style gss "
788 "id '%.*s' (len %zu)\n",
789 (int)sa->gssid->l, sa->gssid->v,
790 sa->gssid->l);
791 error = 0;
792 goto out;
52b7d2ce
A
793 }
794
795 /*
796 * For Windows 2000 compatibility, we expect
797 * the GSS ID attribute on the wire to be
798 * encoded in UTF-16LE. Internally, we work
799 * in ISO-Latin-1. Therefore, we should need
800 * 1/2 the specified length, which should always
801 * be a multiple of 2 octets.
802 */
803 cd = iconv_open("latin1", "utf-16le");
804 if (cd == (iconv_t) -1) {
805 plog(LLV_ERROR, LOCATION, NULL,
806 "unable to initialize utf-16le -> latin1 "
807 "conversion descriptor: %s\n",
808 strerror(errno));
d1e348cf 809 goto out;
52b7d2ce
A
810 }
811
d1e348cf
A
812 if ((sa->gssid = vmalloc(len / 2)) == NULL) {
813 plog(LLV_ERROR, LOCATION, NULL,
814 "failed to allocate memory\n");
815 goto out;
816 }
52b7d2ce
A
817
818 src = (__iconv_const char *)(d + 1);
819 srcleft = len;
820
821 dst = sa->gssid->v;
822 dstleft = len / 2;
823
824 rv = iconv(cd, (__iconv_const char **)&src, &srcleft,
825 &dst, &dstleft);
826 if (rv != 0) {
827 if (rv == -1) {
828 plog(LLV_ERROR, LOCATION, NULL,
829 "unable to convert GSS ID from "
830 "utf-16le -> latin1: %s\n",
831 strerror(errno));
832 } else {
833 plog(LLV_ERROR, LOCATION, NULL,
834 "%zd character%s in GSS ID cannot "
835 "be represented in latin1\n",
836 rv, rv == 1 ? "" : "s");
837 }
d1e348cf 838 goto out;
52b7d2ce 839 }
52b7d2ce
A
840
841 /* XXX dstleft should always be 0; assert it? */
842 sa->gssid->l = (len / 2) - dstleft;
843
844 plog(LLV_DEBUG, LOCATION, NULL,
d1e348cf
A
845 "received gss id '%.*s' (len %zu)\n",
846 (int)sa->gssid->l, sa->gssid->v, sa->gssid->l);
847
848 error = 0;
849out:
850 if (cd != (iconv_t)-1)
851 (void)iconv_close(cd);
852
853 if ((error != 0) && (sa->gssid != NULL)) {
854 vfree(sa->gssid);
855 sa->gssid = NULL;
856 }
52b7d2ce
A
857 break;
858 }
859#endif /* HAVE_GSSAPI */
860
861 default:
862 break;
863 }
864
865 prev = d;
866 if (flag) {
867 tlen -= sizeof(*d);
868 d = (struct isakmp_data *)((char *)d + sizeof(*d));
869 } else {
870 tlen -= (sizeof(*d) + ntohs(d->lorv));
871 d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
872 }
873 }
874
875 /* key length must not be specified on some algorithms */
876 if (keylen) {
877 if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
52b7d2ce
A
878 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
879 plog(LLV_ERROR, LOCATION, NULL,
880 "keylen must not be specified "
881 "for encryption algorithm %d\n",
882 sa->enctype);
883 return -1;
884 }
885 }
886
887 return 0;
888err:
889 return error;
890}
891
892/*%%%*/
893/*
894 * check phase 2 SA payload and select single proposal.
895 * make new SA payload to be replyed not including general header.
896 * This function is called by responder only.
897 * OUT:
898 * 0: succeed.
899 * -1: error occured.
900 */
901int
902ipsecdoi_selectph2proposal(iph2)
903 struct ph2handle *iph2;
904{
905 struct prop_pair **pair;
906 struct prop_pair *ret;
907
908 /* get proposal pair */
909 pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
910 if (pair == NULL)
911 return -1;
912
913 /* check and select a proposal. */
914 ret = get_ph2approval(iph2, pair);
915 free_proppair(pair);
916 if (ret == NULL)
917 return -1;
918
919 /* make a SA to be replayed. */
920 /* SPI must be updated later. */
921 iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
922 free_proppair0(ret);
923 if (iph2->sa_ret == NULL)
924 return -1;
925
926 return 0;
927}
928
929/*
930 * check phase 2 SA payload returned from responder.
931 * This function is called by initiator only.
932 * OUT:
933 * 0: valid.
934 * -1: invalid.
935 */
936int
937ipsecdoi_checkph2proposal(iph2)
938 struct ph2handle *iph2;
939{
940 struct prop_pair **rpair = NULL, **spair = NULL;
941 struct prop_pair *p;
942 int i, n, num;
943 int error = -1;
944 vchar_t *sa_ret = NULL;
945
946 /* get proposal pair of SA sent. */
947 spair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
948 if (spair == NULL) {
949 plog(LLV_ERROR, LOCATION, NULL,
950 "failed to get prop pair.\n");
951 goto end;
952 }
953
954 /* XXX should check the number of transform */
955
956 /* get proposal pair of SA replayed */
957 rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
958 if (rpair == NULL) {
959 plog(LLV_ERROR, LOCATION, NULL,
960 "failed to get prop pair.\n");
961 goto end;
962 }
963
964 /* check proposal is only one ? */
965 n = 0;
966 num = 0;
967 for (i = 0; i < MAXPROPPAIRLEN; i++) {
968 if (rpair[i]) {
969 n = i;
970 num++;
971 }
972 }
973 if (num == 0) {
974 plog(LLV_ERROR, LOCATION, NULL,
975 "no proposal received.\n");
976 goto end;
977 }
978 if (num != 1) {
979 plog(LLV_ERROR, LOCATION, NULL,
980 "some proposals received.\n");
981 goto end;
982 }
983
984 if (spair[n] == NULL) {
985 plog(LLV_WARNING, LOCATION, NULL,
986 "invalid proposal number:%d received.\n", i);
987 }
988
989
990 if (rpair[n]->tnext != NULL) {
991 plog(LLV_ERROR, LOCATION, NULL,
992 "multi transforms replyed.\n");
993 goto end;
994 }
995
996 if (cmp_aproppair_i(rpair[n], spair[n])) {
997 plog(LLV_ERROR, LOCATION, NULL,
998 "proposal mismathed.\n");
999 goto end;
1000 }
1001
1002 /*
1003 * check and select a proposal.
1004 * ensure that there is no modification of the proposal by
1005 * cmp_aproppair_i()
1006 */
1007 p = get_ph2approval(iph2, rpair);
1008 if (p == NULL)
1009 goto end;
1010
1011 /* make a SA to be replayed. */
1012 sa_ret = iph2->sa_ret;
1013 iph2->sa_ret = get_sabyproppair(p, iph2->ph1);
1014 free_proppair0(p);
1015 if (iph2->sa_ret == NULL)
1016 goto end;
1017
1018 error = 0;
1019
1020end:
1021 if (rpair)
1022 free_proppair(rpair);
1023 if (spair)
1024 free_proppair(spair);
1025 if (sa_ret)
1026 vfree(sa_ret);
1027
1028 return error;
1029}
1030
1031/*
1032 * compare two prop_pair which is assumed to have same proposal number.
1033 * the case of bundle or single SA, NOT multi transforms.
1034 * a: a proposal that is multi protocols and single transform, usually replyed.
1035 * b: a proposal that is multi protocols and multi transform, usually sent.
1036 * NOTE: this function is for initiator.
1037 * OUT
1038 * 0: equal
1039 * 1: not equal
1040 * XXX cannot understand the comment!
1041 */
1042static int
1043cmp_aproppair_i(a, b)
1044 struct prop_pair *a, *b;
1045{
1046 struct prop_pair *p, *q, *r;
1047 int len;
1048
1049 for (p = a, q = b; p && q; p = p->next, q = q->next) {
1050 for (r = q; r; r = r->tnext) {
1051 /* compare trns */
1052 if (p->trns->t_no == r->trns->t_no)
1053 break;
1054 }
1055 if (!r) {
1056 /* no suitable transform found */
1057 plog(LLV_ERROR, LOCATION, NULL,
1058 "no suitable transform found.\n");
1059 return -1;
1060 }
1061
1062 /* compare prop */
1063 if (p->prop->p_no != r->prop->p_no) {
1064 plog(LLV_WARNING, LOCATION, NULL,
1065 "proposal #%d mismatched, "
1066 "expected #%d.\n",
1067 r->prop->p_no, p->prop->p_no);
1068 /*FALLTHROUGH*/
1069 }
1070
1071 if (p->prop->proto_id != r->prop->proto_id) {
1072 plog(LLV_ERROR, LOCATION, NULL,
1073 "proto_id mismathed: my:%d peer:%d\n",
1074 r->prop->proto_id, p->prop->proto_id);
1075 return -1;
1076 }
1077
1078 if (p->prop->proto_id != r->prop->proto_id) {
1079 plog(LLV_ERROR, LOCATION, NULL,
1080 "invalid spi size: %d.\n",
1081 p->prop->proto_id);
1082 return -1;
1083 }
1084
1085 /* check #of transforms */
1086 if (p->prop->num_t != 1) {
1087 plog(LLV_WARNING, LOCATION, NULL,
1088 "#of transform is %d, "
1089 "but expected 1.\n", p->prop->num_t);
1090 /*FALLTHROUGH*/
1091 }
1092
1093 if (p->trns->t_id != r->trns->t_id) {
1094 plog(LLV_WARNING, LOCATION, NULL,
1095 "transform number has been modified.\n");
1096 /*FALLTHROUGH*/
1097 }
1098 if (p->trns->reserved != r->trns->reserved) {
1099 plog(LLV_WARNING, LOCATION, NULL,
1100 "reserved field should be zero.\n");
1101 /*FALLTHROUGH*/
1102 }
1103
1104 /* compare attribute */
1105 len = ntohs(r->trns->h.len) - sizeof(*p->trns);
1106 if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
1107 plog(LLV_WARNING, LOCATION, NULL,
1108 "attribute has been modified.\n");
1109 /*FALLTHROUGH*/
1110 }
1111 }
1112 if ((p && !q) || (!p && q)) {
1113 /* # of protocols mismatched */
1114 plog(LLV_ERROR, LOCATION, NULL,
1115 "#of protocols mismatched.\n");
1116 return -1;
1117 }
1118
1119 return 0;
1120}
1121
1122/*
1123 * acceptable check for policy configuration.
1124 * return a new SA payload to be reply to peer.
1125 */
1126static struct prop_pair *
1127get_ph2approval(iph2, pair)
1128 struct ph2handle *iph2;
1129 struct prop_pair **pair;
1130{
1131 struct prop_pair *ret;
1132 int i;
1133
1134 iph2->approval = NULL;
1135
1136 plog(LLV_DEBUG, LOCATION, NULL,
1137 "begin compare proposals.\n");
1138
1139 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1140 if (pair[i] == NULL)
1141 continue;
1142 plog(LLV_DEBUG, LOCATION, NULL,
1143 "pair[%d]: %p\n", i, pair[i]);
1144 print_proppair(LLV_DEBUG, pair[i]);;
1145
1146 /* compare proposal and select one */
1147 ret = get_ph2approvalx(iph2, pair[i]);
1148 if (ret != NULL) {
1149 /* found */
1150 return ret;
1151 }
1152 }
1153
1154 plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n");
1155
1156 return NULL;
1157}
1158
1159/*
1160 * compare my proposal and peers just one proposal.
1161 * set a approval.
1162 */
1163static struct prop_pair *
1164get_ph2approvalx(iph2, pp)
1165 struct ph2handle *iph2;
1166 struct prop_pair *pp;
1167{
1168 struct prop_pair *ret = NULL;
1169 struct saprop *pr0, *pr = NULL;
1170 struct saprop *q1, *q2;
1171
1172 pr0 = aproppair2saprop(pp);
1173 if (pr0 == NULL)
1174 return NULL;
1175
1176 for (q1 = pr0; q1; q1 = q1->next) {
1177 for (q2 = iph2->proposal; q2; q2 = q2->next) {
1178 plog(LLV_DEBUG, LOCATION, NULL,
1179 "peer's single bundle:\n");
1180 printsaprop0(LLV_DEBUG, q1);
1181 plog(LLV_DEBUG, LOCATION, NULL,
1182 "my single bundle:\n");
1183 printsaprop0(LLV_DEBUG, q2);
1184
1185 pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
1186 if (pr != NULL)
1187 goto found;
1188
1189 plog(LLV_ERROR, LOCATION, NULL,
1190 "not matched\n");
1191 }
1192 }
1193 /* no proposal matching */
1194err:
1195 flushsaprop(pr0);
1196 return NULL;
1197
1198found:
1199 flushsaprop(pr0);
1200 plog(LLV_DEBUG, LOCATION, NULL, "matched\n");
1201 iph2->approval = pr;
1202
1203 {
1204 struct saproto *sp;
d1e348cf
A
1205 struct prop_pair *p, *x;
1206 struct prop_pair *n = NULL;
52b7d2ce
A
1207
1208 ret = NULL;
1209
1210 for (p = pp; p; p = p->next) {
1211 /*
1212 * find a proposal with matching proto_id.
1213 * we have analyzed validity already, in cmpsaprop_alloc().
1214 */
1215 for (sp = pr->head; sp; sp = sp->next) {
1216 if (sp->proto_id == p->prop->proto_id)
1217 break;
1218 }
1219 if (!sp)
1220 goto err;
1221 if (sp->head->next)
1222 goto err; /* XXX */
1223
1224 for (x = p; x; x = x->tnext)
1225 if (sp->head->trns_no == x->trns->t_no)
1226 break;
1227 if (!x)
1228 goto err; /* XXX */
1229
1230 n = racoon_calloc(1, sizeof(struct prop_pair));
d1e348cf 1231 if (n == NULL) {
52b7d2ce
A
1232 plog(LLV_ERROR, LOCATION, NULL,
1233 "failed to get buffer.\n");
1234 goto err;
1235 }
1236
1237 n->prop = x->prop;
1238 n->trns = x->trns;
1239
1240 /* need to preserve the order */
1241 for (x = ret; x && x->next; x = x->next)
1242 ;
1243 if (x && x->prop == n->prop) {
1244 for (/*nothing*/; x && x->tnext; x = x->tnext)
1245 ;
1246 x->tnext = n;
1247 } else {
1248 if (x)
1249 x->next = n;
1250 else {
1251 ret = n;
1252 }
1253 }
1254
1255 /* #of transforms should be updated ? */
1256 }
1257 }
1258
1259 return ret;
1260}
1261
1262void
1263free_proppair(pair)
1264 struct prop_pair **pair;
1265{
1266 int i;
1267
1268 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1269 free_proppair0(pair[i]);
1270 pair[i] = NULL;
1271 }
1272 racoon_free(pair);
1273}
1274
1275static void
1276free_proppair0(pair)
1277 struct prop_pair *pair;
1278{
1279 struct prop_pair *p, *q, *r, *s;
1280
1281 p = pair;
1282 while (p) {
1283 q = p->next;
1284 r = p;
1285 while (r) {
1286 s = r->tnext;
1287 racoon_free(r);
1288 r = s;
1289 }
1290 p = q;
1291 }
1292}
1293
1294/*
1295 * get proposal pairs from SA payload.
1296 * tiny check for proposal payload.
1297 */
1298struct prop_pair **
1299get_proppair(sa, mode)
1300 vchar_t *sa;
1301 int mode;
1302{
d1e348cf 1303 struct prop_pair **pair = NULL;
52b7d2ce
A
1304 int num_p = 0; /* number of proposal for use */
1305 int tlen;
1306 caddr_t bp;
1307 int i;
85f41bec 1308 struct ipsecdoi_sa_b *sab = ALIGNED_CAST(struct ipsecdoi_sa_b *)sa->v;
52b7d2ce
A
1309
1310 plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l);
1311 plogdump(LLV_DEBUG, sa->v, sa->l);
1312
1313 /* check SA payload size */
1314 if (sa->l < sizeof(*sab)) {
1315 plog(LLV_ERROR, LOCATION, NULL,
1316 "Invalid SA length = %zu.\n", sa->l);
d1e348cf 1317 goto bad;
52b7d2ce
A
1318 }
1319
1320 /* check DOI */
1321 if (check_doi(ntohl(sab->doi)) < 0)
d1e348cf 1322 goto bad;
52b7d2ce
A
1323
1324 /* check SITUATION */
1325 if (check_situation(ntohl(sab->sit)) < 0)
d1e348cf 1326 goto bad;
52b7d2ce
A
1327
1328 pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
1329 if (pair == NULL) {
1330 plog(LLV_ERROR, LOCATION, NULL,
1331 "failed to get buffer.\n");
d1e348cf 1332 goto bad;
52b7d2ce
A
1333 }
1334 memset(pair, 0, sizeof(pair));
1335
1336 bp = (caddr_t)(sab + 1);
1337 tlen = sa->l - sizeof(*sab);
1338
1339 {
1340 struct isakmp_pl_p *prop;
1341 int proplen;
1342 vchar_t *pbuf = NULL;
1343 struct isakmp_parse_t *pa;
1344
1345 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
1346 if (pbuf == NULL)
d1e348cf 1347 goto bad;
52b7d2ce 1348
85f41bec 1349 for (pa = ALIGNED_CAST(struct isakmp_parse_t *)pbuf->v;
52b7d2ce
A
1350 pa->type != ISAKMP_NPTYPE_NONE;
1351 pa++) {
1352 /* check the value of next payload */
1353 if (pa->type != ISAKMP_NPTYPE_P) {
1354 plog(LLV_ERROR, LOCATION, NULL,
1355 "Invalid payload type=%u\n", pa->type);
1356 vfree(pbuf);
d1e348cf 1357 goto bad;
52b7d2ce
A
1358 }
1359
1360 prop = (struct isakmp_pl_p *)pa->ptr;
1361 proplen = pa->len;
1362
1363 plog(LLV_DEBUG, LOCATION, NULL,
1364 "proposal #%u len=%d\n", prop->p_no, proplen);
1365
1366 if (proplen == 0) {
1367 plog(LLV_ERROR, LOCATION, NULL,
1368 "invalid proposal with length %d\n", proplen);
1369 vfree(pbuf);
d1e348cf 1370 goto bad;
52b7d2ce
A
1371 }
1372
1373 /* check Protocol ID */
1374 if (!check_protocol[mode]) {
1375 plog(LLV_ERROR, LOCATION, NULL,
1376 "unsupported mode %d\n", mode);
1377 continue;
1378 }
1379
1380 if (check_protocol[mode](prop->proto_id) < 0)
1381 continue;
1382
1383 /* check SPI length when IKE. */
1384 if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
1385 continue;
1386
1387 /* get transform */
1388 if (get_transform(prop, pair, &num_p) < 0) {
1389 vfree(pbuf);
d1e348cf 1390 goto bad;
52b7d2ce
A
1391 }
1392 }
1393 vfree(pbuf);
1394 pbuf = NULL;
1395 }
1396
1397 {
1398 int notrans, nprop;
1399 struct prop_pair *p, *q;
1400
1401 /* check for proposals with no transforms */
1402 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1403 if (!pair[i])
1404 continue;
1405
1406 plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
1407 print_proppair(LLV_DEBUG, pair[i]);
1408
1409 notrans = nprop = 0;
1410 for (p = pair[i]; p; p = p->next) {
1411 if (p->trns == NULL) {
1412 notrans++;
1413 break;
1414 }
1415 for (q = p; q; q = q->tnext)
1416 nprop++;
1417 }
1418
1419#if 0
1420 /*
1421 * XXX at this moment, we cannot accept proposal group
1422 * with multiple proposals. this should be fixed.
1423 */
1424 if (pair[i]->next) {
1425 plog(LLV_WARNING, LOCATION, NULL,
1426 "proposal #%u ignored "
1427 "(multiple proposal not supported)\n",
1428 pair[i]->prop->p_no);
1429 notrans++;
1430 }
1431#endif
1432
1433 if (notrans) {
1434 for (p = pair[i]; p; p = q) {
1435 q = p->next;
1436 racoon_free(p);
1437 }
1438 pair[i] = NULL;
1439 num_p--;
1440 } else {
1441 plog(LLV_DEBUG, LOCATION, NULL,
1442 "proposal #%u: %d transform\n",
1443 pair[i]->prop->p_no, nprop);
1444 }
1445 }
1446 }
1447
1448 /* bark if no proposal is found. */
1449 if (num_p <= 0) {
1450 plog(LLV_ERROR, LOCATION, NULL,
1451 "no Proposal found.\n");
d1e348cf 1452 goto bad;
52b7d2ce
A
1453 }
1454
1455 return pair;
d1e348cf
A
1456bad:
1457 if (pair != NULL)
1458 racoon_free(pair);
1459 return NULL;
52b7d2ce
A
1460}
1461
1462/*
1463 * check transform payload.
1464 * OUT:
1465 * positive: return the pointer to the payload of valid transform.
1466 * 0 : No valid transform found.
1467 */
1468static int
1469get_transform(prop, pair, num_p)
1470 struct isakmp_pl_p *prop;
1471 struct prop_pair **pair;
1472 int *num_p;
1473{
1474 int tlen; /* total length of all transform in a proposal */
1475 caddr_t bp;
1476 struct isakmp_pl_t *trns;
1477 int trnslen;
1478 vchar_t *pbuf = NULL;
1479 struct isakmp_parse_t *pa;
1480 struct prop_pair *p = NULL, *q;
1481 int num_t;
1482
1483 bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
1484 tlen = ntohs(prop->h.len)
1485 - (sizeof(struct isakmp_pl_p) + prop->spi_size);
1486 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
1487 if (pbuf == NULL)
1488 return -1;
1489
1490 /* check and get transform for use */
1491 num_t = 0;
85f41bec 1492 for (pa = ALIGNED_CAST(struct isakmp_parse_t *)pbuf->v;
52b7d2ce
A
1493 pa->type != ISAKMP_NPTYPE_NONE;
1494 pa++) {
1495
1496 num_t++;
1497
1498 /* check the value of next payload */
1499 if (pa->type != ISAKMP_NPTYPE_T) {
1500 plog(LLV_ERROR, LOCATION, NULL,
1501 "Invalid payload type=%u\n", pa->type);
1502 break;
1503 }
1504
1505 trns = (struct isakmp_pl_t *)pa->ptr;
1506 trnslen = pa->len;
1507
1508 plog(LLV_DEBUG, LOCATION, NULL,
1509 "transform #%u len=%u\n", trns->t_no, trnslen);
1510
1511 /* check transform ID */
1512 if (prop->proto_id >= ARRAYLEN(check_transform)) {
1513 plog(LLV_WARNING, LOCATION, NULL,
1514 "unsupported proto_id %u\n",
1515 prop->proto_id);
1516 continue;
1517 }
1518 if (prop->proto_id >= ARRAYLEN(check_attributes)) {
1519 plog(LLV_WARNING, LOCATION, NULL,
1520 "unsupported proto_id %u\n",
1521 prop->proto_id);
1522 continue;
1523 }
1524
1525 if (!check_transform[prop->proto_id]
1526 || !check_attributes[prop->proto_id]) {
1527 plog(LLV_WARNING, LOCATION, NULL,
1528 "unsupported proto_id %u\n",
1529 prop->proto_id);
1530 continue;
1531 }
1532 if (check_transform[prop->proto_id](trns->t_id) < 0)
1533 continue;
1534
1535 /* check data attributes */
1536 if (check_attributes[prop->proto_id](trns) != 0)
1537 continue;
1538
1539 p = racoon_calloc(1, sizeof(*p));
1540 if (p == NULL) {
1541 plog(LLV_ERROR, LOCATION, NULL,
1542 "failed to get buffer.\n");
1543 vfree(pbuf);
1544 return -1;
1545 }
1546 p->prop = prop;
1547 p->trns = trns;
1548
1549 /* need to preserve the order */
1550 for (q = pair[prop->p_no]; q && q->next; q = q->next)
1551 ;
1552 if (q && q->prop == p->prop) {
1553 for (/*nothing*/; q && q->tnext; q = q->tnext)
1554 ;
1555 q->tnext = p;
1556 } else {
1557 if (q)
1558 q->next = p;
1559 else {
1560 pair[prop->p_no] = p;
1561 (*num_p)++;
1562 }
1563 }
1564 }
1565
1566 vfree(pbuf);
1567
1568 return 0;
1569}
1570
1571/*
1572 * make a new SA payload from prop_pair.
1573 * NOTE: this function make spi value clear.
1574 */
1575vchar_t *
1576get_sabyproppair(pair, iph1)
1577 struct prop_pair *pair;
1578 struct ph1handle *iph1;
1579{
1580 vchar_t *newsa;
1581 int newtlen;
1582 u_int8_t *np_p = NULL;
1583 struct prop_pair *p;
1584 int prophlen, trnslen;
1585 caddr_t bp;
1586
1587 newtlen = sizeof(struct ipsecdoi_sa_b);
1588 for (p = pair; p; p = p->next) {
1589 newtlen += sizeof(struct isakmp_pl_p);
1590 newtlen += p->prop->spi_size;
1591 newtlen += ntohs(p->trns->h.len);
1592 }
1593
1594 newsa = vmalloc(newtlen);
1595 if (newsa == NULL) {
1596 plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1597 return NULL;
1598 }
1599 bp = newsa->v;
1600
1601 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1602
1603 /* update some of values in SA header */
85f41bec
A
1604 (ALIGNED_CAST(struct ipsecdoi_sa_b *)bp)->doi = htonl(iph1->rmconf->doitype);
1605 (ALIGNED_CAST(struct ipsecdoi_sa_b *)bp)->sit = htonl(iph1->rmconf->sittype);
52b7d2ce
A
1606 bp += sizeof(struct ipsecdoi_sa_b);
1607
1608 /* create proposal payloads */
1609 for (p = pair; p; p = p->next) {
1610 prophlen = sizeof(struct isakmp_pl_p)
1611 + p->prop->spi_size;
1612 trnslen = ntohs(p->trns->h.len);
1613
1614 if (np_p)
1615 *np_p = ISAKMP_NPTYPE_P;
1616
1617 /* create proposal */
1618
1619 memcpy(bp, p->prop, prophlen);
1620 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1621 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1622 ((struct isakmp_pl_p *)bp)->num_t = 1;
1623 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1624 memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
1625 bp += prophlen;
1626
1627 /* create transform */
1628 memcpy(bp, p->trns, trnslen);
1629 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1630 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1631 bp += trnslen;
1632 }
1633
1634 return newsa;
1635}
1636
1637/*
1638 * update responder's spi
1639 */
1640int
1641ipsecdoi_updatespi(iph2)
1642 struct ph2handle *iph2;
1643{
1644 struct prop_pair **pair, *p;
1645 struct saprop *pp;
1646 struct saproto *pr;
1647 int i;
1648 int error = -1;
1649 u_int8_t *spi;
1650
1651 pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
1652 if (pair == NULL)
1653 return -1;
1654 for (i = 0; i < MAXPROPPAIRLEN; i++) {
1655 if (pair[i])
1656 break;
1657 }
1658 if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
1659 /* multiple transform must be filtered by selectph2proposal.*/
1660 goto end;
1661 }
1662
1663 pp = iph2->approval;
1664
1665 /* create proposal payloads */
1666 for (p = pair[i]; p; p = p->next) {
1667 /*
1668 * find a proposal/transform with matching proto_id/t_id.
1669 * we have analyzed validity already, in cmpsaprop_alloc().
1670 */
1671 for (pr = pp->head; pr; pr = pr->next) {
1672 if (p->prop->proto_id == pr->proto_id &&
1673 p->trns->t_id == pr->head->trns_id) {
1674 break;
1675 }
1676 }
1677 if (!pr)
1678 goto end;
1679
1680 /*
1681 * XXX SPI bits are left-filled, for use with IPComp.
1682 * we should be switching to variable-length spi field...
1683 */
1684 spi = (u_int8_t *)&pr->spi;
1685 spi += sizeof(pr->spi);
1686 spi -= pr->spisize;
1687 memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
1688 }
1689
1690 error = 0;
1691end:
1692 free_proppair(pair);
1693 return error;
1694}
1695
1696/*
1697 * make a new SA payload from prop_pair.
1698 */
1699vchar_t *
1700get_sabysaprop(pp0, sa0)
1701 struct saprop *pp0;
1702 vchar_t *sa0;
1703{
d1e348cf
A
1704 struct prop_pair **pair = NULL;
1705 vchar_t *newsa = NULL;
52b7d2ce
A
1706 int newtlen;
1707 u_int8_t *np_p = NULL;
1708 struct prop_pair *p = NULL;
1709 struct saprop *pp;
1710 struct saproto *pr;
1711 struct satrns *tr;
1712 int prophlen, trnslen;
1713 caddr_t bp;
d1e348cf 1714 int error = -1;
52b7d2ce
A
1715
1716 /* get proposal pair */
1717 pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
1718 if (pair == NULL)
d1e348cf 1719 goto out;
52b7d2ce
A
1720
1721 newtlen = sizeof(struct ipsecdoi_sa_b);
1722 for (pp = pp0; pp; pp = pp->next) {
1723
1724 if (pair[pp->prop_no] == NULL)
d1e348cf 1725 goto out;
52b7d2ce
A
1726
1727 for (pr = pp->head; pr; pr = pr->next) {
1728 newtlen += (sizeof(struct isakmp_pl_p)
1729 + pr->spisize);
1730
1731 for (tr = pr->head; tr; tr = tr->next) {
1732 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1733 if (tr->trns_no == p->trns->t_no)
1734 break;
1735 }
1736 if (p == NULL)
d1e348cf 1737 goto out;
52b7d2ce
A
1738
1739 newtlen += ntohs(p->trns->h.len);
1740 }
1741 }
1742 }
1743
1744 newsa = vmalloc(newtlen);
1745 if (newsa == NULL) {
1746 plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
d1e348cf 1747 goto out;
52b7d2ce
A
1748 }
1749 bp = newsa->v;
1750
1751 /* some of values of SA must be updated in the out of this function */
1752 ((struct isakmp_gen *)bp)->len = htons(newtlen);
1753 bp += sizeof(struct ipsecdoi_sa_b);
1754
1755 /* create proposal payloads */
1756 for (pp = pp0; pp; pp = pp->next) {
1757
1758 for (pr = pp->head; pr; pr = pr->next) {
1759 prophlen = sizeof(struct isakmp_pl_p)
1760 + p->prop->spi_size;
1761
1762 for (tr = pr->head; tr; tr = tr->next) {
1763 for (p = pair[pp->prop_no]; p; p = p->tnext) {
1764 if (tr->trns_no == p->trns->t_no)
1765 break;
1766 }
1767 if (p == NULL)
d1e348cf 1768 goto out;
52b7d2ce
A
1769
1770 trnslen = ntohs(p->trns->h.len);
1771
1772 if (np_p)
1773 *np_p = ISAKMP_NPTYPE_P;
1774
1775 /* create proposal */
1776
1777 memcpy(bp, p->prop, prophlen);
1778 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1779 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1780 ((struct isakmp_pl_p *)bp)->num_t = 1;
1781 np_p = &((struct isakmp_pl_p *)bp)->h.np;
1782 bp += prophlen;
1783
1784 /* create transform */
1785 memcpy(bp, p->trns, trnslen);
1786 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1787 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1788 bp += trnslen;
1789 }
1790 }
1791 }
1792
d1e348cf
A
1793 error = 0;
1794out:
1795 if (pair != NULL)
1796 racoon_free(pair);
1797
1798 if (error != 0) {
1799 if (newsa != NULL) {
1800 vfree(newsa);
1801 newsa = NULL;
1802 }
1803 }
1804
52b7d2ce
A
1805 return newsa;
1806}
1807
1808/*
1809 * If some error happens then return 0. Although 0 means that lifetime is zero,
1810 * such a value should not be accepted.
1811 * Also 0 of lifebyte should not be included in a packet although 0 means not
1812 * to care of it.
1813 */
1814static u_int32_t
1815ipsecdoi_set_ld(buf)
1816 vchar_t *buf;
1817{
1818 u_int32_t ld;
1819
1820 if (buf == 0)
1821 return 0;
1822
1823 switch (buf->l) {
1824 case 2:
85f41bec 1825 ld = ntohs(*ALIGNED_CAST(u_int16_t *)buf->v);
52b7d2ce
A
1826 break;
1827 case 4:
85f41bec 1828 ld = ntohl(*ALIGNED_CAST(u_int32_t *)buf->v);
52b7d2ce
A
1829 break;
1830 default:
1831 plog(LLV_ERROR, LOCATION, NULL,
1832 "length %zu of life duration "
1833 "isn't supported.\n", buf->l);
1834 return 0;
1835 }
1836
1837 return ld;
1838}
1839
1840/*%%%*/
1841/*
1842 * check DOI
1843 */
1844static int
1845check_doi(doi)
1846 u_int32_t doi;
1847{
1848 switch (doi) {
1849 case IPSEC_DOI:
1850 return 0;
1851 default:
1852 plog(LLV_ERROR, LOCATION, NULL,
1853 "invalid value of DOI 0x%08x.\n", doi);
1854 return -1;
1855 }
1856 /* NOT REACHED */
1857}
1858
1859/*
1860 * check situation
1861 */
1862static int
1863check_situation(sit)
1864 u_int32_t sit;
1865{
1866 switch (sit) {
1867 case IPSECDOI_SIT_IDENTITY_ONLY:
1868 return 0;
1869
1870 case IPSECDOI_SIT_SECRECY:
1871 case IPSECDOI_SIT_INTEGRITY:
1872 plog(LLV_ERROR, LOCATION, NULL,
1873 "situation 0x%08x unsupported yet.\n", sit);
1874 return -1;
1875
1876 default:
1877 plog(LLV_ERROR, LOCATION, NULL,
1878 "invalid situation 0x%08x.\n", sit);
1879 return -1;
1880 }
1881 /* NOT REACHED */
1882}
1883
1884/*
1885 * check protocol id in main mode
1886 */
1887static int
1888check_prot_main(proto_id)
1889 int proto_id;
1890{
1891 switch (proto_id) {
1892 case IPSECDOI_PROTO_ISAKMP:
1893 return 0;
1894
1895 default:
1896 plog(LLV_ERROR, LOCATION, NULL,
1897 "Illegal protocol id=%u.\n", proto_id);
1898 return -1;
1899 }
1900 /* NOT REACHED */
1901}
1902
1903/*
1904 * check protocol id in quick mode
1905 */
1906static int
1907check_prot_quick(proto_id)
1908 int proto_id;
1909{
1910 switch (proto_id) {
1911 case IPSECDOI_PROTO_IPSEC_AH:
1912 case IPSECDOI_PROTO_IPSEC_ESP:
1913 return 0;
1914
1915 case IPSECDOI_PROTO_IPCOMP:
1916 return 0;
1917
1918 default:
1919 plog(LLV_ERROR, LOCATION, NULL,
1920 "invalid protocol id %d.\n", proto_id);
1921 return -1;
1922 }
1923 /* NOT REACHED */
1924}
1925
1926static int
1927check_spi_size(proto_id, size)
1928 int proto_id, size;
1929{
1930 switch (proto_id) {
1931 case IPSECDOI_PROTO_ISAKMP:
1932 if (size != 0) {
1933 /* WARNING */
1934 plog(LLV_WARNING, LOCATION, NULL,
1935 "SPI size isn't zero, but IKE proposal.\n");
1936 }
1937 return 0;
1938
1939 case IPSECDOI_PROTO_IPSEC_AH:
1940 case IPSECDOI_PROTO_IPSEC_ESP:
1941 if (size != 4) {
1942 plog(LLV_ERROR, LOCATION, NULL,
1943 "invalid SPI size=%d for IPSEC proposal.\n",
1944 size);
1945 return -1;
1946 }
1947 return 0;
1948
1949 case IPSECDOI_PROTO_IPCOMP:
1950 if (size != 2 && size != 4) {
1951 plog(LLV_ERROR, LOCATION, NULL,
1952 "invalid SPI size=%d for IPCOMP proposal.\n",
1953 size);
1954 return -1;
1955 }
1956 return 0;
1957
1958 default:
1959 /* ??? */
1960 return -1;
1961 }
1962 /* NOT REACHED */
1963}
1964
1965/*
1966 * check transform ID in ISAKMP.
1967 */
1968static int
1969check_trns_isakmp(t_id)
1970 int t_id;
1971{
1972 switch (t_id) {
1973 case IPSECDOI_KEY_IKE:
1974 return 0;
1975 default:
1976 plog(LLV_ERROR, LOCATION, NULL,
1977 "invalid transform-id=%u in proto_id=%u.\n",
1978 t_id, IPSECDOI_KEY_IKE);
1979 return -1;
1980 }
1981 /* NOT REACHED */
1982}
1983
1984/*
1985 * check transform ID in AH.
1986 */
1987static int
1988check_trns_ah(t_id)
1989 int t_id;
1990{
1991 switch (t_id) {
1992 case IPSECDOI_AH_MD5:
1993 case IPSECDOI_AH_SHA:
1994 case IPSECDOI_AH_SHA256:
1995 case IPSECDOI_AH_SHA384:
1996 case IPSECDOI_AH_SHA512:
1997 return 0;
1998 case IPSECDOI_AH_DES:
1999 plog(LLV_ERROR, LOCATION, NULL,
2000 "not support transform-id=%u in AH.\n", t_id);
2001 return -1;
2002 default:
2003 plog(LLV_ERROR, LOCATION, NULL,
2004 "invalid transform-id=%u in AH.\n", t_id);
2005 return -1;
2006 }
2007 /* NOT REACHED */
2008}
2009
2010/*
2011 * check transform ID in ESP.
2012 */
2013static int
2014check_trns_esp(t_id)
2015 int t_id;
2016{
2017 switch (t_id) {
2018 case IPSECDOI_ESP_DES:
2019 case IPSECDOI_ESP_3DES:
2020 case IPSECDOI_ESP_NULL:
2021 case IPSECDOI_ESP_RC5:
2022 case IPSECDOI_ESP_CAST:
2023 case IPSECDOI_ESP_BLOWFISH:
2024 case IPSECDOI_ESP_AES:
2025 case IPSECDOI_ESP_TWOFISH:
2026 return 0;
2027 case IPSECDOI_ESP_DES_IV32:
2028 case IPSECDOI_ESP_DES_IV64:
2029 case IPSECDOI_ESP_IDEA:
2030 case IPSECDOI_ESP_3IDEA:
2031 case IPSECDOI_ESP_RC4:
2032 plog(LLV_ERROR, LOCATION, NULL,
2033 "not support transform-id=%u in ESP.\n", t_id);
2034 return -1;
2035 default:
2036 plog(LLV_ERROR, LOCATION, NULL,
2037 "invalid transform-id=%u in ESP.\n", t_id);
2038 return -1;
2039 }
2040 /* NOT REACHED */
2041}
2042
2043/*
2044 * check transform ID in IPCOMP.
2045 */
2046static int
2047check_trns_ipcomp(t_id)
2048 int t_id;
2049{
2050 switch (t_id) {
2051 case IPSECDOI_IPCOMP_OUI:
2052 case IPSECDOI_IPCOMP_DEFLATE:
2053 case IPSECDOI_IPCOMP_LZS:
2054 return 0;
2055 default:
2056 plog(LLV_ERROR, LOCATION, NULL,
2057 "invalid transform-id=%u in IPCOMP.\n", t_id);
2058 return -1;
2059 }
2060 /* NOT REACHED */
2061}
2062
2063/*
2064 * check data attributes in IKE.
2065 */
2066static int
2067check_attr_isakmp(trns)
2068 struct isakmp_pl_t *trns;
2069{
2070 struct isakmp_data *d;
2071 int tlen;
2072 int flag, type;
2073 u_int16_t lorv;
2074
2075 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2076 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2077
2078 while (tlen > 0) {
2079 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2080 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2081 lorv = ntohs(d->lorv);
2082
2083 plog(LLV_DEBUG, LOCATION, NULL,
2084 "type=%s, flag=0x%04x, lorv=%s\n",
2085 s_oakley_attr(type), flag,
2086 s_oakley_attr_v(type, lorv));
2087
2088 /*
2089 * some of the attributes must be encoded in TV.
2090 * see RFC2409 Appendix A "Attribute Classes".
2091 */
2092 switch (type) {
2093 case OAKLEY_ATTR_ENC_ALG:
2094 case OAKLEY_ATTR_HASH_ALG:
2095 case OAKLEY_ATTR_AUTH_METHOD:
2096 case OAKLEY_ATTR_GRP_DESC:
2097 case OAKLEY_ATTR_GRP_TYPE:
2098 case OAKLEY_ATTR_SA_LD_TYPE:
2099 case OAKLEY_ATTR_PRF:
2100 case OAKLEY_ATTR_KEY_LEN:
2101 case OAKLEY_ATTR_FIELD_SIZE:
2102 if (!flag) { /* TLV*/
2103 plog(LLV_ERROR, LOCATION, NULL,
2104 "oakley attribute %d must be TV.\n",
2105 type);
2106 return -1;
2107 }
2108 break;
2109 }
2110
2111 /* sanity check for TLV. length must be specified. */
2112 if (!flag && lorv == 0) { /*TLV*/
2113 plog(LLV_ERROR, LOCATION, NULL,
2114 "invalid length %d for TLV attribute %d.\n",
2115 lorv, type);
2116 return -1;
2117 }
2118
2119 switch (type) {
2120 case OAKLEY_ATTR_ENC_ALG:
2121 if (!alg_oakley_encdef_ok(lorv)) {
2122 plog(LLV_ERROR, LOCATION, NULL,
2123 "invalied encryption algorithm=%d.\n",
2124 lorv);
2125 return -1;
2126 }
2127 break;
2128
2129 case OAKLEY_ATTR_HASH_ALG:
2130 if (!alg_oakley_hashdef_ok(lorv)) {
2131 plog(LLV_ERROR, LOCATION, NULL,
2132 "invalied hash algorithm=%d.\n",
2133 lorv);
2134 return -1;
2135 }
2136 break;
2137
2138 case OAKLEY_ATTR_AUTH_METHOD:
2139 switch (lorv) {
2140 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
2141 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2142#ifdef ENABLE_HYBRID
2143 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
d1e348cf
A
2144 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2145#if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
2146 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
2147#endif
2148 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
2149#endif
52b7d2ce
A
2150 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
2151 break;
2152 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2153#ifdef ENABLE_HYBRID
52b7d2ce 2154 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
d1e348cf
A
2155 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
2156 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
52b7d2ce 2157 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
d1e348cf
A
2158 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
2159 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
2160 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
2161 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
2162 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
2163 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
52b7d2ce
A
2164#endif
2165 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2166 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
2167 plog(LLV_ERROR, LOCATION, NULL,
d1e348cf
A
2168 "auth method %s isn't supported.\n",
2169 s_oakley_attr_method(lorv));
52b7d2ce
A
2170 return -1;
2171 default:
2172 plog(LLV_ERROR, LOCATION, NULL,
2173 "invalid auth method %d.\n",
2174 lorv);
2175 return -1;
2176 }
2177 break;
2178
2179 case OAKLEY_ATTR_GRP_DESC:
2180 if (!alg_oakley_dhdef_ok(lorv)) {
2181 plog(LLV_ERROR, LOCATION, NULL,
2182 "invalid DH group %d.\n",
2183 lorv);
2184 return -1;
2185 }
2186 break;
2187
2188 case OAKLEY_ATTR_GRP_TYPE:
2189 switch (lorv) {
2190 case OAKLEY_ATTR_GRP_TYPE_MODP:
2191 break;
2192 default:
2193 plog(LLV_ERROR, LOCATION, NULL,
2194 "unsupported DH group type %d.\n",
2195 lorv);
2196 return -1;
2197 }
2198 break;
2199
2200 case OAKLEY_ATTR_GRP_PI:
2201 case OAKLEY_ATTR_GRP_GEN_ONE:
2202 /* sanity checks? */
2203 break;
2204
2205 case OAKLEY_ATTR_GRP_GEN_TWO:
2206 case OAKLEY_ATTR_GRP_CURVE_A:
2207 case OAKLEY_ATTR_GRP_CURVE_B:
2208 plog(LLV_ERROR, LOCATION, NULL,
2209 "attr type=%u isn't supported.\n", type);
2210 return -1;
2211
2212 case OAKLEY_ATTR_SA_LD_TYPE:
2213 switch (lorv) {
2214 case OAKLEY_ATTR_SA_LD_TYPE_SEC:
2215 case OAKLEY_ATTR_SA_LD_TYPE_KB:
2216 break;
2217 default:
2218 plog(LLV_ERROR, LOCATION, NULL,
2219 "invalid life type %d.\n", lorv);
2220 return -1;
2221 }
2222 break;
2223
2224 case OAKLEY_ATTR_SA_LD:
2225 /* should check the value */
2226 break;
2227
2228 case OAKLEY_ATTR_PRF:
2229 case OAKLEY_ATTR_KEY_LEN:
2230 break;
2231
2232 case OAKLEY_ATTR_FIELD_SIZE:
2233 plog(LLV_ERROR, LOCATION, NULL,
2234 "attr type=%u isn't supported.\n", type);
2235 return -1;
2236
2237 case OAKLEY_ATTR_GRP_ORDER:
2238 break;
2239
2240 case OAKLEY_ATTR_GSS_ID:
2241 break;
2242
2243 default:
2244 plog(LLV_ERROR, LOCATION, NULL,
2245 "invalid attribute type %d.\n", type);
2246 return -1;
2247 }
2248
2249 if (flag) {
2250 tlen -= sizeof(*d);
2251 d = (struct isakmp_data *)((char *)d
2252 + sizeof(*d));
2253 } else {
2254 tlen -= (sizeof(*d) + lorv);
2255 d = (struct isakmp_data *)((char *)d
2256 + sizeof(*d) + lorv);
2257 }
2258 }
2259
2260 return 0;
2261}
2262
2263/*
2264 * check data attributes in IPSEC AH/ESP.
2265 */
2266static int
2267check_attr_ah(trns)
2268 struct isakmp_pl_t *trns;
2269{
2270 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
2271}
2272
2273static int
2274check_attr_esp(trns)
2275 struct isakmp_pl_t *trns;
2276{
2277 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
2278}
2279
2280static int
2281check_attr_ipsec(proto_id, trns)
2282 int proto_id;
2283 struct isakmp_pl_t *trns;
2284{
2285 struct isakmp_data *d;
2286 int tlen;
2287 int flag, type = 0;
2288 u_int16_t lorv;
2289 int attrseen[16]; /* XXX magic number */
2290
2291 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2292 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2293 memset(attrseen, 0, sizeof(attrseen));
2294
2295 while (tlen > 0) {
2296 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2297 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2298 lorv = ntohs(d->lorv);
2299
2300 plog(LLV_DEBUG, LOCATION, NULL,
2301 "type=%s, flag=0x%04x, lorv=%s\n",
2302 s_ipsecdoi_attr(type), flag,
2303 s_ipsecdoi_attr_v(type, lorv));
2304
2305 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2306 attrseen[type]++;
2307
2308 switch (type) {
2309 case IPSECDOI_ATTR_ENC_MODE:
2310 if (! flag) {
2311 plog(LLV_ERROR, LOCATION, NULL,
2312 "must be TV when ENC_MODE.\n");
2313 return -1;
2314 }
2315
2316 switch (lorv) {
2317 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2318 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2319 break;
2320#ifdef ENABLE_NATT
2321 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2322 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2323 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2324 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2325 plog(LLV_DEBUG, LOCATION, NULL,
2326 "UDP encapsulation requested\n");
2327 break;
2328#endif
2329 default:
2330 plog(LLV_ERROR, LOCATION, NULL,
2331 "invalid encryption mode=%u.\n",
2332 lorv);
2333 return -1;
2334 }
2335 break;
2336
2337 case IPSECDOI_ATTR_AUTH:
2338 if (! flag) {
2339 plog(LLV_ERROR, LOCATION, NULL,
2340 "must be TV when AUTH.\n");
2341 return -1;
2342 }
2343
2344 switch (lorv) {
2345 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
2346 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2347 trns->t_id != IPSECDOI_AH_MD5) {
2348ahmismatch:
2349 plog(LLV_ERROR, LOCATION, NULL,
2350 "auth algorithm %u conflicts "
2351 "with transform %u.\n",
2352 lorv, trns->t_id);
2353 return -1;
2354 }
2355 break;
2356 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
2357 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2358 if (trns->t_id != IPSECDOI_AH_SHA)
2359 goto ahmismatch;
2360 }
2361 break;
2362 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
2363 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2364 if (trns->t_id != IPSECDOI_AH_SHA256)
2365 goto ahmismatch;
2366 }
2367 break;
2368 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
2369 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2370 if (trns->t_id != IPSECDOI_AH_SHA384)
2371 goto ahmismatch;
2372 }
2373 break;
2374 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
2375 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
2376 if (trns->t_id != IPSECDOI_AH_SHA512)
2377 goto ahmismatch;
2378 }
2379 break;
2380 case IPSECDOI_ATTR_AUTH_DES_MAC:
2381 case IPSECDOI_ATTR_AUTH_KPDK:
2382 plog(LLV_ERROR, LOCATION, NULL,
2383 "auth algorithm %u isn't supported.\n",
2384 lorv);
2385 return -1;
2386 default:
2387 plog(LLV_ERROR, LOCATION, NULL,
2388 "invalid auth algorithm=%u.\n",
2389 lorv);
2390 return -1;
2391 }
2392 break;
2393
2394 case IPSECDOI_ATTR_SA_LD_TYPE:
2395 if (! flag) {
2396 plog(LLV_ERROR, LOCATION, NULL,
2397 "must be TV when LD_TYPE.\n");
2398 return -1;
2399 }
2400
2401 switch (lorv) {
2402 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2403 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2404 break;
2405 default:
2406 plog(LLV_ERROR, LOCATION, NULL,
2407 "invalid life type %d.\n", lorv);
2408 return -1;
2409 }
2410 break;
2411
2412 case IPSECDOI_ATTR_SA_LD:
2413 if (flag) {
2414 /* i.e. ISAKMP_GEN_TV */
2415 plog(LLV_DEBUG, LOCATION, NULL,
2416 "life duration was in TLV.\n");
2417 } else {
2418 /* i.e. ISAKMP_GEN_TLV */
2419 if (lorv == 0) {
2420 plog(LLV_ERROR, LOCATION, NULL,
2421 "invalid length of LD\n");
2422 return -1;
2423 }
2424 }
2425 break;
2426
2427 case IPSECDOI_ATTR_GRP_DESC:
2428 if (! flag) {
2429 plog(LLV_ERROR, LOCATION, NULL,
2430 "must be TV when GRP_DESC.\n");
2431 return -1;
2432 }
2433
2434 if (!alg_oakley_dhdef_ok(lorv)) {
2435 plog(LLV_ERROR, LOCATION, NULL,
2436 "invalid group description=%u.\n",
2437 lorv);
2438 return -1;
2439 }
2440 break;
2441
2442 case IPSECDOI_ATTR_KEY_LENGTH:
2443 if (! flag) {
2444 plog(LLV_ERROR, LOCATION, NULL,
2445 "must be TV when KEY_LENGTH.\n");
2446 return -1;
2447 }
2448 break;
2449
2450 case IPSECDOI_ATTR_KEY_ROUNDS:
2451 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2452 case IPSECDOI_ATTR_COMP_PRIVALG:
2453 plog(LLV_ERROR, LOCATION, NULL,
2454 "attr type=%u isn't supported.\n", type);
2455 return -1;
2456
2457 default:
2458 plog(LLV_ERROR, LOCATION, NULL,
2459 "invalid attribute type %d.\n", type);
2460 return -1;
2461 }
2462
2463 if (flag) {
2464 tlen -= sizeof(*d);
2465 d = (struct isakmp_data *)((char *)d
2466 + sizeof(*d));
2467 } else {
2468 tlen -= (sizeof(*d) + lorv);
2469 d = (struct isakmp_data *)((caddr_t)d
2470 + sizeof(*d) + lorv);
2471 }
2472 }
2473
2474 if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
2475 !attrseen[IPSECDOI_ATTR_AUTH]) {
2476 plog(LLV_ERROR, LOCATION, NULL,
2477 "attr AUTH must be present for AH.\n");
2478 return -1;
2479 }
2480
2481 if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
2482 trns->t_id == IPSECDOI_ESP_NULL &&
2483 !attrseen[IPSECDOI_ATTR_AUTH]) {
2484 plog(LLV_ERROR, LOCATION, NULL,
2485 "attr AUTH must be present for ESP NULL encryption.\n");
2486 return -1;
2487 }
2488
2489 return 0;
2490}
2491
2492static int
2493check_attr_ipcomp(trns)
2494 struct isakmp_pl_t *trns;
2495{
2496 struct isakmp_data *d;
2497 int tlen;
2498 int flag, type = 0;
2499 u_int16_t lorv;
2500 int attrseen[16]; /* XXX magic number */
2501
2502 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
2503 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
2504 memset(attrseen, 0, sizeof(attrseen));
2505
2506 while (tlen > 0) {
2507 type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
2508 flag = ntohs(d->type) & ISAKMP_GEN_MASK;
2509 lorv = ntohs(d->lorv);
2510
2511 plog(LLV_DEBUG, LOCATION, NULL,
2512 "type=%d, flag=0x%04x, lorv=0x%04x\n",
2513 type, flag, lorv);
2514
2515 if (type < sizeof(attrseen)/sizeof(attrseen[0]))
2516 attrseen[type]++;
2517
2518 switch (type) {
2519 case IPSECDOI_ATTR_ENC_MODE:
2520 if (! flag) {
2521 plog(LLV_ERROR, LOCATION, NULL,
2522 "must be TV when ENC_MODE.\n");
2523 return -1;
2524 }
2525
2526 switch (lorv) {
2527 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
2528 case IPSECDOI_ATTR_ENC_MODE_TRNS:
2529 break;
2530#ifdef ENABLE_NATT
2531 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
2532 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
2533 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
2534 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
2535 plog(LLV_DEBUG, LOCATION, NULL,
2536 "UDP encapsulation requested\n");
2537 break;
2538#endif
2539 default:
2540 plog(LLV_ERROR, LOCATION, NULL,
2541 "invalid encryption mode=%u.\n",
2542 lorv);
2543 return -1;
2544 }
2545 break;
2546
2547 case IPSECDOI_ATTR_SA_LD_TYPE:
2548 if (! flag) {
2549 plog(LLV_ERROR, LOCATION, NULL,
2550 "must be TV when LD_TYPE.\n");
2551 return -1;
2552 }
2553
2554 switch (lorv) {
2555 case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
2556 case IPSECDOI_ATTR_SA_LD_TYPE_KB:
2557 break;
2558 default:
2559 plog(LLV_ERROR, LOCATION, NULL,
2560 "invalid life type %d.\n", lorv);
2561 return -1;
2562 }
2563 break;
2564
2565 case IPSECDOI_ATTR_SA_LD:
2566 if (flag) {
2567 /* i.e. ISAKMP_GEN_TV */
2568 plog(LLV_DEBUG, LOCATION, NULL,
2569 "life duration was in TLV.\n");
2570 } else {
2571 /* i.e. ISAKMP_GEN_TLV */
2572 if (lorv == 0) {
2573 plog(LLV_ERROR, LOCATION, NULL,
2574 "invalid length of LD\n");
2575 return -1;
2576 }
2577 }
2578 break;
2579
2580 case IPSECDOI_ATTR_GRP_DESC:
2581 if (! flag) {
2582 plog(LLV_ERROR, LOCATION, NULL,
2583 "must be TV when GRP_DESC.\n");
2584 return -1;
2585 }
2586
2587 if (!alg_oakley_dhdef_ok(lorv)) {
2588 plog(LLV_ERROR, LOCATION, NULL,
2589 "invalid group description=%u.\n",
2590 lorv);
2591 return -1;
2592 }
2593 break;
2594
2595 case IPSECDOI_ATTR_AUTH:
2596 plog(LLV_ERROR, LOCATION, NULL,
2597 "invalid attr type=%u.\n", type);
2598 return -1;
2599
2600 case IPSECDOI_ATTR_KEY_LENGTH:
2601 case IPSECDOI_ATTR_KEY_ROUNDS:
2602 case IPSECDOI_ATTR_COMP_DICT_SIZE:
2603 case IPSECDOI_ATTR_COMP_PRIVALG:
2604 plog(LLV_ERROR, LOCATION, NULL,
2605 "attr type=%u isn't supported.\n", type);
2606 return -1;
2607
2608 default:
2609 plog(LLV_ERROR, LOCATION, NULL,
2610 "invalid attribute type %d.\n", type);
2611 return -1;
2612 }
2613
2614 if (flag) {
2615 tlen -= sizeof(*d);
2616 d = (struct isakmp_data *)((char *)d
2617 + sizeof(*d));
2618 } else {
2619 tlen -= (sizeof(*d) + lorv);
2620 d = (struct isakmp_data *)((caddr_t)d
2621 + sizeof(*d) + lorv);
2622 }
2623 }
2624
2625#if 0
2626 if (proto_id == IPSECDOI_PROTO_IPCOMP &&
2627 !attrseen[IPSECDOI_ATTR_AUTH]) {
2628 plog(LLV_ERROR, LOCATION, NULL,
2629 "attr AUTH must be present for AH.\n", type);
2630 return -1;
2631 }
2632#endif
2633
2634 return 0;
2635}
2636
2637/* %%% */
2638/*
2639 * create phase1 proposal from remote configuration.
2640 * NOT INCLUDING isakmp general header of SA payload
2641 */
2642vchar_t *
2643ipsecdoi_setph1proposal(props)
2644 struct isakmpsa *props;
2645{
2646 vchar_t *mysa;
2647 int sablen;
2648
2649 /* count total size of SA minus isakmp general header */
2650 /* not including isakmp general header of SA payload */
2651 sablen = sizeof(struct ipsecdoi_sa_b);
2652 sablen += setph1prop(props, NULL);
2653
2654 mysa = vmalloc(sablen);
2655 if (mysa == NULL) {
2656 plog(LLV_ERROR, LOCATION, NULL,
2657 "failed to allocate my sa buffer\n");
2658 return NULL;
2659 }
2660
2661 /* create SA payload */
2662 /* not including isakmp general header */
85f41bec
A
2663 (ALIGNED_CAST(struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(props->rmconf->doitype);
2664 (ALIGNED_CAST(struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(props->rmconf->sittype);
52b7d2ce
A
2665
2666 (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
2667
2668 return mysa;
2669}
2670
2671static int
2672setph1prop(props, buf)
2673 struct isakmpsa *props;
2674 caddr_t buf;
2675{
2676 struct isakmp_pl_p *prop = NULL;
2677 struct isakmpsa *s = NULL;
2678 int proplen, trnslen;
2679 u_int8_t *np_t; /* pointer next trns type in previous header */
2680 int trns_num;
2681 caddr_t p = buf;
2682
2683 proplen = sizeof(*prop);
2684 if (buf) {
2685 /* create proposal */
2686 prop = (struct isakmp_pl_p *)p;
2687 prop->h.np = ISAKMP_NPTYPE_NONE;
2688 prop->p_no = props->prop_no;
2689 prop->proto_id = IPSECDOI_PROTO_ISAKMP;
2690 prop->spi_size = 0;
2691 p += sizeof(*prop);
2692 }
2693
2694 np_t = NULL;
2695 trns_num = 0;
2696
2697 for (s = props; s != NULL; s = s->next) {
2698 if (np_t)
2699 *np_t = ISAKMP_NPTYPE_T;
2700
2701 trnslen = setph1trns(s, p);
2702 proplen += trnslen;
2703 if (buf) {
2704 /* save buffer to pre-next payload */
2705 np_t = &((struct isakmp_pl_t *)p)->h.np;
2706 p += trnslen;
2707
2708 /* count up transform length */
2709 trns_num++;
2710 }
2711 }
2712
2713 /* update proposal length */
2714 if (buf) {
2715 prop->h.len = htons(proplen);
2716 prop->num_t = trns_num;
2717 }
2718
2719 return proplen;
2720}
2721
2722static int
2723setph1trns(sa, buf)
2724 struct isakmpsa *sa;
2725 caddr_t buf;
2726{
2727 struct isakmp_pl_t *trns = NULL;
2728 int trnslen, attrlen;
2729 caddr_t p = buf;
2730
2731 trnslen = sizeof(*trns);
2732 if (buf) {
2733 /* create transform */
2734 trns = (struct isakmp_pl_t *)p;
2735 trns->h.np = ISAKMP_NPTYPE_NONE;
2736 trns->t_no = sa->trns_no;
2737 trns->t_id = IPSECDOI_KEY_IKE;
2738 p += sizeof(*trns);
2739 }
2740
2741 attrlen = setph1attr(sa, p);
2742 trnslen += attrlen;
2743 if (buf)
2744 p += attrlen;
2745
2746 if (buf)
2747 trns->h.len = htons(trnslen);
2748
2749 return trnslen;
2750}
2751
2752static int
2753setph1attr(sa, buf)
2754 struct isakmpsa *sa;
2755 caddr_t buf;
2756{
2757 caddr_t p = buf;
2758 int attrlen = 0;
2759
2760 if (sa->lifetime) {
2761 u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
2762
2763 attrlen += sizeof(struct isakmp_data)
2764 + sizeof(struct isakmp_data);
2765 if (sa->lifetime > 0xffff)
2766 attrlen += sizeof(lifetime);
2767 if (buf) {
2768 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2769 OAKLEY_ATTR_SA_LD_TYPE_SEC);
2770 if (sa->lifetime > 0xffff) {
2771 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2772 (caddr_t)&lifetime,
2773 sizeof(lifetime));
2774 } else {
2775 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2776 sa->lifetime);
2777 }
2778 }
2779 }
2780
2781 if (sa->lifebyte) {
2782 u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
2783
2784 attrlen += sizeof(struct isakmp_data)
2785 + sizeof(struct isakmp_data);
2786 if (sa->lifebyte > 0xffff)
2787 attrlen += sizeof(lifebyte);
2788 if (buf) {
2789 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
2790 OAKLEY_ATTR_SA_LD_TYPE_KB);
2791 if (sa->lifebyte > 0xffff) {
2792 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
2793 (caddr_t)&lifebyte,
2794 sizeof(lifebyte));
2795 } else {
2796 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
2797 sa->lifebyte);
2798 }
2799 }
2800 }
2801
2802 if (sa->enctype) {
2803 attrlen += sizeof(struct isakmp_data);
2804 if (buf)
2805 p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
2806 }
2807 if (sa->encklen) {
2808 attrlen += sizeof(struct isakmp_data);
2809 if (buf)
2810 p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
2811 }
2812 if (sa->authmethod) {
2813 int authmethod;
2814
2815#ifdef ENABLE_HYBRID
2816 authmethod = switch_authmethod(sa->authmethod);
2817#else
2818 authmethod = sa->authmethod;
2819#endif
2820 attrlen += sizeof(struct isakmp_data);
2821 if (buf)
2822 p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
2823 }
2824 if (sa->hashtype) {
2825 attrlen += sizeof(struct isakmp_data);
2826 if (buf)
2827 p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
2828 }
2829 switch (sa->dh_group) {
2830 case OAKLEY_ATTR_GRP_DESC_MODP768:
2831 case OAKLEY_ATTR_GRP_DESC_MODP1024:
2832 case OAKLEY_ATTR_GRP_DESC_MODP1536:
2833 case OAKLEY_ATTR_GRP_DESC_MODP2048:
2834 case OAKLEY_ATTR_GRP_DESC_MODP3072:
2835 case OAKLEY_ATTR_GRP_DESC_MODP4096:
2836 case OAKLEY_ATTR_GRP_DESC_MODP6144:
2837 case OAKLEY_ATTR_GRP_DESC_MODP8192:
2838 /* don't attach group type for known groups */
2839 attrlen += sizeof(struct isakmp_data);
2840 if (buf) {
2841 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
2842 sa->dh_group);
2843 }
2844 break;
2845 case OAKLEY_ATTR_GRP_DESC_EC2N155:
2846 case OAKLEY_ATTR_GRP_DESC_EC2N185:
2847 /* don't attach group type for known groups */
2848 attrlen += sizeof(struct isakmp_data);
2849 if (buf) {
2850 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
2851 OAKLEY_ATTR_GRP_TYPE_EC2N);
2852 }
2853 break;
2854 case 0:
2855 default:
2856 break;
2857 }
2858
2859#ifdef HAVE_GSSAPI
2860 if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
2861 sa->gssid != NULL) {
2862 attrlen += sizeof(struct isakmp_data);
2863 /*
2864 * Older versions of racoon just placed the ISO-Latin-1
2865 * string on the wire directly. Check to see if we are
2866 * configured to be compatible with this behavior. Otherwise,
2867 * we encode the GSS ID as UTF-16LE for Windows 2000
2868 * compatibility, which requires twice the number of octets.
2869 */
2870 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
2871 attrlen += sa->gssid->l;
2872 else
2873 attrlen += sa->gssid->l * 2;
2874 if (buf) {
d1e348cf
A
2875 plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
2876 "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
52b7d2ce
A
2877 sa->gssid->v);
2878 if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
2879 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2880 (caddr_t)sa->gssid->v,
2881 sa->gssid->l);
2882 } else {
2883 size_t dstleft = sa->gssid->l * 2;
2884 size_t srcleft = sa->gssid->l;
2885 const char *src = (const char *)sa->gssid->v;
2886 char *odst, *dst = racoon_malloc(dstleft);
2887 iconv_t cd;
2888 size_t rv;
2889
2890 cd = iconv_open("utf-16le", "latin1");
2891 if (cd == (iconv_t) -1) {
2892 plog(LLV_ERROR, LOCATION, NULL,
2893 "unable to initialize "
2894 "latin1 -> utf-16le "
2895 "converstion descriptor: %s\n",
2896 strerror(errno));
2897 attrlen -= sa->gssid->l * 2;
2898 goto gssid_done;
2899 }
2900 odst = dst;
2901 rv = iconv(cd, (__iconv_const char **)&src,
2902 &srcleft, &dst, &dstleft);
2903 if (rv != 0) {
2904 if (rv == -1) {
2905 plog(LLV_ERROR, LOCATION, NULL,
2906 "unable to convert GSS ID "
2907 "from latin1 -> utf-16le: "
2908 "%s\n", strerror(errno));
2909 } else {
2910 /* should never happen */
2911 plog(LLV_ERROR, LOCATION, NULL,
2912 "%zd character%s in GSS ID "
2913 "cannot be represented "
2914 "in utf-16le\n",
2915 rv, rv == 1 ? "" : "s");
2916 }
2917 (void) iconv_close(cd);
2918 attrlen -= sa->gssid->l * 2;
2919 goto gssid_done;
2920 }
2921 (void) iconv_close(cd);
2922
2923 /* XXX Check srcleft and dstleft? */
2924
2925 p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
2926 odst, sa->gssid->l * 2);
2927
2928 racoon_free(odst);
2929 }
2930 }
2931 }
2932 gssid_done:
2933#endif /* HAVE_GSSAPI */
2934
2935 return attrlen;
2936}
2937
2938static vchar_t *
2939setph2proposal0(iph2, pp, pr)
2940 const struct ph2handle *iph2;
2941 const struct saprop *pp;
2942 const struct saproto *pr;
2943{
2944 vchar_t *p;
2945 struct isakmp_pl_p *prop;
2946 struct isakmp_pl_t *trns;
2947 struct satrns *tr;
2948 int attrlen;
2949 size_t trnsoff;
2950 caddr_t x0, x;
2951 u_int8_t *np_t; /* pointer next trns type in previous header */
2952 const u_int8_t *spi;
2953
2954 p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
2955 if (p == NULL)
2956 return NULL;
2957
2958 /* create proposal */
2959 prop = (struct isakmp_pl_p *)p->v;
2960 prop->h.np = ISAKMP_NPTYPE_NONE;
2961 prop->p_no = pp->prop_no;
2962 prop->proto_id = pr->proto_id;
2963 prop->num_t = 1;
2964
2965 spi = (const u_int8_t *)&pr->spi;
2966 switch (pr->proto_id) {
2967 case IPSECDOI_PROTO_IPCOMP:
2968 /*
2969 * draft-shacham-ippcp-rfc2393bis-05.txt:
2970 * construct 16bit SPI (CPI).
2971 * XXX we may need to provide a configuration option to
2972 * generate 32bit SPI. otherwise we cannot interoeprate
2973 * with nodes that uses 32bit SPI, in case we are initiator.
2974 */
2975 prop->spi_size = sizeof(u_int16_t);
2976 spi += sizeof(pr->spi) - sizeof(u_int16_t);
2977 p->l -= sizeof(pr->spi);
2978 p->l += sizeof(u_int16_t);
2979 break;
2980 default:
2981 prop->spi_size = sizeof(pr->spi);
2982 break;
2983 }
2984 memcpy(prop + 1, spi, prop->spi_size);
2985
2986 /* create transform */
2987 trnsoff = sizeof(*prop) + prop->spi_size;
2988 np_t = NULL;
2989
2990 for (tr = pr->head; tr; tr = tr->next) {
2991
2992 switch (pr->proto_id) {
2993 case IPSECDOI_PROTO_IPSEC_ESP:
2994 /*
2995 * don't build a null encryption
2996 * with no authentication transform.
2997 */
2998 if (tr->trns_id == IPSECDOI_ESP_NULL &&
2999 tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
3000 continue;
3001 break;
3002 }
3003
3004 if (np_t) {
3005 *np_t = ISAKMP_NPTYPE_T;
3006 prop->num_t++;
3007 }
3008
3009 /* get attribute length */
3010 attrlen = 0;
3011 if (pp->lifetime) {
3012 attrlen += sizeof(struct isakmp_data)
3013 + sizeof(struct isakmp_data);
3014 if (pp->lifetime > 0xffff)
3015 attrlen += sizeof(u_int32_t);
3016 }
3017 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
3018 attrlen += sizeof(struct isakmp_data)
3019 + sizeof(struct isakmp_data);
3020 if (pp->lifebyte > 0xffff)
3021 attrlen += sizeof(u_int32_t);
3022 }
3023 attrlen += sizeof(struct isakmp_data); /* enc mode */
3024 if (tr->encklen)
3025 attrlen += sizeof(struct isakmp_data);
3026
3027 switch (pr->proto_id) {
3028 case IPSECDOI_PROTO_IPSEC_ESP:
3029 /* non authentication mode ? */
3030 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
3031 attrlen += sizeof(struct isakmp_data);
3032 break;
3033 case IPSECDOI_PROTO_IPSEC_AH:
3034 if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
3035 plog(LLV_ERROR, LOCATION, NULL,
3036 "no authentication algorithm found "
3037 "but protocol is AH.\n");
3038 vfree(p);
3039 return NULL;
3040 }
3041 attrlen += sizeof(struct isakmp_data);
3042 break;
3043 case IPSECDOI_PROTO_IPCOMP:
3044 break;
3045 default:
3046 plog(LLV_ERROR, LOCATION, NULL,
3047 "invalid protocol: %d\n", pr->proto_id);
3048 vfree(p);
3049 return NULL;
3050 }
3051
3052 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
3053 attrlen += sizeof(struct isakmp_data);
3054
3055 p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
3056 if (p == NULL)
3057 return NULL;
3058 prop = (struct isakmp_pl_p *)p->v;
3059
3060 /* set transform's values */
3061 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
3062 trns->h.np = ISAKMP_NPTYPE_NONE;
3063 trns->t_no = tr->trns_no;
3064 trns->t_id = tr->trns_id;
3065
3066 /* set attributes */
3067 x = x0 = p->v + trnsoff + sizeof(*trns);
3068
3069 if (pp->lifetime) {
3070 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
3071 IPSECDOI_ATTR_SA_LD_TYPE_SEC);
3072 if (pp->lifetime > 0xffff) {
3073 u_int32_t v = htonl((u_int32_t)pp->lifetime);
3074 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
3075 (caddr_t)&v, sizeof(v));
3076 } else {
3077 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
3078 pp->lifetime);
3079 }
3080 }
3081
3082 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
3083 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
3084 IPSECDOI_ATTR_SA_LD_TYPE_KB);
3085 if (pp->lifebyte > 0xffff) {
3086 u_int32_t v = htonl((u_int32_t)pp->lifebyte);
3087 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
3088 (caddr_t)&v, sizeof(v));
3089 } else {
3090 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
3091 pp->lifebyte);
3092 }
3093 }
3094
3095 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
3096
3097 if (tr->encklen)
3098 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
3099
3100 /* mandatory check has done above. */
3101 if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
3102 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
3103 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
3104
3105 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
3106 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
3107 iph2->sainfo->pfs_group);
3108
3109 /* update length of this transform. */
3110 trns = (struct isakmp_pl_t *)(p->v + trnsoff);
3111 trns->h.len = htons(sizeof(*trns) + attrlen);
3112
3113 /* save buffer to pre-next payload */
3114 np_t = &trns->h.np;
3115
3116 trnsoff += (sizeof(*trns) + attrlen);
3117 }
3118
3119 if (np_t == NULL) {
3120 plog(LLV_ERROR, LOCATION, NULL,
3121 "no suitable proposal was created.\n");
3122 return NULL;
3123 }
3124
3125 /* update length of this protocol. */
3126 prop->h.len = htons(p->l);
3127
3128 return p;
3129}
3130
3131/*
3132 * create phase2 proposal from policy configuration.
3133 * NOT INCLUDING isakmp general header of SA payload.
3134 * This function is called by initiator only.
3135 */
3136int
3137ipsecdoi_setph2proposal(iph2)
3138 struct ph2handle *iph2;
3139{
3140 struct saprop *proposal, *a;
3141 struct saproto *b = NULL;
3142 vchar_t *q;
3143 struct ipsecdoi_sa_b *sab;
3144 struct isakmp_pl_p *prop;
3145 size_t propoff; /* for previous field of type of next payload. */
3146
3147 proposal = iph2->proposal;
3148
3149 iph2->sa = vmalloc(sizeof(*sab));
3150 if (iph2->sa == NULL) {
3151 plog(LLV_ERROR, LOCATION, NULL,
3152 "failed to allocate my sa buffer\n");
3153 return -1;
3154 }
3155
3156 /* create SA payload */
85f41bec 3157 sab = ALIGNED_CAST(struct ipsecdoi_sa_b *)iph2->sa->v;
52b7d2ce
A
3158 sab->doi = htonl(IPSEC_DOI);
3159 sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */
3160
3161 prop = NULL;
3162 propoff = 0;
3163 for (a = proposal; a; a = a->next) {
3164 for (b = a->head; b; b = b->next) {
3165#ifdef ENABLE_NATT
3166 if (iph2->ph1->natt_flags & NAT_DETECTED) {
3167 int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
3168 plog (LLV_INFO, LOCATION, NULL,
3169 "NAT detected -> UDP encapsulation "
3170 "(ENC_MODE %d->%d).\n",
3171 b->encmode,
3172 b->encmode+udp_diff);
3173 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
3174 b->encmode += udp_diff;
3175 b->udp_encap = 1;
3176 }
3177#endif
3178
3179 q = setph2proposal0(iph2, a, b);
3180 if (q == NULL) {
3181 VPTRINIT(iph2->sa);
3182 return -1;
3183 }
3184
3185 iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
3186 if (iph2->sa == NULL) {
3187 plog(LLV_ERROR, LOCATION, NULL,
3188 "failed to allocate my sa buffer\n");
3189 if (q)
3190 vfree(q);
3191 return -1;
3192 }
3193 memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
3194 if (propoff != 0) {
3195 prop = (struct isakmp_pl_p *)(iph2->sa->v +
3196 propoff);
3197 prop->h.np = ISAKMP_NPTYPE_P;
3198 }
3199 propoff = iph2->sa->l - q->l;
3200
3201 vfree(q);
3202 }
3203 }
3204
3205 return 0;
3206}
3207
52b7d2ce 3208/*
d1e348cf 3209 * return 1 if all of the given protocols are tunnel mode.
52b7d2ce
A
3210 */
3211int
3212ipsecdoi_tunnelmode(iph2)
3213 struct ph2handle *iph2;
3214{
3215 struct saprop *pp;
3216 struct saproto *pr = NULL;
3217
3218 for (pp = iph2->proposal; pp; pp = pp->next) {
3219 for (pr = pp->head; pr; pr = pr->next) {
3220 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TUNNEL &&
3221 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC &&
3222 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT)
3223 return 0;
3224 }
3225 }
3226
3227 return 1;
3228}
d1e348cf
A
3229
3230/*
3231 * return 1 if any of the given protocols are transport mode.
3232 */
3233int
3234ipsecdoi_any_transportmode(pp)
3235struct saprop *pp;
3236{
3237 struct saproto *pr = NULL;
3238
3239 for (; pp; pp = pp->next) {
3240 for (pr = pp->head; pr; pr = pr->next) {
3241 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TRNS ||
3242 pr->encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC ||
3243 pr->encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
3244 return 1;
3245 }
3246 }
3247
3248 return 0;
3249}
52b7d2ce
A
3250
3251/*
3252 * return 1 if all of the given protocols are transport mode.
3253 */
3254int
3255ipsecdoi_transportmode(pp)
3256 struct saprop *pp;
3257{
3258 struct saproto *pr = NULL;
3259
3260 for (; pp; pp = pp->next) {
3261 for (pr = pp->head; pr; pr = pr->next) {
3262 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
3263 return 0;
3264 }
3265 }
3266
3267 return 1;
3268}
3269
3270int
3271ipsecdoi_get_defaultlifetime()
3272{
3273 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3274}
3275
3276int
3277ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
3278 int proto_id, enc, auth, comp;
3279{
3280#define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3281 switch (proto_id) {
3282 case IPSECDOI_PROTO_IPSEC_ESP:
3283 if (enc == 0 || comp != 0) {
3284 plog(LLV_ERROR, LOCATION, NULL,
3285 "illegal algorithm defined "
3286 "ESP enc=%s auth=%s comp=%s.\n",
3287 TMPALGTYPE2STR(enc),
3288 TMPALGTYPE2STR(auth),
3289 TMPALGTYPE2STR(comp));
3290 return -1;
3291 }
3292 break;
3293 case IPSECDOI_PROTO_IPSEC_AH:
3294 if (enc != 0 || auth == 0 || comp != 0) {
3295 plog(LLV_ERROR, LOCATION, NULL,
3296 "illegal algorithm defined "
3297 "AH enc=%s auth=%s comp=%s.\n",
3298 TMPALGTYPE2STR(enc),
3299 TMPALGTYPE2STR(auth),
3300 TMPALGTYPE2STR(comp));
3301 return -1;
3302 }
3303 break;
3304 case IPSECDOI_PROTO_IPCOMP:
3305 if (enc != 0 || auth != 0 || comp == 0) {
3306 plog(LLV_ERROR, LOCATION, NULL,
3307 "illegal algorithm defined "
3308 "IPcomp enc=%s auth=%s comp=%s.\n",
3309 TMPALGTYPE2STR(enc),
3310 TMPALGTYPE2STR(auth),
3311 TMPALGTYPE2STR(comp));
3312 return -1;
3313 }
3314 break;
3315 default:
3316 plog(LLV_ERROR, LOCATION, NULL,
3317 "invalid ipsec protocol %d\n", proto_id);
3318 return -1;
3319 }
3320#undef TMPALGTYPE2STR
3321 return 0;
3322}
3323
3324int
3325ipproto2doi(proto)
3326 int proto;
3327{
3328 switch (proto) {
3329 case IPPROTO_AH:
3330 return IPSECDOI_PROTO_IPSEC_AH;
3331 case IPPROTO_ESP:
3332 return IPSECDOI_PROTO_IPSEC_ESP;
3333 case IPPROTO_IPCOMP:
3334 return IPSECDOI_PROTO_IPCOMP;
3335 }
3336 return -1; /* XXX */
3337}
3338
3339int
3340doi2ipproto(proto)
3341 int proto;
3342{
3343 switch (proto) {
3344 case IPSECDOI_PROTO_IPSEC_AH:
3345 return IPPROTO_AH;
3346 case IPSECDOI_PROTO_IPSEC_ESP:
3347 return IPPROTO_ESP;
3348 case IPSECDOI_PROTO_IPCOMP:
3349 return IPPROTO_IPCOMP;
3350 }
3351 return -1; /* XXX */
3352}
3353
d1e348cf
A
3354/*
3355 * Check if a subnet id is valid for comparison
3356 * with an address id ( address length mask )
3357 * and compare them
3358 * Return value
3359 * = 0 for match
3360 * = 1 for mismatch
3361 */
3362
3363int
3364ipsecdoi_subnetisaddr_v4( subnet, address )
3365 const vchar_t *subnet;
3366 const vchar_t *address;
3367{
3368 struct in_addr *mask;
3369
3370 if (address->l != sizeof(struct in_addr))
3371 return 1;
3372
3373 if (subnet->l != (sizeof(struct in_addr)*2))
3374 return 1;
3375
85f41bec 3376 mask = ALIGNED_CAST(struct in_addr*)(subnet->v + sizeof(struct in_addr));
d1e348cf
A
3377
3378 if (mask->s_addr!=0xffffffff)
3379 return 1;
3380
3381 return memcmp(subnet->v,address->v,address->l);
3382}
3383
3384#ifdef INET6
3385
3386int
3387ipsecdoi_subnetisaddr_v6( subnet, address )
3388 const vchar_t *subnet;
3389 const vchar_t *address;
3390{
3391 struct in6_addr *mask;
3392 int i;
3393
3394 if (address->l != sizeof(struct in6_addr))
3395 return 1;
3396
3397 if (subnet->l != (sizeof(struct in6_addr)*2))
3398 return 1;
3399
85f41bec 3400 mask = ALIGNED_CAST(struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
d1e348cf
A
3401
3402 for (i=0; i<16; i++)
3403 if(mask->s6_addr[i]!=0xff)
3404 return 1;
3405
3406 return memcmp(subnet->v,address->v,address->l);
3407}
3408
3409#endif
3410
e8d9021d 3411#ifdef NOT_USED
d1e348cf
A
3412/*
3413 * Check and Compare two IDs
3414 * - specify 0 for exact if wildcards are allowed
3415 * Return value
3416 * = 0 for match
3417 * = 1 for misatch
3418 * = -1 for integrity error
3419 */
3420
3421int
3422ipsecdoi_chkcmpids( idt, ids, exact )
3423 const vchar_t *idt; /* id cmp target */
3424 const vchar_t *ids; /* id cmp source */
3425 int exact;
3426{
3427 struct ipsecdoi_id_b *id_bt;
3428 struct ipsecdoi_id_b *id_bs;
3429 vchar_t ident_t;
3430 vchar_t ident_s;
3431 int result;
3432
3433 /* handle wildcard IDs */
3434
3435 if (idt == NULL || ids == NULL)
3436 {
3437 if( !exact )
3438 {
3439 plog(LLV_DEBUG, LOCATION, NULL,
3440 "check and compare ids : values matched (ANONYMOUS)\n" );
3441 return 0;
3442 }
3443 else
3444 {
3445 plog(LLV_DEBUG, LOCATION, NULL,
3446 "check and compare ids : value mismatch (ANONYMOUS)\n" );
3447 return -1;
3448 }
3449 }
3450
3451 /* make sure the ids are of the same type */
3452
3453 id_bt = (struct ipsecdoi_id_b *) idt->v;
3454 id_bs = (struct ipsecdoi_id_b *) ids->v;
3455
3456 ident_t.v = idt->v + sizeof(*id_bt);
3457 ident_t.l = idt->l - sizeof(*id_bt);
3458 ident_s.v = ids->v + sizeof(*id_bs);
3459 ident_s.l = ids->l - sizeof(*id_bs);
3460
3461 if (id_bs->type != id_bt->type)
3462 {
3463 /*
3464 * special exception for comparing
3465 * address to subnet id types when
3466 * the netmask is address length
3467 */
3468
3469 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
3470 (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
3471 result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
3472 goto cmpid_result;
3473 }
3474
3475 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
3476 (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
3477 result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
3478 goto cmpid_result;
3479 }
3480
3481#ifdef INET6
3482 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
3483 (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
3484 result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
3485 goto cmpid_result;
3486 }
3487
3488 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
3489 (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
3490 result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
3491 goto cmpid_result;
3492 }
3493#endif
3494 plog(LLV_DEBUG, LOCATION, NULL,
3495 "check and compare ids : id type mismatch %s != %s\n",
3496 s_ipsecdoi_ident(id_bs->type),
3497 s_ipsecdoi_ident(id_bt->type));
3498
3499 return 1;
3500 }
3501
3502 if(id_bs->proto_id != id_bt->proto_id){
3503 plog(LLV_DEBUG, LOCATION, NULL,
3504 "check and compare ids : proto_id mismatch %d != %d\n",
3505 id_bs->proto_id, id_bt->proto_id);
3506
3507 return 1;
3508 }
3509
3510 /* compare the ID data. */
3511
3512 switch (id_bt->type) {
3513 case IPSECDOI_ID_DER_ASN1_DN:
3514 case IPSECDOI_ID_DER_ASN1_GN:
3515 /* compare asn1 ids */
3516 result = eay_cmp_asn1dn(&ident_t, &ident_s);
3517 goto cmpid_result;
3518
3519 case IPSECDOI_ID_IPV4_ADDR:
3520 /* validate lengths */
3521 if ((ident_t.l != sizeof(struct in_addr))||
3522 (ident_s.l != sizeof(struct in_addr)))
3523 goto cmpid_invalid;
3524 break;
3525
3526 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3527 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3528 /* validate lengths */
3529 if ((ident_t.l != (sizeof(struct in_addr)*2))||
3530 (ident_s.l != (sizeof(struct in_addr)*2)))
3531 goto cmpid_invalid;
3532 break;
3533
3534#ifdef INET6
3535 case IPSECDOI_ID_IPV6_ADDR:
3536 /* validate lengths */
3537 if ((ident_t.l != sizeof(struct in6_addr))||
3538 (ident_s.l != sizeof(struct in6_addr)))
3539 goto cmpid_invalid;
3540 break;
3541
3542 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3543 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3544 /* validate lengths */
3545 if ((ident_t.l != (sizeof(struct in6_addr)*2))||
3546 (ident_s.l != (sizeof(struct in6_addr)*2)))
3547 goto cmpid_invalid;
3548 break;
3549#endif
3550 case IPSECDOI_ID_FQDN:
3551 case IPSECDOI_ID_USER_FQDN:
3552 case IPSECDOI_ID_KEY_ID:
3553 break;
3554
3555 default:
3556 plog(LLV_ERROR, LOCATION, NULL,
3557 "Unhandled id type %i specified for comparison\n",
3558 id_bt->type);
3559 return -1;
3560 }
3561
3562 /* validate matching data and length */
3563 if (ident_t.l == ident_s.l)
3564 result = memcmp(ident_t.v,ident_s.v,ident_t.l);
3565 else
3566 result = 1;
3567
3568cmpid_result:
3569
3570 /* debug level output */
3571 if(loglevel >= LLV_DEBUG) {
3572 char *idstrt = ipsecdoi_id2str(idt);
3573 char *idstrs = ipsecdoi_id2str(ids);
3574
3575 if (!result)
3576 plog(LLV_DEBUG, LOCATION, NULL,
3577 "check and compare ids : values matched (%s)\n",
3578 s_ipsecdoi_ident(id_bs->type) );
3579 else
3580 plog(LLV_DEBUG, LOCATION, NULL,
3581 "check and compare ids : value mismatch (%s)\n",
3582 s_ipsecdoi_ident(id_bs->type));
3583
3584 plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
3585 plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
3586
3587 racoon_free(idstrs);
3588 racoon_free(idstrt);
3589 }
3590
3591 /* return result */
3592 if( !result )
3593 return 0;
3594 else
3595 return 1;
3596
3597cmpid_invalid:
3598
3599 /* id integrity error */
3600 plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
3601 s_ipsecdoi_ident(id_bs->type));
3602 plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
3603 plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
3604
3605 return -1;
3606}
e8d9021d 3607#endif
d1e348cf 3608
52b7d2ce
A
3609/*
3610 * check the following:
3611 * - In main mode with pre-shared key, only address type can be used.
3612 * - if proper type for phase 1 ?
3613 * - if phase 1 ID payload conformed RFC2407 4.6.2.
3614 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3615 * - if ID payload sent from peer is equal to the ID expected by me.
3616 *
3617 * both of "id" and "id_p" should be ID payload without general header,
3618 */
3619int
3620ipsecdoi_checkid1(iph1)
3621 struct ph1handle *iph1;
3622{
3623 struct ipsecdoi_id_b *id_b;
85f41bec 3624 struct sockaddr_storage *sa;
52b7d2ce
A
3625 caddr_t sa1, sa2;
3626
3627 if (iph1->id_p == NULL) {
3628 plog(LLV_ERROR, LOCATION, NULL,
3629 "invalid iph1 passed id_p == NULL\n");
3630 return ISAKMP_INTERNAL_ERROR;
3631 }
3632 if (iph1->id_p->l < sizeof(*id_b)) {
3633 plog(LLV_ERROR, LOCATION, NULL,
3634 "invalid value passed as \"ident\" (len=%lu)\n",
3635 (u_long)iph1->id_p->l);
3636 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3637 }
3638
85f41bec 3639 id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v;
52b7d2ce
A
3640
3641 /* In main mode with pre-shared key, only address type can be used.
3642 * If NAT Traversal being used and peer is behind nat and
3643 * natt version = 02 - allow non-address ID type.
3644 */
3645 if (iph1->etype == ISAKMP_ETYPE_IDENT
3646 && iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY
3647#ifdef ENABLE_NATT
3648 && (iph1->natt_flags & NAT_DETECTED_PEER) == 0
3649#endif
3650 ) {
3651 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3652 && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3653 plog(LLV_ERROR, LOCATION, NULL,
3654 "Expecting IP address type in main mode, "
3655 "but %s.\n", s_ipsecdoi_ident(id_b->type));
3656 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3657 }
3658 }
3659
3660 /* if proper type for phase 1 ? */
3661 switch (id_b->type) {
3662 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3663 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3664 case IPSECDOI_ID_IPV4_ADDR_RANGE:
3665 case IPSECDOI_ID_IPV6_ADDR_RANGE:
3666 plog(LLV_WARNING, LOCATION, NULL,
3667 "such ID type %s is not proper.\n",
3668 s_ipsecdoi_ident(id_b->type));
3669 /*FALLTHROUGH*/
3670 }
3671
3672 /* if phase 1 ID payload conformed RFC2407 4.6.2. */
d1e348cf 3673 if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
52b7d2ce
A
3674 id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3675
3676 if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
3677 plog(LLV_WARNING, LOCATION, NULL,
3678 "protocol ID and Port mismatched. "
3679 "proto_id:%d port:%d\n",
3680 id_b->proto_id, ntohs(id_b->port));
3681 /*FALLTHROUGH*/
3682
3683 } else if (id_b->proto_id == IPPROTO_UDP) {
3684 /*
3685 * copmaring with expected port.
3686 * always permit if port is equal to PORT_ISAKMP
3687 */
3688 if (ntohs(id_b->port) != PORT_ISAKMP) {
3689
3690 u_int16_t port;
3691
85f41bec 3692 switch (iph1->remote->ss_family) {
52b7d2ce
A
3693 case AF_INET:
3694 port = ((struct sockaddr_in *)iph1->remote)->sin_port;
3695 break;
3696#ifdef INET6
3697 case AF_INET6:
3698 port = ((struct sockaddr_in6 *)iph1->remote)->sin6_port;
3699 break;
3700#endif
3701 default:
3702 plog(LLV_ERROR, LOCATION, NULL,
3703 "invalid family: %d\n",
85f41bec 3704 iph1->remote->ss_family);
52b7d2ce
A
3705 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3706 }
3707 if (ntohs(id_b->port) != port) {
3708 plog(LLV_WARNING, LOCATION, NULL,
3709 "port %d expected, but %d\n",
3710 port, ntohs(id_b->port));
3711 /*FALLTHROUGH*/
3712 }
3713 }
3714 }
3715 }
3716
3717 /* compare with the ID if specified. */
3718 if (genlist_next(iph1->rmconf->idvl_p, 0)) {
3719 vchar_t *ident0 = NULL;
85f41bec 3720#ifdef HAVE_OPENSSL
52b7d2ce 3721 vchar_t ident;
85f41bec 3722#endif
52b7d2ce
A
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:
85f41bec 3751 sa = ALIGNED_CAST(struct sockaddr_storage *)ident0->v;
52b7d2ce 3752 sa2 = (caddr_t)(id_b + 1);
85f41bec 3753 switch (sa->ss_family) {
52b7d2ce
A
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;
85f41bec 3807 struct sockaddr_storage *ipid = NULL;
52b7d2ce
A
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)
85f41bec 3886 ipid = ALIGNED_CAST(struct sockaddr_storage *)iph1->rmconf->idv->v;
52b7d2ce
A
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 */
85f41bec 3897 switch (ipid->ss_family) {
52b7d2ce
A
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: {
85f41bec 4068 struct sockaddr_storage *sa;
52b7d2ce
A
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
85f41bec 4081 new = vmalloc(sysdep_sa_len((struct sockaddr *)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
85f41bec 4155 iph2->id = ipsecdoi_sockaddr2id(&sp->spidx.src,
52b7d2ce
A
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 }
85f41bec
A
4163 if (((ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id->v)->type == IPSECDOI_ID_IPV4_ADDR ||
4164 (ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id->v)->type == IPSECDOI_ID_IPV4_ADDR_SUBNET) &&
e8d9021d
A
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 4173 plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
85f41bec 4174 s_ipsecdoi_ident((ALIGNED_CAST(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 */
85f41bec 4178 iph2->id_p = ipsecdoi_sockaddr2id(&sp->spidx.dst,
52b7d2ce
A
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",
85f41bec 4189 s_ipsecdoi_ident((ALIGNED_CAST(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)
85f41bec 4201 struct sockaddr_storage *saddr;
52b7d2ce
A
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 */
85f41bec 4214 switch (saddr->ss_family) {
52b7d2ce
A
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,
85f41bec 4243 "invalid family: %d.\n", saddr->ss_family);
52b7d2ce
A
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. */
85f41bec 4258 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->type = type;
52b7d2ce
A
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 */
85f41bec 4265 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->proto_id =
52b7d2ce 4266 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
85f41bec 4267 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->port =
52b7d2ce
A
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)
85f41bec 4293 struct sockaddr_storage *laddr, *haddr;
d1e348cf
A
4294 u_int ul_proto;
4295{
4296 vchar_t *new;
4297 int type, len1, len2;
4298 u_short port;
4299
85f41bec 4300 if (laddr->ss_family != haddr->ss_family) {
d1e348cf
A
4301 plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
4302 return NULL;
4303 }
4304
85f41bec 4305 switch (laddr->ss_family) {
d1e348cf
A
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,
85f41bec 4320 "invalid family: %d.\n", laddr->ss_family);
d1e348cf
A
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. */
85f41bec 4334 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->type = type;
d1e348cf
A
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 */
85f41bec 4341 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->proto_id =
d1e348cf
A
4342 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4343 port = ((struct sockaddr_in *)(laddr))->sin_port;
85f41bec 4344 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->port =
d1e348cf
A
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 4356/*
85f41bec 4357 * create sockaddr_storage structure from ID payload (buf).
52b7d2ce
A
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;
85f41bec 4364 struct sockaddr_storage *saddr;
52b7d2ce
A
4365 u_int8_t *prefixlen;
4366 u_int16_t *ul_proto;
4367{
85f41bec 4368 struct ipsecdoi_id_b *id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)buf->v;
52b7d2ce
A
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:
85f41bec
A
4381 saddr->ss_len = sizeof(struct sockaddr_in);
4382 saddr->ss_family = AF_INET;
52b7d2ce
A
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:
85f41bec
A
4393 saddr->ss_len = sizeof(struct sockaddr_in6);
4394 saddr->ss_family = AF_INET6;
52b7d2ce
A
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];
85f41bec 4493 struct ipsecdoi_id_b *id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)id->v;
d1e348cf
A
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
85f41bec
A
4504 saddr.ss_len = sizeof(struct sockaddr_in);
4505 saddr.ss_family = AF_INET;
d1e348cf
A
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:
85f41bec
A
4514 saddr.ss_len = sizeof(struct sockaddr_in6);
4515 saddr.ss_family = AF_INET6;
d1e348cf
A
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)
85f41bec 4521 ? (ALIGNED_CAST(struct sockaddr_in6 *)id_b)->sin6_scope_id
47612122 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
85f41bec
A
4596 saddr.ss_len = sizeof(struct sockaddr_in);
4597 saddr.ss_family = AF_INET;
d1e348cf
A
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
85f41bec
A
4614 saddr.ss_len = sizeof(struct sockaddr_in6);
4615 saddr.ss_family = AF_INET6;
d1e348cf
A
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)
85f41bec 4622 ? (ALIGNED_CAST(struct sockaddr_in6 *)id_b)->sin6_scope_id
47612122 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