]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/pfkey_racoon.c
ipsec-332.100.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / pfkey_racoon.c
CommitLineData
52b7d2ce
A
1/* $Id: pfkey.c,v 1.31.2.10 2005/10/03 14:52:19 manubsd 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 "config.h"
65c25746 33#include "racoon_types.h"
52b7d2ce
A
34
35#include <stdlib.h>
36#include <string.h>
37#include <stdio.h>
38#include <netdb.h>
39#include <errno.h>
40#ifdef HAVE_UNISTD_H
41#include <unistd.h>
42#endif
43#include <netdb.h>
44#include <netinet/in.h>
45#include <arpa/inet.h>
46
47#ifdef ENABLE_NATT
e8d9021d 48#include <netinet/udp.h>
52b7d2ce
A
49#endif
50
51#include <sys/types.h>
52#include <sys/param.h>
53#include <sys/socket.h>
54#include <sys/queue.h>
55#include <sys/sysctl.h>
56
57#include <net/route.h>
65c25746 58#include <net/pfkeyv2.h>
52b7d2ce
A
59
60#include <netinet/in.h>
61#ifndef HAVE_NETINET6_IPSEC
62#include <netinet/ipsec.h>
63#else
64#include <netinet6/ipsec.h>
65#endif
66
67#include "libpfkey.h"
68
69#include "var.h"
70#include "misc.h"
71#include "vmbuf.h"
72#include "plog.h"
73#include "sockmisc.h"
74#include "debug.h"
65c25746
A
75#include "fsm.h"
76#include "ike_session.h"
52b7d2ce
A
77
78#include "schedule.h"
79#include "localconf.h"
80#include "remoteconf.h"
81#include "isakmp_var.h"
82#include "isakmp.h"
83#include "isakmp_inf.h"
84#include "ipsec_doi.h"
85#include "oakley.h"
86#include "pfkey.h"
87#include "handler.h"
88#include "policy.h"
89#include "algorithm.h"
90#include "sainfo.h"
91#include "proposal.h"
52b7d2ce 92#include "strnames.h"
52b7d2ce
A
93#include "gcmalloc.h"
94#include "nattraversal.h"
95#include "crypto_openssl.h"
96#include "grabmyaddr.h"
97#include "vpn_control.h"
98#include "vpn_control_var.h"
d1e348cf 99#include "ike_session.h"
e8d9021d 100#include "power_mgmt.h"
65c25746 101#include "session.h"
52b7d2ce
A
102
103#if defined(SADB_X_EALG_RIJNDAELCBC) && !defined(SADB_X_EALG_AESCBC)
104#define SADB_X_EALG_AESCBC SADB_X_EALG_RIJNDAELCBC
105#endif
106
107/* prototype */
65c25746
A
108static u_int ipsecdoi2pfkey_aalg (u_int);
109static u_int ipsecdoi2pfkey_ealg (u_int);
110static u_int ipsecdoi2pfkey_calg (u_int);
111static u_int ipsecdoi2pfkey_alg (u_int, u_int);
112static u_int keylen_aalg (u_int);
113static u_int keylen_ealg (u_int, int);
114
115static int pk_recvgetspi (caddr_t *);
116static int pk_recvupdate (caddr_t *);
117static int pk_recvadd (caddr_t *);
118static int pk_recvdelete (caddr_t *);
119static int pk_recvacquire (caddr_t *);
120static int pk_recvexpire (caddr_t *);
121static int pk_recvflush (caddr_t *);
122static int getsadbpolicy (caddr_t *, int *, int, phase2_handle_t *);
123static int pk_recvspdupdate (caddr_t *);
124static int pk_recvspdadd (caddr_t *);
125static int pk_recvspddelete (caddr_t *);
126static int pk_recvspdexpire (caddr_t *);
127static int pk_recvspdget (caddr_t *);
128static int pk_recvspddump (caddr_t *);
129static int pk_recvspdflush (caddr_t *);
130static int pk_recvgetsastat (caddr_t *);
131static struct sadb_msg *pk_recv (int, ssize_t *);
132
133static int (*pkrecvf[]) (caddr_t *) = {
52b7d2ce
A
134NULL,
135pk_recvgetspi,
136pk_recvupdate,
137pk_recvadd,
138pk_recvdelete,
139NULL, /* SADB_GET */
140pk_recvacquire,
141NULL, /* SABD_REGISTER */
142pk_recvexpire,
143pk_recvflush,
144NULL, /* SADB_DUMP */
145NULL, /* SADB_X_PROMISC */
146NULL, /* SADB_X_PCHANGE */
147pk_recvspdupdate,
148pk_recvspdadd,
149pk_recvspddelete,
150pk_recvspdget,
151NULL, /* SADB_X_SPDACQUIRE */
152pk_recvspddump,
153pk_recvspdflush,
154NULL, /* SADB_X_SPDSETIDX */
155pk_recvspdexpire,
156NULL, /* SADB_X_SPDDELETE2 */
d1e348cf 157pk_recvgetsastat, /* SADB_GETSASTAT */
c8d8bee0
A
158NULL, /* SADB_X_SPDENABLE */
159NULL, /* SADB_X_SPDDISNABLE */
160NULL, /* SADB_MIGRATE */
161#if (SADB_MAX > 26)
162#warning "SADB extra message?"
52b7d2ce
A
163#endif
164};
165
52b7d2ce
A
166/* cope with old kame headers - ugly */
167#ifndef SADB_X_AALG_MD5
168#define SADB_X_AALG_MD5 SADB_AALG_MD5
169#endif
170#ifndef SADB_X_AALG_SHA
171#define SADB_X_AALG_SHA SADB_AALG_SHA
172#endif
173#ifndef SADB_X_AALG_NULL
174#define SADB_X_AALG_NULL SADB_AALG_NULL
175#endif
176
177#ifndef SADB_X_EALG_BLOWFISHCBC
178#define SADB_X_EALG_BLOWFISHCBC SADB_EALG_BLOWFISHCBC
179#endif
180#ifndef SADB_X_EALG_CAST128CBC
181#define SADB_X_EALG_CAST128CBC SADB_EALG_CAST128CBC
182#endif
183#ifndef SADB_X_EALG_RC5CBC
184#ifdef SADB_EALG_RC5CBC
185#define SADB_X_EALG_RC5CBC SADB_EALG_RC5CBC
186#endif
187#endif
188
52b7d2ce 189int
fd507379 190pfkey_process(msg)
52b7d2ce 191 struct sadb_msg *msg;
fd507379 192{
52b7d2ce
A
193 caddr_t mhp[SADB_EXT_MAX + 1];
194 int error = -1;
fd507379 195
65c25746
A
196 // Special debug use only - creates large logs
197 // plogdump(ASL_LEVEL_DEBUG, msg, msg->sadb_msg_len << 3, "get pfkey %s message\n",
198 // s_pfkey_type(msg->sadb_msg_type));
52b7d2ce
A
199
200 /* validity check */
65c25746
A
201 /* check pfkey message. */
202 if (pfkey_align(msg, mhp)) {
203 plog(ASL_LEVEL_ERR,
204 "libipsec failed pfkey align (%s)\n",
205 ipsec_strerror());
206 goto end;
207 }
208 if (pfkey_check(mhp)) {
209 plog(ASL_LEVEL_ERR,
210 "libipsec failed pfkey check (%s)\n",
211 ipsec_strerror());
212 goto end;
213 }
214 msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
215
52b7d2ce
A
216 if (msg->sadb_msg_errno) {
217 int pri;
218
219 /* when SPD is empty, treat the state as no error. */
220 if (msg->sadb_msg_type == SADB_X_SPDDUMP &&
221 msg->sadb_msg_errno == ENOENT)
7ebaebe2 222 pri = ASL_LEVEL_NOTICE;
52b7d2ce 223 else
65c25746 224 pri = ASL_LEVEL_ERR;
52b7d2ce 225
65c25746 226 plog(pri,
52b7d2ce
A
227 "pfkey %s failed: %s\n",
228 s_pfkey_type(msg->sadb_msg_type),
229 strerror(msg->sadb_msg_errno));
52b7d2ce
A
230 goto end;
231 }
65c25746 232
52b7d2ce
A
233 /* safety check */
234 if (msg->sadb_msg_type >= ARRAYLEN(pkrecvf)) {
65c25746 235 plog(ASL_LEVEL_ERR,
52b7d2ce
A
236 "unknown PF_KEY message type=%u\n",
237 msg->sadb_msg_type);
238 goto end;
239 }
240
241 if (pkrecvf[msg->sadb_msg_type] == NULL) {
7ebaebe2 242 plog(ASL_LEVEL_NOTICE,
52b7d2ce
A
243 "unsupported PF_KEY message %s\n",
244 s_pfkey_type(msg->sadb_msg_type));
245 goto end;
246 }
247
248 if ((pkrecvf[msg->sadb_msg_type])(mhp) < 0)
249 goto end;
250
251 error = 0;
252end:
253 if (msg)
254 racoon_free(msg);
255 return(error);
256}
257
fd507379
A
258/*
259 * PF_KEY packet handler
260 * 0: success
261 * -1: fail
262 */
65c25746
A
263
264//%%%%%%%%%%%%%%%%%% need to handle errors encountered here - this no longer returns a result
265void
266pfkey_handler(void *unused)
fd507379
A
267{
268 struct sadb_msg *msg;
85f41bec 269 ssize_t len;
fd507379 270
e8d9021d 271 if (slept_at || woke_at) {
7ebaebe2 272 plog(ASL_LEVEL_DEBUG,
e8d9021d 273 "ignoring pfkey port until power-mgmt event is handled.\n");
65c25746 274 return;
e8d9021d
A
275 }
276
fd507379
A
277 /* receive pfkey message. */
278 len = 0;
279 msg = (struct sadb_msg *)pk_recv(lcconf->sock_pfkey, &len);
65c25746 280
fd507379
A
281 if (msg == NULL) {
282 if (len < 0) {
65c25746 283 plog(ASL_LEVEL_ERR,
fd507379
A
284 "failed to recv from pfkey (%s)\n",
285 strerror(errno));
65c25746 286 return;
fd507379
A
287 } else {
288 /* short message - msg not ready */
7ebaebe2 289 plog(ASL_LEVEL_NOTICE, "recv short message from pfkey\n");
65c25746 290 return;
fd507379
A
291 }
292 }
65c25746 293 pfkey_process(msg);
fd507379
A
294}
295
296void
297pfkey_post_handler()
298{
299 struct saved_msg_elem *elem;
300 struct saved_msg_elem *elem_tmp = NULL;
e8d9021d
A
301
302 if (slept_at || woke_at) {
7ebaebe2 303 plog(ASL_LEVEL_NOTICE,
e8d9021d 304 "ignoring (saved) pfkey messages until power-mgmt event is handled.\n");
85f41bec 305 return;
e8d9021d
A
306 }
307
fd507379
A
308 TAILQ_FOREACH_SAFE(elem, &lcconf->saved_msg_queue, chain, elem_tmp) {
309 pfkey_process((struct sadb_msg *)elem->msg);
310 TAILQ_REMOVE(&lcconf->saved_msg_queue, elem, chain);
311 racoon_free(elem);
312
313 }
314}
315
316int
317pfkey_save_msg(msg)
318 struct sadb_msg *msg;
319{
320 struct saved_msg_elem *elem;
321
322 elem = (struct saved_msg_elem *)racoon_calloc(sizeof(struct saved_msg_elem), 1);
323 if (elem == NULL)
324 return -1;
325 elem->msg = msg;
326 TAILQ_INSERT_TAIL(&lcconf->saved_msg_queue, elem, chain);
327 return 0;
328}
329
52b7d2ce
A
330/*
331 * dump SADB
332 */
333vchar_t *
334pfkey_dump_sadb(satype)
335 int satype;
336{
337 int s = -1;
338 vchar_t *buf = NULL;
339 pid_t pid = getpid();
340 struct sadb_msg *msg = NULL;
341 size_t bl, ml;
85f41bec 342 ssize_t len;
52b7d2ce 343
65c25746
A
344 if ((s = pfkey_open()) < 0) {
345 plog(ASL_LEVEL_ERR,
52b7d2ce
A
346 "libipsec failed pfkey open: %s\n",
347 ipsec_strerror());
348 return NULL;
349 }
350
65c25746 351 plog(ASL_LEVEL_DEBUG, "call pfkey_send_dump\n");
52b7d2ce 352 if (pfkey_send_dump(s, satype) < 0) {
65c25746 353 plog(ASL_LEVEL_ERR,
52b7d2ce
A
354 "libipsec failed dump: %s\n", ipsec_strerror());
355 goto fail;
356 }
357
358 while (1) {
359 if (msg)
360 racoon_free(msg);
361 msg = pk_recv(s, &len);
362 if (msg == NULL) {
363 if (len < 0)
364 goto done;
365 else
366 continue;
367 }
368
fd507379
A
369 /*
370 * for multi-processor system this had to be added because the messages can
371 * be interleaved - they won't all be dump messages
372 */
373 if (msg->sadb_msg_type != SADB_DUMP) { /* save for later processing */
374 pfkey_save_msg(msg);
375 msg = NULL;
52b7d2ce 376 continue;
fd507379 377 }
52b7d2ce 378
e8d9021d
A
379 // ignore dump messages that aren't racoon's
380 if (msg->sadb_msg_pid != pid)
381 continue;
382
52b7d2ce
A
383 ml = msg->sadb_msg_len << 3;
384 bl = buf ? buf->l : 0;
385 buf = vrealloc(buf, bl + ml);
386 if (buf == NULL) {
65c25746 387 plog(ASL_LEVEL_ERR,
52b7d2ce
A
388 "failed to reallocate buffer to dump.\n");
389 goto fail;
390 }
391 memcpy(buf->v + bl, msg, ml);
392
393 if (msg->sadb_msg_seq == 0)
394 break;
395 }
396 goto done;
397
398fail:
399 if (buf)
400 vfree(buf);
401 buf = NULL;
402done:
403 if (msg)
404 racoon_free(msg);
405 if (s >= 0)
65c25746 406 pfkey_close_sock(s);
52b7d2ce
A
407 return buf;
408}
409
52b7d2ce
A
410
411/*
412 * These are the SATYPEs that we manage. We register to get
413 * PF_KEY messages related to these SATYPEs, and we also use
414 * this list to determine which SATYPEs to delete SAs for when
415 * we receive an INITIAL-CONTACT.
416 */
417const struct pfkey_satype pfkey_satypes[] = {
418 { SADB_SATYPE_AH, "AH" },
419 { SADB_SATYPE_ESP, "ESP" },
420 { SADB_X_SATYPE_IPCOMP, "IPCOMP" },
421};
422const int pfkey_nsatypes =
423 sizeof(pfkey_satypes) / sizeof(pfkey_satypes[0]);
424
425/*
426 * PF_KEY initialization
427 */
428int
65c25746 429pfkey_init(void)
52b7d2ce 430{
65c25746 431 int i, reg_fail, sock;
52b7d2ce 432
65c25746
A
433 if ((lcconf->sock_pfkey = pfkey_open()) < 0) {
434 plog(ASL_LEVEL_ERR,
52b7d2ce
A
435 "libipsec failed pfkey open (%s)\n", ipsec_strerror());
436 return -1;
437 }
438
439 for (i = 0, reg_fail = 0; i < pfkey_nsatypes; i++) {
65c25746 440 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
441 "call pfkey_send_register for %s\n",
442 pfkey_satypes[i].ps_name);
443 if (pfkey_send_register(lcconf->sock_pfkey,
444 pfkey_satypes[i].ps_satype) < 0 ||
445 pfkey_recv_register(lcconf->sock_pfkey) < 0) {
65c25746 446 plog(ASL_LEVEL_WARNING,
52b7d2ce
A
447 "failed to register %s (%s)\n",
448 pfkey_satypes[i].ps_name,
449 ipsec_strerror());
450 reg_fail++;
451 }
452 }
453
454 if (reg_fail == pfkey_nsatypes) {
65c25746 455 plog(ASL_LEVEL_ERR,
52b7d2ce 456 "failed to regist any protocol.\n");
65c25746 457 close(lcconf->sock_pfkey);
52b7d2ce
A
458 return -1;
459 }
65c25746
A
460 initsp();
461
462 lcconf->pfkey_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, lcconf->sock_pfkey, 0, dispatch_get_main_queue());
463 if (lcconf->pfkey_source == NULL) {
464 plog(ASL_LEVEL_ERR, "could not create pfkey socket source.");
465 return -1;
466 }
467 dispatch_source_set_event_handler_f(lcconf->pfkey_source, pfkey_handler);
468 sock = lcconf->sock_pfkey;
469 dispatch_source_set_cancel_handler(lcconf->pfkey_source,
470 ^{
471 pfkey_close_sock(sock);
472 });
473 dispatch_resume(lcconf->pfkey_source);
52b7d2ce
A
474
475 if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
65c25746 476 plog(ASL_LEVEL_ERR,
52b7d2ce
A
477 "libipsec sending spddump failed: %s\n",
478 ipsec_strerror());
65c25746 479 pfkey_close();
52b7d2ce
A
480 return -1;
481 }
482#if 0
483 if (pfkey_promisc_toggle(1) < 0) {
65c25746 484 pfkey_close();
52b7d2ce
A
485 return -1;
486 }
487#endif
65c25746 488
52b7d2ce
A
489 return 0;
490}
491
65c25746
A
492void
493pfkey_close(void)
494{
495 dispatch_source_cancel(lcconf->pfkey_source);
496 lcconf->pfkey_source = NULL;
497}
498
52b7d2ce
A
499/* %%% for conversion */
500/* IPSECDOI_ATTR_AUTH -> SADB_AALG */
501static u_int
502ipsecdoi2pfkey_aalg(hashtype)
503 u_int hashtype;
504{
505 switch (hashtype) {
65c25746
A
506 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
507 case IPSECDOI_ATTR_AUTH_HMAC_MD5_96:
508 return SADB_AALG_MD5HMAC;
509 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
510 case IPSECDOI_ATTR_AUTH_HMAC_SHA1_96:
511 return SADB_AALG_SHA1HMAC;
512 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
52b7d2ce 513#if (defined SADB_X_AALG_SHA2_256) && !defined(SADB_X_AALG_SHA2_256HMAC)
65c25746 514 return SADB_X_AALG_SHA2_256;
52b7d2ce 515#else
65c25746 516 return SADB_X_AALG_SHA2_256HMAC;
52b7d2ce 517#endif
65c25746 518 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
52b7d2ce 519#if (defined SADB_X_AALG_SHA2_384) && !defined(SADB_X_AALG_SHA2_384HMAC)
65c25746 520 return SADB_X_AALG_SHA2_384;
52b7d2ce 521#else
65c25746 522 return SADB_X_AALG_SHA2_384HMAC;
52b7d2ce 523#endif
65c25746 524 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
52b7d2ce 525#if (defined SADB_X_AALG_SHA2_512) && !defined(SADB_X_AALG_SHA2_512HMAC)
65c25746 526 return SADB_X_AALG_SHA2_512;
52b7d2ce 527#else
65c25746 528 return SADB_X_AALG_SHA2_512HMAC;
52b7d2ce 529#endif
65c25746
A
530 case IPSECDOI_ATTR_AUTH_KPDK: /* need special care */
531 return SADB_AALG_NONE;
532
533 /* not supported */
534 case IPSECDOI_ATTR_AUTH_DES_MAC:
535 plog(ASL_LEVEL_ERR,
536 "Not supported hash type: %u\n", hashtype);
537 return ~0;
538
539 case 0: /* reserved */
540 default:
541 return SADB_AALG_NONE;
542
543 plog(ASL_LEVEL_ERR,
544 "Invalid hash type: %u\n", hashtype);
545 return ~0;
52b7d2ce
A
546 }
547 /*NOTREACHED*/
548}
549
550/* IPSECDOI_ESP -> SADB_EALG */
551static u_int
552ipsecdoi2pfkey_ealg(t_id)
553 u_int t_id;
554{
555 switch (t_id) {
556 case IPSECDOI_ESP_DES_IV64: /* sa_flags |= SADB_X_EXT_OLD */
557 return SADB_EALG_DESCBC;
558 case IPSECDOI_ESP_DES:
559 return SADB_EALG_DESCBC;
560 case IPSECDOI_ESP_3DES:
561 return SADB_EALG_3DESCBC;
562#ifdef SADB_X_EALG_RC5CBC
563 case IPSECDOI_ESP_RC5:
564 return SADB_X_EALG_RC5CBC;
565#endif
566 case IPSECDOI_ESP_CAST:
567 return SADB_X_EALG_CAST128CBC;
568 case IPSECDOI_ESP_BLOWFISH:
569 return SADB_X_EALG_BLOWFISHCBC;
570 case IPSECDOI_ESP_DES_IV32: /* flags |= (SADB_X_EXT_OLD|
571 SADB_X_EXT_IV4B)*/
572 return SADB_EALG_DESCBC;
573 case IPSECDOI_ESP_NULL:
574 return SADB_EALG_NULL;
575#ifdef SADB_X_EALG_AESCBC
576 case IPSECDOI_ESP_AES:
577 return SADB_X_EALG_AESCBC;
578#endif
579#ifdef SADB_X_EALG_TWOFISHCBC
580 case IPSECDOI_ESP_TWOFISH:
581 return SADB_X_EALG_TWOFISHCBC;
582#endif
583
584 /* not supported */
585 case IPSECDOI_ESP_3IDEA:
586 case IPSECDOI_ESP_IDEA:
587 case IPSECDOI_ESP_RC4:
65c25746 588 plog(ASL_LEVEL_ERR,
52b7d2ce
A
589 "Not supported transform: %u\n", t_id);
590 return ~0;
591
592 case 0: /* reserved */
593 default:
65c25746 594 plog(ASL_LEVEL_ERR,
52b7d2ce
A
595 "Invalid transform id: %u\n", t_id);
596 return ~0;
597 }
598 /*NOTREACHED*/
599}
600
601/* IPCOMP -> SADB_CALG */
602static u_int
603ipsecdoi2pfkey_calg(t_id)
604 u_int t_id;
605{
606 switch (t_id) {
607 case IPSECDOI_IPCOMP_OUI:
608 return SADB_X_CALG_OUI;
609 case IPSECDOI_IPCOMP_DEFLATE:
610 return SADB_X_CALG_DEFLATE;
611 case IPSECDOI_IPCOMP_LZS:
612 return SADB_X_CALG_LZS;
613
614 case 0: /* reserved */
615 default:
65c25746 616 plog(ASL_LEVEL_ERR,
52b7d2ce
A
617 "Invalid transform id: %u\n", t_id);
618 return ~0;
619 }
620 /*NOTREACHED*/
621}
622
623/* IPSECDOI_PROTO -> SADB_SATYPE */
624u_int
625ipsecdoi2pfkey_proto(proto)
626 u_int proto;
627{
628 switch (proto) {
629 case IPSECDOI_PROTO_IPSEC_AH:
630 return SADB_SATYPE_AH;
631 case IPSECDOI_PROTO_IPSEC_ESP:
632 return SADB_SATYPE_ESP;
633 case IPSECDOI_PROTO_IPCOMP:
634 return SADB_X_SATYPE_IPCOMP;
635
636 default:
65c25746 637 plog(ASL_LEVEL_ERR,
52b7d2ce
A
638 "Invalid ipsec_doi proto: %u\n", proto);
639 return ~0;
640 }
641 /*NOTREACHED*/
642}
643
644static u_int
645ipsecdoi2pfkey_alg(algclass, type)
646 u_int algclass, type;
647{
648 switch (algclass) {
649 case IPSECDOI_ATTR_AUTH:
650 return ipsecdoi2pfkey_aalg(type);
651 case IPSECDOI_PROTO_IPSEC_ESP:
652 return ipsecdoi2pfkey_ealg(type);
653 case IPSECDOI_PROTO_IPCOMP:
654 return ipsecdoi2pfkey_calg(type);
655 default:
65c25746 656 plog(ASL_LEVEL_ERR,
52b7d2ce
A
657 "Invalid ipsec_doi algclass: %u\n", algclass);
658 return ~0;
659 }
660 /*NOTREACHED*/
661}
662
663/* SADB_SATYPE -> IPSECDOI_PROTO */
664u_int
665pfkey2ipsecdoi_proto(satype)
666 u_int satype;
667{
668 switch (satype) {
669 case SADB_SATYPE_AH:
670 return IPSECDOI_PROTO_IPSEC_AH;
671 case SADB_SATYPE_ESP:
672 return IPSECDOI_PROTO_IPSEC_ESP;
673 case SADB_X_SATYPE_IPCOMP:
674 return IPSECDOI_PROTO_IPCOMP;
675
676 default:
65c25746 677 plog(ASL_LEVEL_ERR,
52b7d2ce
A
678 "Invalid pfkey proto: %u\n", satype);
679 return ~0;
680 }
681 /*NOTREACHED*/
682}
683
684/* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
685u_int
686ipsecdoi2pfkey_mode(mode)
687 u_int mode;
688{
689 switch (mode) {
690 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
691#ifdef ENABLE_NATT
692 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
693 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
694#endif
695 return IPSEC_MODE_TUNNEL;
696 case IPSECDOI_ATTR_ENC_MODE_TRNS:
697#ifdef ENABLE_NATT
698 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
699 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
700#endif
701 return IPSEC_MODE_TRANSPORT;
702 default:
65c25746 703 plog(ASL_LEVEL_ERR, "Invalid mode type: %u\n", mode);
52b7d2ce
A
704 return ~0;
705 }
706 /*NOTREACHED*/
707}
708
709/* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
710u_int
711pfkey2ipsecdoi_mode(mode)
712 u_int mode;
713{
714 switch (mode) {
715 case IPSEC_MODE_TUNNEL:
716 return IPSECDOI_ATTR_ENC_MODE_TUNNEL;
717 case IPSEC_MODE_TRANSPORT:
718 return IPSECDOI_ATTR_ENC_MODE_TRNS;
719 case IPSEC_MODE_ANY:
720 return IPSECDOI_ATTR_ENC_MODE_ANY;
721 default:
65c25746 722 plog(ASL_LEVEL_ERR, "Invalid mode type: %u\n", mode);
52b7d2ce
A
723 return ~0;
724 }
725 /*NOTREACHED*/
726}
727
728/* default key length for encryption algorithm */
729static u_int
730keylen_aalg(hashtype)
731 u_int hashtype;
732{
733 int res;
734
735 if (hashtype == 0)
736 return SADB_AALG_NONE;
737
738 res = alg_ipsec_hmacdef_hashlen(hashtype);
739 if (res == -1) {
65c25746 740 plog(ASL_LEVEL_ERR,
52b7d2ce
A
741 "invalid hmac algorithm %u.\n", hashtype);
742 return ~0;
743 }
744 return res;
745}
746
747/* default key length for encryption algorithm */
748static u_int
749keylen_ealg(enctype, encklen)
750 u_int enctype;
751 int encklen;
752{
753 int res;
754
755 res = alg_ipsec_encdef_keylen(enctype, encklen);
756 if (res == -1) {
65c25746 757 plog(ASL_LEVEL_ERR,
52b7d2ce
A
758 "invalid encryption algorithm %u.\n", enctype);
759 return ~0;
760 }
761 return res;
762}
763
764int
65c25746 765pfkey_convertfromipsecdoi(iph2, proto_id, t_id, hashtype,
52b7d2ce 766 e_type, e_keylen, a_type, a_keylen, flags)
65c25746 767 phase2_handle_t *iph2;
52b7d2ce
A
768 u_int proto_id;
769 u_int t_id;
770 u_int hashtype;
771 u_int *e_type;
772 u_int *e_keylen;
773 u_int *a_type;
774 u_int *a_keylen;
775 u_int *flags;
776{
777 *flags = 0;
778 switch (proto_id) {
779 case IPSECDOI_PROTO_IPSEC_ESP:
780 if ((*e_type = ipsecdoi2pfkey_ealg(t_id)) == ~0)
781 goto bad;
782 if ((*e_keylen = keylen_ealg(t_id, *e_keylen)) == ~0)
783 goto bad;
784 *e_keylen >>= 3;
785
786 if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
787 goto bad;
788 if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
789 goto bad;
790 *a_keylen >>= 3;
d9c572c0 791
52b7d2ce 792 if (*e_type == SADB_EALG_NONE) {
65c25746 793 plog(ASL_LEVEL_ERR, "no ESP algorithm.\n");
52b7d2ce
A
794 goto bad;
795 }
796 break;
797
798 case IPSECDOI_PROTO_IPSEC_AH:
799 if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
800 goto bad;
801 if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
802 goto bad;
803 *a_keylen >>= 3;
804
805 if (t_id == IPSECDOI_ATTR_AUTH_HMAC_MD5
806 && hashtype == IPSECDOI_ATTR_AUTH_KPDK) {
807 /* AH_MD5 + Auth(KPDK) = RFC1826 keyed-MD5 */
808 *a_type = SADB_X_AALG_MD5;
809 *flags |= SADB_X_EXT_OLD;
810 }
811 *e_type = SADB_EALG_NONE;
812 *e_keylen = 0;
813 if (*a_type == SADB_AALG_NONE) {
65c25746 814 plog(ASL_LEVEL_ERR, "no AH algorithm.\n");
52b7d2ce
A
815 goto bad;
816 }
817 break;
818
819 case IPSECDOI_PROTO_IPCOMP:
820 if ((*e_type = ipsecdoi2pfkey_calg(t_id)) == ~0)
821 goto bad;
822 *e_keylen = 0;
823
824 *flags = SADB_X_EXT_RAWCPI;
825
826 *a_type = SADB_AALG_NONE;
827 *a_keylen = 0;
828 if (*e_type == SADB_X_CALG_NONE) {
65c25746 829 plog(ASL_LEVEL_ERR, "no IPCOMP algorithm.\n");
52b7d2ce
A
830 goto bad;
831 }
832 break;
833
834 default:
65c25746 835 plog(ASL_LEVEL_ERR, "unknown IPsec protocol.\n");
52b7d2ce
A
836 goto bad;
837 }
838
839 return 0;
840
841 bad:
842 errno = EINVAL;
843 return -1;
844}
845
846/* called from scheduler */
847void
848pfkey_timeover_stub(p)
849 void *p;
850{
851
65c25746 852 pfkey_timeover((phase2_handle_t *)p);
52b7d2ce
A
853}
854
855void
856pfkey_timeover(iph2)
65c25746 857 phase2_handle_t *iph2;
52b7d2ce 858{
65c25746 859 plog(ASL_LEVEL_ERR,
52b7d2ce 860 "%s give up to get IPsec-SA due to time up to wait.\n",
85f41bec 861 saddrwop2str((struct sockaddr *)iph2->dst));
52b7d2ce
A
862 SCHED_KILL(iph2->sce);
863
864 /* If initiator side, send error to kernel by SADB_ACQUIRE. */
865 if (iph2->side == INITIATOR)
866 pk_sendeacquire(iph2);
867
65c25746 868 ike_session_unlink_phase2(iph2);
52b7d2ce
A
869
870 return;
871}
872
873/*%%%*/
874/* send getspi message per ipsec protocol per remote address */
875/*
876 * the local address and remote address in ph1handle are dealed
877 * with destination address and source address respectively.
878 * Because SPI is decided by responder.
879 */
880int
881pk_sendgetspi(iph2)
65c25746 882 phase2_handle_t *iph2;
52b7d2ce 883{
85f41bec 884 struct sockaddr_storage *src = NULL, *dst = NULL;
52b7d2ce
A
885 u_int satype, mode;
886 struct saprop *pp;
887 struct saproto *pr;
888 u_int32_t minspi, maxspi;
889 int proxy = 0;
890
891 if (iph2->side == INITIATOR) {
892 pp = iph2->proposal;
893 proxy = iph2->ph1->rmconf->support_proxy;
894 } else {
895 pp = iph2->approval;
896 if (iph2->sainfo && iph2->sainfo->id_i)
897 proxy = 1;
898 }
899
900 /* for mobile IPv6 */
901 if (proxy && iph2->src_id && iph2->dst_id &&
902 ipsecdoi_transportmode(pp)) {
903 src = iph2->src_id;
904 dst = iph2->dst_id;
905 } else {
906 src = iph2->src;
907 dst = iph2->dst;
908 }
909
910 for (pr = pp->head; pr != NULL; pr = pr->next) {
911
912 /* validity check */
913 satype = ipsecdoi2pfkey_proto(pr->proto_id);
914 if (satype == ~0) {
65c25746 915 plog(ASL_LEVEL_ERR,
52b7d2ce
A
916 "invalid proto_id %d\n", pr->proto_id);
917 return -1;
918 }
919 /* this works around a bug in Linux kernel where it allocates 4 byte
920 spi's for IPCOMP */
921 else if (satype == SADB_X_SATYPE_IPCOMP) {
922 minspi = 0x100;
923 maxspi = 0xffff;
924 }
925 else {
926 minspi = 0;
927 maxspi = 0;
928 }
929 mode = ipsecdoi2pfkey_mode(pr->encmode);
930 if (mode == ~0) {
65c25746 931 plog(ASL_LEVEL_ERR,
52b7d2ce
A
932 "invalid encmode %d\n", pr->encmode);
933 return -1;
934 }
935
65c25746 936 plog(ASL_LEVEL_DEBUG, "call pfkey_send_getspi\n");
52b7d2ce
A
937 if (pfkey_send_getspi(
938 lcconf->sock_pfkey,
939 satype,
940 mode,
941 dst, /* src of SA */
942 src, /* dst of SA */
943 minspi, maxspi,
65c25746
A
944 pr->reqid_in, 0, 0, iph2->seq, 0) < 0) {
945 plog(ASL_LEVEL_ERR,
52b7d2ce
A
946 "ipseclib failed send getspi (%s)\n",
947 ipsec_strerror());
948 return -1;
949 }
65c25746
A
950
951 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
952 "pfkey GETSPI sent: %s\n",
953 sadbsecas2str(dst, src, satype, 0, mode));
954 }
955
956 return 0;
957}
958
959/*
960 * receive GETSPI from kernel.
961 */
962static int
963pk_recvgetspi(mhp)
964 caddr_t *mhp;
965{
966 struct sadb_msg *msg;
967 struct sadb_sa *sa;
65c25746 968 phase2_handle_t *iph2;
85f41bec 969 struct sockaddr_storage *dst;
52b7d2ce
A
970 int proto_id;
971 int allspiok, notfound;
972 struct saprop *pp;
973 struct saproto *pr;
974
975 /* validity check */
976 if (mhp[SADB_EXT_SA] == NULL
977 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
65c25746
A
978 plog(ASL_LEVEL_ERR,
979 "Inappropriate sadb getspi message passed.\n");
52b7d2ce
A
980 return -1;
981 }
85f41bec
A
982 msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
983 sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
984 dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */
52b7d2ce
A
985
986 /* the message has to be processed or not ? */
987 if (msg->sadb_msg_pid != getpid()) {
65c25746 988 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
989 "%s message is not interesting "
990 "because pid %d is not mine.\n",
991 s_pfkey_type(msg->sadb_msg_type),
992 msg->sadb_msg_pid);
993 return -1;
994 }
995
65c25746 996 iph2 = ike_session_getph2byseq(msg->sadb_msg_seq);
52b7d2ce 997 if (iph2 == NULL) {
65c25746
A
998 plog(ASL_LEVEL_DEBUG,
999 "Seq %d of %s message not interesting.\n",
52b7d2ce
A
1000 msg->sadb_msg_seq,
1001 s_pfkey_type(msg->sadb_msg_type));
1002 return -1;
1003 }
1004
80318cb7 1005 if (iph2->is_dying) {
65c25746
A
1006 plog(ASL_LEVEL_ERR,
1007 "Status mismatch Phase 2 dying (db:%d)\n",
1008 iph2->status);
80318cb7
A
1009 return -1;
1010 }
65c25746
A
1011
1012 switch (iph2->version) {
1013 case ISAKMP_VERSION_NUMBER_IKEV1:
1014 if (iph2->status != IKEV1_STATE_QUICK_I_GETSPISENT &&
1015 iph2->status != IKEV1_STATE_QUICK_R_GETSPISENT) {
1016 plog(ASL_LEVEL_ERR, "Status mismatch (db:%d)\n", iph2->status);
1017 return -1;
1018 }
1019 // check the underlying iph2->ph1
1020 if (!iph2->ph1) {
1021 if (!ike_session_update_ph2_ph1bind(iph2)) {
1022 plog(ASL_LEVEL_ERR,
1023 "Can't proceed with getspi for %s. no suitable ISAKMP-SA found \n",
1024 saddrwop2str((struct sockaddr *)iph2->dst));
1025 ike_session_unlink_phase2(iph2);
1026 return -1;
1027 }
1028 }
1029 break;
1030 default:
1031 plog(ASL_LEVEL_ERR, "Internal error: invalid IKE major version %d\n", iph2->version);
d1e348cf 1032 return -1;
d1e348cf
A
1033 }
1034
52b7d2ce
A
1035 /* set SPI, and check to get all spi whether or not */
1036 allspiok = 1;
1037 notfound = 1;
1038 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1039 pp = iph2->side == INITIATOR ? iph2->proposal : iph2->approval;
1040
1041 for (pr = pp->head; pr != NULL; pr = pr->next) {
1042 if (pr->proto_id == proto_id && pr->spi == 0) {
1043 pr->spi = sa->sadb_sa_spi;
1044 notfound = 0;
65c25746 1045 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1046 "pfkey GETSPI succeeded: %s\n",
1047 sadbsecas2str(iph2->dst, iph2->src,
1048 msg->sadb_msg_satype,
1049 sa->sadb_sa_spi,
1050 ipsecdoi2pfkey_mode(pr->encmode)));
1051 }
1052 if (pr->spi == 0)
1053 allspiok = 0; /* not get all spi */
1054 }
1055
1056 if (notfound) {
65c25746
A
1057 plog(ASL_LEVEL_ERR,
1058 "Get spi for unknown address %s\n",
85f41bec 1059 saddrwop2str((struct sockaddr *)iph2->dst));
65c25746 1060 ike_session_unlink_phase2(iph2);
52b7d2ce
A
1061 return -1;
1062 }
1063
1064 if (allspiok) {
65c25746
A
1065 switch (iph2->version) {
1066 case ISAKMP_VERSION_NUMBER_IKEV1:
1067 if (isakmp_post_getspi(iph2) < 0) {
1068 plog(ASL_LEVEL_ERR, "IKEv1 post getspi failed.\n");
1069 ike_session_unlink_phase2(iph2);
1070 iph2 = NULL;
1071 return -1;
1072 }
1073 break;
1074 }
1075 }
52b7d2ce
A
1076 return 0;
1077}
1078
1079/*
1080 * set inbound SA
1081 */
1082int
1083pk_sendupdate(iph2)
65c25746 1084 phase2_handle_t *iph2;
52b7d2ce
A
1085{
1086 struct saproto *pr;
85f41bec 1087 struct sockaddr_storage *src = NULL, *dst = NULL;
52b7d2ce
A
1088 u_int e_type, e_keylen, a_type, a_keylen, flags;
1089 u_int satype, mode;
1090 u_int64_t lifebyte = 0;
1091 u_int wsize = 4; /* XXX static size of window */
1092 int proxy = 0;
1093 struct ph2natt natt;
65c25746 1094 int authtype;
52b7d2ce
A
1095
1096 /* sanity check */
1097 if (iph2->approval == NULL) {
65c25746
A
1098 plog(ASL_LEVEL_ERR,
1099 "No approved SAs found.\n");
52b7d2ce
A
1100 }
1101
1102 if (iph2->side == INITIATOR)
1103 proxy = iph2->ph1->rmconf->support_proxy;
1104 else if (iph2->sainfo && iph2->sainfo->id_i)
1105 proxy = 1;
1106
1107 /* for mobile IPv6 */
1108 if (proxy && iph2->src_id && iph2->dst_id &&
1109 ipsecdoi_transportmode(iph2->approval)) {
1110 src = iph2->src_id;
1111 dst = iph2->dst_id;
1112 } else {
1113 src = iph2->src;
1114 dst = iph2->dst;
1115 }
1116
1117 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1118 /* validity check */
1119 satype = ipsecdoi2pfkey_proto(pr->proto_id);
1120 if (satype == ~0) {
65c25746
A
1121 plog(ASL_LEVEL_ERR,
1122 "Invalid proto_id %d\n", pr->proto_id);
52b7d2ce
A
1123 return -1;
1124 }
1125 else if (satype == SADB_X_SATYPE_IPCOMP) {
1126 /* IPCOMP has no replay window */
1127 wsize = 0;
1128 }
1129#ifdef ENABLE_SAMODE_UNSPECIFIED
1130 mode = IPSEC_MODE_ANY;
1131#else
1132 mode = ipsecdoi2pfkey_mode(pr->encmode);
1133 if (mode == ~0) {
65c25746
A
1134 plog(ASL_LEVEL_ERR,
1135 "Invalid encmode %d\n", pr->encmode);
52b7d2ce
A
1136 return -1;
1137 }
1138#endif
1139
1140 /* set algorithm type and key length */
1141 e_keylen = pr->head->encklen;
65c25746
A
1142 authtype = pr->head->authtype;
1143 a_keylen = 0;
52b7d2ce 1144 if (pfkey_convertfromipsecdoi(
65c25746 1145 iph2,
52b7d2ce
A
1146 pr->proto_id,
1147 pr->head->trns_id,
65c25746 1148 authtype,
52b7d2ce
A
1149 &e_type, &e_keylen,
1150 &a_type, &a_keylen, &flags) < 0)
1151 return -1;
1152
1153#if 0
1154 lifebyte = iph2->approval->lifebyte * 1024,
1155#else
1156 lifebyte = 0;
1157#endif
1158
52b7d2ce 1159#ifdef ENABLE_NATT
65c25746
A
1160 //plog(ASL_LEVEL_DEBUG, "call pfkey_send_update\n");
1161 plog(ASL_LEVEL_DEBUG, "call pfkey_send_update: e_type %d, e_klen %d, a_type %d, a_klen %d\n",
1162 e_type, e_keylen, a_type, a_keylen);
52b7d2ce
A
1163 if (pr->udp_encap) {
1164 memset (&natt, 0, sizeof (natt));
1165 natt.sport = extract_port (iph2->ph1->remote);
1166 flags |= SADB_X_EXT_NATT;
1760d65d
A
1167 if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
1168 mode == IPSEC_MODE_TRANSPORT &&
1169 src->ss_family == AF_INET) {
1170 flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
1171 if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
1172 // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
1173 flags |= SADB_X_EXT_NATT_DETECTED_PEER;
1174 }
1175 } else if (iph2->ph1->natt_flags & NAT_DETECTED_ME) {
d1e348cf
A
1176 if (iph2->ph1->rmconf->natt_keepalive == TRUE)
1177 flags |= SADB_X_EXT_NATT_KEEPALIVE;
e8d9021d 1178 } else {
e8d9021d
A
1179 if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
1180 // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
1181 flags |= SADB_X_EXT_NATT_DETECTED_PEER;
1182 }
1183 }
52b7d2ce
A
1184 } else {
1185 memset (&natt, 0, sizeof (natt));
1186 }
1187
1188 if (pfkey_send_update(
1189 lcconf->sock_pfkey,
1190 satype,
1191 mode,
1192 dst,
1193 src,
1194 pr->spi,
1195 pr->reqid_in,
1196 wsize,
1197 pr->keymat->v,
1198 e_type, e_keylen, a_type, a_keylen, flags,
1199 0, lifebyte, iph2->approval->lifetime, 0,
65c25746
A
1200 iph2->seq, natt.sport, 0) < 0) {
1201 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1202 "libipsec failed send update (%s)\n",
1203 ipsec_strerror());
1204 return -1;
1205 }
1206#else
65c25746 1207 plog(ASL_LEVEL_DEBUG, "call pfkey_send_update\n");
52b7d2ce
A
1208 if (pfkey_send_update(
1209 lcconf->sock_pfkey,
1210 satype,
1211 mode,
1212 dst,
1213 src,
1214 pr->spi,
1215 pr->reqid_in,
1216 wsize,
1217 pr->keymat->v,
1218 e_type, e_keylen, a_type, a_keylen, flags,
1219 0, lifebyte, iph2->approval->lifetime, 0,
65c25746
A
1220 iph2->seq, 0, 0) < 0) {
1221 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1222 "libipsec failed send update (%s)\n",
1223 ipsec_strerror());
1224 return -1;
1225 }
1226#endif /* ENABLE_NATT */
52b7d2ce 1227
52b7d2ce 1228
52b7d2ce
A
1229 }
1230
1231 return 0;
1232}
1233
1234static int
1235pk_recvupdate(mhp)
1236 caddr_t *mhp;
1237{
1238 struct sadb_msg *msg;
1239 struct sadb_sa *sa;
85f41bec 1240 struct sockaddr_storage *src, *dst;
65c25746 1241 phase2_handle_t *iph2;
52b7d2ce
A
1242 u_int proto_id, encmode, sa_mode;
1243 int incomplete = 0;
1244 struct saproto *pr;
1245
1246 /* ignore this message because of local test mode. */
1247 if (f_local)
1248 return 0;
1249
1250 /* sanity check */
1251 if (mhp[0] == NULL
1252 || mhp[SADB_EXT_SA] == NULL
1253 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1254 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
65c25746 1255 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1256 "inappropriate sadb update message passed.\n");
1257 return -1;
1258 }
85f41bec
A
1259 msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1260 src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1261 dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1262 sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
52b7d2ce
A
1263
1264 sa_mode = mhp[SADB_X_EXT_SA2] == NULL
1265 ? IPSEC_MODE_ANY
85f41bec 1266 : (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
52b7d2ce
A
1267
1268 /* the message has to be processed or not ? */
1269 if (msg->sadb_msg_pid != getpid()) {
65c25746 1270 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1271 "%s message is not interesting "
1272 "because pid %d is not mine.\n",
1273 s_pfkey_type(msg->sadb_msg_type),
1274 msg->sadb_msg_pid);
1275 return -1;
1276 }
1277
65c25746 1278 iph2 = ike_session_getph2byseq(msg->sadb_msg_seq);
52b7d2ce 1279 if (iph2 == NULL) {
65c25746
A
1280 plog(ASL_LEVEL_DEBUG,
1281 "Seq %d of %s message not interesting.\n",
52b7d2ce
A
1282 msg->sadb_msg_seq,
1283 s_pfkey_type(msg->sadb_msg_type));
1284 return -1;
1285 }
1286
80318cb7 1287 if (iph2->is_dying) {
65c25746
A
1288 plog(ASL_LEVEL_ERR,
1289 "Status mismatch Phase 2 dying (db:%d)\n",
1290 iph2->status);
80318cb7
A
1291 return -1;
1292 }
65c25746
A
1293 if (iph2->status != IKEV1_STATE_QUICK_I_ADDSA &&
1294 iph2->status != IKEV1_STATE_QUICK_R_ADDSA) {
1295 plog(ASL_LEVEL_ERR,
1296 "Status mismatch (db:%d)\n",
1297 iph2->status);
52b7d2ce
A
1298 return -1;
1299 }
1300
1301 /* check to complete all keys ? */
1302 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1303 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1304 if (proto_id == ~0) {
65c25746 1305 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1306 "invalid proto_id %d\n", msg->sadb_msg_satype);
1307 return -1;
1308 }
1309 encmode = pfkey2ipsecdoi_mode(sa_mode);
1310 if (encmode == ~0) {
65c25746 1311 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1312 "invalid encmode %d\n", sa_mode);
1313 return -1;
1314 }
1315
1316 if (pr->proto_id == proto_id
1317 && pr->spi == sa->sadb_sa_spi) {
1318 pr->ok = 1;
65c25746 1319 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1320 "pfkey UPDATE succeeded: %s\n",
1321 sadbsecas2str(iph2->dst, iph2->src,
1322 msg->sadb_msg_satype,
1323 sa->sadb_sa_spi,
1324 sa_mode));
1325
7ebaebe2
A
1326 plog(ASL_LEVEL_NOTICE,
1327 "IPsec-SA established (update): satype=%u spi=%#x mode=%u\n",
1328 msg->sadb_msg_satype, ntohl(sa->sadb_sa_spi), sa_mode);
1329 plog(ASL_LEVEL_DEBUG,
1330 "IPsec-SA established (update): %s\n",
1331 sadbsecas2str(iph2->dst, iph2->src,
1332 msg->sadb_msg_satype, sa->sadb_sa_spi,
1333 sa_mode));
52b7d2ce
A
1334 }
1335
1336 if (pr->ok == 0)
1337 incomplete = 1;
1338 }
1339
1340 if (incomplete)
1341 return 0;
1342
1343 /* turn off the timer for calling pfkey_timeover() */
1344 SCHED_KILL(iph2->sce);
1345
1346 /* update status */
65c25746 1347 fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_ESTABLISHED);
52b7d2ce 1348
d1e348cf
A
1349 ike_session_ph2_established(iph2);
1350
65c25746 1351 IPSECLOGASLMSG("IPSec Phase 2 established (Initiated by %s).\n",
e8d9021d
A
1352 (iph2->side == INITIATOR)? "me" : "peer");
1353
52b7d2ce
A
1354#ifdef ENABLE_STATS
1355 gettimeofday(&iph2->end, NULL);
65c25746
A
1356 plog(ASL_LEVEL_NOTICE, "%s(%s): %8.6f",
1357 "Phase 2", "quick", timedelta(&iph2->start, &iph2->end));
52b7d2ce
A
1358#endif
1359
1360 /* count up */
fce29cd9
A
1361 if (iph2->ph1)
1362 iph2->ph1->ph2cnt++;
52b7d2ce
A
1363
1364 /* turn off schedule */
1365 if (iph2->scr)
1366 SCHED_KILL(iph2->scr);
1367
1368 /*
1369 * since we are going to reuse the phase2 handler, we need to
1370 * remain it and refresh all the references between ph1 and ph2 to use.
1371 */
65c25746 1372 ike_session_unbindph12(iph2); //%%%%% fix this
52b7d2ce
A
1373
1374 iph2->sce = sched_new(iph2->approval->lifetime,
1375 isakmp_ph2expire_stub, iph2);
1376
65c25746 1377 plog(ASL_LEVEL_DEBUG, "===\n");
52b7d2ce
A
1378 return 0;
1379}
1380
1381/*
1382 * set outbound SA
1383 */
1384int
1385pk_sendadd(iph2)
65c25746 1386 phase2_handle_t *iph2;
52b7d2ce
A
1387{
1388 struct saproto *pr;
85f41bec 1389 struct sockaddr_storage *src = NULL, *dst = NULL;
52b7d2ce
A
1390 u_int e_type, e_keylen, a_type, a_keylen, flags;
1391 u_int satype, mode;
1392 u_int64_t lifebyte = 0;
1393 u_int wsize = 4; /* XXX static size of window */
1394 int proxy = 0;
1395 struct ph2natt natt;
65c25746 1396 int authtype;
52b7d2ce
A
1397
1398 /* sanity check */
1399 if (iph2->approval == NULL) {
65c25746 1400 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1401 "no approvaled SAs found.\n");
1402 }
1403
1404 if (iph2->side == INITIATOR)
1405 proxy = iph2->ph1->rmconf->support_proxy;
1406 else if (iph2->sainfo && iph2->sainfo->id_i)
1407 proxy = 1;
1408
1409 /* for mobile IPv6 */
1410 if (proxy && iph2->src_id && iph2->dst_id &&
1411 ipsecdoi_transportmode(iph2->approval)) {
1412 src = iph2->src_id;
1413 dst = iph2->dst_id;
1414 } else {
1415 src = iph2->src;
1416 dst = iph2->dst;
1417 }
1418
1419 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1420 /* validity check */
1421 satype = ipsecdoi2pfkey_proto(pr->proto_id);
1422 if (satype == ~0) {
65c25746 1423 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1424 "invalid proto_id %d\n", pr->proto_id);
1425 return -1;
1426 }
1427 else if (satype == SADB_X_SATYPE_IPCOMP) {
1428 /* no replay window for IPCOMP */
1429 wsize = 0;
1430 }
1431#ifdef ENABLE_SAMODE_UNSPECIFIED
1432 mode = IPSEC_MODE_ANY;
1433#else
1434 mode = ipsecdoi2pfkey_mode(pr->encmode);
1435 if (mode == ~0) {
65c25746 1436 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1437 "invalid encmode %d\n", pr->encmode);
1438 return -1;
1439 }
1440#endif
1441
1442 /* set algorithm type and key length */
1443 e_keylen = pr->head->encklen;
65c25746
A
1444 authtype = pr->head->authtype;
1445 a_keylen = 0;
52b7d2ce 1446 if (pfkey_convertfromipsecdoi(
65c25746 1447 iph2,
52b7d2ce
A
1448 pr->proto_id,
1449 pr->head->trns_id,
65c25746 1450 authtype,
52b7d2ce
A
1451 &e_type, &e_keylen,
1452 &a_type, &a_keylen, &flags) < 0)
1453 return -1;
1454
1455#if 0
1456 lifebyte = iph2->approval->lifebyte * 1024,
1457#else
1458 lifebyte = 0;
1459#endif
1460
52b7d2ce 1461#ifdef ENABLE_NATT
65c25746
A
1462 //plog(ASL_LEVEL_DEBUG, "call pfkey_send_add\n");
1463 plog(ASL_LEVEL_DEBUG, "call pfkey_send_add: e_type %d, e_klen %d, a_type %d, a_klen %d\n",
1464 e_type, e_keylen, a_type, a_keylen);
52b7d2ce
A
1465
1466 if (pr->udp_encap) {
1467 memset (&natt, 0, sizeof (natt));
1468 natt.dport = extract_port (iph2->ph1->remote);
1469 flags |= SADB_X_EXT_NATT;
1760d65d
A
1470 if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
1471 mode == IPSEC_MODE_TRANSPORT &&
1472 src->ss_family == AF_INET) {
1473 flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
1474 if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
1475 // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
1476 flags |= SADB_X_EXT_NATT_DETECTED_PEER;
1477 }
1478 } else if (iph2->ph1->natt_flags & NAT_DETECTED_ME) {
d1e348cf
A
1479 if (iph2->ph1->rmconf->natt_keepalive == TRUE)
1480 flags |= SADB_X_EXT_NATT_KEEPALIVE;
e8d9021d 1481 } else {
e8d9021d
A
1482 if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
1483 // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
1484 flags |= SADB_X_EXT_NATT_DETECTED_PEER;
1485 }
1486 }
52b7d2ce
A
1487 } else {
1488 memset (&natt, 0, sizeof (natt));
1489
1490 /* Remove port information, that SA doesn't use it */
1491 //set_port(src, 0);
1492 //set_port(dst, 0);
1493 }
1494
1495 if (pfkey_send_add(
1496 lcconf->sock_pfkey,
1497 satype,
1498 mode,
1499 src,
1500 dst,
1501 pr->spi_p,
1502 pr->reqid_out,
1503 wsize,
1504 pr->keymat_p->v,
1505 e_type, e_keylen, a_type, a_keylen, flags,
1506 0, lifebyte, iph2->approval->lifetime, 0,
65c25746
A
1507 iph2->seq,natt.dport, 0) < 0) {
1508 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1509 "libipsec failed send add (%s)\n",
1510 ipsec_strerror());
1511 return -1;
1512 }
1513#else
65c25746 1514 plog(ASL_LEVEL_DEBUG, "call pfkey_send_add\n");
52b7d2ce
A
1515
1516 /* Remove port information, it is not used without NAT-T */
1517 //set_port(src, 0);
1518 //set_port(dst, 0);
1519
1520 if (pfkey_send_add(
1521 lcconf->sock_pfkey,
1522 satype,
1523 mode,
1524 src,
1525 dst,
1526 pr->spi_p,
1527 pr->reqid_out,
1528 wsize,
1529 pr->keymat_p->v,
1530 e_type, e_keylen, a_type, a_keylen, flags,
1531 0, lifebyte, iph2->approval->lifetime, 0,
65c25746
A
1532 iph2->seq, 0, 0) < 0) {
1533 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1534 "libipsec failed send add (%s)\n",
1535 ipsec_strerror());
1536 return -1;
1537 }
1538#endif /* ENABLE_NATT */
52b7d2ce
A
1539 }
1540
1541 return 0;
1542}
1543
1544static int
1545pk_recvadd(mhp)
1546 caddr_t *mhp;
1547{
1548 struct sadb_msg *msg;
1549 struct sadb_sa *sa;
85f41bec 1550 struct sockaddr_storage *src, *dst;
65c25746 1551 phase2_handle_t *iph2;
52b7d2ce
A
1552 u_int sa_mode;
1553
1554 /* ignore this message because of local test mode. */
1555 if (f_local)
1556 return 0;
1557
1558 /* sanity check */
1559 if (mhp[0] == NULL
1560 || mhp[SADB_EXT_SA] == NULL
1561 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1562 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
65c25746 1563 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1564 "inappropriate sadb add message passed.\n");
1565 return -1;
1566 }
85f41bec
A
1567 msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1568 src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1569 dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1570 sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
52b7d2ce
A
1571
1572 sa_mode = mhp[SADB_X_EXT_SA2] == NULL
1573 ? IPSEC_MODE_ANY
85f41bec 1574 : (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
52b7d2ce
A
1575
1576 /* the message has to be processed or not ? */
1577 if (msg->sadb_msg_pid != getpid()) {
65c25746 1578 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1579 "%s message is not interesting "
1580 "because pid %d is not mine.\n",
1581 s_pfkey_type(msg->sadb_msg_type),
1582 msg->sadb_msg_pid);
1583 return -1;
1584 }
1585
65c25746 1586 iph2 = ike_session_getph2byseq(msg->sadb_msg_seq);
52b7d2ce 1587 if (iph2 == NULL) {
65c25746 1588 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1589 "seq %d of %s message not interesting.\n",
1590 msg->sadb_msg_seq,
1591 s_pfkey_type(msg->sadb_msg_type));
1592 return -1;
1593 }
52b7d2ce
A
1594 /*
1595 * NOTE don't update any status of phase2 handle
1596 * because they must be updated by SADB_UPDATE message
1597 */
1598
7ebaebe2
A
1599 plog(ASL_LEVEL_NOTICE,
1600 "IPsec-SA established (add): satype=%u spi=%#x mode=%u\n",
1601 msg->sadb_msg_satype, ntohl(sa->sadb_sa_spi), sa_mode);
1602 plog(ASL_LEVEL_DEBUG,
1603 "IPsec-SA established (add): %s\n",
52b7d2ce
A
1604 sadbsecas2str(iph2->src, iph2->dst,
1605 msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
1606
d1e348cf
A
1607 ike_session_cleanup_other_established_ph2s(iph2->parent_session, iph2);
1608
52b7d2ce
A
1609#ifdef ENABLE_VPNCONTROL_PORT
1610 {
52b7d2ce
A
1611 vpncontrol_notify_phase_change(0, FROM_LOCAL, NULL, iph2);
1612 }
1613#endif
1614
65c25746 1615 plog(ASL_LEVEL_DEBUG, "===\n");
52b7d2ce
A
1616 return 0;
1617}
1618
1619static int
1620pk_recvexpire(mhp)
1621 caddr_t *mhp;
1622{
1623 struct sadb_msg *msg;
1624 struct sadb_sa *sa;
85f41bec 1625 struct sockaddr_storage *src, *dst;
65c25746 1626 phase2_handle_t *iph2;
52b7d2ce
A
1627 u_int proto_id, sa_mode;
1628
1629 /* sanity check */
1630 if (mhp[0] == NULL
1631 || mhp[SADB_EXT_SA] == NULL
1632 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1633 || mhp[SADB_EXT_ADDRESS_DST] == NULL
1634 || (mhp[SADB_EXT_LIFETIME_HARD] != NULL
1635 && mhp[SADB_EXT_LIFETIME_SOFT] != NULL)) {
65c25746 1636 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1637 "inappropriate sadb expire message passed.\n");
1638 return -1;
1639 }
85f41bec
A
1640 msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1641 sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
1642 src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1643 dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
52b7d2ce
A
1644
1645 sa_mode = mhp[SADB_X_EXT_SA2] == NULL
1646 ? IPSEC_MODE_ANY
85f41bec 1647 : (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
52b7d2ce
A
1648
1649 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1650 if (proto_id == ~0) {
65c25746 1651 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1652 "invalid proto_id %d\n", msg->sadb_msg_satype);
1653 return -1;
1654 }
1655
7ebaebe2
A
1656 plog(ASL_LEVEL_NOTICE,
1657 "IPsec-SA expired: satype=%u spi=%#x mode=%u\n",
1658 msg->sadb_msg_satype, ntohl(sa->sadb_sa_spi), sa_mode);
1659 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1660 "IPsec-SA expired: %s\n",
1661 sadbsecas2str(src, dst,
1662 msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
1663
65c25746 1664 iph2 = ike_session_getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
52b7d2ce
A
1665 if (iph2 == NULL) {
1666 /*
1667 * Ignore it because two expire messages are come up.
1668 * phase2 handler has been deleted already when 2nd message
1669 * is received.
1670 */
65c25746 1671 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1672 "no such a SA found: %s\n",
1673 sadbsecas2str(src, dst,
1674 msg->sadb_msg_satype, sa->sadb_sa_spi,
1675 sa_mode));
1676 return 0;
1677 }
65c25746 1678 if (iph2->is_dying || !FSM_STATE_IS_ESTABLISHED(iph2->status)) {
52b7d2ce
A
1679 /*
1680 * If the status is not equal to PHASE2ST_ESTABLISHED,
1681 * racoon ignores this expire message. There are two reason.
1682 * One is that the phase 2 probably starts because there is
1683 * a potential that racoon receives the acquire message
1684 * without receiving a expire message. Another is that racoon
1685 * may receive the multiple expire messages from the kernel.
1686 */
65c25746
A
1687 plog(ASL_LEVEL_WARNING,
1688 "The expire message is received but the handler %s (status = 0x%x).\n",
1689 iph2->is_dying ? "is dying" : "has not been established", iph2->status);
52b7d2ce
A
1690 return 0;
1691 }
1692
1693 /* turn off the timer for calling isakmp_ph2expire() */
1694 SCHED_KILL(iph2->sce);
d9c572c0
A
1695
1696 fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_EXPIRED);
1697
1698 /* INITIATOR, begin phase 2 exchange only if there's no other established ph2. */
1699 /* allocate buffer for status management of pfkey message */
1700 if (iph2->side == INITIATOR &&
1701 !ike_session_has_other_established_ph2(iph2->parent_session, iph2) &&
1702 !ike_session_drop_rekey(iph2->parent_session, IKE_SESSION_REKEY_TYPE_PH2)) {
1703
1704 ike_session_initph2(iph2);
1705
1706 /* start isakmp initiation by using ident exchange */
1707 if (isakmp_post_acquire(iph2) < 0) {
1708 plog(ASL_LEVEL_ERR,
1709 "failed to begin ipsec sa "
1710 "re-negotiation.\n");
1711 ike_session_unlink_phase2(iph2);
1712 return -1;
1713 }
52b7d2ce 1714
d9c572c0
A
1715 return 0;
1716 /*NOTREACHED*/
1717 }
52b7d2ce 1718
52b7d2ce
A
1719
1720 /* If not received SADB_EXPIRE, INITIATOR delete ph2handle. */
1721 /* RESPONDER always delete ph2handle, keep silent. RESPONDER doesn't
1722 * manage IPsec SA, so delete the list */
65c25746 1723 ike_session_unlink_phase2(iph2);
52b7d2ce
A
1724
1725 return 0;
1726}
1727
1728static int
1729pk_recvacquire(mhp)
1730 caddr_t *mhp;
1731{
1732 struct sadb_msg *msg;
1733 struct sadb_x_policy *xpl;
1734 struct secpolicy *sp_out = NULL, *sp_in = NULL;
65c25746 1735 phase2_handle_t *iph2;
85f41bec 1736 struct sockaddr_storage *src, *dst;
65c25746
A
1737 ike_session_t *session = NULL;
1738 struct remoteconf *rmconf;
52b7d2ce
A
1739
1740 /* ignore this message because of local test mode. */
1741 if (f_local)
1742 return 0;
1743
1744 /* sanity check */
1745 if (mhp[0] == NULL
1746 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1747 || mhp[SADB_EXT_ADDRESS_DST] == NULL
1748 || mhp[SADB_X_EXT_POLICY] == NULL) {
65c25746 1749 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1750 "inappropriate sadb acquire message passed.\n");
1751 return -1;
1752 }
85f41bec
A
1753 msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1754 xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
1755 src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1756 dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
52b7d2ce
A
1757
1758 /* ignore if type is not IPSEC_POLICY_IPSEC */
1759 if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
65c25746 1760 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1761 "ignore ACQUIRE message. type is not IPsec.\n");
1762 return 0;
1763 }
1764
1765 /* ignore it if src is multicast address */
1766 {
85f41bec 1767 struct sockaddr_storage *sa = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
52b7d2ce 1768
85f41bec 1769 if ((sa->ss_family == AF_INET
52b7d2ce
A
1770 && IN_MULTICAST(ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr)))
1771#ifdef INET6
85f41bec 1772 || (sa->ss_family == AF_INET6
52b7d2ce
A
1773 && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sa)->sin6_addr))
1774#endif
1775 ) {
65c25746 1776 plog(ASL_LEVEL_DEBUG,
52b7d2ce 1777 "ignore due to multicast address: %s.\n",
85f41bec 1778 saddrwop2str((struct sockaddr *)sa));
52b7d2ce
A
1779 return 0;
1780 }
1781 }
1782
1783 /* ignore, if we do not listen on source address */
1784 {
1785 /* reasons behind:
1786 * - if we'll contact peer from address we do not listen -
1787 * we will be unable to complete negotiation;
1788 * - if we'll negotiate using address we're listening -
1789 * remote peer will send packets to address different
1790 * than one in the policy, so kernel will drop them;
1791 * => therefore this acquire is not for us! --Aidas
1792 */
85f41bec
A
1793 // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1794 struct sockaddr_storage *sa = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
52b7d2ce
A
1795 struct myaddrs *p;
1796 int do_listen = 0;
65c25746 1797 char * str;
52b7d2ce 1798 for (p = lcconf->myaddrs; p; p = p->next) {
65c25746
A
1799 str = saddr2str((struct sockaddr *)p->addr);
1800 plog(ASL_LEVEL_DEBUG,
1801 "checking listen addrs: %s", str);
1802
52b7d2ce
A
1803 if (!cmpsaddrwop(p->addr, sa)) {
1804 do_listen = 1;
1805 break;
1806 }
1807 }
1808
1809 if (!do_listen) {
65c25746 1810 plog(ASL_LEVEL_DEBUG,
52b7d2ce 1811 "ignore because do not listen on source address : %s.\n",
85f41bec 1812 saddrwop2str((struct sockaddr *)sa));
52b7d2ce
A
1813 return 0;
1814 }
1815 }
1816
1817 /*
1818 * If there is a phase 2 handler against the policy identifier in
1819 * the acquire message, and if
1820 * 1. its state is less than PHASE2ST_ESTABLISHED, then racoon
1821 * should ignore such a acquire message because the phase 2
1822 * is just negotiating.
1823 * 2. its state is equal to PHASE2ST_ESTABLISHED, then racoon
d1e348cf
A
1824 * has to process such a acquire message because racoon may
1825 * have lost the expire message.
52b7d2ce 1826 */
65c25746
A
1827 iph2 = ike_session_getph2byid(src, dst, xpl->sadb_x_policy_id);
1828 if (iph2 != NULL) {
1829 session = iph2->parent_session;
1830 if (!FSM_STATE_IS_ESTABLISHED(iph2->status)) {
1831 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1832 "ignore the acquire because ph2 found\n");
1833 return -1;
1834 }
65c25746
A
1835 if (FSM_STATE_IS_EXPIRED(iph2->status))
1836 iph2 = NULL;
52b7d2ce
A
1837 /*FALLTHROUGH*/
1838 }
1839
1840 /* search for proper policyindex */
1841 sp_out = getspbyspid(xpl->sadb_x_policy_id);
1842 if (sp_out == NULL) {
65c25746 1843 plog(ASL_LEVEL_ERR, "no policy found: id:%d.\n",
52b7d2ce
A
1844 xpl->sadb_x_policy_id);
1845 return -1;
1846 }
65c25746 1847 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1848 "suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx));
1849
1850 /* get inbound policy */
1851 {
65c25746
A
1852 struct policyindex spidx;
1853
1854 spidx.dir = IPSEC_DIR_INBOUND;
1855 memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src));
1856 memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst));
1857 spidx.prefs = sp_out->spidx.prefd;
1858 spidx.prefd = sp_out->spidx.prefs;
1859 spidx.ul_proto = sp_out->spidx.ul_proto;
1860
1861 sp_in = getsp(&spidx);
1862 if (sp_in) {
1863 plog(ASL_LEVEL_DEBUG,
1864 "Suitable inbound SP found: %s.\n",
1865 spidx2str(&sp_in->spidx));
1866 } else {
1867 plog(ASL_LEVEL_NOTICE,
1868 "No in-bound policy found: %s\n",
1869 spidx2str(&spidx));
1870 }
52b7d2ce 1871 }
65c25746 1872
52b7d2ce 1873 /* allocate a phase 2 */
65c25746
A
1874 rmconf = getrmconf(dst);
1875 if (rmconf == NULL) {
1876 plog(ASL_LEVEL_ERR, "No configuration found for %s.\n",
1877 saddrwop2str((struct sockaddr *)dst));
1878 return -1;
1879 }
1880
1881 iph2 = ike_session_newph2(rmconf->ike_version, PHASE2_TYPE_SA);
1882 if (iph2 == NULL) {
1883 plog(ASL_LEVEL_ERR,
1884 "Failed to allocate Phase 2 entry.\n");
52b7d2ce
A
1885 return -1;
1886 }
65c25746
A
1887 plog(ASL_LEVEL_DEBUG, "Got new Phase 2 version %d\n", iph2->version);
1888 iph2->version = rmconf->ike_version;
1889 iph2->side = INITIATOR;
1890 iph2->spid = xpl->sadb_x_policy_id;
52b7d2ce 1891
65c25746
A
1892 iph2->satype = msg->sadb_msg_satype;
1893 iph2->seq = msg->sadb_msg_seq;
d06a7ccb 1894 vpncontrol_set_nat64_prefix(&iph2->nat64_prefix);
52b7d2ce 1895 /* set end addresses of SA */
85f41bec 1896 // Wcast_align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
65c25746
A
1897 iph2->src = dupsaddr(ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]));
1898 if (iph2->src == NULL) {
1899 ike_session_delph2(iph2);
52b7d2ce
A
1900 return -1;
1901 }
65c25746
A
1902 iph2->dst = dupsaddr(ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]));
1903 if (iph2->dst == NULL) {
1904 ike_session_delph2(iph2);
52b7d2ce 1905 return -1;
65c25746
A
1906 }
1907
1908 if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) {
1909 fsm_set_state(&iph2->status, IKEV1_STATE_QUICK_I_START);
52b7d2ce
A
1910 }
1911
65c25746 1912 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
1913 "new acquire %s\n", spidx2str(&sp_out->spidx));
1914
1915 /* get sainfo */
1916 {
65c25746
A
1917 vchar_t *idsrc, *iddst;
1918
1919 idsrc = ipsecdoi_sockaddr2id(&sp_out->spidx.src,
1920 sp_out->spidx.prefs, sp_out->spidx.ul_proto);
1921 if (idsrc == NULL) {
1922 plog(ASL_LEVEL_ERR,
1923 "failed to get ID for %s\n",
1924 spidx2str(&sp_out->spidx));
1925 ike_session_delph2(iph2);
1926 return -1;
1927 }
1928 iddst = ipsecdoi_sockaddr2id(&sp_out->spidx.dst,
1929 sp_out->spidx.prefd, sp_out->spidx.ul_proto);
1930 if (iddst == NULL) {
1931 plog(ASL_LEVEL_ERR,
1932 "failed to get ID for %s\n",
1933 spidx2str(&sp_out->spidx));
1934 vfree(idsrc);
1935 ike_session_delph2(iph2);
1936 return -1;
1937 }
1938 iph2->sainfo = getsainfo(idsrc, iddst, NULL, 0);
1939 vfree(idsrc);
1940 vfree(iddst);
1941 if (iph2->sainfo == NULL) {
1942 plog(ASL_LEVEL_ERR,
1943 "failed to get sainfo.\n");
1944 ike_session_delph2(iph2);
1945 return -1;
1946 /* XXX should use the algorithm list from register message */
1947 }
52b7d2ce 1948 }
65c25746 1949 retain_sainfo(iph2->sainfo);
52b7d2ce 1950
65c25746
A
1951 if (set_proposal_from_policy(iph2, sp_out, sp_in) < 0) {
1952 plog(ASL_LEVEL_ERR,
1953 "failed to create saprop.\n");
1954 ike_session_delph2(iph2);
52b7d2ce
A
1955 return -1;
1956 }
65c25746
A
1957
1958 if (session == NULL)
1760d65d 1959 session = ike_session_get_session(iph2->src, iph2->dst, 1, NULL);
65c25746
A
1960 if (session == NULL)
1961 fatal_error(-1);
1962
1963 if (ike_session_link_phase2(session, iph2))
1964 fatal_error(-1); //????? fix ???
52b7d2ce
A
1965
1966 /* start isakmp initiation by using ident exchange */
1967 /* XXX should be looped if there are multiple phase 2 handler. */
65c25746
A
1968 if (isakmp_post_acquire(iph2) < 0) {
1969 plog(ASL_LEVEL_ERR,
d1e348cf 1970 "failed to begin ipsec sa negotiation.\n");
52b7d2ce
A
1971 goto err;
1972 }
d1e348cf 1973
4aae5213 1974#if !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
d1e348cf
A
1975 if ( lcconf->vt == NULL){
1976 if (!(lcconf->vt = vproc_transaction_begin(NULL)))
65c25746 1977 plog(ASL_LEVEL_ERR,
d1e348cf
A
1978 "vproc_transaction_begin returns NULL.\n");
1979 }
4aae5213 1980#endif // !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
52b7d2ce 1981
d1e348cf 1982
52b7d2ce
A
1983 return 0;
1984
1985err:
65c25746 1986 ike_session_unlink_phase2(iph2);
52b7d2ce
A
1987 return -1;
1988}
1989
1990static int
1991pk_recvdelete(mhp)
1992 caddr_t *mhp;
1993{
1994 struct sadb_msg *msg;
1995 struct sadb_sa *sa;
85f41bec 1996 struct sockaddr_storage *src, *dst;
65c25746 1997 phase2_handle_t *iph2 = NULL;
52b7d2ce
A
1998 u_int proto_id;
1999
2000 /* ignore this message because of local test mode. */
2001 if (f_local)
2002 return 0;
2003
2004 /* sanity check */
2005 if (mhp[0] == NULL
52b7d2ce
A
2006 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2007 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
65c25746 2008 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2009 "inappropriate sadb delete message passed.\n");
2010 return -1;
2011 }
85f41bec
A
2012 msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2013 sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
2014 src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
2015 dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
52b7d2ce
A
2016
2017 /* the message has to be processed or not ? */
2018 if (msg->sadb_msg_pid == getpid()) {
65c25746 2019 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
2020 "%s message is not interesting "
2021 "because the message was originated by me.\n",
2022 s_pfkey_type(msg->sadb_msg_type));
2023 return -1;
2024 }
2025
2026 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
2027 if (proto_id == ~0) {
65c25746 2028 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2029 "invalid proto_id %d\n", msg->sadb_msg_satype);
2030 return -1;
2031 }
2032
65c25746
A
2033 plog(ASL_LEVEL_DEBUG, "SADB delete message: proto-id %d\n", proto_id);
2034 plog(ASL_LEVEL_DEBUG, "src: %s\n", saddr2str((struct sockaddr *)src));
2035 plog(ASL_LEVEL_DEBUG, "dst: %s\n", saddr2str((struct sockaddr *)dst));
d1e348cf
A
2036
2037 if (!sa) {
65c25746
A
2038 ike_session_deleteallph2(src, dst, proto_id);
2039 ike_session_deleteallph1(src, dst);
d1e348cf
A
2040 return 0;
2041 }
2042
65c25746 2043 iph2 = ike_session_getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
52b7d2ce
A
2044 if (iph2 == NULL) {
2045 /* ignore */
65c25746 2046 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2047 "no iph2 found: %s\n",
2048 sadbsecas2str(src, dst, msg->sadb_msg_satype,
2049 sa->sadb_sa_spi, IPSEC_MODE_ANY));
2050 return 0;
2051 }
2052
65c25746 2053 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2054 "pfkey DELETE received: %s\n",
2055 sadbsecas2str(iph2->src, iph2->dst,
2056 msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY));
2057
2058 /* send delete information */
65c25746
A
2059
2060 /* TODO: Look into handling this properly. Currently, if we get here, we can end up sending delete messages to the server for their own SAs, which is rejected. */
2061 /*if (FSM_STATE_IS_ESTABLISHED(iph2->status))
52b7d2ce
A
2062 isakmp_info_send_d2(iph2);
2063
d1e348cf 2064 ike_session_cleanup_ph1s_by_ph2(iph2);
65c25746 2065 ike_session_unlink_phase2(iph2);*/
52b7d2ce
A
2066
2067 return 0;
2068}
2069
2070static int
2071pk_recvflush(mhp)
2072 caddr_t *mhp;
2073{
52b7d2ce
A
2074 /* sanity check */
2075 if (mhp[0] == NULL) {
65c25746 2076 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2077 "inappropriate sadb flush message passed.\n");
2078 return -1;
2079 }
2080
65c25746
A
2081 ike_session_flush_all_phase2(false);
2082 ike_session_flush_all_phase1(false);
52b7d2ce
A
2083
2084 return 0;
2085}
2086
2087static int
2088getsadbpolicy(policy0, policylen0, type, iph2)
2089 caddr_t *policy0;
2090 int *policylen0, type;
65c25746 2091 phase2_handle_t *iph2;
52b7d2ce 2092{
85f41bec 2093 struct policyindex *spidx = iph2->spidx_gen;
52b7d2ce
A
2094 struct sadb_x_policy *xpl;
2095 struct sadb_x_ipsecrequest *xisr;
2096 struct saproto *pr;
2097 caddr_t policy, p;
2098 int policylen;
2099 int xisrlen;
2100 u_int satype, mode;
2101
2102 /* get policy buffer size */
2103 policylen = sizeof(struct sadb_x_policy);
2104 if (type != SADB_X_SPDDELETE) {
2105 for (pr = iph2->approval->head; pr; pr = pr->next) {
2106 xisrlen = sizeof(*xisr);
2107 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
85f41bec
A
2108 xisrlen += (sysdep_sa_len((struct sockaddr *)iph2->src)
2109 + sysdep_sa_len((struct sockaddr *)iph2->dst));
52b7d2ce
A
2110 }
2111
2112 policylen += PFKEY_ALIGN8(xisrlen);
2113 }
2114 }
2115
2116 /* make policy structure */
2117 policy = racoon_malloc(policylen);
2118 if (!policy) {
65c25746 2119 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2120 "buffer allocation failed.\n");
2121 return -1;
2122 }
2123
85f41bec 2124 xpl = ALIGNED_CAST(struct sadb_x_policy *)policy;
52b7d2ce
A
2125 xpl->sadb_x_policy_len = PFKEY_UNIT64(policylen);
2126 xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
2127 xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
2128 xpl->sadb_x_policy_dir = spidx->dir;
2129 xpl->sadb_x_policy_id = 0;
2130#ifdef HAVE_PFKEY_POLICY_PRIORITY
2131 xpl->sadb_x_policy_priority = PRIORITY_DEFAULT;
2132#endif
2133
2134 /* no need to append policy information any more if type is SPDDELETE */
2135 if (type == SADB_X_SPDDELETE)
2136 goto end;
2137
2138 xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
2139
2140 for (pr = iph2->approval->head; pr; pr = pr->next) {
2141
2142 satype = doi2ipproto(pr->proto_id);
2143 if (satype == ~0) {
65c25746 2144 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2145 "invalid proto_id %d\n", pr->proto_id);
2146 goto err;
2147 }
2148 mode = ipsecdoi2pfkey_mode(pr->encmode);
2149 if (mode == ~0) {
65c25746 2150 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2151 "invalid encmode %d\n", pr->encmode);
2152 goto err;
2153 }
2154
2155 /*
2156 * the policy level cannot be unique because the policy
2157 * is defined later than SA, so req_id cannot be bound to SA.
2158 */
2159 xisr->sadb_x_ipsecrequest_proto = satype;
2160 xisr->sadb_x_ipsecrequest_mode = mode;
2161 xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
2162 xisr->sadb_x_ipsecrequest_reqid = 0;
2163 p = (caddr_t)(xisr + 1);
2164
2165 xisrlen = sizeof(*xisr);
2166
2167 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
2168 int src_len, dst_len;
2169
85f41bec
A
2170 src_len = sysdep_sa_len((struct sockaddr *)iph2->src);
2171 dst_len = sysdep_sa_len((struct sockaddr *)iph2->dst);
52b7d2ce
A
2172 xisrlen += src_len + dst_len;
2173
2174 memcpy(p, iph2->src, src_len);
2175 p += src_len;
2176
2177 memcpy(p, iph2->dst, dst_len);
2178 p += dst_len;
2179 }
2180
2181 xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(xisrlen);
2182 }
2183
2184end:
2185 *policy0 = policy;
2186 *policylen0 = policylen;
2187
2188 return 0;
2189
2190err:
2191 if (policy)
2192 racoon_free(policy);
2193
2194 return -1;
2195}
2196
2197int
2198pk_sendspdupdate2(iph2)
65c25746 2199 phase2_handle_t *iph2;
52b7d2ce 2200{
85f41bec 2201 struct policyindex *spidx = iph2->spidx_gen;
52b7d2ce
A
2202 caddr_t policy = NULL;
2203 int policylen = 0;
2204 u_int64_t ltime, vtime;
2205
2206 ltime = iph2->approval->lifetime;
2207 vtime = 0;
2208
2209 if (getsadbpolicy(&policy, &policylen, SADB_X_SPDUPDATE, iph2)) {
65c25746 2210 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2211 "getting sadb policy failed.\n");
2212 return -1;
2213 }
2214
2215 if (pfkey_send_spdupdate2(
2216 lcconf->sock_pfkey,
85f41bec 2217 &spidx->src,
52b7d2ce 2218 spidx->prefs,
85f41bec 2219 &spidx->dst,
52b7d2ce
A
2220 spidx->prefd,
2221 spidx->ul_proto,
2222 ltime, vtime,
2223 policy, policylen, 0) < 0) {
65c25746 2224 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2225 "libipsec failed send spdupdate2 (%s)\n",
2226 ipsec_strerror());
2227 goto end;
2228 }
65c25746 2229 plog(ASL_LEVEL_DEBUG, "call pfkey_send_spdupdate2\n");
52b7d2ce
A
2230
2231end:
2232 if (policy)
2233 racoon_free(policy);
2234
2235 return 0;
2236}
2237
2238static int
2239pk_recvspdupdate(mhp)
2240 caddr_t *mhp;
2241{
2242 struct sadb_address *saddr, *daddr;
2243 struct sadb_x_policy *xpl;
2244 struct policyindex spidx;
2245 struct secpolicy *sp;
2246
2247 /* sanity check */
2248 if (mhp[0] == NULL
2249 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2250 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2251 || mhp[SADB_X_EXT_POLICY] == NULL) {
65c25746 2252 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2253 "inappropriate sadb spdupdate message passed.\n");
2254 return -1;
2255 }
85f41bec
A
2256 saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2257 daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2258 xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
52b7d2ce
A
2259
2260#ifdef HAVE_PFKEY_POLICY_PRIORITY
2261 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2262 saddr + 1,
2263 daddr + 1,
2264 saddr->sadb_address_prefixlen,
2265 daddr->sadb_address_prefixlen,
2266 saddr->sadb_address_proto,
2267 xpl->sadb_x_policy_priority,
2268 &spidx);
2269#else
2270 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2271 saddr + 1,
2272 daddr + 1,
2273 saddr->sadb_address_prefixlen,
2274 daddr->sadb_address_prefixlen,
2275 saddr->sadb_address_proto,
2276 &spidx);
2277#endif
2278
2279 sp = getsp(&spidx);
2280 if (sp == NULL) {
65c25746 2281 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2282 "such policy does not already exist: \"%s\"\n",
2283 spidx2str(&spidx));
2284 } else {
2285 remsp(sp);
2286 delsp(sp);
2287 }
2288
2289 if (addnewsp(mhp) < 0)
2290 return -1;
2291
2292 return 0;
2293}
2294
2295/*
2296 * this function has to be used by responder side.
2297 */
2298int
2299pk_sendspdadd2(iph2)
65c25746 2300 phase2_handle_t *iph2;
52b7d2ce 2301{
85f41bec 2302 struct policyindex *spidx = iph2->spidx_gen;
52b7d2ce
A
2303 caddr_t policy = NULL;
2304 int policylen = 0;
2305 u_int64_t ltime, vtime;
2306
2307 ltime = iph2->approval->lifetime;
2308 vtime = 0;
2309
2310 if (getsadbpolicy(&policy, &policylen, SADB_X_SPDADD, iph2)) {
65c25746 2311 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2312 "getting sadb policy failed.\n");
2313 return -1;
2314 }
2315
2316 if (pfkey_send_spdadd2(
2317 lcconf->sock_pfkey,
85f41bec 2318 &spidx->src,
52b7d2ce 2319 spidx->prefs,
85f41bec 2320 &spidx->dst,
52b7d2ce
A
2321 spidx->prefd,
2322 spidx->ul_proto,
2323 ltime, vtime,
2324 policy, policylen, 0) < 0) {
65c25746 2325 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2326 "libipsec failed send spdadd2 (%s)\n",
2327 ipsec_strerror());
2328 goto end;
2329 }
65c25746 2330 plog(ASL_LEVEL_DEBUG, "call pfkey_send_spdadd2\n");
52b7d2ce
A
2331
2332end:
2333 if (policy)
2334 racoon_free(policy);
2335
2336 return 0;
2337}
2338
2339static int
2340pk_recvspdadd(mhp)
2341 caddr_t *mhp;
2342{
2343 struct sadb_address *saddr, *daddr;
2344 struct sadb_x_policy *xpl;
2345 struct policyindex spidx;
2346 struct secpolicy *sp;
2347
2348 /* sanity check */
2349 if (mhp[0] == NULL
2350 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2351 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2352 || mhp[SADB_X_EXT_POLICY] == NULL) {
65c25746 2353 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2354 "inappropriate sadb spdadd message passed.\n");
2355 return -1;
2356 }
85f41bec
A
2357 saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2358 daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2359 xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
52b7d2ce
A
2360
2361#ifdef HAVE_PFKEY_POLICY_PRIORITY
2362 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2363 saddr + 1,
2364 daddr + 1,
2365 saddr->sadb_address_prefixlen,
2366 daddr->sadb_address_prefixlen,
2367 saddr->sadb_address_proto,
2368 xpl->sadb_x_policy_priority,
2369 &spidx);
2370#else
2371 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2372 saddr + 1,
2373 daddr + 1,
2374 saddr->sadb_address_prefixlen,
2375 daddr->sadb_address_prefixlen,
2376 saddr->sadb_address_proto,
2377 &spidx);
2378#endif
2379
2380 sp = getsp(&spidx);
2381 if (sp != NULL) {
65c25746 2382 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2383 "such policy already exists. "
2384 "anyway replace it: %s\n",
2385 spidx2str(&spidx));
2386 remsp(sp);
2387 delsp(sp);
2388 }
2389
2390 if (addnewsp(mhp) < 0)
2391 return -1;
2392
2393 return 0;
2394}
2395
2396/*
2397 * this function has to be used by responder side.
2398 */
2399int
2400pk_sendspddelete(iph2)
65c25746 2401 phase2_handle_t *iph2;
52b7d2ce 2402{
85f41bec 2403 struct policyindex *spidx = iph2->spidx_gen;
52b7d2ce
A
2404 caddr_t policy = NULL;
2405 int policylen;
2406
2407 if (getsadbpolicy(&policy, &policylen, SADB_X_SPDDELETE, iph2)) {
65c25746 2408 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2409 "getting sadb policy failed.\n");
2410 return -1;
2411 }
2412
2413 if (pfkey_send_spddelete(
2414 lcconf->sock_pfkey,
85f41bec 2415 &spidx->src,
52b7d2ce 2416 spidx->prefs,
85f41bec 2417 &spidx->dst,
52b7d2ce
A
2418 spidx->prefd,
2419 spidx->ul_proto,
2420 policy, policylen, 0) < 0) {
65c25746 2421 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2422 "libipsec failed send spddelete (%s)\n",
2423 ipsec_strerror());
2424 goto end;
2425 }
65c25746 2426 plog(ASL_LEVEL_DEBUG, "call pfkey_send_spddelete\n");
52b7d2ce
A
2427
2428end:
2429 if (policy)
2430 racoon_free(policy);
2431
2432 return 0;
2433}
2434
2435static int
2436pk_recvspddelete(mhp)
2437 caddr_t *mhp;
2438{
2439 struct sadb_address *saddr, *daddr;
2440 struct sadb_x_policy *xpl;
2441 struct policyindex spidx;
2442 struct secpolicy *sp;
2443
2444 /* sanity check */
2445 if (mhp[0] == NULL
2446 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2447 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2448 || mhp[SADB_X_EXT_POLICY] == NULL) {
65c25746 2449 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2450 "inappropriate sadb spddelete message passed.\n");
2451 return -1;
2452 }
85f41bec
A
2453 saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2454 daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2455 xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
52b7d2ce
A
2456
2457#ifdef HAVE_PFKEY_POLICY_PRIORITY
2458 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2459 saddr + 1,
2460 daddr + 1,
2461 saddr->sadb_address_prefixlen,
2462 daddr->sadb_address_prefixlen,
2463 saddr->sadb_address_proto,
2464 xpl->sadb_x_policy_priority,
2465 &spidx);
2466#else
2467 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2468 saddr + 1,
2469 daddr + 1,
2470 saddr->sadb_address_prefixlen,
2471 daddr->sadb_address_prefixlen,
2472 saddr->sadb_address_proto,
2473 &spidx);
2474#endif
2475
2476 sp = getsp(&spidx);
2477 if (sp == NULL) {
65c25746 2478 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2479 "no policy found: %s\n",
2480 spidx2str(&spidx));
2481 return -1;
2482 }
2483
65c25746 2484 ike_session_purgephXbyspid(xpl->sadb_x_policy_id, true);
d1e348cf 2485
52b7d2ce
A
2486 remsp(sp);
2487 delsp(sp);
2488
2489 return 0;
2490}
2491
2492static int
2493pk_recvspdexpire(mhp)
2494 caddr_t *mhp;
2495{
2496 struct sadb_address *saddr, *daddr;
2497 struct sadb_x_policy *xpl;
2498 struct policyindex spidx;
2499 struct secpolicy *sp;
2500
2501 /* sanity check */
2502 if (mhp[0] == NULL
2503 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2504 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2505 || mhp[SADB_X_EXT_POLICY] == NULL) {
65c25746 2506 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2507 "inappropriate sadb spdexpire message passed.\n");
2508 return -1;
2509 }
85f41bec
A
2510 saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2511 daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2512 xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
52b7d2ce
A
2513
2514#ifdef HAVE_PFKEY_POLICY_PRIORITY
2515 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2516 saddr + 1,
2517 daddr + 1,
2518 saddr->sadb_address_prefixlen,
2519 daddr->sadb_address_prefixlen,
2520 saddr->sadb_address_proto,
2521 xpl->sadb_x_policy_priority,
2522 &spidx);
2523#else
2524 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2525 saddr + 1,
2526 daddr + 1,
2527 saddr->sadb_address_prefixlen,
2528 daddr->sadb_address_prefixlen,
2529 saddr->sadb_address_proto,
2530 &spidx);
2531#endif
2532
2533 sp = getsp(&spidx);
2534 if (sp == NULL) {
65c25746 2535 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2536 "no policy found: %s\n",
2537 spidx2str(&spidx));
2538 return -1;
2539 }
2540
65c25746 2541 ike_session_purgephXbyspid(xpl->sadb_x_policy_id, false);
d1e348cf 2542
52b7d2ce
A
2543 remsp(sp);
2544 delsp(sp);
2545
2546 return 0;
2547}
2548
2549static int
2550pk_recvspdget(mhp)
2551 caddr_t *mhp;
2552{
2553 /* sanity check */
2554 if (mhp[0] == NULL) {
65c25746 2555 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2556 "inappropriate sadb spdget message passed.\n");
2557 return -1;
2558 }
2559
2560 return 0;
2561}
2562
2563static int
2564pk_recvspddump(mhp)
2565 caddr_t *mhp;
2566{
2567 struct sadb_msg *msg;
2568 struct sadb_address *saddr, *daddr;
2569 struct sadb_x_policy *xpl;
2570 struct policyindex spidx;
2571 struct secpolicy *sp;
2572
2573 /* sanity check */
2574 if (mhp[0] == NULL) {
65c25746 2575 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2576 "inappropriate sadb spddump message passed.\n");
2577 return -1;
2578 }
85f41bec 2579 msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
52b7d2ce 2580
85f41bec
A
2581 saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
2582 daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2583 xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
52b7d2ce
A
2584
2585 if (saddr == NULL || daddr == NULL || xpl == NULL) {
65c25746 2586 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2587 "inappropriate sadb spddump message passed.\n");
2588 return -1;
2589 }
2590
2591#ifdef HAVE_PFKEY_POLICY_PRIORITY
2592 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2593 saddr + 1,
2594 daddr + 1,
2595 saddr->sadb_address_prefixlen,
2596 daddr->sadb_address_prefixlen,
2597 saddr->sadb_address_proto,
2598 xpl->sadb_x_policy_priority,
2599 &spidx);
2600#else
2601 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2602 saddr + 1,
2603 daddr + 1,
2604 saddr->sadb_address_prefixlen,
2605 daddr->sadb_address_prefixlen,
2606 saddr->sadb_address_proto,
2607 &spidx);
2608#endif
2609
2610 sp = getsp(&spidx);
2611 if (sp != NULL) {
65c25746 2612 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2613 "such policy already exists. "
2614 "anyway replace it: %s\n",
2615 spidx2str(&spidx));
2616 remsp(sp);
2617 delsp(sp);
2618 }
2619
2620 if (addnewsp(mhp) < 0)
2621 return -1;
2622
2623 return 0;
2624}
2625
2626static int
2627pk_recvspdflush(mhp)
2628 caddr_t *mhp;
2629{
2630 /* sanity check */
2631 if (mhp[0] == NULL) {
65c25746 2632 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2633 "inappropriate sadb spdflush message passed.\n");
2634 return -1;
2635 }
2636
65c25746
A
2637 ike_session_flush_all_phase2(false);
2638 ike_session_flush_all_phase1(false);
52b7d2ce
A
2639 flushsp();
2640
2641 return 0;
2642}
2643
2644/*
2645 * send error against acquire message to kenrel.
2646 */
2647int
2648pk_sendeacquire(iph2)
65c25746 2649 phase2_handle_t *iph2;
52b7d2ce
A
2650{
2651 struct sadb_msg *newmsg;
2652 int len;
2653
2654 len = sizeof(struct sadb_msg);
2655 newmsg = racoon_calloc(1, len);
2656 if (newmsg == NULL) {
65c25746 2657 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2658 "failed to get buffer to send acquire.\n");
2659 return -1;
2660 }
2661
2662 memset(newmsg, 0, len);
2663 newmsg->sadb_msg_version = PF_KEY_V2;
2664 newmsg->sadb_msg_type = SADB_ACQUIRE;
2665 newmsg->sadb_msg_errno = ENOENT; /* XXX */
2666 newmsg->sadb_msg_satype = iph2->satype;
2667 newmsg->sadb_msg_len = PFKEY_UNIT64(len);
2668 newmsg->sadb_msg_reserved = 0;
2669 newmsg->sadb_msg_seq = iph2->seq;
2670 newmsg->sadb_msg_pid = (u_int32_t)getpid();
2671
2672 /* send message */
2673 len = pfkey_send(lcconf->sock_pfkey, newmsg, len);
2674
2675 racoon_free(newmsg);
2676
2677 return 0;
2678}
2679
d1e348cf
A
2680int
2681pk_sendget_inbound_sastats(ike_session_t *session)
2682{
2683 u_int32_t max_stats;
2684 u_int32_t seq;
2685
2686 if (!session) {
65c25746 2687 plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__);
d1e348cf
A
2688 return -1;
2689 }
2690
2691 session->traffic_monitor.num_in_curr_req = 0;
2692 bzero(session->traffic_monitor.in_curr_req, sizeof(session->traffic_monitor.in_curr_req));
2693 max_stats = (sizeof(session->traffic_monitor.in_curr_req) / sizeof(session->traffic_monitor.in_curr_req[0]));
2694
2695 // get list of SAs
2696 if ((session->traffic_monitor.num_in_curr_req = ike_session_get_sas_for_stats(session,
2697 IPSEC_DIR_INBOUND,
2698 &seq,
2699 session->traffic_monitor.in_curr_req,
2700 max_stats))) {
2701 u_int64_t session_ids[] = {(u_int64_t)session, 0};
2702
65c25746 2703 //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__);
d1e348cf
A
2704
2705 if (pfkey_send_getsastats(lcconf->sock_pfkey,
2706 seq,
2707 session_ids,
2708 1,
2709 IPSEC_DIR_INBOUND,
2710 session->traffic_monitor.in_curr_req,
2711 session->traffic_monitor.num_in_curr_req) < 0) {
2712 return -1;
2713 }
65c25746 2714 //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__);
d1e348cf
A
2715
2716 return session->traffic_monitor.num_in_curr_req;
2717 }
2718 return 0;
2719}
2720
2721int
2722pk_sendget_outbound_sastats(ike_session_t *session)
2723{
2724 u_int32_t max_stats;
2725 u_int32_t seq;
2726
2727 if (!session) {
65c25746 2728 plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__);
d1e348cf
A
2729 return -1;
2730 }
2731
2732 session->traffic_monitor.num_out_curr_req = 0;
2733 bzero(session->traffic_monitor.out_curr_req, sizeof(session->traffic_monitor.out_curr_req));
2734 max_stats = (sizeof(session->traffic_monitor.out_curr_req) / sizeof(session->traffic_monitor.out_curr_req[0]));
2735
2736 // get list of SAs
2737 if ((session->traffic_monitor.num_out_curr_req = ike_session_get_sas_for_stats(session,
2738 IPSEC_DIR_OUTBOUND,
2739 &seq,
2740 session->traffic_monitor.out_curr_req,
2741 max_stats))) {
2742 u_int64_t session_ids[] = {(u_int64_t)session, 0};
2743
65c25746 2744 //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__);
d1e348cf
A
2745
2746 if (pfkey_send_getsastats(lcconf->sock_pfkey,
2747 seq,
2748 session_ids,
2749 1,
2750 IPSEC_DIR_OUTBOUND,
2751 session->traffic_monitor.out_curr_req,
2752 session->traffic_monitor.num_out_curr_req) < 0) {
2753 return -1;
2754 }
65c25746 2755 //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__);
d1e348cf
A
2756
2757 return session->traffic_monitor.num_out_curr_req;
2758 }
2759 return 0;
2760}
2761
2762/*
2763 * receive GETSPDSTAT from kernel.
2764 */
2765static int
2766pk_recvgetsastat(mhp)
2767caddr_t *mhp;
2768{
2769 struct sadb_msg *msg;
2770 struct sadb_session_id *session_id;
2771 struct sadb_sastat *stat_resp;
2772 ike_session_t *session;
2773
2774 /* validity check */
2775 if (mhp[0] == NULL ||
2776 mhp[SADB_EXT_SESSION_ID] == NULL ||
2777 mhp[SADB_EXT_SASTAT] == NULL) {
65c25746 2778 plog(ASL_LEVEL_ERR,
d1e348cf
A
2779 "inappropriate sadb getsastat response.\n");
2780 return -1;
2781 }
85f41bec
A
2782 msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to structs in an aligned buffer
2783 session_id = ALIGNED_CAST(struct sadb_session_id *)mhp[SADB_EXT_SESSION_ID];
2784 stat_resp = ALIGNED_CAST(struct sadb_sastat *)mhp[SADB_EXT_SASTAT];
d1e348cf
A
2785
2786 /* the message has to be processed or not ? */
2787 if (msg->sadb_msg_pid != getpid()) {
65c25746 2788 plog(ASL_LEVEL_DEBUG,
d1e348cf
A
2789 "%s message is not interesting "
2790 "because pid %d is not mine.\n",
2791 s_pfkey_type(msg->sadb_msg_type),
2792 msg->sadb_msg_pid);
2793 return -1;
2794 }
2795 if (!session_id->sadb_session_id_v[0]) {
65c25746 2796 plog(ASL_LEVEL_DEBUG,
d1e348cf
A
2797 "%s message is bad "
2798 "because session-id[0] is invalid.\n",
2799 s_pfkey_type(msg->sadb_msg_type));
2800 return -1;
2801 }
85f41bec 2802 session = ALIGNED_CAST(__typeof__(session))session_id->sadb_session_id_v[0];
d1e348cf
A
2803
2804 if (!stat_resp->sadb_sastat_list_len) {
65c25746 2805 plog(ASL_LEVEL_DEBUG,
d1e348cf
A
2806 "%s message is bad "
2807 "because it has no sastats.\n",
2808 s_pfkey_type(msg->sadb_msg_type));
2809 return -1;
2810 }
2811
2812 ike_session_update_traffic_idle_status(session,
2813 stat_resp->sadb_sastat_dir,
2814 (struct sastat *)(stat_resp + 1),
2815 stat_resp->sadb_sastat_list_len);
2816 return 0;
2817}
2818
52b7d2ce
A
2819/*
2820 * check if the algorithm is supported or not.
2821 * OUT 0: ok
2822 * -1: ng
2823 */
2824int
2825pk_checkalg(class, calg, keylen)
2826 int class, calg, keylen;
2827{
2828 int sup, error;
2829 u_int alg;
2830 struct sadb_alg alg0;
2831
2832 switch (algclass2doi(class)) {
2833 case IPSECDOI_PROTO_IPSEC_ESP:
2834 sup = SADB_EXT_SUPPORTED_ENCRYPT;
2835 break;
2836 case IPSECDOI_ATTR_AUTH:
2837 sup = SADB_EXT_SUPPORTED_AUTH;
2838 break;
2839 case IPSECDOI_PROTO_IPCOMP:
52b7d2ce
A
2840 return 0;
2841 default:
65c25746 2842 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2843 "invalid algorithm class.\n");
2844 return -1;
2845 }
2846 alg = ipsecdoi2pfkey_alg(algclass2doi(class), algtype2doi(class, calg));
2847 if (alg == ~0)
2848 return -1;
2849
2850 if (keylen == 0) {
2851 if (ipsec_get_keylen(sup, alg, &alg0)) {
65c25746 2852 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2853 "%s.\n", ipsec_strerror());
2854 return -1;
2855 }
2856 keylen = alg0.sadb_alg_minbits;
2857 }
2858
2859 error = ipsec_check_keylen(sup, alg, keylen);
2860 if (error)
65c25746 2861 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2862 "%s.\n", ipsec_strerror());
2863
2864 return error;
2865}
2866
2867/*
2868 * differences with pfkey_recv() in libipsec/pfkey.c:
2869 * - never performs busy wait loop.
2870 * - returns NULL and set *lenp to negative on fatal failures
2871 * - returns NULL and set *lenp to non-negative on non-fatal failures
2872 * - returns non-NULL on success
2873 */
2874static struct sadb_msg *
2875pk_recv(so, lenp)
d1e348cf 2876 int so;
85f41bec 2877 ssize_t *lenp;
52b7d2ce 2878{
05434fec
A
2879 struct sadb_msg *newmsg;
2880 int reallen = 0;
2881 socklen_t optlen = sizeof(reallen);
2882
2883 if (getsockopt(so, SOL_SOCKET, SO_NREAD, &reallen, &optlen) < 0)
52b7d2ce 2884 return NULL; /*fatal*/
05434fec
A
2885
2886 if (reallen == 0)
52b7d2ce 2887 return NULL;
d1e348cf 2888
52b7d2ce
A
2889 if ((newmsg = racoon_calloc(1, reallen)) == NULL)
2890 return NULL;
d1e348cf 2891
85f41bec
A
2892 while ((*lenp = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) {
2893 if (errno == EINTR)
2894 continue;
65c25746 2895 plog(ASL_LEVEL_ERR, "failed to recv pfkey message: %s\n", strerror(errno));
85f41bec
A
2896 break;
2897 }
52b7d2ce
A
2898 if (*lenp < 0) {
2899 racoon_free(newmsg);
2900 return NULL; /*fatal*/
05434fec 2901 } else if (*lenp != reallen || *lenp < sizeof(struct sadb_msg)) {
52b7d2ce
A
2902 racoon_free(newmsg);
2903 return NULL;
2904 }
d1e348cf 2905
52b7d2ce
A
2906 return newmsg;
2907}
2908
2909/* see handler.h */
2910u_int32_t
2911pk_getseq()
2912{
2913 return eay_random();
2914}
2915
674a30ce 2916int
52b7d2ce
A
2917addnewsp(mhp)
2918 caddr_t *mhp;
2919{
2920 struct secpolicy *new;
2921 struct sadb_address *saddr, *daddr;
2922 struct sadb_x_policy *xpl;
674a30ce 2923 struct sadb_ext *ext;
52b7d2ce
A
2924
2925 /* sanity check */
2926 if (mhp[SADB_EXT_ADDRESS_SRC] == NULL
2927 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2928 || mhp[SADB_X_EXT_POLICY] == NULL) {
65c25746 2929 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2930 "inappropriate sadb spd management message passed.\n");
2931 return -1;
2932 }
2933
85f41bec
A
2934 saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2935 daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
674a30ce 2936
85f41bec 2937 xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
674a30ce
A
2938 /* validity check */
2939 if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
2940 plog(ASL_LEVEL_ERR,
2941 "invalid msg length.\n");
2942 return -1;
2943 }
52b7d2ce 2944
52b7d2ce
A
2945 new = newsp();
2946 if (new == NULL) {
65c25746 2947 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2948 "failed to allocate buffer\n");
2949 return -1;
2950 }
2951
2952 new->spidx.dir = xpl->sadb_x_policy_dir;
2953 new->id = xpl->sadb_x_policy_id;
2954 new->policy = xpl->sadb_x_policy_type;
2955 new->req = NULL;
2956
2957 /* check policy */
2958 switch (xpl->sadb_x_policy_type) {
2959 case IPSEC_POLICY_DISCARD:
2960 case IPSEC_POLICY_GENERATE:
2961 case IPSEC_POLICY_NONE:
2962 case IPSEC_POLICY_ENTRUST:
2963 case IPSEC_POLICY_BYPASS:
2964 break;
2965
2966 case IPSEC_POLICY_IPSEC:
2967 {
2968 int tlen;
2969 struct sadb_x_ipsecrequest *xisr;
2970 struct ipsecrequest **p_isr = &new->req;
2971
52b7d2ce
A
2972 tlen = PFKEY_EXTLEN(xpl) - sizeof(*xpl);
2973 xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
2974
2975 while (tlen > 0) {
674a30ce
A
2976 if (tlen < sizeof(*xisr) ||
2977 tlen < xisr->sadb_x_ipsecrequest_len) {
2978 plog(ASL_LEVEL_ERR,
2979 "invalid msg length for ipsec request.\n");
2980 return -1;
2981 }
52b7d2ce
A
2982
2983 /* length check */
2984 if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
65c25746 2985 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2986 "invalid msg length.\n");
2987 return -1;
2988 }
2989
2990 /* allocate request buffer */
2991 *p_isr = newipsecreq();
2992 if (*p_isr == NULL) {
65c25746 2993 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2994 "failed to get new ipsecreq.\n");
2995 return -1;
2996 }
2997
2998 /* set values */
2999 (*p_isr)->next = NULL;
3000
3001 switch (xisr->sadb_x_ipsecrequest_proto) {
3002 case IPPROTO_ESP:
3003 case IPPROTO_AH:
3004 case IPPROTO_IPCOMP:
3005 break;
3006 default:
65c25746 3007 plog(ASL_LEVEL_ERR,
52b7d2ce
A
3008 "invalid proto type: %u\n",
3009 xisr->sadb_x_ipsecrequest_proto);
3010 return -1;
3011 }
3012 (*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto;
3013
3014 switch (xisr->sadb_x_ipsecrequest_mode) {
3015 case IPSEC_MODE_TRANSPORT:
3016 case IPSEC_MODE_TUNNEL:
3017 break;
3018 case IPSEC_MODE_ANY:
3019 default:
65c25746 3020 plog(ASL_LEVEL_ERR,
52b7d2ce
A
3021 "invalid mode: %u\n",
3022 xisr->sadb_x_ipsecrequest_mode);
3023 return -1;
3024 }
3025 (*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode;
3026
3027 switch (xisr->sadb_x_ipsecrequest_level) {
3028 case IPSEC_LEVEL_DEFAULT:
3029 case IPSEC_LEVEL_USE:
3030 case IPSEC_LEVEL_REQUIRE:
3031 break;
3032 case IPSEC_LEVEL_UNIQUE:
3033 (*p_isr)->saidx.reqid =
3034 xisr->sadb_x_ipsecrequest_reqid;
3035 break;
3036
3037 default:
65c25746 3038 plog(ASL_LEVEL_ERR,
52b7d2ce
A
3039 "invalid level: %u\n",
3040 xisr->sadb_x_ipsecrequest_level);
3041 return -1;
3042 }
3043 (*p_isr)->level = xisr->sadb_x_ipsecrequest_level;
3044
3045 /* set IP addresses if there */
3046 if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
3047 struct sockaddr *paddr;
674a30ce 3048 int rem_buf_len = xisr->sadb_x_ipsecrequest_len - sizeof(*xisr);
52b7d2ce
A
3049
3050 paddr = (struct sockaddr *)(xisr + 1);
674a30ce
A
3051 if (rem_buf_len < sizeof(*paddr) ||
3052 rem_buf_len < sysdep_sa_len(paddr)) {
3053 plog(ASL_LEVEL_ERR,
3054 "invalid msg length for src ip address.\n");
3055 return -1;
3056 }
52b7d2ce
A
3057 bcopy(paddr, &(*p_isr)->saidx.src,
3058 sysdep_sa_len(paddr));
3059
674a30ce
A
3060 rem_buf_len -= sysdep_sa_len(paddr);
3061
52b7d2ce
A
3062 paddr = (struct sockaddr *)((caddr_t)paddr
3063 + sysdep_sa_len(paddr));
674a30ce
A
3064 if (rem_buf_len < sizeof(*paddr) ||
3065 rem_buf_len < sysdep_sa_len(paddr)) {
3066 plog(ASL_LEVEL_ERR,
3067 "invalid msg length for dst ip address.\n");
3068 return -1;
3069 }
52b7d2ce
A
3070 bcopy(paddr, &(*p_isr)->saidx.dst,
3071 sysdep_sa_len(paddr));
3072 }
3073
3074 (*p_isr)->sp = new;
3075
3076 /* initialization for the next. */
3077 p_isr = &(*p_isr)->next;
3078 tlen -= xisr->sadb_x_ipsecrequest_len;
3079
3080 /* validity check */
3081 if (tlen < 0) {
65c25746 3082 plog(ASL_LEVEL_ERR,
52b7d2ce
A
3083 "becoming tlen < 0\n");
3084 }
3085
85f41bec 3086 xisr = ALIGNED_CAST(struct sadb_x_ipsecrequest *)((caddr_t)xisr
52b7d2ce
A
3087 + xisr->sadb_x_ipsecrequest_len);
3088 }
3089 }
3090 break;
3091 default:
65c25746 3092 plog(ASL_LEVEL_ERR,
52b7d2ce 3093 "invalid policy type.\n");
7ebaebe2 3094 delsp(new);
52b7d2ce
A
3095 return -1;
3096 }
3097
3098#ifdef HAVE_PFKEY_POLICY_PRIORITY
3099 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
3100 saddr + 1,
3101 daddr + 1,
3102 saddr->sadb_address_prefixlen,
3103 daddr->sadb_address_prefixlen,
3104 saddr->sadb_address_proto,
3105 xpl->sadb_x_policy_priority,
3106 &new->spidx);
3107#else
3108 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
3109 saddr + 1,
3110 daddr + 1,
3111 saddr->sadb_address_prefixlen,
3112 daddr->sadb_address_prefixlen,
3113 saddr->sadb_address_proto,
3114 &new->spidx);
3115#endif
3116
3117 inssp(new);
3118
3119 return 0;
3120}
3121
3122/* proto/mode/src->dst spi */
3123const char *
3124sadbsecas2str(src, dst, proto, spi, mode)
85f41bec 3125 struct sockaddr_storage *src, *dst;
52b7d2ce
A
3126 int proto;
3127 u_int32_t spi;
3128 int mode;
3129{
3130 static char buf[256];
3131 u_int doi_proto, doi_mode = 0;
3132 char *p;
3133 int blen, i;
3134
3135 doi_proto = pfkey2ipsecdoi_proto(proto);
3136 if (doi_proto == ~0)
3137 return NULL;
3138 if (mode) {
3139 doi_mode = pfkey2ipsecdoi_mode(mode);
3140 if (doi_mode == ~0)
3141 return NULL;
3142 }
3143
3144 blen = sizeof(buf) - 1;
3145 p = buf;
3146
3147 i = snprintf(p, blen, "%s%s%s ",
3148 s_ipsecdoi_proto(doi_proto),
3149 mode ? "/" : "",
3150 mode ? s_ipsecdoi_encmode(doi_mode) : "");
3151 if (i < 0 || i >= blen)
3152 return NULL;
3153 p += i;
3154 blen -= i;
3155
85f41bec 3156 i = snprintf(p, blen, "%s->", saddr2str((struct sockaddr *)src));
52b7d2ce
A
3157 if (i < 0 || i >= blen)
3158 return NULL;
3159 p += i;
3160 blen -= i;
3161
85f41bec 3162 i = snprintf(p, blen, "%s ", saddr2str((struct sockaddr *)dst));
52b7d2ce
A
3163 if (i < 0 || i >= blen)
3164 return NULL;
3165 p += i;
3166 blen -= i;
3167
3168 if (spi) {
3169 snprintf(p, blen, "spi=%lu(0x%lx)", (unsigned long)ntohl(spi),
3170 (unsigned long)ntohl(spi));
3171 }
3172
3173 return buf;
3174}