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