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/isakmp_inf.c
+++ new/iked/ikev1/isakmp_inf.c
1 1 /* $Id: isakmp_inf.c,v 1.18 2008/07/07 09:36:08 fukumoto 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>
36 36 #include <sys/socket.h>
|
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
37 37
38 38 #include <netinet/in.h>
39 39 #include <sys/queue.h>
40 40
41 41 #ifdef HAVE_NETINET6_IPSEC_H
42 42 # include <netinet6/ipsec.h>
43 43 #else
44 44 # ifdef HAVE_NETIPSEC_IPSEC_H
45 45 # include <netipsec/ipsec.h>
46 46 # else
47 -# include <linux/ipsec.h>
47 +# ifndef sun /* XXX KEBE SAYS OpenSolaris */
48 +# include <linux/ipsec.h>
49 +# endif
48 50 # endif
49 51 #endif
50 52
51 53 #include <stdlib.h>
52 54 #include <stdio.h>
53 55 #include <string.h>
54 56 #include <errno.h>
55 57 #if TIME_WITH_SYS_TIME
56 58 # include <sys/time.h>
57 59 # include <time.h>
58 60 #else
59 61 # if HAVE_SYS_TIME_H
60 62 # include <sys/time.h>
61 63 # else
62 64 # include <time.h>
63 65 # endif
64 66 #endif
65 67 #ifdef ENABLE_HYBRID
66 68 #include <resolv.h>
67 69 #endif
68 70
69 71 #include "racoon.h"
70 72
71 73 /* #include "libpfkey.h" */
72 74
73 75 #include "var.h"
74 76 /* #include "vmbuf.h" */
75 77 /* #include "schedule.h" */
76 78 #include "str2val.h"
77 79 /* #include "misc.h" */
78 80 #include "plog.h"
79 81 #include "debug.h"
80 82
81 83 /* #include "localconf.h" */
82 84 #include "remoteconf.h"
83 85 #include "proposal.h"
84 86 #include "sockmisc.h"
85 87 #include "evt.h"
86 88 #include "isakmp.h"
87 89 #include "isakmp_var.h"
88 90 #include "isakmp_impl.h"
89 91 #include "ikev1_impl.h"
90 92 #ifdef ENABLE_HYBRID
91 93 #include "isakmp_xauth.h"
92 94 #include "isakmp_unity.h"
93 95 #include "isakmp_cfg.h"
94 96 #endif
95 97 #include "isakmp_inf.h"
96 98 #include "oakley.h"
97 99 #include "ipsec_doi.h"
98 100 #include "handler.h"
99 101 #include "crypto_impl.h"
100 102 #include "pfkey.h"
101 103 /* #include "policy.h" */
102 104 #include "algorithm.h"
103 105 /* #include "admin.h" */
104 106 #include "strnames.h"
105 107 #ifdef ENABLE_NATT
106 108 #include "ikev1_natt.h"
107 109 #endif
108 110
109 111 #include "ike_conf.h"
110 112
111 113 /* information exchange */
112 114 static int isakmp_info_recv_n (struct ph1handle *, rc_vchar_t *);
113 115 static int isakmp_info_recv_d (struct ph1handle *, rc_vchar_t *);
114 116
115 117
116 118 static int isakmp_info_recv_r_u (struct ph1handle *,
117 119 struct isakmp_pl_ru *, uint32_t);
118 120 static int isakmp_info_recv_r_u_ack (struct ph1handle *,
119 121 struct isakmp_pl_ru *, uint32_t);
120 122 static void isakmp_info_send_r_u (void *);
121 123
122 124 /* static void purge_isakmp_spi (int, isakmp_index_t *, size_t); */
123 125 static void info_recv_initialcontact (struct ph1handle *);
124 126
125 127 /* %%%
126 128 * Information Exchange
127 129 */
128 130 /*
129 131 * receive Information
130 132 */
131 133 int
132 134 isakmp_info_recv(struct ph1handle *iph1, rc_vchar_t *msg0)
133 135 {
134 136 rc_vchar_t *msg = NULL;
135 137 struct isakmp *isakmp;
136 138 struct isakmp_gen *gen;
137 139 void *p;
138 140 rc_vchar_t *hash, *payload;
139 141 struct isakmp_gen *nd;
140 142 uint8_t np;
141 143 int encrypted;
142 144
143 145 plog(PLOG_DEBUG, PLOGLOC, NULL, "receive Information.\n");
144 146
145 147 encrypted = ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E);
146 148
147 149 /* Use new IV to decrypt Informational message. */
148 150 if (encrypted) {
149 151 struct isakmp_ivm *ivm;
150 152
151 153 if (iph1->ivm == NULL) {
152 154 plog(PLOG_INTERR, PLOGLOC, NULL, "iph1->ivm == NULL\n");
153 155 return -1;
154 156 }
155 157
156 158 /* compute IV */
157 159 ivm = oakley_newiv2(iph1, ((struct isakmp *)msg0->v)->msgid);
158 160 if (ivm == NULL)
159 161 return -1;
160 162
161 163 msg = oakley_do_decrypt(iph1, msg0, ivm->iv, ivm->ive);
162 164 oakley_delivm(ivm);
163 165 if (msg == NULL)
164 166 return -1;
165 167
166 168 } else
167 169 msg = rc_vdup(msg0);
168 170
169 171 /* Safety check */
170 172 if (msg->l < sizeof(*isakmp) + sizeof(*gen)) {
171 173 plog(PLOG_PROTOERR, PLOGLOC, NULL,
172 174 "ignore information because the "
173 175 "message is way too short\n");
174 176 goto end;
175 177 }
176 178
177 179 isakmp = (struct isakmp *)msg->v;
178 180 gen = (struct isakmp_gen *)((caddr_t)isakmp + sizeof(struct isakmp));
179 181 np = gen->np;
180 182
181 183 if (encrypted) {
182 184 if (isakmp->np != ISAKMP_NPTYPE_HASH) {
183 185 plog(PLOG_PROTOERR, PLOGLOC, NULL,
184 186 "ignore information because the "
185 187 "message has no hash payload.\n");
186 188 goto end;
187 189 }
188 190
189 191 if (iph1->status != PHASE1ST_ESTABLISHED) {
190 192 plog(PLOG_PROTOERR, PLOGLOC, NULL,
191 193 "ignore information because ISAKMP-SA "
192 194 "has not been established yet.\n");
193 195 goto end;
194 196 }
195 197
196 198 /* Safety check */
197 199 if (msg->l < sizeof(*isakmp) + get_uint16(&gen->len) + sizeof(*nd)) {
198 200 plog(PLOG_PROTOERR, PLOGLOC, NULL,
199 201 "ignore information because the "
200 202 "message is too short\n");
201 203 goto end;
202 204 }
203 205
204 206 p = (caddr_t) gen + sizeof(struct isakmp_gen);
205 207 nd = (struct isakmp_gen *) ((caddr_t) gen + get_uint16(&gen->len));
206 208
207 209 /* nd length check */
208 210 if (get_uint16(&nd->len) > msg->l - (sizeof(struct isakmp) +
209 211 get_uint16(&gen->len))) {
210 212 plog(PLOG_PROTOERR, PLOGLOC, NULL,
211 213 "too long payload length (broken message?)\n");
212 214 goto end;
213 215 }
214 216
215 217 if (get_uint16(&nd->len) < sizeof(*nd)) {
216 218 plog(PLOG_PROTOERR, PLOGLOC, NULL,
217 219 "too short payload length (broken message?)\n");
218 220 goto end;
219 221 }
220 222
221 223 payload = rc_vmalloc(get_uint16(&nd->len));
222 224 if (payload == NULL) {
223 225 plog(PLOG_INTERR, PLOGLOC, NULL,
224 226 "cannot allocate memory\n");
225 227 goto end;
226 228 }
227 229
228 230 memcpy(payload->v, (caddr_t) nd, get_uint16(&nd->len));
229 231
230 232 /* compute HASH */
231 233 hash = oakley_compute_hash1(iph1, isakmp->msgid, payload);
232 234 if (hash == NULL) {
233 235 plog(PLOG_INTERR, PLOGLOC, NULL,
234 236 "cannot compute hash\n");
235 237
236 238 rc_vfree(payload);
237 239 goto end;
238 240 }
239 241
240 242 if (get_uint16(&gen->len) - sizeof(struct isakmp_gen) != hash->l) {
241 243 plog(PLOG_PROTOERR, PLOGLOC, NULL,
242 244 "ignore information due to hash length mismatch\n");
243 245
244 246 rc_vfree(hash);
245 247 rc_vfree(payload);
246 248 goto end;
247 249 }
248 250
249 251 if (memcmp(p, hash->v, hash->l) != 0) {
250 252 plog(PLOG_PROTOERR, PLOGLOC, NULL,
251 253 "ignore information due to hash mismatch\n");
252 254
253 255 rc_vfree(hash);
254 256 rc_vfree(payload);
255 257 goto end;
256 258 }
257 259
258 260 plog(PLOG_DEBUG, PLOGLOC, NULL, "hash validated.\n");
259 261
260 262 rc_vfree(hash);
261 263 rc_vfree(payload);
262 264 } else {
263 265 /* make sure the packet was encrypted after the beginning of phase 1. */
264 266 switch (iph1->etype) {
265 267 case ISAKMP_ETYPE_AGG:
266 268 case ISAKMP_ETYPE_BASE:
267 269 case ISAKMP_ETYPE_IDENT:
268 270 if ((iph1->side == INITIATOR && iph1->status < PHASE1ST_MSG3SENT)
269 271 || (iph1->side == RESPONDER && iph1->status < PHASE1ST_MSG2SENT)) {
270 272 break;
271 273 }
272 274 /*FALLTHRU*/
273 275 default:
274 276 plog(PLOG_PROTOERR, PLOGLOC, 0,
275 277 "received %s payload is not encrypted\n",
276 278 s_isakmp_nptype(isakmp->np));
277 279 goto end;
278 280 }
279 281 }
280 282
281 283 switch (np) {
282 284 case ISAKMP_NPTYPE_N:
283 285 if ( encrypted )
284 286 isakmp_info_recv_n(iph1, msg);
285 287 else
286 288 plog(PLOG_PROTOWARN, PLOGLOC, 0,
287 289 "received unencrypted Notify payload, ignored\n");
288 290 break;
289 291 case ISAKMP_NPTYPE_D:
290 292 if ( encrypted )
291 293 isakmp_info_recv_d(iph1, msg);
292 294 else
293 295 plog(PLOG_PROTOWARN, PLOGLOC, 0,
294 296 "received unencrypted Delete payload, ignored\n");
295 297 break;
296 298 case ISAKMP_NPTYPE_NONCE:
297 299 /* XXX to be 6.4.2 ike-01.txt */
298 300 /* XXX IV is to be synchronized. */
299 301 plog(PLOG_PROTOERR, PLOGLOC, 0,
300 302 "ignore Acknowledged Informational\n");
301 303 break;
302 304 default:
303 305 /* don't send information, see isakmp_ident_r1() */
304 306 plog(PLOG_PROTOERR, PLOGLOC, 0,
305 307 "reject the packet, "
306 308 "received unexpected payload type %s.\n",
307 309 s_isakmp_nptype(gen->np));
308 310 goto end;
309 311 }
310 312
311 313 end:
312 314 if (msg != NULL)
313 315 rc_vfree(msg);
314 316 return 0;
315 317 }
316 318
317 319 /*
318 320 * send Delete payload (for ISAKMP SA) in Informational exchange.
319 321 */
320 322 int
321 323 isakmp_info_send_d1(struct ph1handle *iph1)
322 324 {
323 325 struct isakmp_pl_d *d;
324 326 rc_vchar_t *payload = NULL;
325 327 int tlen;
326 328 int error = 0;
327 329
328 330 if (iph1->status != PHASE2ST_ESTABLISHED)
329 331 return 0;
330 332
331 333 /* create delete payload */
332 334
333 335 /* send SPIs of inbound SAs. */
334 336 /* XXX should send outbound SAs's ? */
335 337 tlen = sizeof(*d) + sizeof(isakmp_index_t);
336 338 payload = rc_vmalloc(tlen);
337 339 if (payload == NULL) {
338 340 plog(PLOG_INTERR, PLOGLOC, NULL,
339 341 "failed to get buffer for payload.\n");
340 342 return errno;
341 343 }
342 344
343 345 d = (struct isakmp_pl_d *)payload->v;
344 346 d->h.np = ISAKMP_NPTYPE_NONE;
345 347 put_uint16(&d->h.len, tlen);
346 348 put_uint32(&d->doi, IPSEC_DOI);
347 349 d->proto_id = IPSECDOI_PROTO_ISAKMP;
348 350 d->spi_size = sizeof(isakmp_index_t);
349 351 put_uint16(&d->num_spi, 1);
350 352 memcpy(d + 1, &iph1->index, sizeof(isakmp_index_t));
351 353
352 354 error = isakmp_info_send_common(iph1, payload,
353 355 ISAKMP_NPTYPE_D, 0);
354 356 rc_vfree(payload);
355 357
356 358 return error;
357 359 }
358 360
359 361 /*
360 362 * send Delete payload (for IPsec SA) in Informational exchange, based on
361 363 * pfkey msg. It sends always single SPI.
362 364 */
363 365 int
364 366 isakmp_info_send_d2(struct ph2handle *iph2)
365 367 {
366 368 struct ph1handle *iph1;
367 369 struct saproto *pr;
368 370 struct isakmp_pl_d *d;
369 371 rc_vchar_t *payload = NULL;
370 372 int tlen;
371 373 int error = 0;
372 374 uint8_t *spi;
373 375
374 376 if (iph2->status != PHASE2ST_ESTABLISHED)
375 377 return 0;
376 378
377 379 /*
378 380 * don't send delete information if there is no phase 1 handler.
379 381 * It's nonsensical to negotiate phase 1 to send the information.
380 382 */
381 383 iph1 = getph1byaddr(iph2->src, iph2->dst);
382 384 if (iph1 == NULL)
383 385 return 0;
384 386
385 387 /* create delete payload */
386 388 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
387 389
388 390 /* send SPIs of inbound SAs. */
389 391 /*
390 392 * XXX should I send outbound SAs's ?
391 393 * I send inbound SAs's SPI only at the moment because I can't
392 394 * decode any more if peer send encoded packet without aware of
393 395 * deletion of SA. Outbound SAs don't come under the situation.
394 396 */
395 397 tlen = sizeof(*d) + pr->spisize;
396 398 payload = rc_vmalloc(tlen);
397 399 if (payload == NULL) {
398 400 plog(PLOG_INTERR, PLOGLOC, NULL,
399 401 "failed to get buffer for payload.\n");
400 402 return errno;
401 403 }
402 404
403 405 d = (struct isakmp_pl_d *)payload->v;
404 406 d->h.np = ISAKMP_NPTYPE_NONE;
405 407 put_uint16(&d->h.len, tlen);
406 408 put_uint32(&d->doi, IPSEC_DOI);
407 409 d->proto_id = pr->proto_id;
408 410 d->spi_size = pr->spisize;
409 411 put_uint16(&d->num_spi, 1);
410 412 /*
411 413 * XXX SPI bits are left-filled, for use with IPComp.
412 414 * we should be switching to variable-length spi field...
413 415 */
414 416 spi = (uint8_t *)&pr->spi;
415 417 spi += sizeof(pr->spi);
416 418 spi -= pr->spisize;
417 419 memcpy(d + 1, spi, pr->spisize);
418 420
419 421 error = isakmp_info_send_common(iph1, payload,
420 422 ISAKMP_NPTYPE_D, 0);
421 423 rc_vfree(payload);
422 424 }
423 425
424 426 return error;
425 427 }
426 428
427 429 /*
428 430 * send Notification payload (for without ISAKMP SA) in Informational exchange
429 431 */
430 432 int
431 433 isakmp_info_send_nx(struct isakmp *isakmp, struct sockaddr *remote, struct sockaddr *local,
432 434 int type, rc_vchar_t *data)
433 435 {
434 436 struct ph1handle *iph1 = NULL;
435 437 struct rcf_remote *rmconf;
436 438 rc_vchar_t *payload = NULL;
437 439 int tlen;
438 440 int error = -1;
439 441 struct isakmp_pl_n *n;
440 442 int spisiz = 0; /* see below */
441 443
442 444 /* search appropreate configuration */
443 445 rmconf = getrmconf(remote);
444 446 if (rmconf == NULL) {
445 447 plog(PLOG_INTERR, PLOGLOC, 0,
446 448 "no configuration found for peer address.\n");
447 449 goto end;
448 450 }
449 451
450 452 /* add new entry to isakmp status table. */
451 453 iph1 = newph1();
452 454 if (iph1 == NULL)
453 455 return -1;
454 456
455 457 memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(isakmp_cookie_t));
456 458 isakmp_newcookie((char *)&iph1->index.r_ck, remote, local);
457 459 iph1->status = PHASE1ST_START;
458 460 iph1->rmconf = rmconf;
459 461 iph1->side = INITIATOR;
460 462 iph1->version = isakmp->v;
461 463 iph1->flags = 0;
462 464 iph1->msgid = 0; /* XXX */
463 465 #ifdef ENABLE_HYBRID
464 466 if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) {
465 467 error = -1;
466 468 goto end;
467 469 }
468 470 #endif
469 471 #ifdef ENABLE_FRAG
470 472 iph1->frag = 0;
471 473 iph1->frag_chain = NULL;
472 474 #endif
473 475 iph1->proposal = ikev1_conf_to_isakmpsa(rmconf);
474 476
475 477 /* copy remote address */
476 478 if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
477 479 error = -1;
478 480 goto end;
479 481 }
480 482
481 483 tlen = sizeof(*n) + spisiz;
482 484 if (data)
483 485 tlen += data->l;
484 486 payload = rc_vmalloc(tlen);
485 487 if (payload == NULL) {
486 488 plog(PLOG_INTERR, PLOGLOC, NULL,
487 489 "failed to get buffer to send.\n");
488 490 error = -1;
489 491 goto end;
490 492 }
491 493
492 494 n = (struct isakmp_pl_n *)payload->v;
493 495 n->h.np = ISAKMP_NPTYPE_NONE;
494 496 put_uint16(&n->h.len, tlen);
495 497 put_uint32(&n->doi, IPSEC_DOI);
496 498 n->proto_id = IPSECDOI_KEY_IKE;
497 499 n->spi_size = spisiz;
498 500 put_uint16(&n->type, type);
499 501 if (spisiz)
500 502 memset(n + 1, 0, spisiz); /*XXX*/
501 503 if (data)
502 504 memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
503 505
504 506 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
505 507 rc_vfree(payload);
506 508
507 509 end:
508 510 if (iph1 != NULL)
509 511 delph1(iph1);
510 512
511 513 return error;
512 514 }
513 515
514 516 /*
515 517 * send Notification payload (for ISAKMP SA) in Informational exchange
516 518 */
517 519 int
518 520 isakmp_info_send_n1(struct ph1handle *iph1, int type, rc_vchar_t *data)
519 521 {
520 522 rc_vchar_t *payload = NULL;
521 523 int tlen;
522 524 int error = 0;
523 525 struct isakmp_pl_n *n;
524 526 int spisiz;
525 527
526 528 /*
527 529 * note on SPI size: which description is correct? I have chosen
528 530 * this to be 0.
529 531 *
530 532 * RFC2408 3.1, 2nd paragraph says: ISAKMP SA is identified by
531 533 * Initiator/Responder cookie and SPI has no meaning, SPI size = 0.
532 534 * RFC2408 3.1, first paragraph on page 40: ISAKMP SA is identified
533 535 * by cookie and SPI has no meaning, 0 <= SPI size <= 16.
534 536 * RFC2407 4.6.3.3, INITIAL-CONTACT is required to set to 16.
535 537 */
536 538 if (type == ISAKMP_NTYPE_INITIAL_CONTACT)
537 539 spisiz = sizeof(isakmp_index_t);
538 540 else
539 541 spisiz = 0;
540 542
541 543 tlen = sizeof(*n) + spisiz;
542 544 if (data)
543 545 tlen += data->l;
544 546 payload = rc_vmalloc(tlen);
545 547 if (payload == NULL) {
546 548 plog(PLOG_INTERR, PLOGLOC, NULL,
547 549 "failed to get buffer to send.\n");
548 550 return errno;
549 551 }
550 552
551 553 n = (struct isakmp_pl_n *)payload->v;
552 554 n->h.np = ISAKMP_NPTYPE_NONE;
553 555 put_uint16(&n->h.len, tlen);
554 556 put_uint32(&n->doi, ikev1_doitype(iph1->rmconf));
555 557 n->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX to be configurable ? */
556 558 n->spi_size = spisiz;
557 559 put_uint16(&n->type, type);
558 560 if (spisiz)
559 561 memcpy(n + 1, &iph1->index, sizeof(isakmp_index_t));
560 562 if (data)
561 563 memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
562 564
563 565 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph1->flags);
564 566 rc_vfree(payload);
565 567
566 568 return error;
567 569 }
568 570
569 571 /*
570 572 * send Notification payload (for IPsec SA) in Informational exchange
571 573 */
572 574 int
573 575 isakmp_info_send_n2(struct ph2handle *iph2, int type, rc_vchar_t *data)
574 576 {
575 577 struct ph1handle *iph1 = iph2->ph1;
576 578 rc_vchar_t *payload = NULL;
577 579 int tlen;
578 580 int error = 0;
579 581 struct isakmp_pl_n *n;
580 582 struct saproto *pr;
581 583
582 584 if (!iph2->approval)
583 585 return EINVAL;
584 586
585 587 pr = iph2->approval->head;
586 588
587 589 /* XXX must be get proper spi */
588 590 tlen = sizeof(*n) + pr->spisize;
589 591 if (data)
590 592 tlen += data->l;
591 593 payload = rc_vmalloc(tlen);
592 594 if (payload == NULL) {
593 595 plog(PLOG_INTERR, PLOGLOC, NULL,
594 596 "failed to get buffer to send.\n");
595 597 return errno;
596 598 }
597 599
598 600 n = (struct isakmp_pl_n *)payload->v;
599 601 n->h.np = ISAKMP_NPTYPE_NONE;
600 602 put_uint16(&n->h.len, tlen);
601 603 put_uint32(&n->doi, IPSEC_DOI); /* IPSEC DOI (1) */
602 604 n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/
603 605 n->spi_size = pr->spisize;
604 606 put_uint16(&n->type, type);
605 607 memcpy((uint8_t *)(n + 1), &pr->spi, pr->spisize);
606 608 if (data)
607 609 memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
608 610
609 611 iph2->flags |= ISAKMP_FLAG_E; /* XXX Should we do FLAG_A ? */
610 612 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph2->flags);
611 613 rc_vfree(payload);
612 614
613 615 return error;
614 616 }
615 617
616 618 /*
617 619 * send Information
618 620 * When ph1->skeyid_a == NULL, send message without encoding.
619 621 */
620 622 int
621 623 isakmp_info_send_common(struct ph1handle *iph1, rc_vchar_t *payload, uint32_t np, int flags)
622 624 {
623 625 struct ph2handle *iph2 = NULL;
624 626 rc_vchar_t *hash = NULL;
625 627 struct isakmp *isakmp;
626 628 struct isakmp_gen *gen;
627 629 char *p;
628 630 int tlen;
629 631 int error = -1;
630 632
631 633 /* add new entry to isakmp status table */
632 634 iph2 = newph2();
633 635 if (iph2 == NULL)
634 636 goto end;
635 637
636 638 iph2->dst = rcs_sadup(iph1->remote);
637 639 if (iph2->dst == NULL) {
638 640 delph2(iph2);
639 641 goto end;
640 642 }
641 643
642 644 iph2->src = rcs_sadup(iph1->local);
643 645 if (iph2->src == NULL) {
644 646 delph2(iph2);
645 647 goto end;
646 648 }
647 649
648 650 iph2->ph1 = iph1;
649 651 iph2->side = INITIATOR;
650 652 iph2->status = PHASE2ST_START;
651 653 iph2->msgid = isakmp_newmsgid2(iph1);
652 654
653 655 /* get IV and HASH(1) if skeyid_a was generated. */
654 656 if (iph1->skeyid_a != NULL) {
655 657 iph2->ivm = oakley_newiv2(iph1, iph2->msgid);
656 658 if (iph2->ivm == NULL) {
657 659 delph2(iph2);
658 660 goto end;
659 661 }
660 662
661 663 /* generate HASH(1) */
662 664 hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, payload);
663 665 if (hash == NULL) {
664 666 delph2(iph2);
665 667 goto end;
666 668 }
667 669
668 670 /* initialized total buffer length */
669 671 tlen = hash->l;
670 672 tlen += sizeof(*gen);
671 673 } else {
672 674 /* IKE-SA is not established */
673 675 hash = NULL;
674 676
675 677 /* initialized total buffer length */
676 678 tlen = 0;
677 679 }
678 680 if ((flags & ISAKMP_FLAG_A) == 0)
679 681 iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
680 682 else
681 683 iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
682 684
683 685 insph2(iph2);
684 686 bindph12(iph1, iph2);
685 687
686 688 tlen += sizeof(*isakmp) + payload->l;
687 689
688 690 /* create buffer for isakmp payload */
689 691 iph2->sendbuf = rc_vmalloc(tlen);
690 692 if (iph2->sendbuf == NULL) {
691 693 plog(PLOG_INTERR, PLOGLOC, NULL,
692 694 "failed to get buffer to send.\n");
693 695 goto err;
694 696 }
695 697
696 698 /* create isakmp header */
697 699 isakmp = (struct isakmp *)iph2->sendbuf->v;
698 700 memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(isakmp_cookie_t));
699 701 memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(isakmp_cookie_t));
700 702 isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
701 703 isakmp->v = iph1->version;
702 704 isakmp->etype = ISAKMP_ETYPE_INFO;
703 705 isakmp->flags = iph2->flags;
704 706 memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
705 707 put_uint32(&isakmp->len, tlen);
706 708 p = (char *)(isakmp + 1);
707 709
708 710 /* create HASH payload */
709 711 if (hash != NULL) {
710 712 gen = (struct isakmp_gen *)p;
711 713 gen->np = np & 0xff;
712 714 put_uint16(&gen->len, sizeof(*gen) + hash->l);
713 715 p += sizeof(*gen);
714 716 memcpy(p, hash->v, hash->l);
715 717 p += hash->l;
716 718 }
717 719
718 720 /* add payload */
719 721 memcpy(p, payload->v, payload->l);
720 722 p += payload->l;
721 723
722 724 #ifdef HAVE_PRINT_ISAKMP_C
723 725 isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
724 726 #endif
725 727
726 728 /* encoding */
727 729 if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
728 730 rc_vchar_t *tmp;
729 731
730 732 tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, iph2->ivm->ive,
731 733 iph2->ivm->iv);
732 734 VPTRINIT(iph2->sendbuf);
733 735 if (tmp == NULL)
734 736 goto err;
735 737 iph2->sendbuf = tmp;
736 738 }
737 739
738 740 /* HDR*, HASH(1), N */
739 741 if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
740 742 VPTRINIT(iph2->sendbuf);
741 743 goto err;
742 744 }
743 745
744 746 plog(PLOG_DEBUG, PLOGLOC, NULL,
745 747 "sendto Information %s.\n", s_isakmp_nptype(np));
746 748
747 749 /*
748 750 * don't resend notify message because peer can use Acknowledged
749 751 * Informational if peer requires the reply of the notify message.
750 752 */
751 753
752 754 /* XXX If Acknowledged Informational required, don't delete ph2handle */
753 755 error = 0;
754 756 VPTRINIT(iph2->sendbuf);
755 757 goto err; /* XXX */
756 758
757 759 end:
758 760 if (hash)
759 761 rc_vfree(hash);
760 762 return error;
761 763
762 764 err:
763 765 unbindph12(iph2);
764 766 remph2(iph2);
765 767 delph2(iph2);
766 768 goto end;
767 769 }
768 770
769 771 /*
770 772 * add a notify payload to buffer by reallocating buffer.
771 773 * If buf == NULL, the function only create a notify payload.
772 774 *
773 775 * XXX Which is SPI to be included, inbound or outbound ?
774 776 */
775 777 rc_vchar_t *
776 778 isakmp_add_pl_n(rc_vchar_t *buf0, uint8_t **np_p, int type,
777 779 struct saproto *pr, rc_vchar_t *data)
778 780 {
779 781 rc_vchar_t *buf = NULL;
780 782 struct isakmp_pl_n *n;
781 783 int tlen;
782 784 int oldlen = 0;
783 785
784 786 if (*np_p)
785 787 **np_p = ISAKMP_NPTYPE_N;
786 788
787 789 tlen = sizeof(*n) + pr->spisize;
788 790
789 791 if (data)
790 792 tlen += data->l;
791 793 if (buf0) {
792 794 oldlen = buf0->l;
793 795 buf = rc_vrealloc(buf0, buf0->l + tlen);
794 796 } else
795 797 buf = rc_vmalloc(tlen);
796 798 if (!buf) {
797 799 plog(PLOG_INTERR, PLOGLOC, NULL,
798 800 "failed to get a payload buffer.\n");
799 801 return NULL;
800 802 }
801 803
802 804 n = (struct isakmp_pl_n *)(buf->v + oldlen);
803 805 n->h.np = ISAKMP_NPTYPE_NONE;
804 806 put_uint16(&n->h.len, tlen);
805 807 put_uint32(&n->doi, IPSEC_DOI); /* IPSEC DOI (1) */
806 808 n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/
807 809 n->spi_size = pr->spisize;
808 810 put_uint16(&n->type, type);
809 811 memcpy((uint8_t *)(n + 1), &pr->spi, pr->spisize);
810 812 if (data)
811 813 memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
812 814
813 815 /* save the pointer of next payload type */
814 816 *np_p = &n->h.np;
815 817
816 818 return buf;
817 819 }
818 820
819 821 /*
820 822 * handling to receive Notification payload
821 823 */
822 824 static int
823 825 isakmp_info_recv_n(struct ph1handle *iph1, rc_vchar_t *msg)
824 826 {
825 827 struct isakmp_pl_n *n = NULL;
826 828 unsigned int type;
827 829 rc_vchar_t *pbuf;
828 830 struct isakmp_parse_t *pa, *pap;
829 831 char *spi;
830 832
831 833 if (!(pbuf = isakmp_parse(msg)))
832 834 return -1;
833 835 pa = (struct isakmp_parse_t *)pbuf->v;
834 836 for (pap = pa; pap->type; pap++) {
835 837 switch (pap->type) {
836 838 case ISAKMP_NPTYPE_HASH:
837 839 /* do something here */
838 840 break;
839 841 case ISAKMP_NPTYPE_NONCE:
840 842 /* send to ack */
841 843 break;
842 844 case ISAKMP_NPTYPE_N:
843 845 n = (struct isakmp_pl_n *)pap->ptr;
844 846 break;
845 847 default:
846 848 rc_vfree(pbuf);
847 849 return -1;
848 850 }
849 851 }
850 852 rc_vfree(pbuf);
851 853 if (!n)
852 854 return -1;
853 855
854 856 type = get_uint16(&n->type);
855 857
856 858 switch (type) {
857 859 case ISAKMP_NTYPE_CONNECTED:
858 860 case ISAKMP_NTYPE_RESPONDER_LIFETIME:
859 861 case ISAKMP_NTYPE_REPLAY_STATUS:
860 862 /* do something */
861 863 break;
862 864 case ISAKMP_NTYPE_INITIAL_CONTACT:
863 865 info_recv_initialcontact(iph1);
864 866 break;
865 867 case ISAKMP_NTYPE_R_U_THERE:
866 868 isakmp_info_recv_r_u(iph1, (struct isakmp_pl_ru *)n,
867 869 ((struct isakmp *)msg->v)->msgid);
868 870 break;
869 871 case ISAKMP_NTYPE_R_U_THERE_ACK:
870 872 isakmp_info_recv_r_u_ack(iph1, (struct isakmp_pl_ru *)n,
871 873 ((struct isakmp *)msg->v)->msgid);
872 874 break;
873 875
874 876 default:
875 877 {
876 878 uint32_t msgid = ((struct isakmp *)msg->v)->msgid;
877 879 struct ph2handle *iph2;
878 880
|
↓ open down ↓ |
821 lines elided |
↑ open up ↑ |
879 881 /* XXX there is a potential of dos attack. */
880 882 if (msgid == 0) {
881 883 /* delete ph1 */
882 884 plog(PLOG_PROTOERR, PLOGLOC, 0,
883 885 "delete phase1 handle.\n");
884 886 return -1;
885 887 } else {
886 888 iph2 = getph2bymsgid(iph1, msgid);
887 889 if (iph2 == NULL) {
888 890 plog(PLOG_PROTOERR, PLOGLOC, 0,
889 - "unknown notify message, "
890 - "no phase2 handle found.\n");
891 + "unknown notify message (%d), "
892 + "no phase2 handle found.\n", type);
891 893 } else {
892 894 /* delete ph2 */
893 895 unbindph12(iph2);
894 896 remph2(iph2);
895 897 delph2(iph2);
896 898 }
897 899 }
898 900 }
899 901 break;
900 902 }
901 903
902 904 /* get spi and allocate */
903 905 if (get_uint16(&n->h.len) < sizeof(*n) + n->spi_size) {
904 906 plog(PLOG_PROTOERR, PLOGLOC, 0,
905 907 "invalid spi_size in notification payload.\n");
906 908 return -1;
907 909 }
908 910 spi = val2str((char *)(n + 1), n->spi_size);
909 911
910 912 plog(PLOG_DEBUG, PLOGLOC, 0,
911 913 "notification message %d:%s, "
912 914 "doi=%d proto_id=%d spi=%s(size=%d).\n",
913 915 type, s_isakmp_notify_msg(type),
914 916 get_uint32(&n->doi), n->proto_id, spi, n->spi_size);
915 917
916 918 racoon_free(spi);
917 919
918 920 return(0);
919 921 }
920 922
921 923 #if 0
922 924 static void
923 925 purge_isakmp_spi(proto, spi, n)
924 926 int proto;
925 927 isakmp_index_t *spi; /*network byteorder*/
926 928 size_t n;
927 929 {
928 930 struct ph1handle *iph1;
929 931 size_t i;
930 932
931 933 for (i = 0; i < n; i++) {
932 934 iph1 = getph1byindex(&spi[i]);
933 935 if (!iph1)
934 936 continue;
935 937
936 938 plog(PLOG_INFO, PLOGLOC, NULL,
937 939 "purged ISAKMP-SA proto_id=%s spi=%s.\n",
938 940 s_ipsecdoi_proto(proto),
939 941 isakmp_pindex(&spi[i], 0));
940 942
941 943 if (iph1->sce)
942 944 SCHED_KILL(iph1->sce);
943 945 iph1->status = PHASE1ST_EXPIRED;
944 946 iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
945 947 }
946 948 }
947 949 #endif
948 950
949 951
950 952 /*
951 953 * delete all phase2 sa relatived to the destination address.
952 954 * Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore
953 955 * an INITIAL-CONTACT if we have contacted the peer. This matches the
954 956 * Sun IKE behavior, and makes rekeying work much better when the peer
955 957 * restarts.
956 958 */
957 959 static void
958 960 info_recv_initialcontact(struct ph1handle *iph1)
959 961 {
960 962 plog(PLOG_INFO, PLOGLOC, 0,
961 963 "INITIALCONTACT processing unimplemented");
962 964
963 965 #ifdef notyet
964 966 struct ph2handle *ph2;
965 967 struct ph2handle *next_ph2;
966 968 struct saprop *pp;
967 969 struct saproto *pr;
968 970
969 971 plog(PLOG_INFO, PLOGLOC, 0,
970 972 "processing INITIALCONTACT for %s->%s\n",
971 973 rcs_sa2str(iph1->local), rcs_sa2str(iph1->remote));
972 974
973 975 for (ph2 = LIST_FIRST(&ph2tree); ph2; ph2 = next_ph2) {
974 976 next_ph2 = LIST_NEXT(ph2, chain);
975 977
976 978 #ifdef ENABLE_NATT
977 979 /*
978 980 * XXX RFC 3947 says that whe MUST NOT use IP+port to find old SAs
979 981 * from this peer !
980 982 */
981 983 if(iph1->natt_flags & NAT_DETECTED){
982 984 if (CMPSADDR(iph1->local, ph2->src) == 0 &&
983 985 CMPSADDR(iph1->remote, ph2->dst) == 0)
984 986 ;
985 987 else if (CMPSADDR(iph1->remote, ph2->src) == 0 &&
986 988 CMPSADDR(iph1->local, ph2->dst) == 0)
987 989 ;
988 990 else
989 991 continue;
990 992 } else
991 993 #endif
992 994 /* If there is no NAT-T, we don't have to check addr + port...
993 995 * XXX what about a configuration with a remote peers which is not
994 996 * NATed, but which NATs some other peers ?
995 997 * Here, the INITIAl-CONTACT would also flush all those NATed peers !!
996 998 */
997 999 if (rcs_cmpsa_wop(iph1->local, ph2->src) == 0 &&
998 1000 rcs_cmpsa_wop(iph1->remote, ph2->dst) == 0)
999 1001 ;
1000 1002 else if (rcs_cmpsa_wop(iph1->remote, ph2->src) == 0 &&
1001 1003 rcs_cmpsa_wop(iph1->local, ph2->dst) == 0)
1002 1004 ;
1003 1005 else
1004 1006 continue;
1005 1007
1006 1008 pp = ph2->approval;
1007 1009 if (! pp) {
1008 1010 TRACE((PLOGLOC, "no negotiated protocols, skipping\n"));
1009 1011 continue;
1010 1012 }
1011 1013
1012 1014 for (pr = pp->head; pr; pr = pr->next) {
1013 1015 plog(PLOG_INFO, PLOGLOC, NULL,
1014 1016 "purging proto=%d spi=%lu outbound.\n",
1015 1017 pr->proto_id, ntohl(pr->spi_p));
1016 1018 delete_ipsec_sa(&ph2->sadb_request,
1017 1019 ph2->src, ph2->dst,
1018 1020 pr->proto_id, pr->spi_p);
1019 1021 plog(PLOG_INFO, PLOGLOC, NULL,
1020 1022 "purging proto=%d spi=%lu inbound.\n",
1021 1023 pr->proto_id, ntohl(pr->spi));
1022 1024 delete_ipsec_sa(&ph2->sadb_request,
1023 1025 ph2->dst, ph2->src,
1024 1026 pr->proto_id, pr->spi);
1025 1027 }
1026 1028
1027 1029 destroy_ph2(ph2);
1028 1030 }
1029 1031 #endif
1030 1032 }
1031 1033
1032 1034 /*
1033 1035 * handling to receive Deletion payload
1034 1036 */
1035 1037 static int
1036 1038 isakmp_info_recv_d(struct ph1handle *iph1, rc_vchar_t *msg)
1037 1039 {
1038 1040 struct isakmp_pl_d *d;
1039 1041 int tlen, num_spi;
1040 1042 rc_vchar_t *pbuf;
1041 1043 struct isakmp_parse_t *pa, *pap;
1042 1044 int protected = 0;
1043 1045 union {
1044 1046 uint32_t spi32;
1045 1047 uint16_t spi16[2];
1046 1048 } spi;
1047 1049
1048 1050 /* validate the type of next payload */
1049 1051 if (!(pbuf = isakmp_parse(msg)))
1050 1052 return -1;
1051 1053 pa = (struct isakmp_parse_t *)pbuf->v;
1052 1054 for (pap = pa; pap->type; pap++) {
1053 1055 switch (pap->type) {
1054 1056 case ISAKMP_NPTYPE_D:
1055 1057 break;
1056 1058 case ISAKMP_NPTYPE_HASH:
1057 1059 if (pap == pa) {
1058 1060 protected++;
1059 1061 break;
1060 1062 }
1061 1063 plog(PLOG_PROTOERR, PLOGLOC, 0,
1062 1064 "received next payload type %d "
1063 1065 "in wrong place (must be the first payload).\n",
1064 1066 pap->type);
1065 1067 rc_vfree(pbuf);
1066 1068 return -1;
1067 1069 default:
1068 1070 /* don't send information, see isakmp_ident_r1() */
1069 1071 plog(PLOG_PROTOERR, PLOGLOC, 0,
1070 1072 "reject the packet, "
1071 1073 "received unexpecting payload type %d.\n",
1072 1074 pap->type);
1073 1075 rc_vfree(pbuf);
1074 1076 return 0;
1075 1077 }
1076 1078 }
1077 1079
1078 1080 if (!protected) {
1079 1081 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1080 1082 "delete payload is not proteted, "
1081 1083 "ignored.\n");
1082 1084 rc_vfree(pbuf);
1083 1085 return -1;
1084 1086 }
1085 1087
1086 1088 /* process a delete payload */
1087 1089 for (pap = pa; pap->type; pap++) {
1088 1090 if (pap->type != ISAKMP_NPTYPE_D)
1089 1091 continue;
1090 1092
1091 1093 d = (struct isakmp_pl_d *)pap->ptr;
1092 1094
1093 1095 if (get_uint32(&d->doi) != IPSEC_DOI) {
1094 1096 plog(PLOG_PROTOERR, PLOGLOC, 0,
1095 1097 "delete payload with invalid doi:%d.\n",
1096 1098 get_uint32(&d->doi));
1097 1099 #ifdef ENABLE_HYBRID
1098 1100 /*
1099 1101 * At deconnexion time, Cisco VPN client does this
1100 1102 * with a zero DOI. Don't give up in that situation.
1101 1103 */
1102 1104 if (((iph1->mode_cfg->flags &
1103 1105 ISAKMP_CFG_VENDORID_UNITY) == 0) || (d->doi != 0))
1104 1106 continue;
1105 1107 #else
1106 1108 continue;
1107 1109 #endif
1108 1110 }
1109 1111
1110 1112 num_spi = get_uint16(&d->num_spi);
1111 1113 tlen = get_uint16(&d->h.len) - sizeof(struct isakmp_pl_d);
1112 1114
1113 1115 if (tlen != num_spi * d->spi_size) {
1114 1116 plog(PLOG_PROTOERR, PLOGLOC, 0,
1115 1117 "deletion payload with invalid length.\n");
1116 1118 rc_vfree(pbuf);
1117 1119 return -1;
1118 1120 }
1119 1121
1120 1122 switch (d->proto_id) {
1121 1123 case IPSECDOI_PROTO_ISAKMP:
1122 1124 if (d->spi_size != sizeof(isakmp_index_t)) {
1123 1125 plog(PLOG_PROTOERR, PLOGLOC, 0,
1124 1126 "delete payload with strange spi "
1125 1127 "size %d(proto_id:%d)\n",
1126 1128 d->spi_size, d->proto_id);
1127 1129 continue;
1128 1130 }
1129 1131
1130 1132 if (iph1->scr)
1131 1133 SCHED_KILL(iph1->scr);
1132 1134
1133 1135 purge_remote(iph1);
1134 1136 break;
1135 1137
1136 1138 case IPSECDOI_PROTO_IPSEC_AH:
1137 1139 case IPSECDOI_PROTO_IPSEC_ESP:
1138 1140 if (d->spi_size != sizeof(uint32_t)) {
1139 1141 plog(PLOG_PROTOERR, PLOGLOC, 0,
1140 1142 "delete payload with strange spi "
1141 1143 "size %d(proto_id:%d)\n",
1142 1144 d->spi_size, d->proto_id);
1143 1145 continue;
1144 1146 }
1145 1147 EVT_PUSH(iph1->local, iph1->remote,
1146 1148 EVTT_PEER_DELETE, NULL);
1147 1149 purge_ipsec_spi(iph1, iph1->remote, d->proto_id,
1148 1150 (uint32_t *)(d + 1), num_spi);
1149 1151 break;
1150 1152
1151 1153 case IPSECDOI_PROTO_IPCOMP:
1152 1154 /* need to handle both 16bit/32bit SPI */
1153 1155 memset(&spi, 0, sizeof(spi));
1154 1156 if (d->spi_size == sizeof(spi.spi16[1])) {
1155 1157 memcpy(&spi.spi16[1], d + 1,
1156 1158 sizeof(spi.spi16[1]));
1157 1159 } else if (d->spi_size == sizeof(spi.spi32))
1158 1160 memcpy(&spi.spi32, d + 1, sizeof(spi.spi32));
1159 1161 else {
1160 1162 plog(PLOG_PROTOERR, PLOGLOC, 0,
1161 1163 "delete payload with strange spi "
1162 1164 "size %d(proto_id:%d)\n",
1163 1165 d->spi_size, d->proto_id);
1164 1166 continue;
1165 1167 }
1166 1168 purge_ipsec_spi(iph1, iph1->remote, d->proto_id,
1167 1169 &spi.spi32, num_spi);
1168 1170 break;
1169 1171
1170 1172 default:
1171 1173 plog(PLOG_PROTOERR, PLOGLOC, 0,
1172 1174 "deletion message received, "
1173 1175 "invalid proto_id: %d\n",
1174 1176 d->proto_id);
1175 1177 continue;
1176 1178 }
1177 1179
1178 1180 plog(PLOG_DEBUG, PLOGLOC, NULL, "purged SAs.\n");
1179 1181 }
1180 1182
1181 1183 rc_vfree(pbuf);
1182 1184
1183 1185 return 0;
1184 1186 }
1185 1187
1186 1188 void
1187 1189 isakmp_check_notify(struct isakmp_gen *gen, /* points to Notify payload */
1188 1190 struct ph1handle *iph1)
1189 1191 {
1190 1192 struct isakmp_pl_n *notify = (struct isakmp_pl_n *)gen;
1191 1193
1192 1194 plog(PLOG_DEBUG, PLOGLOC, 0,
1193 1195 "Notify Message received\n");
1194 1196
1195 1197 switch (get_uint16(¬ify->type)) {
1196 1198 case ISAKMP_NTYPE_CONNECTED:
1197 1199 case ISAKMP_NTYPE_RESPONDER_LIFETIME:
1198 1200 case ISAKMP_NTYPE_REPLAY_STATUS:
1199 1201 case ISAKMP_NTYPE_HEARTBEAT:
1200 1202 #ifdef ENABLE_HYBRID
1201 1203 case ISAKMP_NTYPE_UNITY_HEARTBEAT:
1202 1204 #endif
1203 1205 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1204 1206 "ignore %s notification.\n",
1205 1207 s_isakmp_notify_msg(get_uint16(¬ify->type)));
1206 1208 break;
1207 1209 case ISAKMP_NTYPE_INITIAL_CONTACT:
1208 1210 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1209 1211 "ignore INITIAL-CONTACT notification, "
1210 1212 "because it is only accepted after phase1.\n");
1211 1213 break;
1212 1214 default:
1213 1215 isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
1214 1216 plog(PLOG_PROTOERR, PLOGLOC, 0,
1215 1217 "received unknown notification type %s.\n",
1216 1218 s_isakmp_notify_msg(get_uint16(¬ify->type)));
1217 1219 }
1218 1220
1219 1221 return;
1220 1222 }
1221 1223
1222 1224
1223 1225 static int
1224 1226 isakmp_info_recv_r_u (struct ph1handle *iph1, struct isakmp_pl_ru *ru, uint32_t msgid)
1225 1227 {
1226 1228 struct isakmp_pl_ru *ru_ack;
1227 1229 rc_vchar_t *payload = NULL;
1228 1230 int tlen;
1229 1231 int error = 0;
1230 1232
1231 1233 plog(PLOG_DEBUG, PLOGLOC, 0,
1232 1234 "DPD R-U-There received\n");
1233 1235
1234 1236 /* XXX should compare cookies with iph1->index?
1235 1237 Or is this already done by calling function? */
1236 1238 tlen = sizeof(*ru_ack);
1237 1239 payload = rc_vmalloc(tlen);
1238 1240 if (payload == NULL) {
1239 1241 plog(PLOG_INTERR, PLOGLOC, NULL,
1240 1242 "failed to get buffer to send.\n");
1241 1243 return errno;
1242 1244 }
1243 1245
1244 1246 ru_ack = (struct isakmp_pl_ru *)payload->v;
1245 1247 ru_ack->h.np = ISAKMP_NPTYPE_NONE;
1246 1248 put_uint16(&ru_ack->h.len, tlen);
1247 1249 put_uint32(&ru_ack->doi, IPSEC_DOI);
1248 1250 put_uint16(&ru_ack->type, ISAKMP_NTYPE_R_U_THERE_ACK);
1249 1251 ru_ack->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ? */
1250 1252 ru_ack->spi_size = sizeof(isakmp_index_t);
1251 1253 memcpy(ru_ack->i_ck, ru->i_ck, sizeof(isakmp_cookie_t));
1252 1254 memcpy(ru_ack->r_ck, ru->r_ck, sizeof(isakmp_cookie_t));
1253 1255 ru_ack->data = ru->data;
1254 1256
1255 1257 /* XXX Should we do FLAG_A ? */
1256 1258 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N,
1257 1259 ISAKMP_FLAG_E);
1258 1260 rc_vfree(payload);
1259 1261
1260 1262 plog(PLOG_DEBUG, PLOGLOC, NULL, "received a valid R-U-THERE, ACK sent\n");
1261 1263
1262 1264 /* Should we mark tunnel as active ? */
1263 1265 return error;
1264 1266 }
1265 1267
1266 1268 static int
1267 1269 isakmp_info_recv_r_u_ack (struct ph1handle *iph1,
1268 1270 struct isakmp_pl_ru *ru, uint32_t msgid)
1269 1271 {
1270 1272
1271 1273 plog(PLOG_DEBUG, PLOGLOC, 0,
1272 1274 "DPD R-U-There-Ack received\n");
1273 1275
1274 1276 /* XXX Maintain window of acceptable sequence numbers ?
1275 1277 * => ru->data <= iph2->dpd_seq &&
1276 1278 * ru->data >= iph2->dpd_seq - iph2->dpd_fails ? */
1277 1279 if (get_uint32(&ru->data) != iph1->dpd_seq-1) {
1278 1280 plog(PLOG_PROTOERR, PLOGLOC, 0,
1279 1281 "Wrong DPD sequence number (%d, %d expected).\n",
1280 1282 get_uint32(&ru->data), iph1->dpd_seq-1);
1281 1283 return 0;
1282 1284 }
1283 1285
1284 1286 if (memcmp(ru->i_ck, iph1->index.i_ck, sizeof(isakmp_cookie_t)) ||
1285 1287 memcmp(ru->r_ck, iph1->index.r_ck, sizeof(isakmp_cookie_t))) {
1286 1288 plog(PLOG_PROTOERR, PLOGLOC, 0,
1287 1289 "Cookie mismatch in DPD ACK!.\n");
1288 1290 return 0;
1289 1291 }
1290 1292
1291 1293 iph1->dpd_fails = 0;
1292 1294
1293 1295 /* Useless ??? */
1294 1296 iph1->dpd_lastack = time(NULL);
1295 1297 plog(PLOG_DEBUG, PLOGLOC, NULL, "received an R-U-THERE-ACK\n");
1296 1298
1297 1299 return 0;
1298 1300 }
1299 1301
1300 1302
1301 1303
1302 1304
1303 1305 /*
1304 1306 * send Delete payload (for ISAKMP SA) in Informational exchange.
1305 1307 */
1306 1308 static void
1307 1309 isakmp_info_send_r_u(void *arg)
1308 1310 {
1309 1311 struct ph2handle *iph2 = arg;
1310 1312 struct ph1handle *iph1;
1311 1313
1312 1314 /* create R-U-THERE payload */
1313 1315 struct isakmp_pl_ru *ru;
1314 1316 rc_vchar_t *payload = NULL;
1315 1317 int tlen;
1316 1318 int error = 0;
1317 1319
1318 1320 plog(PLOG_DEBUG, PLOGLOC, 0, "DPD monitoring....\n");
1319 1321
1320 1322 iph1 = getph1byaddr(iph2->src, iph2->dst);
1321 1323 if (!iph1) {
1322 1324 plog(PLOG_DEBUG, PLOGLOC, 0, "can't find iph1\n");
1323 1325 return;
1324 1326 }
1325 1327 SCHED_KILL(iph1->dpd_r_u);
1326 1328
1327 1329 if (iph1->dpd_fails >= ikev1_dpd_maxfails(iph1->rmconf)) {
1328 1330 EVT_PUSH(iph1->local, iph1->remote, EVTT_DPD_TIMEOUT, NULL);
1329 1331 purge_remote(iph1);
1330 1332 plog(PLOG_DEBUG, PLOGLOC, 0,
1331 1333 "DPD: remote seems to be dead\n");
1332 1334
1333 1335 /* Do not reschedule here: phase1 is deleted,
1334 1336 * DPD will be reactivated when a new ph1 will be negociated
1335 1337 */
1336 1338 return;
1337 1339 }
1338 1340
1339 1341 /* Check recent activity to avoid useless sends... */
1340 1342 if (iph2->status != PHASE2ST_ESTABLISHED)
1341 1343 return;
1342 1344
1343 1345 /*
1344 1346 * DPD is necessary only when peer is idle AND
1345 1347 * self has packets to send
1346 1348 */
1347 1349 if (iph2->prev_peercount != iph2->cur_peercount ||
1348 1350 iph2->prev_selfcount == iph2->cur_selfcount) {
1349 1351 isakmp_sched_r_u(iph2, 0);
1350 1352 return;
1351 1353 }
1352 1354
1353 1355 /* XXX: why do we have a NULL LIST_FIRST even when a Phase2 exists ??? */
1354 1356 #if 0
1355 1357 if (LIST_FIRST(&iph1->ph2tree) == NULL){
1356 1358 /* XXX: No Ph2 => no need to test ph1 ?
1357 1359 */
1358 1360 /* Reschedule the r_u_there....
1359 1361 XXX: reschedule when a new ph2 ?
1360 1362 */
1361 1363 isakmp_sched_r_u(iph2, 0);
1362 1364 plog(PLOG_DEBUG, PLOGLOC, 0,
1363 1365 "no phase2 handler, rescheduling send_r_u (%d).\n", iph1->rmconf->dpd_interval);
1364 1366 return 0;
1365 1367 }
1366 1368 #endif
1367 1369
1368 1370 tlen = sizeof(*ru);
1369 1371 payload = rc_vmalloc(tlen);
1370 1372 if (payload == NULL) {
1371 1373 plog(PLOG_INTERR, PLOGLOC, NULL,
1372 1374 "failed to get buffer for payload.\n");
1373 1375 return;
1374 1376 }
1375 1377 ru = (struct isakmp_pl_ru *)payload->v;
1376 1378 ru->h.np = ISAKMP_NPTYPE_NONE;
1377 1379 put_uint16(&ru->h.len, tlen);
1378 1380 put_uint32(&ru->doi, IPSEC_DOI);
1379 1381 put_uint16(&ru->type, ISAKMP_NTYPE_R_U_THERE);
1380 1382 ru->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ?*/
1381 1383 ru->spi_size = sizeof(isakmp_index_t);
1382 1384
1383 1385 memcpy(ru->i_ck, iph1->index.i_ck, sizeof(isakmp_cookie_t));
1384 1386 memcpy(ru->r_ck, iph1->index.r_ck, sizeof(isakmp_cookie_t));
1385 1387
1386 1388 if (iph1->dpd_seq == 0){
1387 1389 /* generate a random seq which is not too big */
1388 1390 iph1->dpd_seq = eay_random_uint32() & 0x0fff;
1389 1391 }
1390 1392
1391 1393 put_uint32(&ru->data, iph1->dpd_seq);
1392 1394
1393 1395 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
1394 1396 rc_vfree(payload);
1395 1397
1396 1398 plog(PLOG_DEBUG, PLOGLOC, 0,
1397 1399 "DPD R-U-There sent (%d)\n", error);
1398 1400
1399 1401 /* will be decreased if ACK received... */
1400 1402 iph1->dpd_fails++;
1401 1403
1402 1404 /* XXX should be increased only when ACKed ? */
1403 1405 iph1->dpd_seq++;
1404 1406
1405 1407 /* Reschedule the r_u_there with a short delay,
1406 1408 * will be deleted/rescheduled if ACK received before */
1407 1409 if (iph1->dpd_lastack < time(NULL) - ikev1_dpd_interval(iph1->rmconf)) {
1408 1410 isakmp_sched_r_u(iph2, 1);
1409 1411 } else {
1410 1412 isakmp_sched_r_u(iph2, 0);
1411 1413 }
1412 1414
1413 1415 plog(PLOG_DEBUG, PLOGLOC, 0,
1414 1416 "rescheduling send_r_u (%d).\n", ikev1_dpd_retry(iph1->rmconf));
1415 1417 }
1416 1418
1417 1419 /* Schedule a new R-U-THERE */
1418 1420 int
1419 1421 isakmp_sched_r_u(struct ph2handle *iph2, int retry)
1420 1422 {
1421 1423 struct ph1handle *iph1;
1422 1424
1423 1425 if(iph2 == NULL)
1424 1426 return 1;
1425 1427 iph1 = getph1byaddr(iph2->src, iph2->dst);
1426 1428 if (!iph1 || !iph1->rmconf)
1427 1429 return 1;
1428 1430
1429 1431 if (iph2->status != PHASE2ST_ESTABLISHED) {
1430 1432 return 0;
1431 1433 }
1432 1434
1433 1435 if(iph1->dpd_support == 0 ||
1434 1436 ikev1_dpd_interval(iph1->rmconf) == 0)
1435 1437 return 0;
1436 1438
1437 1439 pk_sendget(iph2, 0);
1438 1440 pk_sendget(iph2, 1);
1439 1441
1440 1442 if(retry)
1441 1443 iph1->dpd_r_u = sched_new(ikev1_dpd_retry(iph1->rmconf),
1442 1444 isakmp_info_send_r_u, iph2);
1443 1445 else
1444 1446 sched_new(ikev1_dpd_interval(iph1->rmconf),
1445 1447 isakmp_info_send_r_u, iph2);
1446 1448
1447 1449 return 0;
1448 1450 }
|
↓ open down ↓ |
548 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX