]> git.saurik.com Git - apple/network_cmds.git/blob - racoon.tproj/isakmp_inf.c
69278734e9cf2203c436ce51634afc932e4fdc71
[apple/network_cmds.git] / racoon.tproj / isakmp_inf.c
1 /* $KAME: isakmp_inf.c,v 1.81 2002/04/15 01:58:37 itojun Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/socket.h>
35
36 #include <net/pfkeyv2.h>
37 #include <netkey/keydb.h>
38 #include <netkey/key_var.h>
39 #include <netinet/in.h>
40 #ifdef IPV6_INRIA_VERSION
41 #include <sys/queue.h>
42 #include <netinet/ipsec.h>
43 #else
44 #include <netinet6/ipsec.h>
45 #endif
46
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <errno.h>
51 #if TIME_WITH_SYS_TIME
52 # include <sys/time.h>
53 # include <time.h>
54 #else
55 # if HAVE_SYS_TIME_H
56 # include <sys/time.h>
57 # else
58 # include <time.h>
59 # endif
60 #endif
61
62 #include "libpfkey.h"
63
64 #include "var.h"
65 #include "vmbuf.h"
66 #include "schedule.h"
67 #include "str2val.h"
68 #include "misc.h"
69 #include "plog.h"
70 #include "debug.h"
71
72 #include "localconf.h"
73 #include "remoteconf.h"
74 #include "sockmisc.h"
75 #include "isakmp_var.h"
76 #include "isakmp.h"
77 #include "isakmp_inf.h"
78 #include "oakley.h"
79 #include "handler.h"
80 #include "ipsec_doi.h"
81 #include "crypto_openssl.h"
82 #include "pfkey.h"
83 #include "policy.h"
84 #include "algorithm.h"
85 #include "proposal.h"
86 #include "admin.h"
87 #include "strnames.h"
88
89 /* information exchange */
90 static int isakmp_info_recv_n __P((struct ph1handle *, vchar_t *));
91 static int isakmp_info_recv_d __P((struct ph1handle *, vchar_t *));
92
93 static void purge_isakmp_spi __P((int, isakmp_index *, size_t));
94 static void purge_ipsec_spi __P((struct sockaddr *, int, u_int32_t *, size_t));
95 static void info_recv_initialcontact __P((struct ph1handle *));
96
97 /* \f%%%
98 * Information Exchange
99 */
100 /*
101 * receive Information
102 */
103 int
104 isakmp_info_recv(iph1, msg0)
105 struct ph1handle *iph1;
106 vchar_t *msg0;
107 {
108 vchar_t *msg = NULL;
109 int error = -1;
110 struct isakmp *isakmp;
111 struct isakmp_gen *gen;
112 u_int8_t np;
113 int encrypted;
114
115 plog(LLV_DEBUG, LOCATION, NULL, "receive Information.\n");
116
117 encrypted = ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E);
118
119 /* Use new IV to decrypt Informational message. */
120 if (encrypted) {
121
122 struct isakmp_ivm *ivm;
123
124 /* compute IV */
125 ivm = oakley_newiv2(iph1, ((struct isakmp *)msg0->v)->msgid);
126 if (ivm == NULL)
127 return -1;
128
129 msg = oakley_do_decrypt(iph1, msg0, ivm->iv, ivm->ive);
130 oakley_delivm(ivm);
131 if (msg == NULL)
132 return -1;
133
134 } else
135 msg = vdup(msg0);
136
137 isakmp = (struct isakmp *)msg->v;
138 gen = (struct isakmp_gen *)((caddr_t)isakmp + sizeof(struct isakmp));
139 if (isakmp->np == ISAKMP_NPTYPE_HASH)
140 np = gen->np;
141 else
142 np = isakmp->np;
143
144 /* make sure the packet were encrypted. */
145 if (!encrypted) {
146 switch (iph1->etype) {
147 case ISAKMP_ETYPE_AGG:
148 case ISAKMP_ETYPE_BASE:
149 case ISAKMP_ETYPE_IDENT:
150 if ((iph1->side == INITIATOR && iph1->status < PHASE1ST_MSG3SENT)
151 || (iph1->side == RESPONDER && iph1->status < PHASE1ST_MSG2SENT)) {
152 break;
153 }
154 /*FALLTHRU*/
155 default:
156 plog(LLV_ERROR, LOCATION, iph1->remote,
157 "%s message must be encrypted\n",
158 s_isakmp_nptype(np));
159 goto end;
160 }
161 }
162
163 switch (np) {
164 case ISAKMP_NPTYPE_N:
165 if (isakmp_info_recv_n(iph1, msg) < 0)
166 goto end;
167 break;
168 case ISAKMP_NPTYPE_D:
169 if (isakmp_info_recv_d(iph1, msg) < 0)
170 goto end;
171 break;
172 case ISAKMP_NPTYPE_NONCE:
173 /* XXX to be 6.4.2 ike-01.txt */
174 /* XXX IV is to be synchronized. */
175 plog(LLV_ERROR, LOCATION, iph1->remote,
176 "ignore Acknowledged Informational\n");
177 break;
178 default:
179 /* don't send information, see isakmp_ident_r1() */
180 error = 0;
181 plog(LLV_ERROR, LOCATION, iph1->remote,
182 "reject the packet, "
183 "received unexpecting payload type %d.\n",
184 gen->np);
185 goto end;
186 }
187
188 end:
189 if (msg != NULL)
190 vfree(msg);
191
192 return 0;
193 }
194
195 /*
196 * send Delete payload (for ISAKMP SA) in Informational exchange.
197 */
198 int
199 isakmp_info_send_d1(iph1)
200 struct ph1handle *iph1;
201 {
202 struct isakmp_pl_d *d;
203 vchar_t *payload = NULL;
204 int tlen;
205 int error = 0;
206
207 if (iph1->status != PHASE2ST_ESTABLISHED)
208 return 0;
209
210 /* create delete payload */
211
212 /* send SPIs of inbound SAs. */
213 /* XXX should send outbound SAs's ? */
214 tlen = sizeof(*d) + sizeof(isakmp_index);
215 payload = vmalloc(tlen);
216 if (payload == NULL) {
217 plog(LLV_ERROR, LOCATION, NULL,
218 "failed to get buffer for payload.\n");
219 return errno;
220 }
221
222 d = (struct isakmp_pl_d *)payload->v;
223 d->h.np = ISAKMP_NPTYPE_NONE;
224 d->h.len = htons(tlen);
225 d->doi = htonl(IPSEC_DOI);
226 d->proto_id = IPSECDOI_PROTO_ISAKMP;
227 d->spi_size = sizeof(isakmp_index);
228 d->num_spi = htons(1);
229 memcpy(d + 1, &iph1->index, sizeof(isakmp_index));
230
231 error = isakmp_info_send_common(iph1, payload,
232 ISAKMP_NPTYPE_D, 0);
233 vfree(payload);
234
235 return error;
236 }
237
238 /*
239 * send Delete payload (for IPsec SA) in Informational exchange, based on
240 * pfkey msg. It sends always single SPI.
241 */
242 int
243 isakmp_info_send_d2(iph2)
244 struct ph2handle *iph2;
245 {
246 struct ph1handle *iph1;
247 struct saproto *pr;
248 struct isakmp_pl_d *d;
249 vchar_t *payload = NULL;
250 int tlen;
251 int error = 0;
252 u_int8_t *spi;
253
254 if (iph2->status != PHASE2ST_ESTABLISHED)
255 return 0;
256
257 /*
258 * don't send delete information if there is no phase 1 handler.
259 * It's nonsensical to negotiate phase 1 to send the information.
260 */
261 iph1 = getph1byaddr(iph2->src, iph2->dst);
262 if (iph1 == NULL)
263 return 0;
264
265 /* create delete payload */
266 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
267
268 /* send SPIs of inbound SAs. */
269 /*
270 * XXX should I send outbound SAs's ?
271 * I send inbound SAs's SPI only at the moment because I can't
272 * decode any more if peer send encoded packet without aware of
273 * deletion of SA. Outbound SAs don't come under the situation.
274 */
275 tlen = sizeof(*d) + pr->spisize;
276 payload = vmalloc(tlen);
277 if (payload == NULL) {
278 plog(LLV_ERROR, LOCATION, NULL,
279 "failed to get buffer for payload.\n");
280 return errno;
281 }
282
283 d = (struct isakmp_pl_d *)payload->v;
284 d->h.np = ISAKMP_NPTYPE_NONE;
285 d->h.len = htons(tlen);
286 d->doi = htonl(IPSEC_DOI);
287 d->proto_id = pr->proto_id;
288 d->spi_size = pr->spisize;
289 d->num_spi = htons(1);
290 /*
291 * XXX SPI bits are left-filled, for use with IPComp.
292 * we should be switching to variable-length spi field...
293 */
294 spi = (u_int8_t *)&pr->spi;
295 spi += sizeof(pr->spi);
296 spi -= pr->spisize;
297 memcpy(d + 1, spi, pr->spisize);
298
299 error = isakmp_info_send_common(iph1, payload,
300 ISAKMP_NPTYPE_D, 0);
301 vfree(payload);
302 }
303
304 return error;
305 }
306
307 /*
308 * send Notification payload (for without ISAKMP SA) in Informational exchange
309 */
310 int
311 isakmp_info_send_nx(isakmp, remote, local, type, data)
312 struct isakmp *isakmp;
313 struct sockaddr *remote, *local;
314 int type;
315 vchar_t *data;
316 {
317 struct ph1handle *iph1 = NULL;
318 struct remoteconf *rmconf;
319 vchar_t *payload = NULL;
320 int tlen;
321 int error = -1;
322 struct isakmp_pl_n *n;
323 int spisiz = 0; /* see below */
324
325 /* search appropreate configuration */
326 rmconf = getrmconf(remote);
327 if (rmconf == NULL) {
328 plog(LLV_ERROR, LOCATION, remote,
329 "no configuration found for peer address.\n");
330 goto end;
331 }
332
333 /* add new entry to isakmp status table. */
334 iph1 = newph1();
335 if (iph1 == NULL)
336 return -1;
337
338 memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(cookie_t));
339 isakmp_newcookie((char *)&iph1->index.r_ck, remote, local);
340 iph1->status = PHASE1ST_START;
341 iph1->rmconf = rmconf;
342 iph1->side = INITIATOR;
343 iph1->version = isakmp->v;
344 iph1->flags = 0;
345 iph1->msgid = 0; /* XXX */
346
347 /* copy remote address */
348 if (copy_ph1addresses(iph1, rmconf, remote, local) < 0)
349 return -1;
350
351 tlen = sizeof(*n) + spisiz;
352 if (data)
353 tlen += data->l;
354 payload = vmalloc(tlen);
355 if (payload == NULL) {
356 plog(LLV_ERROR, LOCATION, NULL,
357 "failed to get buffer to send.\n");
358 goto end;
359 }
360
361 n = (struct isakmp_pl_n *)payload->v;
362 n->h.np = ISAKMP_NPTYPE_NONE;
363 n->h.len = htons(tlen);
364 n->doi = htonl(IPSEC_DOI);
365 n->proto_id = IPSECDOI_KEY_IKE;
366 n->spi_size = spisiz;
367 n->type = htons(type);
368 if (spisiz)
369 memset(n + 1, 0, spisiz); /*XXX*/
370 if (data)
371 memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
372
373 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
374 vfree(payload);
375
376 end:
377 if (iph1 != NULL)
378 delph1(iph1);
379
380 return error;
381 }
382
383 /*
384 * send Notification payload (for ISAKMP SA) in Informational exchange
385 */
386 int
387 isakmp_info_send_n1(iph1, type, data)
388 struct ph1handle *iph1;
389 int type;
390 vchar_t *data;
391 {
392 vchar_t *payload = NULL;
393 int tlen;
394 int error = 0;
395 struct isakmp_pl_n *n;
396 int spisiz;
397
398 /*
399 * note on SPI size: which description is correct? I have chosen
400 * this to be 0.
401 *
402 * RFC2408 3.1, 2nd paragraph says: ISAKMP SA is identified by
403 * Initiator/Responder cookie and SPI has no meaning, SPI size = 0.
404 * RFC2408 3.1, first paragraph on page 40: ISAKMP SA is identified
405 * by cookie and SPI has no meaning, 0 <= SPI size <= 16.
406 * RFC2407 4.6.3.3, INITIAL-CONTACT is required to set to 16.
407 */
408 if (type == ISAKMP_NTYPE_INITIAL_CONTACT)
409 spisiz = sizeof(isakmp_index);
410 else
411 spisiz = 0;
412
413 tlen = sizeof(*n) + spisiz;
414 if (data)
415 tlen += data->l;
416 payload = vmalloc(tlen);
417 if (payload == NULL) {
418 plog(LLV_ERROR, LOCATION, NULL,
419 "failed to get buffer to send.\n");
420 return errno;
421 }
422
423 n = (struct isakmp_pl_n *)payload->v;
424 n->h.np = ISAKMP_NPTYPE_NONE;
425 n->h.len = htons(tlen);
426 n->doi = htonl(iph1->rmconf->doitype);
427 n->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX to be configurable ? */
428 n->spi_size = spisiz;
429 n->type = htons(type);
430 if (spisiz)
431 memcpy(n + 1, &iph1->index, sizeof(isakmp_index));
432 if (data)
433 memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
434
435 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph1->flags);
436 vfree(payload);
437
438 return error;
439 }
440
441 /*
442 * send Notification payload (for IPsec SA) in Informational exchange
443 */
444 int
445 isakmp_info_send_n2(iph2, type, data)
446 struct ph2handle *iph2;
447 int type;
448 vchar_t *data;
449 {
450 struct ph1handle *iph1 = iph2->ph1;
451 vchar_t *payload = NULL;
452 int tlen;
453 int error = 0;
454 struct isakmp_pl_n *n;
455 struct saproto *pr;
456
457 if (!iph2->approval)
458 return EINVAL;
459
460 pr = iph2->approval->head;
461
462 /* XXX must be get proper spi */
463 tlen = sizeof(*n) + pr->spisize;
464 if (data)
465 tlen += data->l;
466 payload = vmalloc(tlen);
467 if (payload == NULL) {
468 plog(LLV_ERROR, LOCATION, NULL,
469 "failed to get buffer to send.\n");
470 return errno;
471 }
472
473 n = (struct isakmp_pl_n *)payload->v;
474 n->h.np = ISAKMP_NPTYPE_NONE;
475 n->h.len = htons(tlen);
476 n->doi = htonl(IPSEC_DOI); /* IPSEC DOI (1) */
477 n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/
478 n->spi_size = pr->spisize;
479 n->type = htons(type);
480 *(u_int32_t *)(n + 1) = pr->spi;
481 if (data)
482 memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
483
484 iph2->flags |= ISAKMP_FLAG_E; /* XXX Should we do FLAG_A ? */
485 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph2->flags);
486 vfree(payload);
487
488 return error;
489 }
490
491 /*
492 * send Information
493 * When ph1->skeyid_a == NULL, send message without encoding.
494 */
495 int
496 isakmp_info_send_common(iph1, payload, np, flags)
497 struct ph1handle *iph1;
498 vchar_t *payload;
499 u_int32_t np;
500 int flags;
501 {
502 struct ph2handle *iph2 = NULL;
503 vchar_t *hash = NULL;
504 struct isakmp *isakmp;
505 struct isakmp_gen *gen;
506 char *p;
507 int tlen;
508 int error = -1;
509
510 /* add new entry to isakmp status table */
511 iph2 = newph2();
512 if (iph2 == NULL)
513 goto end;
514
515 iph2->dst = dupsaddr(iph1->remote);
516 iph2->src = dupsaddr(iph1->local);
517 switch (iph1->remote->sa_family) {
518 case AF_INET:
519 ((struct sockaddr_in *)iph2->dst)->sin_port = 0;
520 ((struct sockaddr_in *)iph2->src)->sin_port = 0;
521 break;
522 #ifdef INET6
523 case AF_INET6:
524 ((struct sockaddr_in6 *)iph2->dst)->sin6_port = 0;
525 ((struct sockaddr_in6 *)iph2->src)->sin6_port = 0;
526 break;
527 #endif
528 default:
529 plog(LLV_ERROR, LOCATION, NULL,
530 "invalid family: %d\n", iph1->remote->sa_family);
531 delph2(iph2);
532 goto end;
533 }
534 iph2->ph1 = iph1;
535 iph2->side = INITIATOR;
536 iph2->status = PHASE2ST_START;
537 iph2->msgid = isakmp_newmsgid2(iph1);
538
539 /* get IV and HASH(1) if skeyid_a was generated. */
540 if (iph1->skeyid_a != NULL) {
541 iph2->ivm = oakley_newiv2(iph1, iph2->msgid);
542 if (iph2->ivm == NULL) {
543 delph2(iph2);
544 goto end;
545 }
546
547 /* generate HASH(1) */
548 hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, payload);
549 if (hash == NULL) {
550 delph2(iph2);
551 goto end;
552 }
553
554 /* initialized total buffer length */
555 tlen = hash->l;
556 tlen += sizeof(*gen);
557 } else {
558 /* IKE-SA is not established */
559 hash = NULL;
560
561 /* initialized total buffer length */
562 tlen = 0;
563 }
564 if ((flags & ISAKMP_FLAG_A) == 0)
565 iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
566 else
567 iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
568
569 insph2(iph2);
570 bindph12(iph1, iph2);
571
572 tlen += sizeof(*isakmp) + payload->l;
573
574 /* create buffer for isakmp payload */
575 iph2->sendbuf = vmalloc(tlen);
576 if (iph2->sendbuf == NULL) {
577 plog(LLV_ERROR, LOCATION, NULL,
578 "failed to get buffer to send.\n");
579 goto err;
580 }
581
582 /* create isakmp header */
583 isakmp = (struct isakmp *)iph2->sendbuf->v;
584 memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
585 memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
586 isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
587 isakmp->v = iph1->version;
588 isakmp->etype = ISAKMP_ETYPE_INFO;
589 isakmp->flags = iph2->flags;
590 memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
591 isakmp->len = htonl(tlen);
592 p = (char *)(isakmp + 1);
593
594 /* create HASH payload */
595 if (hash != NULL) {
596 gen = (struct isakmp_gen *)p;
597 gen->np = np & 0xff;
598 gen->len = htons(sizeof(*gen) + hash->l);
599 p += sizeof(*gen);
600 memcpy(p, hash->v, hash->l);
601 p += hash->l;
602 }
603
604 /* add payload */
605 memcpy(p, payload->v, payload->l);
606 p += payload->l;
607
608 #ifdef HAVE_PRINT_ISAKMP_C
609 isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
610 #endif
611
612 /* encoding */
613 if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
614 vchar_t *tmp;
615
616 tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, iph2->ivm->ive,
617 iph2->ivm->iv);
618 if (tmp == NULL) {
619 vfree(iph2->sendbuf);
620 iph2->sendbuf = NULL;
621 goto err;
622 }
623 vfree(iph2->sendbuf);
624 iph2->sendbuf = tmp;
625 }
626
627 /* HDR*, HASH(1), N */
628 if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
629 vfree(iph2->sendbuf);
630 iph2->sendbuf = NULL;
631 goto err;
632 }
633
634 plog(LLV_DEBUG, LOCATION, NULL,
635 "sendto Information %s.\n", s_isakmp_nptype(np));
636
637 /*
638 * don't resend notify message because peer can use Acknowledged
639 * Informational if peer requires the reply of the notify message.
640 */
641
642 /* XXX If Acknowledged Informational required, don't delete ph2handle */
643 error = 0;
644 vfree(iph2->sendbuf);
645 iph2->sendbuf = NULL;
646 goto err; /* XXX */
647
648 end:
649 if (hash)
650 vfree(hash);
651 return error;
652
653 err:
654 unbindph12(iph2);
655 remph2(iph2);
656 delph2(iph2);
657 goto end;
658 }
659
660 /*
661 * add a notify payload to buffer by reallocating buffer.
662 * If buf == NULL, the function only create a notify payload.
663 *
664 * XXX Which is SPI to be included, inbound or outbound ?
665 */
666 vchar_t *
667 isakmp_add_pl_n(buf0, np_p, type, pr, data)
668 vchar_t *buf0;
669 u_int8_t **np_p;
670 int type;
671 struct saproto *pr;
672 vchar_t *data;
673 {
674 vchar_t *buf = NULL;
675 struct isakmp_pl_n *n;
676 int tlen;
677 int oldlen = 0;
678
679 if (*np_p)
680 **np_p = ISAKMP_NPTYPE_N;
681
682 tlen = sizeof(*n) + pr->spisize;
683
684 if (data)
685 tlen += data->l;
686 if (buf0) {
687 oldlen = buf0->l;
688 buf = vrealloc(buf0, buf0->l + tlen);
689 } else
690 buf = vmalloc(tlen);
691 if (!buf) {
692 plog(LLV_ERROR, LOCATION, NULL,
693 "failed to get a payload buffer.\n");
694 return NULL;
695 }
696
697 n = (struct isakmp_pl_n *)(buf->v + oldlen);
698 n->h.np = ISAKMP_NPTYPE_NONE;
699 n->h.len = htons(tlen);
700 n->doi = htonl(IPSEC_DOI); /* IPSEC DOI (1) */
701 n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/
702 n->spi_size = pr->spisize;
703 n->type = htons(type);
704 *(u_int32_t *)(n + 1) = pr->spi; /* XXX */
705 if (data)
706 memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
707
708 /* save the pointer of next payload type */
709 *np_p = &n->h.np;
710
711 return buf;
712 }
713
714 /*
715 * handling to receive Notification payload
716 */
717 static int
718 isakmp_info_recv_n(iph1, msg)
719 struct ph1handle *iph1;
720 vchar_t *msg;
721 {
722 struct isakmp_pl_n *n = NULL;
723 u_int type;
724 vchar_t *pbuf;
725 struct isakmp_parse_t *pa, *pap;
726 char *spi;
727
728 if (!(pbuf = isakmp_parse(msg)))
729 return -1;
730 pa = (struct isakmp_parse_t *)pbuf->v;
731 for (pap = pa; pap->type; pap++) {
732 switch (pap->type) {
733 case ISAKMP_NPTYPE_HASH:
734 /* do something here */
735 break;
736 case ISAKMP_NPTYPE_NONCE:
737 /* send to ack */
738 break;
739 case ISAKMP_NPTYPE_N:
740 n = (struct isakmp_pl_n *)pap->ptr;
741 break;
742 default:
743 vfree(pbuf);
744 return -1;
745 }
746 }
747 vfree(pbuf);
748 if (!n)
749 return -1;
750
751 type = ntohs(n->type);
752
753 switch (type) {
754 case ISAKMP_NTYPE_CONNECTED:
755 case ISAKMP_NTYPE_RESPONDER_LIFETIME:
756 case ISAKMP_NTYPE_REPLAY_STATUS:
757 /* do something */
758 break;
759 case ISAKMP_NTYPE_INITIAL_CONTACT:
760 info_recv_initialcontact(iph1);
761 break;
762 default:
763 {
764 u_int32_t msgid = ((struct isakmp *)msg->v)->msgid;
765 struct ph2handle *iph2;
766
767 /* XXX there is a potential of dos attack. */
768 if (msgid == 0) {
769 /* delete ph1 */
770 plog(LLV_ERROR, LOCATION, iph1->remote,
771 "delete phase1 handle.\n");
772 return -1;
773 } else {
774 iph2 = getph2bymsgid(iph1, msgid);
775 if (iph2 == NULL) {
776 plog(LLV_ERROR, LOCATION, iph1->remote,
777 "unknown notify message, "
778 "no phase2 handle found.\n");
779 } else {
780 /* delete ph2 */
781 unbindph12(iph2);
782 remph2(iph2);
783 delph2(iph2);
784 }
785 }
786 }
787 break;
788 }
789
790 /* get spi and allocate */
791 if (ntohs(n->h.len) < sizeof(*n) + n->spi_size) {
792 plog(LLV_ERROR, LOCATION, iph1->remote,
793 "invalid spi_size in notification payload.\n");
794 return -1;
795 }
796 spi = val2str((u_char *)(n + 1), n->spi_size);
797
798 plog(LLV_DEBUG, LOCATION, iph1->remote,
799 "notification message %d:%s, "
800 "doi=%d proto_id=%d spi=%s(size=%d).\n",
801 type, s_isakmp_notify_msg(type),
802 ntohl(n->doi), n->proto_id, spi, n->spi_size);
803
804 racoon_free(spi);
805
806 return(0);
807 }
808
809 static void
810 purge_isakmp_spi(proto, spi, n)
811 int proto;
812 isakmp_index *spi; /*network byteorder*/
813 size_t n;
814 {
815 struct ph1handle *iph1;
816 size_t i;
817
818 for (i = 0; i < n; i++) {
819 iph1 = getph1byindex(&spi[i]);
820 if (!iph1)
821 continue;
822
823 plog(LLV_INFO, LOCATION, NULL,
824 "purged ISAKMP-SA proto_id=%s spi=%s.\n",
825 s_ipsecdoi_proto(proto),
826 isakmp_pindex(&spi[i], 0));
827
828 if (iph1->sce)
829 SCHED_KILL(iph1->sce);
830 iph1->status = PHASE1ST_EXPIRED;
831 iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
832 }
833 }
834
835 static void
836 purge_ipsec_spi(dst0, proto, spi, n)
837 struct sockaddr *dst0;
838 int proto;
839 u_int32_t *spi; /*network byteorder*/
840 size_t n;
841 {
842 vchar_t *buf = NULL;
843 struct sadb_msg *msg, *next, *end;
844 struct sadb_sa *sa;
845 struct sockaddr *src, *dst;
846 struct ph2handle *iph2;
847 size_t i;
848 caddr_t mhp[SADB_EXT_MAX + 1];
849
850 buf = pfkey_dump_sadb(ipsecdoi2pfkey_proto(proto));
851 if (buf == NULL) {
852 plog(LLV_DEBUG, LOCATION, NULL,
853 "pfkey_dump_sadb returned nothing.\n");
854 return;
855 }
856
857 msg = (struct sadb_msg *)buf->v;
858 end = (struct sadb_msg *)(buf->v + buf->l);
859
860 while (msg < end) {
861 if ((msg->sadb_msg_len << 3) < sizeof(*msg))
862 break;
863 next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
864 if (msg->sadb_msg_type != SADB_DUMP) {
865 msg = next;
866 continue;
867 }
868
869 if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
870 plog(LLV_ERROR, LOCATION, NULL,
871 "pfkey_check (%s)\n", ipsec_strerror());
872 msg = next;
873 continue;
874 }
875
876 sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
877 if (!sa
878 || !mhp[SADB_EXT_ADDRESS_SRC]
879 || !mhp[SADB_EXT_ADDRESS_DST]) {
880 msg = next;
881 continue;
882 }
883 src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
884 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
885
886 if (sa->sadb_sa_state != SADB_SASTATE_MATURE
887 && sa->sadb_sa_state != SADB_SASTATE_DYING) {
888 msg = next;
889 continue;
890 }
891
892 /* XXX n^2 algorithm, inefficient */
893
894 /* don't delete inbound SAs at the moment */
895 /* XXX should we remove SAs with opposite direction as well? */
896 if (cmpsaddrwop(dst0, dst)) {
897 msg = next;
898 continue;
899 }
900
901 for (i = 0; i < n; i++) {
902 plog(LLV_DEBUG, LOCATION, NULL,
903 "check spi(packet)=%u spi(db)=%u.\n",
904 ntohl(spi[i]), ntohl(sa->sadb_sa_spi));
905 if (spi[i] != sa->sadb_sa_spi)
906 continue;
907
908 pfkey_send_delete(lcconf->sock_pfkey,
909 msg->sadb_msg_satype,
910 IPSEC_MODE_ANY,
911 src, dst, sa->sadb_sa_spi);
912
913 /*
914 * delete a relative phase 2 handler.
915 * continue to process if no relative phase 2 handler
916 * exists.
917 */
918 iph2 = getph2bysaidx(src, dst, proto, spi[i]);
919 if (iph2) {
920 unbindph12(iph2);
921 remph2(iph2);
922 delph2(iph2);
923 }
924
925 plog(LLV_INFO, LOCATION, NULL,
926 "purged IPsec-SA proto_id=%s spi=%u.\n",
927 s_ipsecdoi_proto(proto),
928 ntohl(spi[i]));
929 }
930
931 msg = next;
932 }
933
934 if (buf)
935 vfree(buf);
936 }
937
938 /*
939 * delete all phase2 sa relatived to the destination address.
940 * Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore
941 * an INITIAL-CONTACT if we have contacted the peer. This matches the
942 * Sun IKE behavior, and makes rekeying work much better when the peer
943 * restarts.
944 */
945 static void
946 info_recv_initialcontact(iph1)
947 struct ph1handle *iph1;
948 {
949 vchar_t *buf = NULL;
950 struct sadb_msg *msg, *next, *end;
951 struct sadb_sa *sa;
952 struct sockaddr *src, *dst;
953 caddr_t mhp[SADB_EXT_MAX + 1];
954 int proto_id, i;
955 struct ph2handle *iph2;
956 #if 0
957 char *loc, *rem;
958 #endif
959
960 if (f_local)
961 return;
962
963 #if 0
964 loc = strdup(saddrwop2str(iph1->local));
965 rem = strdup(saddrwop2str(iph1->remote));
966
967 /*
968 * Purge all IPSEC-SAs for the peer. We can do this
969 * the easy way (using a PF_KEY SADB_DELETE extension)
970 * or we can do it the hard way.
971 */
972 for (i = 0; i < pfkey_nsatypes; i++) {
973 proto_id = pfkey2ipsecdoi_proto(pfkey_satypes[i].ps_satype);
974
975 plog(LLV_INFO, LOCATION, NULL,
976 "purging %s SAs for %s -> %s\n",
977 pfkey_satypes[i].ps_name, loc, rem);
978 if (pfkey_send_delete_all(lcconf->sock_pfkey,
979 pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
980 iph1->local, iph1->remote) == -1) {
981 plog(LLV_ERROR, LOCATION, NULL,
982 "delete_all %s -> %s failed for %s (%s)\n",
983 loc, rem,
984 pfkey_satypes[i].ps_name, ipsec_strerror());
985 goto the_hard_way;
986 }
987
988 deleteallph2(iph1->local, iph1->remote, proto_id);
989
990 plog(LLV_INFO, LOCATION, NULL,
991 "purging %s SAs for %s -> %s\n",
992 pfkey_satypes[i].ps_name, rem, loc);
993 if (pfkey_send_delete_all(lcconf->sock_pfkey,
994 pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
995 iph1->remote, iph1->local) == -1) {
996 plog(LLV_ERROR, LOCATION, NULL,
997 "delete_all %s -> %s failed for %s (%s)\n",
998 rem, loc,
999 pfkey_satypes[i].ps_name, ipsec_strerror());
1000 goto the_hard_way;
1001 }
1002
1003 deleteallph2(iph1->remote, iph1->local, proto_id);
1004 }
1005
1006 racoon_free(loc);
1007 racoon_free(rem);
1008 return;
1009
1010 the_hard_way:
1011 racoon_free(loc);
1012 racoon_free(rem);
1013 #endif
1014
1015 buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
1016 if (buf == NULL) {
1017 plog(LLV_DEBUG, LOCATION, NULL,
1018 "pfkey_dump_sadb returned nothing.\n");
1019 return;
1020 }
1021
1022 msg = (struct sadb_msg *)buf->v;
1023 end = (struct sadb_msg *)(buf->v + buf->l);
1024
1025 while (msg < end) {
1026 if ((msg->sadb_msg_len << 3) < sizeof(*msg))
1027 break;
1028 next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
1029 if (msg->sadb_msg_type != SADB_DUMP) {
1030 msg = next;
1031 continue;
1032 }
1033
1034 if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
1035 plog(LLV_ERROR, LOCATION, NULL,
1036 "pfkey_check (%s)\n", ipsec_strerror());
1037 msg = next;
1038 continue;
1039 }
1040
1041 if (mhp[SADB_EXT_SA] == NULL
1042 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1043 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
1044 msg = next;
1045 continue;
1046 }
1047 sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
1048 src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1049 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1050
1051 if (sa->sadb_sa_state != SADB_SASTATE_MATURE
1052 && sa->sadb_sa_state != SADB_SASTATE_DYING) {
1053 msg = next;
1054 continue;
1055 }
1056
1057 /*
1058 * RFC2407 4.6.3.3 INITIAL-CONTACT is the message that
1059 * announces the sender of the message was rebooted.
1060 * it is interpreted to delete all SAs which source address
1061 * is the sender of the message.
1062 * racoon only deletes SA which is matched both the
1063 * source address and the destination accress.
1064 */
1065 if (cmpsaddrwop(iph1->local, src) == 0 &&
1066 cmpsaddrwop(iph1->remote, dst) == 0)
1067 ;
1068 else if (cmpsaddrwop(iph1->remote, src) == 0 &&
1069 cmpsaddrwop(iph1->local, dst) == 0)
1070 ;
1071 else {
1072 msg = next;
1073 continue;
1074 }
1075
1076 /*
1077 * Make sure this is an SATYPE that we manage.
1078 * This is gross; too bad we couldn't do it the
1079 * easy way.
1080 */
1081 for (i = 0; i < pfkey_nsatypes; i++) {
1082 if (pfkey_satypes[i].ps_satype ==
1083 msg->sadb_msg_satype)
1084 break;
1085 }
1086 if (i == pfkey_nsatypes) {
1087 msg = next;
1088 continue;
1089 }
1090
1091 plog(LLV_INFO, LOCATION, NULL,
1092 "purging spi=%u.\n", ntohl(sa->sadb_sa_spi));
1093 pfkey_send_delete(lcconf->sock_pfkey,
1094 msg->sadb_msg_satype,
1095 IPSEC_MODE_ANY, src, dst, sa->sadb_sa_spi);
1096
1097 /*
1098 * delete a relative phase 2 handler.
1099 * continue to process if no relative phase 2 handler
1100 * exists.
1101 */
1102 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1103 iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
1104 if (iph2) {
1105 unbindph12(iph2);
1106 remph2(iph2);
1107 delph2(iph2);
1108 }
1109
1110 msg = next;
1111 }
1112
1113 vfree(buf);
1114 }
1115
1116 /*
1117 * handling to receive Deletion payload
1118 */
1119 static int
1120 isakmp_info_recv_d(iph1, msg)
1121 struct ph1handle *iph1;
1122 vchar_t *msg;
1123 {
1124 struct isakmp_pl_d *d;
1125 int tlen, num_spi;
1126 vchar_t *pbuf;
1127 struct isakmp_parse_t *pa, *pap;
1128 int protected = 0;
1129 union {
1130 u_int32_t spi32;
1131 u_int16_t spi16[2];
1132 } spi;
1133
1134 /* validate the type of next payload */
1135 if (!(pbuf = isakmp_parse(msg)))
1136 return -1;
1137 pa = (struct isakmp_parse_t *)pbuf->v;
1138 for (pap = pa; pap->type; pap++) {
1139 switch (pap->type) {
1140 case ISAKMP_NPTYPE_D:
1141 break;
1142 case ISAKMP_NPTYPE_HASH:
1143 if (pap == pa) {
1144 protected++;
1145 break;
1146 }
1147 plog(LLV_ERROR, LOCATION, iph1->remote,
1148 "received next payload type %d "
1149 "in wrong place (must be the first payload).\n",
1150 pap->type);
1151 vfree(pbuf);
1152 return -1;
1153 default:
1154 /* don't send information, see isakmp_ident_r1() */
1155 plog(LLV_ERROR, LOCATION, iph1->remote,
1156 "reject the packet, "
1157 "received unexpecting payload type %d.\n",
1158 pap->type);
1159 vfree(pbuf);
1160 return 0;
1161 }
1162 }
1163
1164 if (!protected) {
1165 plog(LLV_ERROR, LOCATION, NULL,
1166 "delete payload is not proteted, "
1167 "ignored.\n");
1168 vfree(pbuf);
1169 return -1;
1170 }
1171
1172 /* process a delete payload */
1173 for (pap = pa; pap->type; pap++) {
1174 if (pap->type != ISAKMP_NPTYPE_D)
1175 continue;
1176
1177 d = (struct isakmp_pl_d *)pap->ptr;
1178
1179 if (ntohl(d->doi) != IPSEC_DOI) {
1180 plog(LLV_ERROR, LOCATION, iph1->remote,
1181 "delete payload with invalid doi:%d.\n",
1182 ntohl(d->doi));
1183 continue;
1184 }
1185
1186 num_spi = ntohs(d->num_spi);
1187 tlen = ntohs(d->h.len) - sizeof(struct isakmp_pl_d);
1188
1189 if (tlen != num_spi * d->spi_size) {
1190 plog(LLV_ERROR, LOCATION, iph1->remote,
1191 "deletion payload with invalid length.\n");
1192 vfree(pbuf);
1193 return -1;
1194 }
1195
1196 switch (d->proto_id) {
1197 case IPSECDOI_PROTO_ISAKMP:
1198 if (d->spi_size != sizeof(isakmp_index)) {
1199 plog(LLV_ERROR, LOCATION, iph1->remote,
1200 "delete payload with strange spi "
1201 "size %d(proto_id:%d)\n",
1202 d->spi_size, d->proto_id);
1203 continue;
1204 }
1205 purge_isakmp_spi(d->proto_id,
1206 (isakmp_index *)(d + 1), num_spi);
1207 break;
1208
1209 case IPSECDOI_PROTO_IPSEC_AH:
1210 case IPSECDOI_PROTO_IPSEC_ESP:
1211 if (d->spi_size != sizeof(u_int32_t)) {
1212 plog(LLV_ERROR, LOCATION, iph1->remote,
1213 "delete payload with strange spi "
1214 "size %d(proto_id:%d)\n",
1215 d->spi_size, d->proto_id);
1216 continue;
1217 }
1218 purge_ipsec_spi(iph1->remote, d->proto_id,
1219 (u_int32_t *)(d + 1), num_spi);
1220 break;
1221
1222 case IPSECDOI_PROTO_IPCOMP:
1223 /* need to handle both 16bit/32bit SPI */
1224 memset(&spi, 0, sizeof(spi));
1225 if (d->spi_size == sizeof(spi.spi16[1])) {
1226 memcpy(&spi.spi16[1], d + 1,
1227 sizeof(spi.spi16[1]));
1228 } else if (d->spi_size == sizeof(spi.spi32))
1229 memcpy(&spi.spi32, d + 1, sizeof(spi.spi32));
1230 else {
1231 plog(LLV_ERROR, LOCATION, iph1->remote,
1232 "delete payload with strange spi "
1233 "size %d(proto_id:%d)\n",
1234 d->spi_size, d->proto_id);
1235 continue;
1236 }
1237 purge_ipsec_spi(iph1->remote, d->proto_id,
1238 &spi.spi32, num_spi);
1239 break;
1240
1241 default:
1242 plog(LLV_ERROR, LOCATION, iph1->remote,
1243 "deletion message received, "
1244 "invalid proto_id: %d\n",
1245 d->proto_id);
1246 continue;
1247 }
1248
1249 plog(LLV_DEBUG, LOCATION, NULL, "purged SAs.\n");
1250 }
1251
1252 vfree(pbuf);
1253
1254 return 0;
1255 }
1256
1257 void
1258 isakmp_check_notify(gen, iph1)
1259 struct isakmp_gen *gen; /* points to Notify payload */
1260 struct ph1handle *iph1;
1261 {
1262 struct isakmp_pl_n *notify = (struct isakmp_pl_n *)gen;
1263
1264 plog(LLV_DEBUG, LOCATION, iph1->remote,
1265 "Notify Message received\n");
1266
1267 switch (ntohs(notify->type)) {
1268 case ISAKMP_NTYPE_CONNECTED:
1269 plog(LLV_WARNING, LOCATION, iph1->remote,
1270 "ignore CONNECTED notification.\n");
1271 break;
1272 case ISAKMP_NTYPE_RESPONDER_LIFETIME:
1273 plog(LLV_WARNING, LOCATION, iph1->remote,
1274 "ignore RESPONDER-LIFETIME notification.\n");
1275 break;
1276 case ISAKMP_NTYPE_REPLAY_STATUS:
1277 plog(LLV_WARNING, LOCATION, iph1->remote,
1278 "ignore REPLAY-STATUS notification.\n");
1279 break;
1280 case ISAKMP_NTYPE_INITIAL_CONTACT:
1281 plog(LLV_WARNING, LOCATION, iph1->remote,
1282 "ignore INITIAL-CONTACT notification, "
1283 "because it is only accepted after phase1.\n");
1284 break;
1285 default:
1286 isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
1287 plog(LLV_ERROR, LOCATION, iph1->remote,
1288 "received unknown notification type %u.\n",
1289 ntohs(notify->type));
1290 }
1291
1292 return;
1293 }
1294