Annotation of src/crypto/dist/ipsec-tools/src/racoon/ipsec_doi.c, Revision 1.22.2.3
1.22.2.3! jdc 1: /* $NetBSD: ipsec_doi.c,v 1.22.2.2 2007/08/28 11:14:44 liamjfoy 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.22.2.2 liamjfoy 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.13 manu 319: if (newsa == NULL){
1.5 manu 320: delisakmpsa(iph1->approval);
1.1 manu 321: iph1->approval = NULL;
1.5 manu 322: }
1.1 manu 323:
324: return newsa;
325: }
326:
327: /*
328: * compare peer's single proposal and all of my proposal.
329: * and select one if suiatable.
330: * p : one of peer's proposal.
331: * proposal: my proposals.
332: */
333: static struct isakmpsa *
334: get_ph1approvalx(p, proposal, sap, check_level)
335: struct prop_pair *p;
336: struct isakmpsa *proposal, *sap;
337: int check_level;
338: {
339: struct isakmp_pl_p *prop = p->prop;
340: struct isakmp_pl_t *trns = p->trns;
341: struct isakmpsa sa, *s, *tsap;
342: int authmethod;
343:
344: plog(LLV_DEBUG, LOCATION, NULL,
345: "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
346: prop->p_no, s_ipsecdoi_proto(prop->proto_id),
347: prop->spi_size, prop->num_t);
348:
349: plog(LLV_DEBUG, LOCATION, NULL,
350: "trns#=%d, trns-id=%s\n",
351: trns->t_no,
352: s_ipsecdoi_trns(prop->proto_id, trns->t_id));
353:
354: tsap = sap != NULL ? sap : &sa;
355:
356: memset(tsap, 0, sizeof(*tsap));
357: if (t2isakmpsa(trns, tsap) < 0)
358: return NULL;
359: for (s = proposal; s != NULL; s = s->next) {
360: #ifdef ENABLE_HYBRID
361: authmethod = switch_authmethod(s->authmethod);
362: #else
363: authmethod = s->authmethod;
364: #endif
365: plog(LLV_DEBUG, LOCATION, NULL, "Compared: DB:Peer\n");
366: plog(LLV_DEBUG, LOCATION, NULL, "(lifetime = %ld:%ld)\n",
367: (long)s->lifetime, (long)tsap->lifetime);
368: plog(LLV_DEBUG, LOCATION, NULL, "(lifebyte = %zu:%zu)\n",
369: s->lifebyte, tsap->lifebyte);
370: plog(LLV_DEBUG, LOCATION, NULL, "enctype = %s:%s\n",
371: s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
372: s->enctype),
373: s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
374: tsap->enctype));
375: plog(LLV_DEBUG, LOCATION, NULL, "(encklen = %d:%d)\n",
376: s->encklen, tsap->encklen);
377: plog(LLV_DEBUG, LOCATION, NULL, "hashtype = %s:%s\n",
378: s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
379: s->hashtype),
380: s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
381: tsap->hashtype));
382: plog(LLV_DEBUG, LOCATION, NULL, "authmethod = %s:%s\n",
383: s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
1.13 manu 384: s->authmethod),
1.1 manu 385: s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
386: tsap->authmethod));
387: plog(LLV_DEBUG, LOCATION, NULL, "dh_group = %s:%s\n",
388: s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
389: s->dh_group),
390: s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
391: tsap->dh_group));
392: #if 0
393: /* XXX to be considered ? */
394: if (tsap->lifebyte > s->lifebyte) ;
395: #endif
396: /*
397: * if responder side and peer's key length in proposal
398: * is bigger than mine, it might be accepted.
399: */
400: if(tsap->enctype == s->enctype &&
401: tsap->authmethod == authmethod &&
402: tsap->hashtype == s->hashtype &&
403: tsap->dh_group == s->dh_group &&
1.4 manu 404: tsap->encklen == s->encklen) {
405: switch(check_level) {
1.1 manu 406: case PROP_CHECK_OBEY:
407: goto found;
408: break;
1.4 manu 409:
1.1 manu 410: case PROP_CHECK_STRICT:
1.4 manu 411: if ((tsap->lifetime > s->lifetime) ||
412: (tsap->lifebyte > s->lifebyte))
413: continue;
414: goto found;
415: break;
416:
1.1 manu 417: case PROP_CHECK_CLAIM:
1.4 manu 418: if (tsap->lifetime < s->lifetime)
419: s->lifetime = tsap->lifetime;
420: if (tsap->lifebyte < s->lifebyte)
421: s->lifebyte = tsap->lifebyte;
1.1 manu 422: goto found;
423: break;
1.4 manu 424:
1.1 manu 425: case PROP_CHECK_EXACT:
1.4 manu 426: if ((tsap->lifetime != s->lifetime) ||
427: (tsap->lifebyte != s->lifebyte))
428: continue;
1.1 manu 429: goto found;
430: break;
1.4 manu 431:
432: default:
433: plog(LLV_ERROR, LOCATION, NULL,
434: "Unexpected proposal_check value\n");
435: continue;
436: break;
1.1 manu 437: }
1.4 manu 438: }
1.1 manu 439: }
440:
441: found:
1.13 manu 442: if (tsap->dhgrp != NULL){
1.1 manu 443: oakley_dhgrp_free(tsap->dhgrp);
1.13 manu 444: tsap->dhgrp = NULL;
445: }
1.5 manu 446:
447: if ((s = dupisakmpsa(s)) != NULL) {
448: switch(check_level) {
449: case PROP_CHECK_OBEY:
450: s->lifetime = tsap->lifetime;
451: s->lifebyte = tsap->lifebyte;
452: break;
453:
454: case PROP_CHECK_STRICT:
455: s->lifetime = tsap->lifetime;
456: s->lifebyte = tsap->lifebyte;
457: break;
458:
459: case PROP_CHECK_CLAIM:
460: if (tsap->lifetime < s->lifetime)
461: s->lifetime = tsap->lifetime;
462: if (tsap->lifebyte < s->lifebyte)
463: s->lifebyte = tsap->lifebyte;
464: break;
465:
466: default:
467: break;
468: }
469: }
1.1 manu 470: return s;
471: }
472:
473: /*
474: * print all of items in peer's proposal which are mismatched to my proposal.
475: * p : one of peer's proposal.
476: * proposal: my proposals.
477: */
478: static void
479: print_ph1mismatched(p, proposal)
480: struct prop_pair *p;
481: struct isakmpsa *proposal;
482: {
483: struct isakmpsa sa, *s;
484:
485: memset(&sa, 0, sizeof(sa));
486: if (t2isakmpsa(p->trns, &sa) < 0)
487: return;
488: for (s = proposal; s ; s = s->next) {
489: if (sa.enctype != s->enctype) {
490: plog(LLV_ERROR, LOCATION, NULL,
491: "rejected enctype: "
492: "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
493: "%s:%s\n",
494: s->prop_no, s->trns_no,
495: p->prop->p_no, p->trns->t_no,
496: s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
497: s->enctype),
498: s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
499: sa.enctype));
500: }
501: if (sa.authmethod != s->authmethod) {
502: plog(LLV_ERROR, LOCATION, NULL,
503: "rejected authmethod: "
504: "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
505: "%s:%s\n",
506: s->prop_no, s->trns_no,
507: p->prop->p_no, p->trns->t_no,
508: s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
509: s->authmethod),
510: s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
511: sa.authmethod));
512: }
513: if (sa.hashtype != s->hashtype) {
514: plog(LLV_ERROR, LOCATION, NULL,
515: "rejected hashtype: "
516: "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
517: "%s:%s\n",
518: s->prop_no, s->trns_no,
519: p->prop->p_no, p->trns->t_no,
520: s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
521: s->hashtype),
522: s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
523: sa.hashtype));
524: }
525: if (sa.dh_group != s->dh_group) {
526: plog(LLV_ERROR, LOCATION, NULL,
527: "rejected dh_group: "
528: "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
529: "%s:%s\n",
530: s->prop_no, s->trns_no,
531: p->prop->p_no, p->trns->t_no,
532: s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
533: s->dh_group),
534: s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
535: sa.dh_group));
536: }
537: }
538:
1.13 manu 539: if (sa.dhgrp != NULL){
1.1 manu 540: oakley_dhgrp_free(sa.dhgrp);
1.13 manu 541: sa.dhgrp=NULL;
542: }
1.1 manu 543: }
544:
545: /*
546: * get ISAKMP data attributes
547: */
548: static int
549: t2isakmpsa(trns, sa)
550: struct isakmp_pl_t *trns;
551: struct isakmpsa *sa;
552: {
553: struct isakmp_data *d, *prev;
554: int flag, type;
555: int error = -1;
556: int life_t;
557: int keylen = 0;
558: vchar_t *val = NULL;
559: int len, tlen;
560: u_char *p;
561:
562: tlen = ntohs(trns->h.len) - sizeof(*trns);
563: prev = (struct isakmp_data *)NULL;
564: d = (struct isakmp_data *)(trns + 1);
565:
566: /* default */
567: life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
568: sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
569: sa->lifebyte = 0;
570: sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
571: if (!sa->dhgrp)
572: goto err;
573:
574: while (tlen > 0) {
575:
576: type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
577: flag = ntohs(d->type) & ISAKMP_GEN_MASK;
578:
579: plog(LLV_DEBUG, LOCATION, NULL,
580: "type=%s, flag=0x%04x, lorv=%s\n",
581: s_oakley_attr(type), flag,
582: s_oakley_attr_v(type, ntohs(d->lorv)));
583:
584: /* get variable-sized item */
585: switch (type) {
586: case OAKLEY_ATTR_GRP_PI:
587: case OAKLEY_ATTR_GRP_GEN_ONE:
588: case OAKLEY_ATTR_GRP_GEN_TWO:
589: case OAKLEY_ATTR_GRP_CURVE_A:
590: case OAKLEY_ATTR_GRP_CURVE_B:
591: case OAKLEY_ATTR_SA_LD:
592: case OAKLEY_ATTR_GRP_ORDER:
593: if (flag) { /*TV*/
594: len = 2;
595: p = (u_char *)&d->lorv;
596: } else { /*TLV*/
597: len = ntohs(d->lorv);
598: p = (u_char *)(d + 1);
599: }
600: val = vmalloc(len);
601: if (!val)
602: return -1;
603: memcpy(val->v, p, len);
604: break;
605:
606: default:
607: break;
608: }
609:
610: switch (type) {
611: case OAKLEY_ATTR_ENC_ALG:
612: sa->enctype = (u_int16_t)ntohs(d->lorv);
613: break;
614:
615: case OAKLEY_ATTR_HASH_ALG:
616: sa->hashtype = (u_int16_t)ntohs(d->lorv);
617: break;
618:
619: case OAKLEY_ATTR_AUTH_METHOD:
620: sa->authmethod = ntohs(d->lorv);
621: break;
622:
623: case OAKLEY_ATTR_GRP_DESC:
624: sa->dh_group = (u_int16_t)ntohs(d->lorv);
625: break;
626:
627: case OAKLEY_ATTR_GRP_TYPE:
628: {
629: int type = (int)ntohs(d->lorv);
630: if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
631: sa->dhgrp->type = type;
632: else
633: return -1;
634: break;
635: }
636: case OAKLEY_ATTR_GRP_PI:
637: sa->dhgrp->prime = val;
638: break;
639:
640: case OAKLEY_ATTR_GRP_GEN_ONE:
641: vfree(val);
642: if (!flag)
643: sa->dhgrp->gen1 = ntohs(d->lorv);
644: else {
645: int len = ntohs(d->lorv);
646: sa->dhgrp->gen1 = 0;
647: if (len > 4)
648: return -1;
649: memcpy(&sa->dhgrp->gen1, d + 1, len);
650: sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
651: }
652: break;
653:
654: case OAKLEY_ATTR_GRP_GEN_TWO:
655: vfree(val);
656: if (!flag)
657: sa->dhgrp->gen2 = ntohs(d->lorv);
658: else {
659: int len = ntohs(d->lorv);
660: sa->dhgrp->gen2 = 0;
661: if (len > 4)
662: return -1;
663: memcpy(&sa->dhgrp->gen2, d + 1, len);
664: sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
665: }
666: break;
667:
668: case OAKLEY_ATTR_GRP_CURVE_A:
669: sa->dhgrp->curve_a = val;
670: break;
671:
672: case OAKLEY_ATTR_GRP_CURVE_B:
673: sa->dhgrp->curve_b = val;
674: break;
675:
676: case OAKLEY_ATTR_SA_LD_TYPE:
677: {
678: int type = (int)ntohs(d->lorv);
679: switch (type) {
680: case OAKLEY_ATTR_SA_LD_TYPE_SEC:
681: case OAKLEY_ATTR_SA_LD_TYPE_KB:
682: life_t = type;
683: break;
684: default:
685: life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
686: break;
687: }
688: break;
689: }
690: case OAKLEY_ATTR_SA_LD:
691: if (!prev
692: || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
693: OAKLEY_ATTR_SA_LD_TYPE) {
694: plog(LLV_ERROR, LOCATION, NULL,
695: "life duration must follow ltype\n");
696: break;
697: }
698:
699: switch (life_t) {
700: case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
701: sa->lifetime = ipsecdoi_set_ld(val);
702: vfree(val);
703: if (sa->lifetime == 0) {
704: plog(LLV_ERROR, LOCATION, NULL,
705: "invalid life duration.\n");
706: goto err;
707: }
708: break;
709: case IPSECDOI_ATTR_SA_LD_TYPE_KB:
710: sa->lifebyte = ipsecdoi_set_ld(val);
711: vfree(val);
1.2 manu 712: if (sa->lifebyte == 0) {
1.1 manu 713: plog(LLV_ERROR, LOCATION, NULL,
714: "invalid life duration.\n");
715: goto err;
716: }
717: break;
718: default:
719: vfree(val);
720: plog(LLV_ERROR, LOCATION, NULL,
721: "invalid life type: %d\n", life_t);
722: goto err;
723: }
724: break;
725:
726: case OAKLEY_ATTR_KEY_LEN:
727: {
728: int len = ntohs(d->lorv);
729: if (len % 8 != 0) {
730: plog(LLV_ERROR, LOCATION, NULL,
731: "keylen %d: not multiple of 8\n",
732: len);
733: goto err;
734: }
735: sa->encklen = (u_int16_t)len;
736: keylen++;
737: break;
738: }
739: case OAKLEY_ATTR_PRF:
740: case OAKLEY_ATTR_FIELD_SIZE:
741: /* unsupported */
742: break;
743:
744: case OAKLEY_ATTR_GRP_ORDER:
745: sa->dhgrp->order = val;
746: break;
747: #ifdef HAVE_GSSAPI
748: case OAKLEY_ATTR_GSS_ID:
749: {
1.19 manu 750: int error = -1;
1.20 dogcow 751: iconv_t cd = (iconv_t) -1;
1.1 manu 752: size_t srcleft, dstleft, rv;
1.9 manu 753: __iconv_const char *src;
1.1 manu 754: char *dst;
755: int len = ntohs(d->lorv);
756:
757: /*
758: * Older verions of racoon just placed the
759: * ISO-Latin-1 string on the wire directly.
760: * Check to see if we are configured to be
761: * compatible with this behavior.
762: */
763: if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
1.19 manu 764: if ((sa->gssid = vmalloc(len)) == NULL) {
765: plog(LLV_ERROR, LOCATION, NULL,
766: "failed to allocate memory\n");
767: goto out;
768: }
1.1 manu 769: memcpy(sa->gssid->v, d + 1, len);
770: plog(LLV_DEBUG, LOCATION, NULL,
1.19 manu 771: "received old-style gss "
772: "id '%.*s' (len %zu)\n",
773: (int)sa->gssid->l, sa->gssid->v,
774: sa->gssid->l);
775: error = 0;
776: goto out;
1.1 manu 777: }
778:
779: /*
780: * For Windows 2000 compatibility, we expect
781: * the GSS ID attribute on the wire to be
782: * encoded in UTF-16LE. Internally, we work
783: * in ISO-Latin-1. Therefore, we should need
784: * 1/2 the specified length, which should always
785: * be a multiple of 2 octets.
786: */
787: cd = iconv_open("latin1", "utf-16le");
788: if (cd == (iconv_t) -1) {
789: plog(LLV_ERROR, LOCATION, NULL,
790: "unable to initialize utf-16le -> latin1 "
791: "conversion descriptor: %s\n",
792: strerror(errno));
1.19 manu 793: goto out;
1.1 manu 794: }
795:
1.19 manu 796: if ((sa->gssid = vmalloc(len / 2)) == NULL) {
797: plog(LLV_ERROR, LOCATION, NULL,
798: "failed to allocate memory\n");
799: goto out;
800: }
1.1 manu 801:
1.11 manu 802: src = (__iconv_const char *)(d + 1);
1.1 manu 803: srcleft = len;
804:
805: dst = sa->gssid->v;
806: dstleft = len / 2;
807:
1.9 manu 808: rv = iconv(cd, (__iconv_const char **)&src, &srcleft,
809: &dst, &dstleft);
1.1 manu 810: if (rv != 0) {
811: if (rv == -1) {
812: plog(LLV_ERROR, LOCATION, NULL,
813: "unable to convert GSS ID from "
814: "utf-16le -> latin1: %s\n",
815: strerror(errno));
816: } else {
817: plog(LLV_ERROR, LOCATION, NULL,
818: "%zd character%s in GSS ID cannot "
819: "be represented in latin1\n",
820: rv, rv == 1 ? "" : "s");
821: }
1.19 manu 822: goto out;
1.1 manu 823: }
824:
825: /* XXX dstleft should always be 0; assert it? */
826: sa->gssid->l = (len / 2) - dstleft;
827:
828: plog(LLV_DEBUG, LOCATION, NULL,
1.13 manu 829: "received gss id '%.*s' (len %zu)\n",
830: (int)sa->gssid->l, sa->gssid->v, sa->gssid->l);
1.19 manu 831:
832: error = 0;
833: out:
834: if (cd != (iconv_t)-1)
835: (void)iconv_close(cd);
836:
837: if ((error != 0) && (sa->gssid != NULL)) {
838: vfree(sa->gssid);
839: sa->gssid = NULL;
840: }
1.1 manu 841: break;
842: }
843: #endif /* HAVE_GSSAPI */
844:
845: default:
846: break;
847: }
848:
849: prev = d;
850: if (flag) {
851: tlen -= sizeof(*d);
852: d = (struct isakmp_data *)((char *)d + sizeof(*d));
853: } else {
854: tlen -= (sizeof(*d) + ntohs(d->lorv));
855: d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
856: }
857: }
858:
859: /* key length must not be specified on some algorithms */
860: if (keylen) {
861: if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
862: #ifdef HAVE_OPENSSL_IDEA_H
863: || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
864: #endif
865: || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
866: plog(LLV_ERROR, LOCATION, NULL,
867: "keylen must not be specified "
868: "for encryption algorithm %d\n",
869: sa->enctype);
870: return -1;
871: }
872: }
873:
874: return 0;
875: err:
876: return error;
877: }
878:
879: /*%%%*/
880: /*
881: * check phase 2 SA payload and select single proposal.
882: * make new SA payload to be replyed not including general header.
883: * This function is called by responder only.
884: * OUT:
885: * 0: succeed.
886: * -1: error occured.
887: */
888: int
889: ipsecdoi_selectph2proposal(iph2)
890: struct ph2handle *iph2;
891: {
892: struct prop_pair **pair;
893: struct prop_pair *ret;
894:
895: /* get proposal pair */
896: pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
897: if (pair == NULL)
898: return -1;
899:
900: /* check and select a proposal. */
901: ret = get_ph2approval(iph2, pair);
902: free_proppair(pair);
903: if (ret == NULL)
904: return -1;
905:
906: /* make a SA to be replayed. */
907: /* SPI must be updated later. */
908: iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
909: free_proppair0(ret);
910: if (iph2->sa_ret == NULL)
911: return -1;
912:
913: return 0;
914: }
915:
916: /*
917: * check phase 2 SA payload returned from responder.
918: * This function is called by initiator only.
919: * OUT:
920: * 0: valid.
921: * -1: invalid.
922: */
923: int
924: ipsecdoi_checkph2proposal(iph2)
925: struct ph2handle *iph2;
926: {
927: struct prop_pair **rpair = NULL, **spair = NULL;
928: struct prop_pair *p;
929: int i, n, num;
930: int error = -1;
931: vchar_t *sa_ret = NULL;
932:
933: /* get proposal pair of SA sent. */
934: spair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
935: if (spair == NULL) {
936: plog(LLV_ERROR, LOCATION, NULL,
937: "failed to get prop pair.\n");
938: goto end;
939: }
940:
941: /* XXX should check the number of transform */
942:
943: /* get proposal pair of SA replayed */
944: rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
945: if (rpair == NULL) {
946: plog(LLV_ERROR, LOCATION, NULL,
947: "failed to get prop pair.\n");
948: goto end;
949: }
950:
951: /* check proposal is only one ? */
952: n = 0;
953: num = 0;
954: for (i = 0; i < MAXPROPPAIRLEN; i++) {
955: if (rpair[i]) {
956: n = i;
957: num++;
958: }
959: }
960: if (num == 0) {
961: plog(LLV_ERROR, LOCATION, NULL,
962: "no proposal received.\n");
963: goto end;
964: }
965: if (num != 1) {
966: plog(LLV_ERROR, LOCATION, NULL,
967: "some proposals received.\n");
968: goto end;
969: }
970:
971: if (spair[n] == NULL) {
972: plog(LLV_WARNING, LOCATION, NULL,
973: "invalid proposal number:%d received.\n", i);
974: }
975:
976:
977: if (rpair[n]->tnext != NULL) {
978: plog(LLV_ERROR, LOCATION, NULL,
979: "multi transforms replyed.\n");
980: goto end;
981: }
982:
983: if (cmp_aproppair_i(rpair[n], spair[n])) {
984: plog(LLV_ERROR, LOCATION, NULL,
985: "proposal mismathed.\n");
986: goto end;
987: }
988:
989: /*
990: * check and select a proposal.
991: * ensure that there is no modification of the proposal by
992: * cmp_aproppair_i()
993: */
994: p = get_ph2approval(iph2, rpair);
995: if (p == NULL)
996: goto end;
997:
998: /* make a SA to be replayed. */
999: sa_ret = iph2->sa_ret;
1000: iph2->sa_ret = get_sabyproppair(p, iph2->ph1);
1001: free_proppair0(p);
1002: if (iph2->sa_ret == NULL)
1003: goto end;
1004:
1005: error = 0;
1006:
1007: end:
1008: if (rpair)
1009: free_proppair(rpair);
1010: if (spair)
1011: free_proppair(spair);
1012: if (sa_ret)
1013: vfree(sa_ret);
1014:
1015: return error;
1016: }
1017:
1018: /*
1019: * compare two prop_pair which is assumed to have same proposal number.
1020: * the case of bundle or single SA, NOT multi transforms.
1021: * a: a proposal that is multi protocols and single transform, usually replyed.
1022: * b: a proposal that is multi protocols and multi transform, usually sent.
1023: * NOTE: this function is for initiator.
1024: * OUT
1025: * 0: equal
1026: * 1: not equal
1027: * XXX cannot understand the comment!
1028: */
1029: static int
1030: cmp_aproppair_i(a, b)
1031: struct prop_pair *a, *b;
1032: {
1033: struct prop_pair *p, *q, *r;
1034: int len;
1035:
1036: for (p = a, q = b; p && q; p = p->next, q = q->next) {
1037: for (r = q; r; r = r->tnext) {
1038: /* compare trns */
1039: if (p->trns->t_no == r->trns->t_no)
1040: break;
1041: }
1042: if (!r) {
1043: /* no suitable transform found */
1044: plog(LLV_ERROR, LOCATION, NULL,
1045: "no suitable transform found.\n");
1046: return -1;
1047: }
1048:
1049: /* compare prop */
1050: if (p->prop->p_no != r->prop->p_no) {
1051: plog(LLV_WARNING, LOCATION, NULL,
1052: "proposal #%d mismatched, "
1053: "expected #%d.\n",
1054: r->prop->p_no, p->prop->p_no);
1055: /*FALLTHROUGH*/
1056: }
1057:
1058: if (p->prop->proto_id != r->prop->proto_id) {
1059: plog(LLV_ERROR, LOCATION, NULL,
1060: "proto_id mismathed: my:%d peer:%d\n",
1061: r->prop->proto_id, p->prop->proto_id);
1062: return -1;
1063: }
1064:
1.22.2.3! jdc 1065: if (p->prop->spi_size != r->prop->spi_size) {
1.1 manu 1066: plog(LLV_ERROR, LOCATION, NULL,
1067: "invalid spi size: %d.\n",
1.22.2.3! jdc 1068: p->prop->spi_size);
1.1 manu 1069: return -1;
1070: }
1071:
1072: /* check #of transforms */
1073: if (p->prop->num_t != 1) {
1074: plog(LLV_WARNING, LOCATION, NULL,
1075: "#of transform is %d, "
1076: "but expected 1.\n", p->prop->num_t);
1077: /*FALLTHROUGH*/
1078: }
1079:
1080: if (p->trns->t_id != r->trns->t_id) {
1081: plog(LLV_WARNING, LOCATION, NULL,
1082: "transform number has been modified.\n");
1083: /*FALLTHROUGH*/
1084: }
1085: if (p->trns->reserved != r->trns->reserved) {
1086: plog(LLV_WARNING, LOCATION, NULL,
1087: "reserved field should be zero.\n");
1088: /*FALLTHROUGH*/
1089: }
1090:
1091: /* compare attribute */
1092: len = ntohs(r->trns->h.len) - sizeof(*p->trns);
1093: if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
1094: plog(LLV_WARNING, LOCATION, NULL,
1095: "attribute has been modified.\n");
1096: /*FALLTHROUGH*/
1097: }
1098: }
1099: if ((p && !q) || (!p && q)) {
1100: /* # of protocols mismatched */
1101: plog(LLV_ERROR, LOCATION, NULL,
1102: "#of protocols mismatched.\n");
1103: return -1;
1104: }
1105:
1106: return 0;
1107: }
1108:
1109: /*
1110: * acceptable check for policy configuration.
1111: * return a new SA payload to be reply to peer.
1112: */
1113: static struct prop_pair *
1114: get_ph2approval(iph2, pair)
1115: struct ph2handle *iph2;
1116: struct prop_pair **pair;
1117: {
1118: struct prop_pair *ret;
1119: int i;
1120:
1121: iph2->approval = NULL;
1122:
1123: plog(LLV_DEBUG, LOCATION, NULL,
1124: "begin compare proposals.\n");
1125:
1126: for (i = 0; i < MAXPROPPAIRLEN; i++) {
1127: if (pair[i] == NULL)
1128: continue;
1129: plog(LLV_DEBUG, LOCATION, NULL,
1130: "pair[%d]: %p\n", i, pair[i]);
1131: print_proppair(LLV_DEBUG, pair[i]);;
1132:
1133: /* compare proposal and select one */
1134: ret = get_ph2approvalx(iph2, pair[i]);
1135: if (ret != NULL) {
1136: /* found */
1137: return ret;
1138: }
1139: }
1140:
1141: plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n");
1142:
1143: return NULL;
1144: }
1145:
1146: /*
1147: * compare my proposal and peers just one proposal.
1148: * set a approval.
1149: */
1150: static struct prop_pair *
1151: get_ph2approvalx(iph2, pp)
1152: struct ph2handle *iph2;
1153: struct prop_pair *pp;
1154: {
1155: struct prop_pair *ret = NULL;
1156: struct saprop *pr0, *pr = NULL;
1157: struct saprop *q1, *q2;
1158:
1159: pr0 = aproppair2saprop(pp);
1160: if (pr0 == NULL)
1161: return NULL;
1162:
1163: for (q1 = pr0; q1; q1 = q1->next) {
1164: for (q2 = iph2->proposal; q2; q2 = q2->next) {
1165: plog(LLV_DEBUG, LOCATION, NULL,
1166: "peer's single bundle:\n");
1167: printsaprop0(LLV_DEBUG, q1);
1168: plog(LLV_DEBUG, LOCATION, NULL,
1169: "my single bundle:\n");
1170: printsaprop0(LLV_DEBUG, q2);
1171:
1172: pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
1173: if (pr != NULL)
1174: goto found;
1175:
1176: plog(LLV_ERROR, LOCATION, NULL,
1177: "not matched\n");
1178: }
1179: }
1180: /* no proposal matching */
1181: err:
1182: flushsaprop(pr0);
1183: return NULL;
1184:
1185: found:
1186: flushsaprop(pr0);
1187: plog(LLV_DEBUG, LOCATION, NULL, "matched\n");
1188: iph2->approval = pr;
1189:
1190: {
1191: struct saproto *sp;
1.13 manu 1192: struct prop_pair *p, *x;
1193: struct prop_pair *n = NULL;
1.1 manu 1194:
1195: ret = NULL;
1196:
1197: for (p = pp; p; p = p->next) {
1198: /*
1199: * find a proposal with matching proto_id.
1200: * we have analyzed validity already, in cmpsaprop_alloc().
1201: */
1202: for (sp = pr->head; sp; sp = sp->next) {
1203: if (sp->proto_id == p->prop->proto_id)
1204: break;
1205: }
1206: if (!sp)
1207: goto err;
1208: if (sp->head->next)
1209: goto err; /* XXX */
1210:
1211: for (x = p; x; x = x->tnext)
1212: if (sp->head->trns_no == x->trns->t_no)
1213: break;
1214: if (!x)
1215: goto err; /* XXX */
1216:
1217: n = racoon_calloc(1, sizeof(struct prop_pair));
1.13 manu 1218: if (n == NULL) {
1.1 manu 1219: plog(LLV_ERROR, LOCATION, NULL,
1220: "failed to get buffer.\n");
1221: goto err;
1222: }
1223:
1224: n->prop = x->prop;
1225: n->trns = x->trns;
1226:
1227: /* need to preserve the order */
1228: for (x = ret; x && x->next; x = x->next)
1229: ;
1230: if (x && x->prop == n->prop) {
1231: for (/*nothing*/; x && x->tnext; x = x->tnext)
1232: ;
1233: x->tnext = n;
1234: } else {
1235: if (x)
1236: x->next = n;
1237: else {
1238: ret = n;
1239: }
1240: }
1241:
1242: /* #of transforms should be updated ? */
1243: }
1244: }
1245:
1246: return ret;
1247: }
1248:
1249: void
1250: free_proppair(pair)
1251: struct prop_pair **pair;
1252: {
1253: int i;
1254:
1255: for (i = 0; i < MAXPROPPAIRLEN; i++) {
1256: free_proppair0(pair[i]);
1257: pair[i] = NULL;
1258: }
1259: racoon_free(pair);
1260: }
1261:
1262: static void
1263: free_proppair0(pair)
1264: struct prop_pair *pair;
1265: {
1266: struct prop_pair *p, *q, *r, *s;
1267:
1268: p = pair;
1269: while (p) {
1270: q = p->next;
1271: r = p;
1272: while (r) {
1273: s = r->tnext;
1274: racoon_free(r);
1275: r = s;
1276: }
1277: p = q;
1278: }
1279: }
1280:
1281: /*
1282: * get proposal pairs from SA payload.
1283: * tiny check for proposal payload.
1284: */
1285: struct prop_pair **
1286: get_proppair(sa, mode)
1287: vchar_t *sa;
1288: int mode;
1289: {
1.13 manu 1290: struct prop_pair **pair = NULL;
1.1 manu 1291: int num_p = 0; /* number of proposal for use */
1292: int tlen;
1293: caddr_t bp;
1294: int i;
1295: struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
1296:
1297: plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l);
1298: plogdump(LLV_DEBUG, sa->v, sa->l);
1299:
1300: /* check SA payload size */
1301: if (sa->l < sizeof(*sab)) {
1302: plog(LLV_ERROR, LOCATION, NULL,
1303: "Invalid SA length = %zu.\n", sa->l);
1.13 manu 1304: goto bad;
1.1 manu 1305: }
1306:
1307: /* check DOI */
1308: if (check_doi(ntohl(sab->doi)) < 0)
1.13 manu 1309: goto bad;
1.1 manu 1310:
1311: /* check SITUATION */
1312: if (check_situation(ntohl(sab->sit)) < 0)
1.13 manu 1313: goto bad;
1.1 manu 1314:
1315: pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
1316: if (pair == NULL) {
1317: plog(LLV_ERROR, LOCATION, NULL,
1318: "failed to get buffer.\n");
1.13 manu 1319: goto bad;
1.1 manu 1320: }
1321: memset(pair, 0, sizeof(pair));
1322:
1323: bp = (caddr_t)(sab + 1);
1324: tlen = sa->l - sizeof(*sab);
1325:
1326: {
1327: struct isakmp_pl_p *prop;
1328: int proplen;
1329: vchar_t *pbuf = NULL;
1330: struct isakmp_parse_t *pa;
1331:
1332: pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
1333: if (pbuf == NULL)
1.13 manu 1334: goto bad;
1.1 manu 1335:
1336: for (pa = (struct isakmp_parse_t *)pbuf->v;
1337: pa->type != ISAKMP_NPTYPE_NONE;
1338: pa++) {
1339: /* check the value of next payload */
1340: if (pa->type != ISAKMP_NPTYPE_P) {
1341: plog(LLV_ERROR, LOCATION, NULL,
1342: "Invalid payload type=%u\n", pa->type);
1343: vfree(pbuf);
1.13 manu 1344: goto bad;
1.1 manu 1345: }
1346:
1347: prop = (struct isakmp_pl_p *)pa->ptr;
1348: proplen = pa->len;
1349:
1350: plog(LLV_DEBUG, LOCATION, NULL,
1351: "proposal #%u len=%d\n", prop->p_no, proplen);
1352:
1353: if (proplen == 0) {
1354: plog(LLV_ERROR, LOCATION, NULL,
1355: "invalid proposal with length %d\n", proplen);
1356: vfree(pbuf);
1.13 manu 1357: goto bad;
1.1 manu 1358: }
1359:
1360: /* check Protocol ID */
1361: if (!check_protocol[mode]) {
1362: plog(LLV_ERROR, LOCATION, NULL,
1363: "unsupported mode %d\n", mode);
1364: continue;
1365: }
1366:
1367: if (check_protocol[mode](prop->proto_id) < 0)
1368: continue;
1369:
1370: /* check SPI length when IKE. */
1371: if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
1372: continue;
1373:
1374: /* get transform */
1375: if (get_transform(prop, pair, &num_p) < 0) {
1376: vfree(pbuf);
1.13 manu 1377: goto bad;
1.1 manu 1378: }
1379: }
1380: vfree(pbuf);
1381: pbuf = NULL;
1382: }
1383:
1384: {
1385: int notrans, nprop;
1386: struct prop_pair *p, *q;
1387:
1388: /* check for proposals with no transforms */
1389: for (i = 0; i < MAXPROPPAIRLEN; i++) {
1390: if (!pair[i])
1391: continue;
1392:
1393: plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
1394: print_proppair(LLV_DEBUG, pair[i]);
1395:
1396: notrans = nprop = 0;
1397: for (p = pair[i]; p; p = p->next) {
1398: if (p->trns == NULL) {
1399: notrans++;
1400: break;
1401: }
1402: for (q = p; q; q = q->tnext)
1403: nprop++;
1404: }
1405:
1406: #if 0
1407: /*
1408: * XXX at this moment, we cannot accept proposal group
1409: * with multiple proposals. this should be fixed.
1410: */
1411: if (pair[i]->next) {
1412: plog(LLV_WARNING, LOCATION, NULL,
1413: "proposal #%u ignored "
1414: "(multiple proposal not supported)\n",
1415: pair[i]->prop->p_no);
1416: notrans++;
1417: }
1418: #endif
1419:
1420: if (notrans) {
1421: for (p = pair[i]; p; p = q) {
1422: q = p->next;
1423: racoon_free(p);
1424: }
1425: pair[i] = NULL;
1426: num_p--;
1427: } else {
1428: plog(LLV_DEBUG, LOCATION, NULL,
1429: "proposal #%u: %d transform\n",
1430: pair[i]->prop->p_no, nprop);
1431: }
1432: }
1433: }
1434:
1435: /* bark if no proposal is found. */
1436: if (num_p <= 0) {
1437: plog(LLV_ERROR, LOCATION, NULL,
1438: "no Proposal found.\n");
1.13 manu 1439: goto bad;
1.1 manu 1440: }
1441:
1442: return pair;
1.13 manu 1443: bad:
1444: if (pair != NULL)
1445: racoon_free(pair);
1446: return NULL;
1.1 manu 1447: }
1448:
1449: /*
1450: * check transform payload.
1451: * OUT:
1452: * positive: return the pointer to the payload of valid transform.
1453: * 0 : No valid transform found.
1454: */
1455: static int
1456: get_transform(prop, pair, num_p)
1457: struct isakmp_pl_p *prop;
1458: struct prop_pair **pair;
1459: int *num_p;
1460: {
1461: int tlen; /* total length of all transform in a proposal */
1462: caddr_t bp;
1463: struct isakmp_pl_t *trns;
1464: int trnslen;
1465: vchar_t *pbuf = NULL;
1466: struct isakmp_parse_t *pa;
1467: struct prop_pair *p = NULL, *q;
1468: int num_t;
1469:
1470: bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
1471: tlen = ntohs(prop->h.len)
1472: - (sizeof(struct isakmp_pl_p) + prop->spi_size);
1473: pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
1474: if (pbuf == NULL)
1475: return -1;
1476:
1477: /* check and get transform for use */
1478: num_t = 0;
1479: for (pa = (struct isakmp_parse_t *)pbuf->v;
1480: pa->type != ISAKMP_NPTYPE_NONE;
1481: pa++) {
1482:
1483: num_t++;
1484:
1485: /* check the value of next payload */
1486: if (pa->type != ISAKMP_NPTYPE_T) {
1487: plog(LLV_ERROR, LOCATION, NULL,
1488: "Invalid payload type=%u\n", pa->type);
1489: break;
1490: }
1491:
1492: trns = (struct isakmp_pl_t *)pa->ptr;
1493: trnslen = pa->len;
1494:
1495: plog(LLV_DEBUG, LOCATION, NULL,
1496: "transform #%u len=%u\n", trns->t_no, trnslen);
1497:
1498: /* check transform ID */
1499: if (prop->proto_id >= ARRAYLEN(check_transform)) {
1500: plog(LLV_WARNING, LOCATION, NULL,
1501: "unsupported proto_id %u\n",
1502: prop->proto_id);
1503: continue;
1504: }
1505: if (prop->proto_id >= ARRAYLEN(check_attributes)) {
1506: plog(LLV_WARNING, LOCATION, NULL,
1507: "unsupported proto_id %u\n",
1508: prop->proto_id);
1509: continue;
1510: }
1511:
1512: if (!check_transform[prop->proto_id]
1513: || !check_attributes[prop->proto_id]) {
1514: plog(LLV_WARNING, LOCATION, NULL,
1515: "unsupported proto_id %u\n",
1516: prop->proto_id);
1517: continue;
1518: }
1519: if (check_transform[prop->proto_id](trns->t_id) < 0)
1520: continue;
1521:
1522: /* check data attributes */
1523: if (check_attributes[prop->proto_id](trns) != 0)
1524: continue;
1525:
1526: p = racoon_calloc(1, sizeof(*p));
1527: if (p == NULL) {
1528: plog(LLV_ERROR, LOCATION, NULL,
1529: "failed to get buffer.\n");
1530: vfree(pbuf);
1531: return -1;
1532: }
1533: p->prop = prop;
1534: p->trns = trns;
1535:
1536: /* need to preserve the order */
1537: for (q = pair[prop->p_no]; q && q->next; q = q->next)
1538: ;
1539: if (q && q->prop == p->prop) {
1540: for (/*nothing*/; q && q->tnext; q = q->tnext)
1541: ;
1542: q->tnext = p;
1543: } else {
1544: if (q)
1545: q->next = p;
1546: else {
1547: pair[prop->p_no] = p;
1548: (*num_p)++;
1549: }
1550: }
1551: }
1552:
1553: vfree(pbuf);
1554:
1555: return 0;
1556: }
1557:
1558: /*
1559: * make a new SA payload from prop_pair.
1560: * NOTE: this function make spi value clear.
1561: */
1562: vchar_t *
1563: get_sabyproppair(pair, iph1)
1564: struct prop_pair *pair;
1565: struct ph1handle *iph1;
1566: {
1567: vchar_t *newsa;
1568: int newtlen;
1569: u_int8_t *np_p = NULL;
1570: struct prop_pair *p;
1571: int prophlen, trnslen;
1572: caddr_t bp;
1573:
1574: newtlen = sizeof(struct ipsecdoi_sa_b);
1575: for (p = pair; p; p = p->next) {
1576: newtlen += sizeof(struct isakmp_pl_p);
1577: newtlen += p->prop->spi_size;
1578: newtlen += ntohs(p->trns->h.len);
1579: }
1580:
1581: newsa = vmalloc(newtlen);
1582: if (newsa == NULL) {
1583: plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1584: return NULL;
1585: }
1586: bp = newsa->v;
1587:
1588: ((struct isakmp_gen *)bp)->len = htons(newtlen);
1589:
1590: /* update some of values in SA header */
1591: ((struct ipsecdoi_sa_b *)bp)->doi = htonl(iph1->rmconf->doitype);
1592: ((struct ipsecdoi_sa_b *)bp)->sit = htonl(iph1->rmconf->sittype);
1593: bp += sizeof(struct ipsecdoi_sa_b);
1594:
1595: /* create proposal payloads */
1596: for (p = pair; p; p = p->next) {
1597: prophlen = sizeof(struct isakmp_pl_p)
1598: + p->prop->spi_size;
1599: trnslen = ntohs(p->trns->h.len);
1600:
1601: if (np_p)
1602: *np_p = ISAKMP_NPTYPE_P;
1603:
1604: /* create proposal */
1605:
1606: memcpy(bp, p->prop, prophlen);
1607: ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1608: ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1609: ((struct isakmp_pl_p *)bp)->num_t = 1;
1610: np_p = &((struct isakmp_pl_p *)bp)->h.np;
1611: memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
1612: bp += prophlen;
1613:
1614: /* create transform */
1615: memcpy(bp, p->trns, trnslen);
1616: ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1617: ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1618: bp += trnslen;
1619: }
1620:
1621: return newsa;
1622: }
1623:
1624: /*
1625: * update responder's spi
1626: */
1627: int
1628: ipsecdoi_updatespi(iph2)
1629: struct ph2handle *iph2;
1630: {
1631: struct prop_pair **pair, *p;
1632: struct saprop *pp;
1633: struct saproto *pr;
1634: int i;
1635: int error = -1;
1636: u_int8_t *spi;
1637:
1638: pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
1639: if (pair == NULL)
1640: return -1;
1641: for (i = 0; i < MAXPROPPAIRLEN; i++) {
1642: if (pair[i])
1643: break;
1644: }
1645: if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
1646: /* multiple transform must be filtered by selectph2proposal.*/
1647: goto end;
1648: }
1649:
1650: pp = iph2->approval;
1651:
1652: /* create proposal payloads */
1653: for (p = pair[i]; p; p = p->next) {
1654: /*
1655: * find a proposal/transform with matching proto_id/t_id.
1656: * we have analyzed validity already, in cmpsaprop_alloc().
1657: */
1658: for (pr = pp->head; pr; pr = pr->next) {
1659: if (p->prop->proto_id == pr->proto_id &&
1660: p->trns->t_id == pr->head->trns_id) {
1661: break;
1662: }
1663: }
1664: if (!pr)
1665: goto end;
1666:
1667: /*
1668: * XXX SPI bits are left-filled, for use with IPComp.
1669: * we should be switching to variable-length spi field...
1670: */
1671: spi = (u_int8_t *)&pr->spi;
1672: spi += sizeof(pr->spi);
1673: spi -= pr->spisize;
1674: memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
1675: }
1676:
1677: error = 0;
1678: end:
1679: free_proppair(pair);
1680: return error;
1681: }
1682:
1683: /*
1684: * make a new SA payload from prop_pair.
1685: */
1686: vchar_t *
1687: get_sabysaprop(pp0, sa0)
1688: struct saprop *pp0;
1689: vchar_t *sa0;
1690: {
1.13 manu 1691: struct prop_pair **pair = NULL;
1692: vchar_t *newsa = NULL;
1.1 manu 1693: int newtlen;
1694: u_int8_t *np_p = NULL;
1695: struct prop_pair *p = NULL;
1696: struct saprop *pp;
1697: struct saproto *pr;
1698: struct satrns *tr;
1699: int prophlen, trnslen;
1700: caddr_t bp;
1.18 manu 1701: int error = -1;
1.1 manu 1702:
1703: /* get proposal pair */
1704: pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
1705: if (pair == NULL)
1.18 manu 1706: goto out;
1.1 manu 1707:
1708: newtlen = sizeof(struct ipsecdoi_sa_b);
1709: for (pp = pp0; pp; pp = pp->next) {
1710:
1711: if (pair[pp->prop_no] == NULL)
1.18 manu 1712: goto out;
1.1 manu 1713:
1714: for (pr = pp->head; pr; pr = pr->next) {
1715: newtlen += (sizeof(struct isakmp_pl_p)
1716: + pr->spisize);
1717:
1718: for (tr = pr->head; tr; tr = tr->next) {
1719: for (p = pair[pp->prop_no]; p; p = p->tnext) {
1720: if (tr->trns_no == p->trns->t_no)
1721: break;
1722: }
1723: if (p == NULL)
1.18 manu 1724: goto out;
1.1 manu 1725:
1726: newtlen += ntohs(p->trns->h.len);
1727: }
1728: }
1729: }
1730:
1731: newsa = vmalloc(newtlen);
1732: if (newsa == NULL) {
1733: plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
1.18 manu 1734: goto out;
1.1 manu 1735: }
1736: bp = newsa->v;
1737:
1738: /* some of values of SA must be updated in the out of this function */
1739: ((struct isakmp_gen *)bp)->len = htons(newtlen);
1740: bp += sizeof(struct ipsecdoi_sa_b);
1741:
1742: /* create proposal payloads */
1743: for (pp = pp0; pp; pp = pp->next) {
1744:
1745: for (pr = pp->head; pr; pr = pr->next) {
1746: prophlen = sizeof(struct isakmp_pl_p)
1747: + p->prop->spi_size;
1748:
1749: for (tr = pr->head; tr; tr = tr->next) {
1750: for (p = pair[pp->prop_no]; p; p = p->tnext) {
1751: if (tr->trns_no == p->trns->t_no)
1752: break;
1753: }
1754: if (p == NULL)
1.18 manu 1755: goto out;
1.1 manu 1756:
1757: trnslen = ntohs(p->trns->h.len);
1758:
1759: if (np_p)
1760: *np_p = ISAKMP_NPTYPE_P;
1761:
1762: /* create proposal */
1763:
1764: memcpy(bp, p->prop, prophlen);
1765: ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1766: ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
1767: ((struct isakmp_pl_p *)bp)->num_t = 1;
1768: np_p = &((struct isakmp_pl_p *)bp)->h.np;
1769: bp += prophlen;
1770:
1771: /* create transform */
1772: memcpy(bp, p->trns, trnslen);
1773: ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
1774: ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
1775: bp += trnslen;
1776: }
1777: }
1778: }
1779:
1.18 manu 1780: error = 0;
1781: out:
1.13 manu 1782: if (pair != NULL)
1783: racoon_free(pair);
1.18 manu 1784:
1785: if (error != 0) {
1786: if (newsa != NULL) {
1787: vfree(newsa);
1788: newsa = NULL;
1789: }
1790: }
1791:
1792: return newsa;
1.1 manu 1793: }
1794:
1795: /*
1796: * If some error happens then return 0. Although 0 means that lifetime is zero,
1797: * such a value should not be accepted.
1798: * Also 0 of lifebyte should not be included in a packet although 0 means not
1799: * to care of it.
1800: */
1801: static u_int32_t
1802: ipsecdoi_set_ld(buf)
1803: vchar_t *buf;
1804: {
1805: u_int32_t ld;
1806:
1807: if (buf == 0)
1808: return 0;
1809:
1810: switch (buf->l) {
1811: case 2:
1812: ld = ntohs(*(u_int16_t *)buf->v);
1813: break;
1814: case 4:
1815: ld = ntohl(*(u_int32_t *)buf->v);
1816: break;
1817: default:
1818: plog(LLV_ERROR, LOCATION, NULL,
1819: "length %zu of life duration "
1820: "isn't supported.\n", buf->l);
1821: return 0;
1822: }
1823:
1824: return ld;
1825: }
1826:
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.22.2.1 jdc 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.22.2.1 jdc 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.22.2.1 jdc 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.22.2.1 jdc 3121: #ifdef HAVE_SECCTX
3122: if (*pp->sctx.ctx_str) {
3123: struct security_ctx secctx;
3124: secctx = pp->sctx;
3125: secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
3126: x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
3127: (caddr_t)&secctx, truectxlen);
3128: }
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) {
3240: if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
3241: return 0;
3242: }
3243: }
3244:
3245: return 1;
3246: }
3247:
3248: int
3249: ipsecdoi_get_defaultlifetime()
3250: {
3251: return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
3252: }
3253:
3254: int
3255: ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
3256: int proto_id, enc, auth, comp;
3257: {
3258: #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
3259: switch (proto_id) {
3260: case IPSECDOI_PROTO_IPSEC_ESP:
3261: if (enc == 0 || comp != 0) {
3262: plog(LLV_ERROR, LOCATION, NULL,
3263: "illegal algorithm defined "
3264: "ESP enc=%s auth=%s comp=%s.\n",
3265: TMPALGTYPE2STR(enc),
3266: TMPALGTYPE2STR(auth),
3267: TMPALGTYPE2STR(comp));
3268: return -1;
3269: }
3270: break;
3271: case IPSECDOI_PROTO_IPSEC_AH:
3272: if (enc != 0 || auth == 0 || comp != 0) {
3273: plog(LLV_ERROR, LOCATION, NULL,
3274: "illegal algorithm defined "
3275: "AH enc=%s auth=%s comp=%s.\n",
3276: TMPALGTYPE2STR(enc),
3277: TMPALGTYPE2STR(auth),
3278: TMPALGTYPE2STR(comp));
3279: return -1;
3280: }
3281: break;
3282: case IPSECDOI_PROTO_IPCOMP:
3283: if (enc != 0 || auth != 0 || comp == 0) {
3284: plog(LLV_ERROR, LOCATION, NULL,
3285: "illegal algorithm defined "
3286: "IPcomp enc=%s auth=%s comp=%s.\n",
3287: TMPALGTYPE2STR(enc),
3288: TMPALGTYPE2STR(auth),
3289: TMPALGTYPE2STR(comp));
3290: return -1;
3291: }
3292: break;
3293: default:
3294: plog(LLV_ERROR, LOCATION, NULL,
3295: "invalid ipsec protocol %d\n", proto_id);
3296: return -1;
3297: }
3298: #undef TMPALGTYPE2STR
3299: return 0;
3300: }
3301:
3302: int
3303: ipproto2doi(proto)
3304: int proto;
3305: {
3306: switch (proto) {
3307: case IPPROTO_AH:
3308: return IPSECDOI_PROTO_IPSEC_AH;
3309: case IPPROTO_ESP:
3310: return IPSECDOI_PROTO_IPSEC_ESP;
3311: case IPPROTO_IPCOMP:
3312: return IPSECDOI_PROTO_IPCOMP;
3313: }
3314: return -1; /* XXX */
3315: }
3316:
3317: int
3318: doi2ipproto(proto)
3319: int proto;
3320: {
3321: switch (proto) {
3322: case IPSECDOI_PROTO_IPSEC_AH:
3323: return IPPROTO_AH;
3324: case IPSECDOI_PROTO_IPSEC_ESP:
3325: return IPPROTO_ESP;
3326: case IPSECDOI_PROTO_IPCOMP:
3327: return IPPROTO_IPCOMP;
3328: }
3329: return -1; /* XXX */
3330: }
3331:
3332: /*
1.22.2.1 jdc 3333: * Check if a subnet id is valid for comparison
3334: * with an address id ( address length mask )
3335: * and compare them
3336: * Return value
3337: * = 0 for match
3338: * = 1 for mismatch
3339: */
3340:
3341: int
3342: ipsecdoi_subnetisaddr_v4( subnet, address )
3343: const vchar_t *subnet;
3344: const vchar_t *address;
3345: {
3346: struct in_addr *mask;
3347:
3348: if (address->l != sizeof(struct in_addr))
3349: return 1;
3350:
3351: if (subnet->l != (sizeof(struct in_addr)*2))
3352: return 1;
3353:
3354: mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
3355:
3356: if (mask->s_addr!=0xffffffff)
3357: return 1;
3358:
3359: return memcmp(subnet->v,address->v,address->l);
3360: }
3361:
3362: #ifdef INET6
3363:
3364: int
3365: ipsecdoi_subnetisaddr_v6( subnet, address )
3366: const vchar_t *subnet;
3367: const vchar_t *address;
3368: {
3369: struct in6_addr *mask;
3370: int i;
3371:
3372: if (address->l != sizeof(struct in6_addr))
3373: return 1;
3374:
3375: if (subnet->l != (sizeof(struct in6_addr)*2))
3376: return 1;
3377:
3378: mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
3379:
3380: for (i=0; i<16; i++)
3381: if(mask->s6_addr[i]!=0xff)
3382: return 1;
3383:
3384: return memcmp(subnet->v,address->v,address->l);
3385: }
3386:
3387: #endif
3388:
3389: /*
1.22 vanhu 3390: * Check and Compare two IDs
3391: * - specify 0 for exact if wildcards are allowed
3392: * Return value
3393: * = 0 for match
3394: * = 1 for misatch
3395: * = -1 for integrity error
3396: */
3397:
3398: int
3399: ipsecdoi_chkcmpids( idt, ids, exact )
3400: const vchar_t *idt; /* id cmp target */
3401: const vchar_t *ids; /* id cmp source */
3402: int exact;
3403: {
3404: struct ipsecdoi_id_b *id_bt;
3405: struct ipsecdoi_id_b *id_bs;
3406: vchar_t ident_t;
3407: vchar_t ident_s;
3408: int result;
3409:
3410: /* handle wildcard IDs */
3411:
3412: if (idt == NULL || ids == NULL)
3413: {
3414: if( !exact )
3415: {
3416: plog(LLV_DEBUG, LOCATION, NULL,
3417: "check and compare ids : values matched (ANONYMOUS)\n" );
3418: return 0;
3419: }
3420: else
3421: {
3422: plog(LLV_DEBUG, LOCATION, NULL,
3423: "check and compare ids : value mismatch (ANONYMOUS)\n" );
3424: return -1;
3425: }
3426: }
3427:
3428: /* make sure the ids are of the same type */
3429:
3430: id_bt = (struct ipsecdoi_id_b *) idt->v;
3431: id_bs = (struct ipsecdoi_id_b *) ids->v;
1.22.2.1 jdc 3432:
3433: ident_t.v = idt->v + sizeof(*id_bt);
3434: ident_t.l = idt->l - sizeof(*id_bt);
3435: ident_s.v = ids->v + sizeof(*id_bs);
3436: ident_s.l = ids->l - sizeof(*id_bs);
3437:
1.22 vanhu 3438: if (id_bs->type != id_bt->type)
3439: {
1.22.2.1 jdc 3440: /*
3441: * special exception for comparing
3442: * address to subnet id types when
3443: * the netmask is address length
3444: */
3445:
3446: if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
3447: (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
3448: result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
3449: goto cmpid_result;
3450: }
3451:
3452: if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
3453: (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
3454: result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
3455: goto cmpid_result;
3456: }
3457:
3458: #ifdef INET6
3459: if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
3460: (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
3461: result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
3462: goto cmpid_result;
3463: }
3464:
3465: if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
3466: (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
3467: result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
3468: goto cmpid_result;
3469: }
3470: #endif
1.22 vanhu 3471: plog(LLV_DEBUG, LOCATION, NULL,
3472: "check and compare ids : id type mismatch %s != %s\n",
3473: s_ipsecdoi_ident(id_bs->type),
3474: s_ipsecdoi_ident(id_bt->type));
1.22.2.1 jdc 3475:
1.22 vanhu 3476: return 1;
3477: }
3478:
1.22.2.2 liamjfoy 3479: if(id_bs->proto_id != id_bt->proto_id){
3480: plog(LLV_DEBUG, LOCATION, NULL,
3481: "check and compare ids : proto_id mismatch %d != %d\n",
3482: id_bs->proto_id, id_bt->proto_id);
3483:
3484: return 1;
3485: }
3486:
1.22 vanhu 3487: /* compare the ID data. */
3488:
3489: switch (id_bt->type) {
3490: case IPSECDOI_ID_DER_ASN1_DN:
3491: case IPSECDOI_ID_DER_ASN1_GN:
3492: /* compare asn1 ids */
3493: result = eay_cmp_asn1dn(&ident_t, &ident_s);
3494: goto cmpid_result;
3495:
3496: case IPSECDOI_ID_IPV4_ADDR:
3497: /* validate lengths */
3498: if ((ident_t.l != sizeof(struct in_addr))||
3499: (ident_s.l != sizeof(struct in_addr)))
3500: goto cmpid_invalid;
3501: break;
3502:
3503: case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3504: case IPSECDOI_ID_IPV4_ADDR_RANGE:
3505: /* validate lengths */
3506: if ((ident_t.l != (sizeof(struct in_addr)*2))||
3507: (ident_s.l != (sizeof(struct in_addr)*2)))
3508: goto cmpid_invalid;
3509: break;
3510:
3511: #ifdef INET6
3512: case IPSECDOI_ID_IPV6_ADDR:
3513: /* validate lengths */
3514: if ((ident_t.l != sizeof(struct in6_addr))||
3515: (ident_s.l != sizeof(struct in6_addr)))
3516: goto cmpid_invalid;
3517: break;
3518:
3519: case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3520: case IPSECDOI_ID_IPV6_ADDR_RANGE:
3521: /* validate lengths */
3522: if ((ident_t.l != (sizeof(struct in6_addr)*2))||
3523: (ident_s.l != (sizeof(struct in6_addr)*2)))
3524: goto cmpid_invalid;
3525: break;
3526: #endif
3527: case IPSECDOI_ID_FQDN:
3528: case IPSECDOI_ID_USER_FQDN:
3529: case IPSECDOI_ID_KEY_ID:
3530: break;
3531:
3532: default:
3533: plog(LLV_ERROR, LOCATION, NULL,
3534: "Unhandled id type %i specified for comparison\n",
3535: id_bt->type);
3536: return -1;
3537: }
3538:
3539: /* validate matching data and length */
3540: if (ident_t.l == ident_s.l)
3541: result = memcmp(ident_t.v,ident_s.v,ident_t.l);
3542: else
3543: result = 1;
3544:
3545: cmpid_result:
3546:
3547: /* debug level output */
3548: if(loglevel >= LLV_DEBUG) {
3549: char *idstrt = ipsecdoi_id2str(idt);
3550: char *idstrs = ipsecdoi_id2str(ids);
3551:
3552: if (!result)
3553: plog(LLV_DEBUG, LOCATION, NULL,
3554: "check and compare ids : values matched (%s)\n",
3555: s_ipsecdoi_ident(id_bs->type) );
3556: else
3557: plog(LLV_DEBUG, LOCATION, NULL,
3558: "check and compare ids : value mismatch (%s)\n",
3559: s_ipsecdoi_ident(id_bs->type));
3560:
3561: plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
3562: plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
3563:
3564: racoon_free(idstrs);
3565: racoon_free(idstrt);
3566: }
3567:
3568: /* return result */
3569: if( !result )
3570: return 0;
3571: else
3572: return 1;
3573:
3574: cmpid_invalid:
3575:
3576: /* id integrity error */
3577: plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
3578: s_ipsecdoi_ident(id_bs->type));
1.22.2.1 jdc 3579: plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
3580: plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
1.22 vanhu 3581:
3582: return -1;
3583: }
3584:
3585: /*
1.1 manu 3586: * check the following:
3587: * - In main mode with pre-shared key, only address type can be used.
3588: * - if proper type for phase 1 ?
3589: * - if phase 1 ID payload conformed RFC2407 4.6.2.
3590: * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
3591: * - if ID payload sent from peer is equal to the ID expected by me.
3592: *
3593: * both of "id" and "id_p" should be ID payload without general header,
3594: */
3595: int
3596: ipsecdoi_checkid1(iph1)
3597: struct ph1handle *iph1;
3598: {
3599: struct ipsecdoi_id_b *id_b;
3600: struct sockaddr *sa;
3601: caddr_t sa1, sa2;
3602:
3603: if (iph1->id_p == NULL) {
3604: plog(LLV_ERROR, LOCATION, NULL,
3605: "invalid iph1 passed id_p == NULL\n");
3606: return ISAKMP_INTERNAL_ERROR;
3607: }
3608: if (iph1->id_p->l < sizeof(*id_b)) {
3609: plog(LLV_ERROR, LOCATION, NULL,
3610: "invalid value passed as \"ident\" (len=%lu)\n",
3611: (u_long)iph1->id_p->l);
3612: return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3613: }
3614:
3615: id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
3616:
3617: /* In main mode with pre-shared key, only address type can be used. */
3618: if (iph1->etype == ISAKMP_ETYPE_IDENT &&
3619: iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
3620: if (id_b->type != IPSECDOI_ID_IPV4_ADDR
3621: && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
3622: plog(LLV_ERROR, LOCATION, NULL,
3623: "Expecting IP address type in main mode, "
3624: "but %s.\n", s_ipsecdoi_ident(id_b->type));
3625: return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3626: }
3627: }
3628:
3629: /* if proper type for phase 1 ? */
3630: switch (id_b->type) {
3631: case IPSECDOI_ID_IPV4_ADDR_SUBNET:
3632: case IPSECDOI_ID_IPV6_ADDR_SUBNET:
3633: case IPSECDOI_ID_IPV4_ADDR_RANGE:
3634: case IPSECDOI_ID_IPV6_ADDR_RANGE:
3635: plog(LLV_WARNING, LOCATION, NULL,
3636: "such ID type %s is not proper.\n",
3637: s_ipsecdoi_ident(id_b->type));
3638: /*FALLTHROUGH*/
3639: }
3640:
3641: /* if phase 1 ID payload conformed RFC2407 4.6.2. */
1.15 manu 3642: if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
1.1 manu 3643: id_b->type == IPSECDOI_ID_IPV6_ADDR) {
3644:
3645: if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
3646: plog(LLV_WARNING, LOCATION, NULL,
3647: "protocol ID and Port mismatched. "
3648: "proto_id:%d port:%d\n",
3649: id_b->proto_id, ntohs(id_b->port));
3650: /*FALLTHROUGH*/
3651:
3652: } else if (id_b->proto_id == IPPROTO_UDP) {
3653: /*
3654: * copmaring with expecting port.
3655: * always permit if port is equal to PORT_ISAKMP
3656: */
3657: if (ntohs(id_b->port) != PORT_ISAKMP) {
3658: u_int16_t port;
3659:
1.22.2.3! jdc 3660: port = extract_port(iph1->remote);
1.1 manu 3661: if (ntohs(id_b->port) != port) {
3662: plog(LLV_WARNING, LOCATION, NULL,
3663: "port %d expected, but %d\n",
3664: port, ntohs(id_b->port));
3665: /*FALLTHROUGH*/
3666: }
3667: }
3668: }
3669: }
3670:
3671: /* compare with the ID if specified. */
3672: if (genlist_next(iph1->rmconf->idvl_p, 0)) {
3673: vchar_t *ident0 = NULL;
3674: vchar_t ident;
3675: struct idspec *id;
3676: struct genlist_entry *gpb;
3677:
3678: for (id = genlist_next (iph1->rmconf->idvl_p, &gpb); id; id = genlist_next (0, &gpb)) {
3679: /* check the type of both IDs */
3680: if (id->idtype != doi2idtype(id_b->type))
3681: continue; /* ID type mismatch */
3682: if (id->id == 0)
3683: goto matched;
3684:
3685: /* compare defined ID with the ID sent by peer. */
3686: if (ident0 != NULL)
3687: vfree(ident0);
3688: ident0 = getidval(id->idtype, id->id);
3689:
3690: switch (id->idtype) {
3691: case IDTYPE_ASN1DN:
1.13 manu 3692: ident.v = iph1->id_p->v + sizeof(*id_b);
3693: ident.l = iph1->id_p->l - sizeof(*id_b);
1.1 manu 3694: if (eay_cmp_asn1dn(ident0, &ident) == 0)
3695: goto matched;
3696: break;
3697: case IDTYPE_ADDRESS:
3698: sa = (struct sockaddr *)ident0->v;
3699: sa2 = (caddr_t)(id_b + 1);
3700: switch (sa->sa_family) {
3701: case AF_INET:
3702: if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
3703: continue; /* ID value mismatch */
3704: sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr;
3705: if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
3706: goto matched;
3707: break;
3708: #ifdef INET6
3709: case AF_INET6:
3710: if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
3711: continue; /* ID value mismatch */
3712: sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr;
3713: if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
3714: goto matched;
3715: break;
3716: #endif
3717: default:
3718: break;
3719: }
3720: break;
3721: default:
3722: if (memcmp(ident0->v, id_b + 1, ident0->l) == 0)
3723: goto matched;
3724: break;
3725: }
3726: }
3727: if (ident0 != NULL) {
3728: vfree(ident0);
3729: ident0 = NULL;
3730: }
3731: plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n");
3732: if (iph1->rmconf->verify_identifier)
3733: return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
3734: matched: /* ID value match */
3735: if (ident0 != NULL)
3736: vfree(ident0);
3737: }
3738:
3739: return 0;
3740: }
3741:
3742: /*
3743: * create ID payload for phase 1 and set into iph1->id.
3744: * NOT INCLUDING isakmp general header.
3745: * see, RFC2407 4.6.2.1
3746: */
3747: int
3748: ipsecdoi_setid1(iph1)
3749: struct ph1handle *iph1;
3750: {
3751: vchar_t *ret = NULL;
3752: struct ipsecdoi_id_b id_b;
3753: vchar_t *ident = NULL;
3754: struct sockaddr *ipid = NULL;
3755:
3756: /* init */
3757: id_b.proto_id = 0;
3758: id_b.port = 0;
3759: ident = NULL;
3760:
3761: switch (iph1->rmconf->idvtype) {
3762: case IDTYPE_FQDN:
3763: id_b.type = IPSECDOI_ID_FQDN;
3764: ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3765: break;
3766: case IDTYPE_USERFQDN:
3767: id_b.type = IPSECDOI_ID_USER_FQDN;
3768: ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3769: break;
3770: case IDTYPE_KEYID:
3771: id_b.type = IPSECDOI_ID_KEY_ID;
3772: ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
3773: break;
3774: case IDTYPE_ASN1DN:
3775: id_b.type = IPSECDOI_ID_DER_ASN1_DN;
3776: if (iph1->rmconf->idv) {
3777: /* XXX it must be encoded to asn1dn. */
3778: ident = vdup(iph1->rmconf->idv);
3779: } else {
3780: if (oakley_getmycert(iph1) < 0) {
3781: plog(LLV_ERROR, LOCATION, NULL,
3782: "failed to get own CERT.\n");
3783: goto err;
3784: }
3785: ident = eay_get_x509asn1subjectname(&iph1->cert->cert);
3786: }
3787: break;
3788: case IDTYPE_ADDRESS:
3789: /*
3790: * if the value of the id type was set by the configuration
3791: * file, then use it. otherwise the value is get from local
3792: * ip address by using ike negotiation.
3793: */
3794: if (iph1->rmconf->idv)
3795: ipid = (struct sockaddr *)iph1->rmconf->idv->v;
3796: /*FALLTHROUGH*/
3797: default:
3798: {
3799: int l;
3800: caddr_t p;
3801:
3802: if (ipid == NULL)
3803: ipid = iph1->local;
3804:
3805: /* use IP address */
3806: switch (ipid->sa_family) {
3807: case AF_INET:
3808: id_b.type = IPSECDOI_ID_IPV4_ADDR;
3809: l = sizeof(struct in_addr);
3810: p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
3811: break;
3812: #ifdef INET6
3813: case AF_INET6:
3814: id_b.type = IPSECDOI_ID_IPV6_ADDR;
3815: l = sizeof(struct in6_addr);
3816: p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
3817: break;
3818: #endif
3819: default:
3820: plog(LLV_ERROR, LOCATION, NULL,
3821: "invalid address family.\n");
3822: goto err;
3823: }
3824: id_b.proto_id = IPPROTO_UDP;
3825: id_b.port = htons(PORT_ISAKMP);
3826: ident = vmalloc(l);
3827: if (!ident) {
3828: plog(LLV_ERROR, LOCATION, NULL,
3829: "failed to get ID buffer.\n");
3830: return 0;
3831: }
3832: memcpy(ident->v, p, ident->l);
3833: }
3834: }
3835: if (!ident) {
3836: plog(LLV_ERROR, LOCATION, NULL,
3837: "failed to get ID buffer.\n");
3838: return 0;
3839: }
3840:
3841: ret = vmalloc(sizeof(id_b) + ident->l);
3842: if (ret == NULL) {
3843: plog(LLV_ERROR, LOCATION, NULL,
3844: "failed to get ID buffer.\n");
3845: goto err;
3846: }
3847:
3848: memcpy(ret->v, &id_b, sizeof(id_b));
3849: memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
3850:
3851: iph1->id = ret;
3852:
3853: plog(LLV_DEBUG, LOCATION, NULL,
3854: "use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
3855: if (ident)
3856: vfree(ident);
3857: return 0;
3858:
3859: err:
3860: if (ident)
3861: vfree(ident);
3862: plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
3863: return -1;
3864: }
3865:
3866: static vchar_t *
3867: getidval(type, val)
3868: int type;
3869: vchar_t *val;
3870: {
3871: vchar_t *new = NULL;
3872:
3873: if (val)
3874: new = vdup(val);
3875: else if (lcconf->ident[type])
3876: new = vdup(lcconf->ident[type]);
3877:
3878: return new;
3879: }
3880:
3881: /* it's only called by cfparse.y. */
3882: int
3883: set_identifier(vpp, type, value)
3884: vchar_t **vpp, *value;
3885: int type;
3886: {
1.13 manu 3887: return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
3888: }
3889:
3890: int
3891: set_identifier_qual(vpp, type, value, qual)
3892: vchar_t **vpp, *value;
3893: int type;
3894: int qual;
3895: {
1.1 manu 3896: vchar_t *new = NULL;
3897:
3898: /* simply return if value is null. */
1.11 manu 3899: if (!value){
3900: if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
3901: plog(LLV_ERROR, LOCATION, NULL,
3902: "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3903: return -1;
3904: }
1.1 manu 3905: return 0;
1.11 manu 3906: }
1.1 manu 3907:
3908: switch (type) {
3909: case IDTYPE_FQDN:
3910: case IDTYPE_USERFQDN:
1.11 manu 3911: if(value->l <= 1){
3912: plog(LLV_ERROR, LOCATION, NULL,
3913: "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
3914: return -1;
3915: }
1.1 manu 3916: /* length is adjusted since QUOTEDSTRING teminates NULL. */
3917: new = vmalloc(value->l - 1);
3918: if (new == NULL)
3919: return -1;
3920: memcpy(new->v, value->v, new->l);
3921: break;
3922: case IDTYPE_KEYID:
1.13 manu 3923: /*
3924: * If no qualifier is specified: IDQUAL_UNSPEC. It means
3925: * to use a file for backward compatibility sake.
3926: */
3927: switch(qual) {
3928: case IDQUAL_FILE:
3929: case IDQUAL_UNSPEC: {
3930: FILE *fp;
3931: char b[512];
3932: int tlen, len;
1.1 manu 3933:
1.13 manu 3934: fp = fopen(value->v, "r");
3935: if (fp == NULL) {
3936: plog(LLV_ERROR, LOCATION, NULL,
3937: "can not open %s\n", value->v);
3938: return -1;
3939: }
3940: tlen = 0;
3941: while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
3942: new = vrealloc(new, tlen + len);
3943: if (!new) {
3944: fclose(fp);
3945: return -1;
3946: }
3947: memcpy(new->v + tlen, b, len);
3948: tlen += len;
3949: }
3950: break;
1.1 manu 3951: }
1.13 manu 3952:
3953: case IDQUAL_TAG:
3954: new = vmalloc(value->l - 1);
3955: if (new == NULL) {
3956: plog(LLV_ERROR, LOCATION, NULL,
3957: "can not allocate memory");
1.1 manu 3958: return -1;
3959: }
1.13 manu 3960: memcpy(new->v, value->v, new->l);
3961: break;
3962:
3963: default:
3964: plog(LLV_ERROR, LOCATION, NULL,
3965: "unknown qualifier");
3966: return -1;
1.1 manu 3967: }
3968: break;
1.13 manu 3969:
3970: case IDTYPE_ADDRESS: {
1.1 manu 3971: struct sockaddr *sa;
3972:
3973: /* length is adjusted since QUOTEDSTRING teminates NULL. */
3974: if (value->l == 0)
3975: break;
3976:
3977: sa = str2saddr(value->v, NULL);
3978: if (sa == NULL) {
3979: plog(LLV_ERROR, LOCATION, NULL,
3980: "invalid ip address %s\n", value->v);
3981: return -1;
3982: }
3983:
3984: new = vmalloc(sysdep_sa_len(sa));
1.13 manu 3985: if (new == NULL) {
3986: racoon_free(sa);
1.1 manu 3987: return -1;
1.13 manu 3988: }
1.1 manu 3989: memcpy(new->v, sa, new->l);
1.13 manu 3990: racoon_free(sa);
1.1 manu 3991: break;
3992: }
3993: case IDTYPE_ASN1DN:
3994: if (value->v[0] == '~')
3995: /* Hex-encoded ASN1 strings */
3996: new = eay_hex2asn1dn(value->v + 1, - 1);
3997: else
3998: /* DN encoded strings */
3999: new = eay_str2asn1dn(value->v, value->l - 1);
4000:
4001: if (new == NULL)
4002: return -1;
4003:
4004: if (loglevel >= LLV_DEBUG) {
4005: X509_NAME *xn;
4006: BIO *bio;
1.9 manu 4007: unsigned char *ptr = (unsigned char *) new->v, *buf;
1.1 manu 4008: size_t len;
4009: char save;
4010:
1.9 manu 4011: xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
1.1 manu 4012: bio = BIO_new(BIO_s_mem());
4013:
4014: X509_NAME_print_ex(bio, xn, 0, 0);
4015: len = BIO_get_mem_data(bio, &ptr);
4016: save = ptr[len];
4017: ptr[len] = 0;
4018: plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
4019: ptr[len] = save;
4020: X509_NAME_free(xn);
4021: BIO_free(bio);
4022: }
4023:
4024: break;
4025: }
4026:
4027: *vpp = new;
4028:
4029: return 0;
4030: }
4031:
4032: /*
4033: * create ID payload for phase 2, and set into iph2->id and id_p. There are
4034: * NOT INCLUDING isakmp general header.
4035: * this function is for initiator. responder will get to copy from payload.
4036: * responder ID type is always address type.
4037: * see, RFC2407 4.6.2.1
4038: */
4039: int
4040: ipsecdoi_setid2(iph2)
4041: struct ph2handle *iph2;
4042: {
4043: struct secpolicy *sp;
4044:
4045: /* check there is phase 2 handler ? */
4046: sp = getspbyspid(iph2->spid);
4047: if (sp == NULL) {
4048: plog(LLV_ERROR, LOCATION, NULL,
4049: "no policy found for spid:%u.\n", iph2->spid);
4050: return -1;
4051: }
4052:
4053: iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
4054: sp->spidx.prefs, sp->spidx.ul_proto);
4055: if (iph2->id == NULL) {
4056: plog(LLV_ERROR, LOCATION, NULL,
4057: "failed to get ID for %s\n",
4058: spidx2str(&sp->spidx));
4059: return -1;
4060: }
4061: plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
4062: s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
4063:
4064: /* remote side */
4065: iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
4066: sp->spidx.prefd, sp->spidx.ul_proto);
4067: if (iph2->id_p == NULL) {
4068: plog(LLV_ERROR, LOCATION, NULL,
4069: "failed to get ID for %s\n",
4070: spidx2str(&sp->spidx));
4071: VPTRINIT(iph2->id);
4072: return -1;
4073: }
4074: plog(LLV_DEBUG, LOCATION, NULL,
4075: "use remote ID type %s\n",
4076: s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
4077:
4078: return 0;
4079: }
4080:
4081: /*
4082: * set address type of ID.
4083: * NOT INCLUDING general header.
4084: */
4085: vchar_t *
4086: ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
4087: struct sockaddr *saddr;
4088: u_int prefixlen;
4089: u_int ul_proto;
4090: {
4091: vchar_t *new;
4092: int type, len1, len2;
4093: caddr_t sa;
4094: u_short port;
4095:
4096: /*
4097: * Q. When type is SUBNET, is it allowed to be ::1/128.
4098: * A. Yes. (consensus at bake-off)
4099: */
4100: switch (saddr->sa_family) {
4101: case AF_INET:
4102: len1 = sizeof(struct in_addr);
1.22.2.1 jdc 4103: if (prefixlen == (sizeof(struct in_addr) << 3)) {
1.1 manu 4104: type = IPSECDOI_ID_IPV4_ADDR;
4105: len2 = 0;
4106: } else {
4107: type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
4108: len2 = sizeof(struct in_addr);
4109: }
4110: sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
4111: port = ((struct sockaddr_in *)(saddr))->sin_port;
4112: break;
4113: #ifdef INET6
4114: case AF_INET6:
4115: len1 = sizeof(struct in6_addr);
1.22.2.1 jdc 4116: if (prefixlen == (sizeof(struct in6_addr) << 3)) {
1.1 manu 4117: type = IPSECDOI_ID_IPV6_ADDR;
4118: len2 = 0;
4119: } else {
4120: type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
4121: len2 = sizeof(struct in6_addr);
4122: }
4123: sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
4124: port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
4125: break;
4126: #endif
4127: default:
4128: plog(LLV_ERROR, LOCATION, NULL,
4129: "invalid family: %d.\n", saddr->sa_family);
4130: return NULL;
4131: }
4132:
4133: /* get ID buffer */
4134: new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4135: if (new == NULL) {
4136: plog(LLV_ERROR, LOCATION, NULL,
4137: "failed to get ID buffer.\n");
4138: return NULL;
4139: }
4140:
4141: memset(new->v, 0, new->l);
4142:
4143: /* set the part of header. */
4144: ((struct ipsecdoi_id_b *)new->v)->type = type;
4145:
4146: /* set ul_proto and port */
4147: /*
4148: * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4149: * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4150: */
4151: ((struct ipsecdoi_id_b *)new->v)->proto_id =
4152: ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4153: ((struct ipsecdoi_id_b *)new->v)->port =
4154: port == IPSEC_PORT_ANY ? 0 : port;
4155: memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
4156:
4157: /* set address */
4158:
4159: /* set prefix */
4160: if (len2) {
1.9 manu 4161: u_char *p = (unsigned char *) new->v +
4162: sizeof(struct ipsecdoi_id_b) + len1;
1.1 manu 4163: u_int bits = prefixlen;
4164:
4165: while (bits >= 8) {
4166: *p++ = 0xff;
4167: bits -= 8;
4168: }
4169:
4170: if (bits > 0)
4171: *p = ~((1 << (8 - bits)) - 1);
4172: }
4173:
4174: return new;
4175: }
4176:
1.13 manu 4177: vchar_t *
4178: ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
4179: struct sockaddr *laddr, *haddr;
4180: u_int ul_proto;
4181: {
4182: vchar_t *new;
4183: int type, len1, len2;
4184: u_short port;
4185:
4186: if (laddr->sa_family != haddr->sa_family) {
4187: plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
4188: return NULL;
4189: }
4190:
4191: switch (laddr->sa_family) {
4192: case AF_INET:
4193: type = IPSECDOI_ID_IPV4_ADDR_RANGE;
4194: len1 = sizeof(struct in_addr);
4195: len2 = sizeof(struct in_addr);
4196: break;
4197: #ifdef INET6
4198: case AF_INET6:
4199: type = IPSECDOI_ID_IPV6_ADDR_RANGE;
4200: len1 = sizeof(struct in6_addr);
4201: len2 = sizeof(struct in6_addr);
4202: break;
4203: #endif
4204: default:
4205: plog(LLV_ERROR, LOCATION, NULL,
4206: "invalid family: %d.\n", laddr->sa_family);
4207: return NULL;
4208: }
4209:
4210: /* get ID buffer */
4211: new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
4212: if (new == NULL) {
4213: plog(LLV_ERROR, LOCATION, NULL,
4214: "failed to get ID buffer.\n");
4215: return NULL;
4216: }
4217:
4218: memset(new->v, 0, new->l);
4219: /* set the part of header. */
4220: ((struct ipsecdoi_id_b *)new->v)->type = type;
4221:
4222: /* set ul_proto and port */
4223: /*
4224: * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
4225: * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
4226: */
4227: ((struct ipsecdoi_id_b *)new->v)->proto_id =
4228: ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
4229: port = ((struct sockaddr_in *)(laddr))->sin_port;
4230: ((struct ipsecdoi_id_b *)new->v)->port =
4231: port == IPSEC_PORT_ANY ? 0 : port;
4232: memcpy(new->v + sizeof(struct ipsecdoi_id_b),
4233: (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
4234: len1);
4235: memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
4236: (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
4237: len2);
4238: return new;
4239: }
4240:
4241:
1.1 manu 4242: /*
4243: * create sockaddr structure from ID payload (buf).
4244: * buffers (saddr, prefixlen, ul_proto) must be allocated.
4245: * see, RFC2407 4.6.2.1
4246: */
4247: int
4248: ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
4249: vchar_t *buf;
4250: struct sockaddr *saddr;
4251: u_int8_t *prefixlen;
4252: u_int16_t *ul_proto;
4253: {
4254: struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
4255: u_int plen = 0;
4256:
4257: /*
4258: * When a ID payload of subnet type with a IP address of full bit
4259: * masked, it has to be processed as host address.
4260: * e.g. below 2 type are same.
4261: * type = ipv6 subnet, data = 2001::1/128
4262: * type = ipv6 address, data = 2001::1
4263: */
4264: switch (id_b->type) {
4265: case IPSECDOI_ID_IPV4_ADDR:
4266: case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4267: #ifndef __linux__
4268: saddr->sa_len = sizeof(struct sockaddr_in);
4269: #endif
4270: saddr->sa_family = AF_INET;
4271: ((struct sockaddr_in *)saddr)->sin_port =
4272: (id_b->port == 0
4273: ? IPSEC_PORT_ANY
4274: : id_b->port); /* see sockaddr2id() */
4275: memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
4276: buf->v + sizeof(*id_b), sizeof(struct in_addr));
4277: break;
4278: #ifdef INET6
4279: case IPSECDOI_ID_IPV6_ADDR:
4280: case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4281: #ifndef __linux__
4282: saddr->sa_len = sizeof(struct sockaddr_in6);
4283: #endif
4284: saddr->sa_family = AF_INET6;
4285: ((struct sockaddr_in6 *)saddr)->sin6_port =
4286: (id_b->port == 0
4287: ? IPSEC_PORT_ANY
4288: : id_b->port); /* see sockaddr2id() */
4289: memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
4290: buf->v + sizeof(*id_b), sizeof(struct in6_addr));
4291: break;
4292: #endif
4293: default:
4294: plog(LLV_ERROR, LOCATION, NULL,
4295: "unsupported ID type %d\n", id_b->type);
4296: return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
4297: }
4298:
4299: /* get prefix length */
4300: switch (id_b->type) {
4301: case IPSECDOI_ID_IPV4_ADDR:
4302: plen = sizeof(struct in_addr) << 3;
4303: break;
4304: #ifdef INET6
4305: case IPSECDOI_ID_IPV6_ADDR:
4306: plen = sizeof(struct in6_addr) << 3;
4307: break;
4308: #endif
4309: case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4310: #ifdef INET6
4311: case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4312: #endif
4313: {
4314: u_char *p;
4315: u_int max;
4316: int alen = sizeof(struct in_addr);
4317:
4318: switch (id_b->type) {
4319: case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4320: alen = sizeof(struct in_addr);
4321: break;
4322: #ifdef INET6
4323: case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4324: alen = sizeof(struct in6_addr);
4325: break;
4326: #endif
4327: }
4328:
4329: /* sanity check */
4330: if (buf->l < alen)
4331: return ISAKMP_INTERNAL_ERROR;
4332:
4333: /* get subnet mask length */
4334: plen = 0;
4335: max = alen <<3;
4336:
1.9 manu 4337: p = (unsigned char *) buf->v
1.1 manu 4338: + sizeof(struct ipsecdoi_id_b)
4339: + alen;
4340:
4341: for (; *p == 0xff; p++) {
1.17 manu 4342: plen += 8;
1.1 manu 4343: if (plen >= max)
4344: break;
4345: }
4346:
4347: if (plen < max) {
4348: u_int l = 0;
4349: u_char b = ~(*p);
4350:
4351: while (b) {
4352: b >>= 1;
4353: l++;
4354: }
4355:
4356: l = 8 - l;
4357: plen += l;
4358: }
4359: }
4360: break;
4361: }
4362:
4363: *prefixlen = plen;
4364: *ul_proto = id_b->proto_id == 0
4365: ? IPSEC_ULPROTO_ANY
4366: : id_b->proto_id; /* see sockaddr2id() */
4367:
4368: return 0;
4369: }
4370:
4371: /*
4372: * make printable string from ID payload except of general header.
4373: */
1.13 manu 4374: char *
1.1 manu 4375: ipsecdoi_id2str(id)
4376: const vchar_t *id;
4377: {
1.13 manu 4378: #define BUFLEN 512
4379: char * ret = NULL;
4380: int len = 0;
4381: char *dat;
4382: static char buf[BUFLEN];
4383: struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
4384: struct sockaddr saddr;
4385: u_int plen = 0;
4386:
4387: switch (id_b->type) {
4388: case IPSECDOI_ID_IPV4_ADDR:
4389: case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4390: case IPSECDOI_ID_IPV4_ADDR_RANGE:
1.1 manu 4391:
1.14 manu 4392: #ifndef __linux__
1.13 manu 4393: saddr.sa_len = sizeof(struct sockaddr_in);
1.14 manu 4394: #endif
1.13 manu 4395: saddr.sa_family = AF_INET;
4396: ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
4397: memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
4398: id->v + sizeof(*id_b), sizeof(struct in_addr));
4399: break;
4400: #ifdef INET6
4401: case IPSECDOI_ID_IPV6_ADDR:
4402: case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4403: case IPSECDOI_ID_IPV6_ADDR_RANGE:
1.1 manu 4404:
1.14 manu 4405: #ifndef __linux__
1.13 manu 4406: saddr.sa_len = sizeof(struct sockaddr_in6);
1.14 manu 4407: #endif
1.13 manu 4408: saddr.sa_family = AF_INET6;
4409: ((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
4410: memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
4411: id->v + sizeof(*id_b), sizeof(struct in6_addr));
4412: break;
4413: #endif
4414: }
4415:
4416: switch (id_b->type) {
4417: case IPSECDOI_ID_IPV4_ADDR:
4418: #ifdef INET6
4419: case IPSECDOI_ID_IPV6_ADDR:
4420: #endif
4421: len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr));
4422: break;
4423:
4424: case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4425: #ifdef INET6
4426: case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4427: #endif
4428: {
4429: u_char *p;
4430: u_int max;
4431: int alen = sizeof(struct in_addr);
4432:
4433: switch (id_b->type) {
4434: case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4435: alen = sizeof(struct in_addr);
4436: break;
4437: #ifdef INET6
4438: case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4439: alen = sizeof(struct in6_addr);
4440: break;
4441: #endif
4442: }
4443:
4444: /* sanity check */
4445: if (id->l < alen) {
4446: len = 0;
4447: break;
4448: }
4449:
4450: /* get subnet mask length */
4451: plen = 0;
4452: max = alen <<3;
4453:
4454: p = (unsigned char *) id->v
4455: + sizeof(struct ipsecdoi_id_b)
4456: + alen;
4457:
4458: for (; *p == 0xff; p++) {
1.17 manu 4459: plen += 8;
1.13 manu 4460: if (plen >= max)
4461: break;
4462: }
4463:
4464: if (plen < max) {
4465: u_int l = 0;
4466: u_char b = ~(*p);
4467:
4468: while (b) {
4469: b >>= 1;
4470: l++;
4471: }
4472:
4473: l = 8 - l;
4474: plen += l;
4475: }
4476:
4477: len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr), plen);
4478: }
4479: break;
4480:
4481: case IPSECDOI_ID_IPV4_ADDR_RANGE:
4482:
4483: len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr));
4484:
1.14 manu 4485: #ifndef __linux__
1.13 manu 4486: saddr.sa_len = sizeof(struct sockaddr_in);
1.14 manu 4487: #endif
1.13 manu 4488: saddr.sa_family = AF_INET;
4489: ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
4490: memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
4491: id->v + sizeof(*id_b) + sizeof(struct in_addr),
4492: sizeof(struct in_addr));
4493:
4494: len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr));
4495:
4496: break;
4497:
4498: #ifdef INET6
4499: case IPSECDOI_ID_IPV6_ADDR_RANGE:
4500:
4501: len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr));
4502:
1.14 manu 4503: #ifndef __linux__
1.13 manu 4504: saddr.sa_len = sizeof(struct sockaddr_in6);
1.14 manu 4505: #endif
1.13 manu 4506: saddr.sa_family = AF_INET6;
4507: ((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
4508: memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
4509: id->v + sizeof(*id_b) + sizeof(struct in6_addr),
4510: sizeof(struct in6_addr));
4511:
4512: len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr));
4513:
4514: break;
4515: #endif
4516:
4517: case IPSECDOI_ID_FQDN:
4518: case IPSECDOI_ID_USER_FQDN:
4519: len = id->l - sizeof(*id_b);
4520: if (len > BUFLEN)
4521: len = BUFLEN;
4522: memcpy(buf, id->v + sizeof(*id_b), len);
4523: break;
4524:
4525: case IPSECDOI_ID_DER_ASN1_DN:
4526: case IPSECDOI_ID_DER_ASN1_GN:
4527: {
1.22.2.1 jdc 4528: X509_NAME *xn = NULL;
4529:
1.13 manu 4530: dat = id->v + sizeof(*id_b);
4531: len = id->l - sizeof(*id_b);
4532:
4533: if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
4534: BIO *bio = BIO_new(BIO_s_mem());
4535: X509_NAME_print_ex(bio, xn, 0, 0);
4536: len = BIO_get_mem_data(bio, &dat);
4537: if (len > BUFLEN)
4538: len = BUFLEN;
4539: memcpy(buf,dat,len);
4540: BIO_free(bio);
4541: X509_NAME_free(xn);
4542: } else {
4543: plog(LLV_ERROR, LOCATION, NULL,
4544: "unable to extract asn1dn from id\n");
4545:
4546: len = sprintf(buf, "<ASN1-DN>");
4547: }
4548:
4549: break;
4550: }
4551:
4552: /* currently unhandled id types */
4553: case IPSECDOI_ID_KEY_ID:
4554: len = sprintf( buf, "<KEY-ID>");
4555: break;
4556:
4557: default:
4558: plog(LLV_ERROR, LOCATION, NULL,
4559: "unknown ID type %d\n", id_b->type);
4560: }
4561:
4562: if (!len)
4563: len = sprintf( buf, "<?>");
4564:
4565: ret = racoon_malloc(len+1);
4566: if (ret != NULL) {
4567: memcpy(ret,buf,len);
4568: ret[len]=0;
4569: }
4570:
4571: return ret;
1.1 manu 4572: }
4573:
4574: /*
4575: * set IPsec data attributes into a proposal.
4576: * NOTE: MUST called per a transform.
4577: */
4578: int
4579: ipsecdoi_t2satrns(t, pp, pr, tr)
4580: struct isakmp_pl_t *t;
4581: struct saprop *pp;
4582: struct saproto *pr;
4583: struct satrns *tr;
4584: {
4585: struct isakmp_data *d, *prev;
4586: int flag, type;
4587: int error = -1;
4588: int life_t;
4589: int tlen;
4590:
4591: tr->trns_no = t->t_no;
4592: tr->trns_id = t->t_id;
4593:
4594: tlen = ntohs(t->h.len) - sizeof(*t);
4595: prev = (struct isakmp_data *)NULL;
4596: d = (struct isakmp_data *)(t + 1);
4597:
4598: /* default */
4599: life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4600: pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
4601: pp->lifebyte = 0;
4602: tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
4603:
4604: while (tlen > 0) {
4605:
4606: type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
4607: flag = ntohs(d->type) & ISAKMP_GEN_MASK;
4608:
4609: plog(LLV_DEBUG, LOCATION, NULL,
4610: "type=%s, flag=0x%04x, lorv=%s\n",
4611: s_ipsecdoi_attr(type), flag,
4612: s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
4613:
4614: switch (type) {
4615: case IPSECDOI_ATTR_SA_LD_TYPE:
4616: {
4617: int type = ntohs(d->lorv);
4618: switch (type) {
4619: case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4620: case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4621: life_t = type;
4622: break;
4623: default:
4624: plog(LLV_WARNING, LOCATION, NULL,
4625: "invalid life duration type. "
4626: "use default\n");
4627: life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
4628: break;
4629: }
4630: break;
4631: }
4632: case IPSECDOI_ATTR_SA_LD:
4633: if (prev == NULL
4634: || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
4635: IPSECDOI_ATTR_SA_LD_TYPE) {
4636: plog(LLV_ERROR, LOCATION, NULL,
4637: "life duration must follow ltype\n");
4638: break;
4639: }
4640:
4641: {
4642: u_int32_t t;
4643: vchar_t *ld_buf = NULL;
4644:
4645: if (flag) {
4646: /* i.e. ISAKMP_GEN_TV */
4647: ld_buf = vmalloc(sizeof(d->lorv));
4648: if (ld_buf == NULL) {
4649: plog(LLV_ERROR, LOCATION, NULL,
4650: "failed to get LD buffer.\n");
4651: goto end;
4652: }
4653: memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
4654: } else {
4655: int len = ntohs(d->lorv);
4656: /* i.e. ISAKMP_GEN_TLV */
4657: ld_buf = vmalloc(len);
4658: if (ld_buf == NULL) {
4659: plog(LLV_ERROR, LOCATION, NULL,
4660: "failed to get LD buffer.\n");
4661: goto end;
4662: }
4663: memcpy(ld_buf->v, d + 1, len);
4664: }
4665: switch (life_t) {
4666: case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
4667: t = ipsecdoi_set_ld(ld_buf);
4668: vfree(ld_buf);
4669: if (t == 0) {
4670: plog(LLV_ERROR, LOCATION, NULL,
4671: "invalid life duration.\n");
4672: goto end;
4673: }
4674: /* lifetime must be equal in a proposal. */
4675: if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
4676: pp->lifetime = t;
4677: else if (pp->lifetime != t) {
4678: plog(LLV_ERROR, LOCATION, NULL,
4679: "lifetime mismatched "
4680: "in a proposal, "
4681: "prev:%ld curr:%u.\n",
4682: (long)pp->lifetime, t);
4683: goto end;
4684: }
4685: break;
4686: case IPSECDOI_ATTR_SA_LD_TYPE_KB:
4687: t = ipsecdoi_set_ld(ld_buf);
4688: vfree(ld_buf);
4689: if (t == 0) {
4690: plog(LLV_ERROR, LOCATION, NULL,
4691: "invalid life duration.\n");
4692: goto end;
4693: }
4694: /* lifebyte must be equal in a proposal. */
4695: if (pp->lifebyte == 0)
4696: pp->lifebyte = t;
4697: else if (pp->lifebyte != t) {
4698: plog(LLV_ERROR, LOCATION, NULL,
4699: "lifebyte mismatched "
4700: "in a proposal, "
4701: "prev:%d curr:%u.\n",
4702: pp->lifebyte, t);
4703: goto end;
4704: }
4705: break;
4706: default:
4707: vfree(ld_buf);
4708: plog(LLV_ERROR, LOCATION, NULL,
4709: "invalid life type: %d\n", life_t);
4710: goto end;
4711: }
4712: }
4713: break;
4714:
4715: case IPSECDOI_ATTR_GRP_DESC:
4716: /*
4717: * RFC2407: 4.5 IPSEC Security Association Attributes
4718: * Specifies the Oakley Group to be used in a PFS QM
4719: * negotiation. For a list of supported values, see
4720: * Appendix A of [IKE].
4721: */
4722: if (pp->pfs_group == 0)
4723: pp->pfs_group = (u_int16_t)ntohs(d->lorv);
4724: else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
4725: plog(LLV_ERROR, LOCATION, NULL,
4726: "pfs_group mismatched "
4727: "in a proposal.\n");
4728: goto end;
4729: }
4730: break;
4731:
4732: case IPSECDOI_ATTR_ENC_MODE:
4733: if (pr->encmode &&
4734: pr->encmode != (u_int16_t)ntohs(d->lorv)) {
4735: plog(LLV_ERROR, LOCATION, NULL,
4736: "multiple encmode exist "
4737: "in a transform.\n");
4738: goto end;
4739: }
4740: pr->encmode = (u_int16_t)ntohs(d->lorv);
4741: break;
4742:
4743: case IPSECDOI_ATTR_AUTH:
4744: if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
4745: plog(LLV_ERROR, LOCATION, NULL,
4746: "multiple authtype exist "
4747: "in a transform.\n");
4748: goto end;
4749: }
4750: tr->authtype = (u_int16_t)ntohs(d->lorv);
4751: break;
4752:
4753: case IPSECDOI_ATTR_KEY_LENGTH:
4754: if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
4755: plog(LLV_ERROR, LOCATION, NULL,
4756: "key length defined but not ESP");
4757: goto end;
4758: }
4759: tr->encklen = ntohs(d->lorv);
4760: break;
1.22.2.1 jdc 4761: #ifdef HAVE_SECCTX
4762: case IPSECDOI_ATTR_SECCTX:
4763: {
4764: int len = ntohs(d->lorv);
4765: memcpy(&pp->sctx, d + 1, len);
4766: pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
4767: break;
4768: }
4769: #endif /* HAVE_SECCTX */
1.1 manu 4770: case IPSECDOI_ATTR_KEY_ROUNDS:
4771: case IPSECDOI_ATTR_COMP_DICT_SIZE:
4772: case IPSECDOI_ATTR_COMP_PRIVALG:
4773: default:
4774: break;
4775: }
4776:
4777: prev = d;
4778: if (flag) {
4779: tlen -= sizeof(*d);
4780: d = (struct isakmp_data *)((char *)d + sizeof(*d));
4781: } else {
4782: tlen -= (sizeof(*d) + ntohs(d->lorv));
4783: d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
4784: }
4785: }
4786:
4787: error = 0;
4788: end:
4789: return error;
4790: }
4791:
4792: int
4793: ipsecdoi_authalg2trnsid(alg)
4794: int alg;
4795: {
4796: switch (alg) {
4797: case IPSECDOI_ATTR_AUTH_HMAC_MD5:
4798: return IPSECDOI_AH_MD5;
4799: case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
4800: return IPSECDOI_AH_SHA;
1.8 manu 4801: case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
4802: return IPSECDOI_AH_SHA256;
4803: case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
4804: return IPSECDOI_AH_SHA384;
4805: case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
4806: return IPSECDOI_AH_SHA512;
1.1 manu 4807: case IPSECDOI_ATTR_AUTH_DES_MAC:
4808: return IPSECDOI_AH_DES;
4809: case IPSECDOI_ATTR_AUTH_KPDK:
4810: return IPSECDOI_AH_MD5; /* XXX */
4811: default:
4812: plog(LLV_ERROR, LOCATION, NULL,
4813: "invalid authentication algorithm:%d\n", alg);
4814: }
4815: return -1;
4816: }
4817:
4818: #ifdef HAVE_GSSAPI
4819: struct isakmpsa *
4820: fixup_initiator_sa(match, received)
4821: struct isakmpsa *match, *received;
4822: {
1.5 manu 4823: if (received->gssid != NULL)
4824: match->gssid = vdup(received->gssid);
1.1 manu 4825:
1.5 manu 4826: return match;
1.1 manu 4827: }
4828: #endif
4829:
4830: static int rm_idtype2doi[] = {
1.9 manu 4831: 255, /* IDTYPE_UNDEFINED, 0 */
1.7 manu 4832: IPSECDOI_ID_FQDN, /* IDTYPE_FQDN, 1 */
4833: IPSECDOI_ID_USER_FQDN, /* IDTYPE_USERFQDN, 2 */
1.9 manu 4834: IPSECDOI_ID_KEY_ID, /* IDTYPE_KEYID, 3 */
4835: 255, /* IDTYPE_ADDRESS, 4
1.1 manu 4836: * it expands into 4 types by another function. */
1.7 manu 4837: IPSECDOI_ID_DER_ASN1_DN, /* IDTYPE_ASN1DN, 5 */
1.1 manu 4838: };
4839:
4840: /*
4841: * convert idtype to DOI value.
4842: * OUT 255 : NG
4843: * other: converted.
4844: */
4845: int
4846: idtype2doi(idtype)
4847: int idtype;
4848: {
4849: if (ARRAYLEN(rm_idtype2doi) > idtype)
4850: return rm_idtype2doi[idtype];
4851: return 255;
4852: }
4853:
4854: int
4855: doi2idtype(doi)
4856: int doi;
4857: {
4858: switch(doi) {
4859: case IPSECDOI_ID_FQDN:
4860: return(IDTYPE_FQDN);
4861: case IPSECDOI_ID_USER_FQDN:
4862: return(IDTYPE_USERFQDN);
4863: case IPSECDOI_ID_KEY_ID:
4864: return(IDTYPE_KEYID);
4865: case IPSECDOI_ID_DER_ASN1_DN:
4866: return(IDTYPE_ASN1DN);
4867: case IPSECDOI_ID_IPV4_ADDR:
4868: case IPSECDOI_ID_IPV4_ADDR_SUBNET:
4869: case IPSECDOI_ID_IPV6_ADDR:
4870: case IPSECDOI_ID_IPV6_ADDR_SUBNET:
4871: return(IDTYPE_ADDRESS);
4872: default:
4873: plog(LLV_WARNING, LOCATION, NULL,
4874: "Inproper idtype:%s in this function.\n",
4875: s_ipsecdoi_ident(doi));
4876: return(IDTYPE_ADDRESS); /* XXX */
4877: }
4878: /*NOTREACHED*/
4879: }
4880:
4881: #ifdef ENABLE_HYBRID
4882: static int
4883: switch_authmethod(authmethod)
4884: int authmethod;
4885: {
4886: switch(authmethod) {
4887: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
4888: authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
4889: break;
4890: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
4891: authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
4892: break;
4893: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
4894: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
4895: break;
1.13 manu 4896: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
4897: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
4898: break;
4899: /* Those are not implemented */
1.1 manu 4900: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
4901: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
4902: break;
4903: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
4904: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
4905: break;
4906: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
4907: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
4908: break;
4909: default:
4910: break;
4911: }
4912:
4913: return authmethod;
4914: }
4915: #endif
CVSweb <webmaster@jp.NetBSD.org>