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