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