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