2002-10-16 02:10:08 +00:00
|
|
|
/* $FreeBSD$ */
|
|
|
|
/* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */
|
|
|
|
|
2005-01-07 01:45:51 +00:00
|
|
|
/*-
|
2002-10-16 02:10:08 +00:00
|
|
|
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. Neither the name of the project nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This code is referd to RFC 2367
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "opt_inet.h"
|
|
|
|
#include "opt_inet6.h"
|
|
|
|
#include "opt_ipsec.h"
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/kernel.h>
|
2003-09-01 05:35:55 +00:00
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/mutex.h>
|
2002-10-16 02:10:08 +00:00
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/domain.h>
|
|
|
|
#include <sys/protosw.h>
|
|
|
|
#include <sys/malloc.h>
|
2014-12-24 18:34:56 +00:00
|
|
|
#include <sys/rmlock.h>
|
2002-10-16 02:10:08 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/socketvar.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/errno.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/queue.h>
|
2006-05-20 15:35:36 +00:00
|
|
|
#include <sys/refcount.h>
|
2002-10-16 02:10:08 +00:00
|
|
|
#include <sys/syslog.h>
|
|
|
|
|
|
|
|
#include <net/if.h>
|
2013-10-26 17:58:36 +00:00
|
|
|
#include <net/if_var.h>
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
#include <net/vnet.h>
|
2013-10-26 17:58:36 +00:00
|
|
|
#include <net/raw_cb.h>
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <netinet/in_var.h>
|
|
|
|
|
|
|
|
#ifdef INET6
|
|
|
|
#include <netinet/ip6.h>
|
|
|
|
#include <netinet6/in6_var.h>
|
|
|
|
#include <netinet6/ip6_var.h>
|
|
|
|
#endif /* INET6 */
|
|
|
|
|
2011-04-27 19:28:42 +00:00
|
|
|
#if defined(INET) || defined(INET6)
|
2002-10-16 02:10:08 +00:00
|
|
|
#include <netinet/in_pcb.h>
|
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
#include <netinet6/in6_pcb.h>
|
|
|
|
#endif /* INET6 */
|
|
|
|
|
|
|
|
#include <net/pfkeyv2.h>
|
|
|
|
#include <netipsec/keydb.h>
|
|
|
|
#include <netipsec/key.h>
|
|
|
|
#include <netipsec/keysock.h>
|
|
|
|
#include <netipsec/key_debug.h>
|
|
|
|
|
|
|
|
#include <netipsec/ipsec.h>
|
|
|
|
#ifdef INET6
|
|
|
|
#include <netipsec/ipsec6.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <netipsec/xform.h>
|
|
|
|
|
|
|
|
#include <machine/stdarg.h>
|
|
|
|
|
|
|
|
/* randomness */
|
|
|
|
#include <sys/random.h>
|
|
|
|
|
|
|
|
#define FULLMASK 0xff
|
|
|
|
#define _BITS(bytes) ((bytes) << 3)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note on SA reference counting:
|
|
|
|
* - SAs that are not in DEAD state will have (total external reference + 1)
|
|
|
|
* following value in reference count field. they cannot be freed and are
|
|
|
|
* referenced from SA header.
|
|
|
|
* - SAs that are in DEAD state will have (total external reference)
|
|
|
|
* in reference count field. they are ready to be freed. reference from
|
|
|
|
* SA header will be removed in key_delsav(), when the reference count
|
|
|
|
* field hits 0 (= no external reference other than from SA header.
|
|
|
|
*/
|
|
|
|
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
VNET_DEFINE(u_int32_t, key_debug_level) = 0;
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(u_int, key_spi_trycnt) = 1000;
|
|
|
|
static VNET_DEFINE(u_int32_t, key_spi_minval) = 0x100;
|
|
|
|
static VNET_DEFINE(u_int32_t, key_spi_maxval) = 0x0fffffff; /* XXX */
|
|
|
|
static VNET_DEFINE(u_int32_t, policy_id) = 0;
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
/*interval to initialize randseed,1(m)*/
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(u_int, key_int_random) = 60;
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
/* interval to expire acquiring, 30(s)*/
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(u_int, key_larval_lifetime) = 30;
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
/* counter for blocking SADB_ACQUIRE.*/
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(int, key_blockacq_count) = 10;
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
/* lifetime for blocking SADB_ACQUIRE.*/
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(int, key_blockacq_lifetime) = 20;
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
/* preferred old sa rather than new sa.*/
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(int, key_preferred_oldsa) = 1;
|
2010-04-29 11:52:42 +00:00
|
|
|
#define V_key_spi_trycnt VNET(key_spi_trycnt)
|
|
|
|
#define V_key_spi_minval VNET(key_spi_minval)
|
|
|
|
#define V_key_spi_maxval VNET(key_spi_maxval)
|
|
|
|
#define V_policy_id VNET(policy_id)
|
|
|
|
#define V_key_int_random VNET(key_int_random)
|
|
|
|
#define V_key_larval_lifetime VNET(key_larval_lifetime)
|
|
|
|
#define V_key_blockacq_count VNET(key_blockacq_count)
|
|
|
|
#define V_key_blockacq_lifetime VNET(key_blockacq_lifetime)
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_key_preferred_oldsa VNET(key_preferred_oldsa)
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(u_int32_t, acq_seq) = 0;
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_acq_seq VNET(acq_seq)
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
|
|
|
|
/* SPD */
|
2014-12-24 18:34:56 +00:00
|
|
|
static VNET_DEFINE(TAILQ_HEAD(_sptree, secpolicy), sptree[IPSEC_DIR_MAX]);
|
|
|
|
static struct rmlock sptree_lock;
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_sptree VNET(sptree)
|
2014-12-24 18:34:56 +00:00
|
|
|
#define SPTREE_LOCK_INIT() rm_init(&sptree_lock, "sptree")
|
|
|
|
#define SPTREE_LOCK_DESTROY() rm_destroy(&sptree_lock)
|
|
|
|
#define SPTREE_RLOCK_TRACKER struct rm_priotracker sptree_tracker
|
|
|
|
#define SPTREE_RLOCK() rm_rlock(&sptree_lock, &sptree_tracker)
|
|
|
|
#define SPTREE_RUNLOCK() rm_runlock(&sptree_lock, &sptree_tracker)
|
|
|
|
#define SPTREE_RLOCK_ASSERT() rm_assert(&sptree_lock, RA_RLOCKED)
|
|
|
|
#define SPTREE_WLOCK() rm_wlock(&sptree_lock)
|
|
|
|
#define SPTREE_WUNLOCK() rm_wunlock(&sptree_lock)
|
|
|
|
#define SPTREE_WLOCK_ASSERT() rm_assert(&sptree_lock, RA_WLOCKED)
|
|
|
|
#define SPTREE_UNLOCK_ASSERT() rm_assert(&sptree_lock, RA_UNLOCKED)
|
2003-09-29 22:57:43 +00:00
|
|
|
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(LIST_HEAD(_sahtree, secashead), sahtree); /* SAD */
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_sahtree VNET(sahtree)
|
2003-09-01 05:35:55 +00:00
|
|
|
static struct mtx sahtree_lock;
|
2003-09-29 22:57:43 +00:00
|
|
|
#define SAHTREE_LOCK_INIT() \
|
|
|
|
mtx_init(&sahtree_lock, "sahtree", \
|
|
|
|
"fast ipsec security association database", MTX_DEF)
|
|
|
|
#define SAHTREE_LOCK_DESTROY() mtx_destroy(&sahtree_lock)
|
|
|
|
#define SAHTREE_LOCK() mtx_lock(&sahtree_lock)
|
|
|
|
#define SAHTREE_UNLOCK() mtx_unlock(&sahtree_lock)
|
|
|
|
#define SAHTREE_LOCK_ASSERT() mtx_assert(&sahtree_lock, MA_OWNED)
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* registed list */
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(LIST_HEAD(_regtree, secreg), regtree[SADB_SATYPE_MAX + 1]);
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_regtree VNET(regtree)
|
2003-09-01 05:35:55 +00:00
|
|
|
static struct mtx regtree_lock;
|
2003-09-29 22:57:43 +00:00
|
|
|
#define REGTREE_LOCK_INIT() \
|
|
|
|
mtx_init(®tree_lock, "regtree", "fast ipsec regtree", MTX_DEF)
|
|
|
|
#define REGTREE_LOCK_DESTROY() mtx_destroy(®tree_lock)
|
|
|
|
#define REGTREE_LOCK() mtx_lock(®tree_lock)
|
|
|
|
#define REGTREE_UNLOCK() mtx_unlock(®tree_lock)
|
|
|
|
#define REGTREE_LOCK_ASSERT() mtx_assert(®tree_lock, MA_OWNED)
|
|
|
|
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(LIST_HEAD(_acqtree, secacq), acqtree); /* acquiring list */
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_acqtree VNET(acqtree)
|
2003-09-01 05:35:55 +00:00
|
|
|
static struct mtx acq_lock;
|
2003-09-29 22:57:43 +00:00
|
|
|
#define ACQ_LOCK_INIT() \
|
|
|
|
mtx_init(&acq_lock, "acqtree", "fast ipsec acquire list", MTX_DEF)
|
|
|
|
#define ACQ_LOCK_DESTROY() mtx_destroy(&acq_lock)
|
|
|
|
#define ACQ_LOCK() mtx_lock(&acq_lock)
|
|
|
|
#define ACQ_UNLOCK() mtx_unlock(&acq_lock)
|
|
|
|
#define ACQ_LOCK_ASSERT() mtx_assert(&acq_lock, MA_OWNED)
|
|
|
|
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
/* SP acquiring list */
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(LIST_HEAD(_spacqtree, secspacq), spacqtree);
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_spacqtree VNET(spacqtree)
|
2003-09-01 05:35:55 +00:00
|
|
|
static struct mtx spacq_lock;
|
2003-09-29 22:57:43 +00:00
|
|
|
#define SPACQ_LOCK_INIT() \
|
|
|
|
mtx_init(&spacq_lock, "spacqtree", \
|
|
|
|
"fast ipsec security policy acquire list", MTX_DEF)
|
|
|
|
#define SPACQ_LOCK_DESTROY() mtx_destroy(&spacq_lock)
|
|
|
|
#define SPACQ_LOCK() mtx_lock(&spacq_lock)
|
|
|
|
#define SPACQ_UNLOCK() mtx_unlock(&spacq_lock)
|
|
|
|
#define SPACQ_LOCK_ASSERT() mtx_assert(&spacq_lock, MA_OWNED)
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* search order for SAs */
|
2004-05-03 03:29:21 +00:00
|
|
|
static const u_int saorder_state_valid_prefer_old[] = {
|
2002-10-16 02:10:08 +00:00
|
|
|
SADB_SASTATE_DYING, SADB_SASTATE_MATURE,
|
2004-05-03 03:29:21 +00:00
|
|
|
};
|
|
|
|
static const u_int saorder_state_valid_prefer_new[] = {
|
|
|
|
SADB_SASTATE_MATURE, SADB_SASTATE_DYING,
|
2002-10-16 02:10:08 +00:00
|
|
|
};
|
2008-11-26 22:32:07 +00:00
|
|
|
static const u_int saorder_state_alive[] = {
|
2002-10-16 02:10:08 +00:00
|
|
|
/* except DEAD */
|
|
|
|
SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL
|
|
|
|
};
|
2008-11-26 22:32:07 +00:00
|
|
|
static const u_int saorder_state_any[] = {
|
2002-10-16 02:10:08 +00:00
|
|
|
SADB_SASTATE_MATURE, SADB_SASTATE_DYING,
|
|
|
|
SADB_SASTATE_LARVAL, SADB_SASTATE_DEAD
|
|
|
|
};
|
|
|
|
|
|
|
|
static const int minsize[] = {
|
|
|
|
sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */
|
|
|
|
sizeof(struct sadb_sa), /* SADB_EXT_SA */
|
|
|
|
sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */
|
|
|
|
sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */
|
|
|
|
sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */
|
|
|
|
sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_SRC */
|
|
|
|
sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_DST */
|
|
|
|
sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_PROXY */
|
|
|
|
sizeof(struct sadb_key), /* SADB_EXT_KEY_AUTH */
|
|
|
|
sizeof(struct sadb_key), /* SADB_EXT_KEY_ENCRYPT */
|
|
|
|
sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_SRC */
|
|
|
|
sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_DST */
|
|
|
|
sizeof(struct sadb_sens), /* SADB_EXT_SENSITIVITY */
|
|
|
|
sizeof(struct sadb_prop), /* SADB_EXT_PROPOSAL */
|
|
|
|
sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_AUTH */
|
|
|
|
sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_ENCRYPT */
|
|
|
|
sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */
|
|
|
|
0, /* SADB_X_EXT_KMPRIVATE */
|
|
|
|
sizeof(struct sadb_x_policy), /* SADB_X_EXT_POLICY */
|
|
|
|
sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
sizeof(struct sadb_x_nat_t_type),/* SADB_X_EXT_NAT_T_TYPE */
|
|
|
|
sizeof(struct sadb_x_nat_t_port),/* SADB_X_EXT_NAT_T_SPORT */
|
|
|
|
sizeof(struct sadb_x_nat_t_port),/* SADB_X_EXT_NAT_T_DPORT */
|
|
|
|
sizeof(struct sadb_address), /* SADB_X_EXT_NAT_T_OAI */
|
|
|
|
sizeof(struct sadb_address), /* SADB_X_EXT_NAT_T_OAR */
|
|
|
|
sizeof(struct sadb_x_nat_t_frag),/* SADB_X_EXT_NAT_T_FRAG */
|
2002-10-16 02:10:08 +00:00
|
|
|
};
|
|
|
|
static const int maxsize[] = {
|
|
|
|
sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */
|
|
|
|
sizeof(struct sadb_sa), /* SADB_EXT_SA */
|
|
|
|
sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */
|
|
|
|
sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */
|
|
|
|
sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */
|
|
|
|
0, /* SADB_EXT_ADDRESS_SRC */
|
|
|
|
0, /* SADB_EXT_ADDRESS_DST */
|
|
|
|
0, /* SADB_EXT_ADDRESS_PROXY */
|
|
|
|
0, /* SADB_EXT_KEY_AUTH */
|
|
|
|
0, /* SADB_EXT_KEY_ENCRYPT */
|
|
|
|
0, /* SADB_EXT_IDENTITY_SRC */
|
|
|
|
0, /* SADB_EXT_IDENTITY_DST */
|
|
|
|
0, /* SADB_EXT_SENSITIVITY */
|
|
|
|
0, /* SADB_EXT_PROPOSAL */
|
|
|
|
0, /* SADB_EXT_SUPPORTED_AUTH */
|
|
|
|
0, /* SADB_EXT_SUPPORTED_ENCRYPT */
|
|
|
|
sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */
|
|
|
|
0, /* SADB_X_EXT_KMPRIVATE */
|
|
|
|
0, /* SADB_X_EXT_POLICY */
|
|
|
|
sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
sizeof(struct sadb_x_nat_t_type),/* SADB_X_EXT_NAT_T_TYPE */
|
|
|
|
sizeof(struct sadb_x_nat_t_port),/* SADB_X_EXT_NAT_T_SPORT */
|
|
|
|
sizeof(struct sadb_x_nat_t_port),/* SADB_X_EXT_NAT_T_DPORT */
|
|
|
|
0, /* SADB_X_EXT_NAT_T_OAI */
|
|
|
|
0, /* SADB_X_EXT_NAT_T_OAR */
|
|
|
|
sizeof(struct sadb_x_nat_t_frag),/* SADB_X_EXT_NAT_T_FRAG */
|
2002-10-16 02:10:08 +00:00
|
|
|
};
|
|
|
|
|
2010-11-22 19:32:54 +00:00
|
|
|
static VNET_DEFINE(int, ipsec_esp_keymin) = 256;
|
|
|
|
static VNET_DEFINE(int, ipsec_esp_auth) = 0;
|
|
|
|
static VNET_DEFINE(int, ipsec_ah_keymin) = 128;
|
2010-04-29 11:52:42 +00:00
|
|
|
|
|
|
|
#define V_ipsec_esp_keymin VNET(ipsec_esp_keymin)
|
|
|
|
#define V_ipsec_esp_auth VNET(ipsec_esp_auth)
|
2009-07-16 21:13:04 +00:00
|
|
|
#define V_ipsec_ah_keymin VNET(ipsec_ah_keymin)
|
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
2009-07-14 22:48:30 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
#ifdef SYSCTL_DECL
|
|
|
|
SYSCTL_DECL(_net_key);
|
|
|
|
#endif
|
|
|
|
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_DEBUG_LEVEL, debug,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(key_debug_level), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* max count of trial for the decision of spi value */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(key_spi_trycnt), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* minimum spi value to allocate automatically. */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(key_spi_minval), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* maximun spi value to allocate automatically. */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(key_spi_maxval), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* interval to initialize randseed */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT, int_random,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(key_int_random), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* lifetime for larval SA */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(key_larval_lifetime), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* counter for blocking to send SADB_ACQUIRE to IKEd */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(key_blockacq_count), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* lifetime for blocking to send SADB_ACQUIRE to IKEd */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(key_blockacq_lifetime), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* ESP auth */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH, esp_auth,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_esp_auth), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* minimum ESP key length */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN, esp_keymin,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_esp_keymin), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* minimum AH key length */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_ah_keymin), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* perfered old SA rather than new SA */
|
2014-11-07 09:39:05 +00:00
|
|
|
SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, preferred_oldsa,
|
|
|
|
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(key_preferred_oldsa), 0, "");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
#define __LIST_CHAINED(elm) \
|
|
|
|
(!((elm)->chain.le_next == NULL && (elm)->chain.le_prev == NULL))
|
|
|
|
#define LIST_INSERT_TAIL(head, elm, type, field) \
|
|
|
|
do {\
|
|
|
|
struct type *curelm = LIST_FIRST(head); \
|
|
|
|
if (curelm == NULL) {\
|
|
|
|
LIST_INSERT_HEAD(head, elm, field); \
|
|
|
|
} else { \
|
|
|
|
while (LIST_NEXT(curelm, field)) \
|
|
|
|
curelm = LIST_NEXT(curelm, field);\
|
|
|
|
LIST_INSERT_AFTER(curelm, elm, field);\
|
|
|
|
}\
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define KEY_CHKSASTATE(head, sav, name) \
|
|
|
|
do { \
|
|
|
|
if ((head) != (sav)) { \
|
|
|
|
ipseclog((LOG_DEBUG, "%s: state mismatched (TREE=%d SA=%d)\n", \
|
|
|
|
(name), (head), (sav))); \
|
|
|
|
continue; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define KEY_CHKSPDIR(head, sp, name) \
|
|
|
|
do { \
|
|
|
|
if ((head) != (sp)) { \
|
|
|
|
ipseclog((LOG_DEBUG, "%s: direction mismatched (TREE=%d SP=%d), " \
|
|
|
|
"anyway continue.\n", \
|
|
|
|
(name), (head), (sp))); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
MALLOC_DEFINE(M_IPSEC_SA, "secasvar", "ipsec security association");
|
|
|
|
MALLOC_DEFINE(M_IPSEC_SAH, "sahead", "ipsec sa head");
|
|
|
|
MALLOC_DEFINE(M_IPSEC_SP, "ipsecpolicy", "ipsec security policy");
|
|
|
|
MALLOC_DEFINE(M_IPSEC_SR, "ipsecrequest", "ipsec security request");
|
|
|
|
MALLOC_DEFINE(M_IPSEC_MISC, "ipsec-misc", "ipsec miscellaneous");
|
|
|
|
MALLOC_DEFINE(M_IPSEC_SAQ, "ipsec-saq", "ipsec sa acquire");
|
|
|
|
MALLOC_DEFINE(M_IPSEC_SAR, "ipsec-reg", "ipsec sa acquire");
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* set parameters into secpolicyindex buffer.
|
|
|
|
* Must allocate secpolicyindex buffer passed to this function.
|
|
|
|
*/
|
|
|
|
#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, idx) \
|
|
|
|
do { \
|
|
|
|
bzero((idx), sizeof(struct secpolicyindex)); \
|
|
|
|
(idx)->dir = (_dir); \
|
|
|
|
(idx)->prefs = (ps); \
|
|
|
|
(idx)->prefd = (pd); \
|
|
|
|
(idx)->ul_proto = (ulp); \
|
|
|
|
bcopy((s), &(idx)->src, ((const struct sockaddr *)(s))->sa_len); \
|
|
|
|
bcopy((d), &(idx)->dst, ((const struct sockaddr *)(d))->sa_len); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set parameters into secasindex buffer.
|
|
|
|
* Must allocate secasindex buffer before calling this function.
|
|
|
|
*/
|
|
|
|
#define KEY_SETSECASIDX(p, m, r, s, d, idx) \
|
|
|
|
do { \
|
|
|
|
bzero((idx), sizeof(struct secasindex)); \
|
|
|
|
(idx)->proto = (p); \
|
|
|
|
(idx)->mode = (m); \
|
|
|
|
(idx)->reqid = (r); \
|
|
|
|
bcopy((s), &(idx)->src, ((const struct sockaddr *)(s))->sa_len); \
|
|
|
|
bcopy((d), &(idx)->dst, ((const struct sockaddr *)(d))->sa_len); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/* key statistics */
|
|
|
|
struct _keystat {
|
|
|
|
u_long getspi_count; /* the avarage of count to try to get new SPI */
|
|
|
|
} keystat;
|
|
|
|
|
|
|
|
struct sadb_msghdr {
|
|
|
|
struct sadb_msg *msg;
|
|
|
|
struct sadb_ext *ext[SADB_EXT_MAX + 1];
|
|
|
|
int extoff[SADB_EXT_MAX + 1];
|
|
|
|
int extlen[SADB_EXT_MAX + 1];
|
|
|
|
};
|
|
|
|
|
2014-10-23 20:43:16 +00:00
|
|
|
#ifndef IPSEC_DEBUG2
|
|
|
|
static struct callout key_timer;
|
|
|
|
#endif
|
|
|
|
|
2014-12-03 04:08:41 +00:00
|
|
|
static struct secasvar *key_allocsa_policy(const struct secasindex *);
|
|
|
|
static void key_freesp_so(struct secpolicy **);
|
|
|
|
static struct secasvar *key_do_allocsa_policy(struct secashead *, u_int);
|
2014-12-24 18:34:56 +00:00
|
|
|
static void key_unlink(struct secpolicy *);
|
2014-12-03 04:08:41 +00:00
|
|
|
static struct secpolicy *key_getsp(struct secpolicyindex *);
|
|
|
|
static struct secpolicy *key_getspbyid(u_int32_t);
|
|
|
|
static u_int32_t key_newreqid(void);
|
|
|
|
static struct mbuf *key_gather_mbuf(struct mbuf *,
|
|
|
|
const struct sadb_msghdr *, int, int, ...);
|
|
|
|
static int key_spdadd(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static u_int32_t key_getnewspid(void);
|
|
|
|
static int key_spddelete(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_spddelete2(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_spdget(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_spdflush(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_spddump(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static struct mbuf *key_setdumpsp(struct secpolicy *,
|
|
|
|
u_int8_t, u_int32_t, u_int32_t);
|
|
|
|
static u_int key_getspreqmsglen(struct secpolicy *);
|
|
|
|
static int key_spdexpire(struct secpolicy *);
|
|
|
|
static struct secashead *key_newsah(struct secasindex *);
|
|
|
|
static void key_delsah(struct secashead *);
|
|
|
|
static struct secasvar *key_newsav(struct mbuf *,
|
2002-10-16 02:10:08 +00:00
|
|
|
const struct sadb_msghdr *, struct secashead *, int *,
|
2014-12-03 04:08:41 +00:00
|
|
|
const char*, int);
|
2002-10-16 02:10:08 +00:00
|
|
|
#define KEY_NEWSAV(m, sadb, sah, e) \
|
|
|
|
key_newsav(m, sadb, sah, e, __FILE__, __LINE__)
|
2014-12-03 04:08:41 +00:00
|
|
|
static void key_delsav(struct secasvar *);
|
|
|
|
static struct secashead *key_getsah(struct secasindex *);
|
|
|
|
static struct secasvar *key_checkspidup(struct secasindex *, u_int32_t);
|
|
|
|
static struct secasvar *key_getsavbyspi(struct secashead *, u_int32_t);
|
|
|
|
static int key_setsaval(struct secasvar *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_mature(struct secasvar *);
|
|
|
|
static struct mbuf *key_setdumpsa(struct secasvar *, u_int8_t,
|
|
|
|
u_int8_t, u_int32_t, u_int32_t);
|
|
|
|
static struct mbuf *key_setsadbmsg(u_int8_t, u_int16_t, u_int8_t,
|
|
|
|
u_int32_t, pid_t, u_int16_t);
|
|
|
|
static struct mbuf *key_setsadbsa(struct secasvar *);
|
|
|
|
static struct mbuf *key_setsadbaddr(u_int16_t,
|
|
|
|
const struct sockaddr *, u_int8_t, u_int16_t);
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
static struct mbuf *key_setsadbxport(u_int16_t, u_int16_t);
|
|
|
|
static struct mbuf *key_setsadbxtype(u_int16_t);
|
|
|
|
#endif
|
|
|
|
static void key_porttosaddr(struct sockaddr *, u_int16_t);
|
|
|
|
#define KEY_PORTTOSADDR(saddr, port) \
|
|
|
|
key_porttosaddr((struct sockaddr *)(saddr), (port))
|
2014-12-03 04:08:41 +00:00
|
|
|
static struct mbuf *key_setsadbxsa2(u_int8_t, u_int32_t, u_int32_t);
|
|
|
|
static struct mbuf *key_setsadbxpolicy(u_int16_t, u_int8_t,
|
|
|
|
u_int32_t);
|
2006-03-25 13:38:52 +00:00
|
|
|
static struct seckey *key_dup_keymsg(const struct sadb_key *, u_int,
|
|
|
|
struct malloc_type *);
|
|
|
|
static struct seclifetime *key_dup_lifemsg(const struct sadb_lifetime *src,
|
|
|
|
struct malloc_type *type);
|
2002-10-16 02:10:08 +00:00
|
|
|
#ifdef INET6
|
2014-12-03 04:08:41 +00:00
|
|
|
static int key_ismyaddr6(struct sockaddr_in6 *);
|
2002-10-16 02:10:08 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* flags for key_cmpsaidx() */
|
|
|
|
#define CMP_HEAD 1 /* protocol, addresses. */
|
|
|
|
#define CMP_MODE_REQID 2 /* additionally HEAD, reqid, mode. */
|
|
|
|
#define CMP_REQID 3 /* additionally HEAD, reaid. */
|
|
|
|
#define CMP_EXACTLY 4 /* all elements. */
|
2014-12-03 04:08:41 +00:00
|
|
|
static int key_cmpsaidx(const struct secasindex *,
|
|
|
|
const struct secasindex *, int);
|
|
|
|
static int key_cmpspidx_exactly(struct secpolicyindex *,
|
|
|
|
struct secpolicyindex *);
|
|
|
|
static int key_cmpspidx_withmask(struct secpolicyindex *,
|
|
|
|
struct secpolicyindex *);
|
|
|
|
static int key_sockaddrcmp(const struct sockaddr *,
|
|
|
|
const struct sockaddr *, int);
|
|
|
|
static int key_bbcmp(const void *, const void *, u_int);
|
|
|
|
static u_int16_t key_satype2proto(u_int8_t);
|
|
|
|
static u_int8_t key_proto2satype(u_int16_t);
|
|
|
|
|
|
|
|
static int key_getspi(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static u_int32_t key_do_getnewspi(struct sadb_spirange *,
|
|
|
|
struct secasindex *);
|
|
|
|
static int key_update(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
2002-10-16 02:10:08 +00:00
|
|
|
#ifdef IPSEC_DOSEQCHECK
|
2014-12-03 04:08:41 +00:00
|
|
|
static struct secasvar *key_getsavbyseq(struct secashead *, u_int32_t);
|
2002-10-16 02:10:08 +00:00
|
|
|
#endif
|
2014-12-03 04:08:41 +00:00
|
|
|
static int key_add(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_setident(struct secashead *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static struct mbuf *key_getmsgbuf_x1(struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_delete(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_delete_all(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *, u_int16_t);
|
|
|
|
static int key_get(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
|
|
|
|
static void key_getcomb_setlifetime(struct sadb_comb *);
|
|
|
|
static struct mbuf *key_getcomb_esp(void);
|
|
|
|
static struct mbuf *key_getcomb_ah(void);
|
|
|
|
static struct mbuf *key_getcomb_ipcomp(void);
|
|
|
|
static struct mbuf *key_getprop(const struct secasindex *);
|
|
|
|
|
|
|
|
static int key_acquire(const struct secasindex *, struct secpolicy *);
|
|
|
|
static struct secacq *key_newacq(const struct secasindex *);
|
|
|
|
static struct secacq *key_getacq(const struct secasindex *);
|
|
|
|
static struct secacq *key_getacqbyseq(u_int32_t);
|
|
|
|
static struct secspacq *key_newspacq(struct secpolicyindex *);
|
|
|
|
static struct secspacq *key_getspacq(struct secpolicyindex *);
|
|
|
|
static int key_acquire2(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_register(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_expire(struct secasvar *);
|
|
|
|
static int key_flush(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_dump(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_promisc(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *);
|
|
|
|
static int key_senderror(struct socket *, struct mbuf *, int);
|
|
|
|
static int key_validate_ext(const struct sadb_ext *, int);
|
|
|
|
static int key_align(struct mbuf *, struct sadb_msghdr *);
|
2006-03-25 13:38:52 +00:00
|
|
|
static struct mbuf *key_setlifetime(struct seclifetime *src,
|
|
|
|
u_int16_t exttype);
|
|
|
|
static struct mbuf *key_setkey(struct seckey *src, u_int16_t exttype);
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
#if 0
|
2014-12-03 04:08:41 +00:00
|
|
|
static const char *key_getfqdn(void);
|
|
|
|
static const char *key_getuserfqdn(void);
|
2002-10-16 02:10:08 +00:00
|
|
|
#endif
|
2014-12-03 04:08:41 +00:00
|
|
|
static void key_sa_chgstate(struct secasvar *, u_int8_t);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2006-05-20 15:35:36 +00:00
|
|
|
static __inline void
|
|
|
|
sa_initref(struct secasvar *sav)
|
|
|
|
{
|
|
|
|
|
|
|
|
refcount_init(&sav->refcnt, 1);
|
|
|
|
}
|
|
|
|
static __inline void
|
|
|
|
sa_addref(struct secasvar *sav)
|
|
|
|
{
|
|
|
|
|
|
|
|
refcount_acquire(&sav->refcnt);
|
|
|
|
IPSEC_ASSERT(sav->refcnt != 0, ("SA refcnt overflow"));
|
|
|
|
}
|
|
|
|
static __inline int
|
|
|
|
sa_delref(struct secasvar *sav)
|
|
|
|
{
|
|
|
|
|
|
|
|
IPSEC_ASSERT(sav->refcnt > 0, ("SA refcnt underflow"));
|
|
|
|
return (refcount_release(&sav->refcnt));
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
#define SP_ADDREF(p) refcount_acquire(&(p)->refcnt)
|
|
|
|
#define SP_DELREF(p) refcount_release(&(p)->refcnt)
|
2004-09-30 01:08:02 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the refcnt while holding the SPTREE lock.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
key_addref(struct secpolicy *sp)
|
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
|
2004-09-30 01:08:02 +00:00
|
|
|
SP_ADDREF(sp);
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return 0 when there are known to be no SP's for the specified
|
|
|
|
* direction. Otherwise return 1. This is used by IPsec code
|
|
|
|
* to optimize performance.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
key_havesp(u_int dir)
|
|
|
|
{
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
return (dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND ?
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_FIRST(&V_sptree[dir]) != NULL : 1);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* %%% IPsec policy management */
|
|
|
|
/*
|
|
|
|
* allocating a SP for OUTBOUND or INBOUND packet.
|
|
|
|
* Must call key_freesp() later.
|
|
|
|
* OUT: NULL: not found
|
|
|
|
* others: found and return the pointer.
|
|
|
|
*/
|
|
|
|
struct secpolicy *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where,
|
|
|
|
int tag)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK_TRACKER;
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secpolicy *sp;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(spidx != NULL, ("null spidx"));
|
|
|
|
IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
|
|
|
|
("invalid direction %u", dir));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s from %s:%u\n", __func__, where, tag));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* get a SP entry */
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
|
|
|
|
printf("*** objects\n");
|
|
|
|
kdebug_secpolicyindex(spidx));
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK();
|
|
|
|
TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
|
|
|
|
printf("*** in SPD\n");
|
|
|
|
kdebug_secpolicyindex(&sp->spidx));
|
|
|
|
if (key_cmpspidx_withmask(&sp->spidx, spidx))
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
sp = NULL;
|
|
|
|
found:
|
|
|
|
if (sp) {
|
|
|
|
/* sanity check */
|
2003-09-29 22:57:43 +00:00
|
|
|
KEY_CHKSPDIR(sp->spidx.dir, dir, __func__);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* found a SPD entry */
|
|
|
|
sp->lastused = time_second;
|
|
|
|
SP_ADDREF(sp);
|
|
|
|
}
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
sp, sp ? sp->id : 0, sp ? sp->refcnt : 0));
|
|
|
|
return sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* allocating a SP for OUTBOUND or INBOUND packet.
|
|
|
|
* Must call key_freesp() later.
|
|
|
|
* OUT: NULL: not found
|
|
|
|
* others: found and return the pointer.
|
|
|
|
*/
|
|
|
|
struct secpolicy *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_allocsp2(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto,
|
|
|
|
u_int dir, const char* where, int tag)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK_TRACKER;
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secpolicy *sp;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(dst != NULL, ("null dst"));
|
|
|
|
IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
|
|
|
|
("invalid direction %u", dir));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s from %s:%u\n", __func__, where, tag));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* get a SP entry */
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
|
|
|
|
printf("*** objects\n");
|
|
|
|
printf("spi %u proto %u dir %u\n", spi, proto, dir);
|
|
|
|
kdebug_sockaddr(&dst->sa));
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK();
|
|
|
|
TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
|
|
|
|
printf("*** in SPD\n");
|
|
|
|
kdebug_secpolicyindex(&sp->spidx));
|
|
|
|
/* compare simple values, then dst address */
|
|
|
|
if (sp->spidx.ul_proto != proto)
|
|
|
|
continue;
|
|
|
|
/* NB: spi's must exist and match */
|
|
|
|
if (!sp->req || !sp->req->sav || sp->req->sav->spi != spi)
|
|
|
|
continue;
|
|
|
|
if (key_sockaddrcmp(&sp->spidx.dst.sa, &dst->sa, 1) == 0)
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
sp = NULL;
|
|
|
|
found:
|
|
|
|
if (sp) {
|
|
|
|
/* sanity check */
|
2003-09-29 22:57:43 +00:00
|
|
|
KEY_CHKSPDIR(sp->spidx.dir, dir, __func__);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* found a SPD entry */
|
|
|
|
sp->lastused = time_second;
|
|
|
|
SP_ADDREF(sp);
|
|
|
|
}
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
sp, sp ? sp->id : 0, sp ? sp->refcnt : 0));
|
|
|
|
return sp;
|
|
|
|
}
|
|
|
|
|
2009-04-27 21:04:16 +00:00
|
|
|
#if 0
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* return a policy that matches this particular inbound packet.
|
|
|
|
* XXX slow
|
|
|
|
*/
|
|
|
|
struct secpolicy *
|
|
|
|
key_gettunnel(const struct sockaddr *osrc,
|
|
|
|
const struct sockaddr *odst,
|
|
|
|
const struct sockaddr *isrc,
|
|
|
|
const struct sockaddr *idst,
|
|
|
|
const char* where, int tag)
|
|
|
|
{
|
|
|
|
struct secpolicy *sp;
|
|
|
|
const int dir = IPSEC_DIR_INBOUND;
|
|
|
|
struct ipsecrequest *r1, *r2, *p;
|
|
|
|
struct secpolicyindex spidx;
|
|
|
|
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s from %s:%u\n", __func__, where, tag));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if (isrc->sa_family != idst->sa_family) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_ERR, "%s: protocol family mismatched %d != %d\n.",
|
|
|
|
__func__, isrc->sa_family, idst->sa_family));
|
2002-10-16 02:10:08 +00:00
|
|
|
sp = NULL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
SPTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sp, &V_sptree[dir], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sp->state == IPSEC_SPSTATE_DEAD)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
r1 = r2 = NULL;
|
|
|
|
for (p = sp->req; p; p = p->next) {
|
|
|
|
if (p->saidx.mode != IPSEC_MODE_TUNNEL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
r1 = r2;
|
|
|
|
r2 = p;
|
|
|
|
|
|
|
|
if (!r1) {
|
|
|
|
/* here we look at address matches only */
|
|
|
|
spidx = sp->spidx;
|
|
|
|
if (isrc->sa_len > sizeof(spidx.src) ||
|
|
|
|
idst->sa_len > sizeof(spidx.dst))
|
|
|
|
continue;
|
|
|
|
bcopy(isrc, &spidx.src, isrc->sa_len);
|
|
|
|
bcopy(idst, &spidx.dst, idst->sa_len);
|
|
|
|
if (!key_cmpspidx_withmask(&sp->spidx, &spidx))
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (key_sockaddrcmp(&r1->saidx.src.sa, isrc, 0) ||
|
|
|
|
key_sockaddrcmp(&r1->saidx.dst.sa, idst, 0))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key_sockaddrcmp(&r2->saidx.src.sa, osrc, 0) ||
|
|
|
|
key_sockaddrcmp(&r2->saidx.dst.sa, odst, 0))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sp = NULL;
|
|
|
|
found:
|
|
|
|
if (sp) {
|
|
|
|
sp->lastused = time_second;
|
|
|
|
SP_ADDREF(sp);
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SPTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
done:
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
sp, sp ? sp->id : 0, sp ? sp->refcnt : 0));
|
|
|
|
return sp;
|
|
|
|
}
|
2009-04-27 21:04:16 +00:00
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* allocating an SA entry for an *OUTBOUND* packet.
|
|
|
|
* checking each request entries in SP, and acquire an SA if need.
|
|
|
|
* OUT: 0: there are valid requests.
|
|
|
|
* ENOENT: policy may be valid, but SA with REQUIRE is on acquiring.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
key_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx)
|
|
|
|
{
|
|
|
|
u_int level;
|
|
|
|
int error;
|
2011-03-31 15:23:32 +00:00
|
|
|
struct secasvar *sav;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(isr != NULL, ("null isr"));
|
|
|
|
IPSEC_ASSERT(saidx != NULL, ("null saidx"));
|
|
|
|
IPSEC_ASSERT(saidx->mode == IPSEC_MODE_TRANSPORT ||
|
2002-10-16 02:10:08 +00:00
|
|
|
saidx->mode == IPSEC_MODE_TUNNEL,
|
2003-09-29 22:57:43 +00:00
|
|
|
("unexpected policy %u", saidx->mode));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX guard against protocol callbacks from the crypto
|
|
|
|
* thread as they reference ipsecrequest.sav which we
|
|
|
|
* temporarily null out below. Need to rethink how we
|
|
|
|
* handle bundled SA's in the callback thread.
|
|
|
|
*/
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSECREQUEST_LOCK_ASSERT(isr);
|
2003-09-01 05:35:55 +00:00
|
|
|
|
|
|
|
/* get current level */
|
|
|
|
level = ipsec_get_reqlevel(isr);
|
2011-03-31 15:23:32 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
2011-03-31 15:23:32 +00:00
|
|
|
* We check new SA in the IPsec request because a different
|
2002-10-16 02:10:08 +00:00
|
|
|
* SA may be involved each time this request is checked, either
|
|
|
|
* because new SAs are being configured, or this request is
|
|
|
|
* associated with an unconnected datagram socket, or this request
|
|
|
|
* is associated with a system default policy.
|
|
|
|
*
|
|
|
|
* key_allocsa_policy should allocate the oldest SA available.
|
|
|
|
* See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt.
|
|
|
|
*/
|
2011-03-31 15:23:32 +00:00
|
|
|
sav = key_allocsa_policy(saidx);
|
|
|
|
if (sav != isr->sav) {
|
|
|
|
/* SA need to be updated. */
|
|
|
|
if (!IPSECREQUEST_UPGRADE(isr)) {
|
|
|
|
/* Kick everyone off. */
|
|
|
|
IPSECREQUEST_UNLOCK(isr);
|
|
|
|
IPSECREQUEST_WLOCK(isr);
|
|
|
|
}
|
|
|
|
if (isr->sav != NULL)
|
|
|
|
KEY_FREESAV(&isr->sav);
|
|
|
|
isr->sav = sav;
|
|
|
|
IPSECREQUEST_DOWNGRADE(isr);
|
|
|
|
} else if (sav != NULL)
|
|
|
|
KEY_FREESAV(&sav);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* When there is SA. */
|
|
|
|
if (isr->sav != NULL) {
|
|
|
|
if (isr->sav->state != SADB_SASTATE_MATURE &&
|
|
|
|
isr->sav->state != SADB_SASTATE_DYING)
|
|
|
|
return EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* there is no SA */
|
|
|
|
error = key_acquire(saidx, isr->sp);
|
|
|
|
if (error != 0) {
|
|
|
|
/* XXX What should I do ? */
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: error %d returned from key_acquire\n",
|
|
|
|
__func__, error));
|
2002-10-16 02:10:08 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (level != IPSEC_LEVEL_REQUIRE) {
|
|
|
|
/* XXX sigh, the interface to this routine is botched */
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(isr->sav == NULL, ("unexpected SA"));
|
2002-10-16 02:10:08 +00:00
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return ENOENT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* allocating a SA for policy entry from SAD.
|
|
|
|
* NOTE: searching SAD of aliving state.
|
|
|
|
* OUT: NULL: not found.
|
|
|
|
* others: found and return the pointer.
|
|
|
|
*/
|
|
|
|
static struct secasvar *
|
|
|
|
key_allocsa_policy(const struct secasindex *saidx)
|
|
|
|
{
|
2004-05-03 03:29:21 +00:00
|
|
|
#define N(a) _ARRAYLEN(a)
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secashead *sah;
|
|
|
|
struct secasvar *sav;
|
2004-05-03 03:29:21 +00:00
|
|
|
u_int stateidx, arraysize;
|
|
|
|
const u_int *state_valid;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2009-09-06 19:05:03 +00:00
|
|
|
state_valid = NULL; /* silence gcc */
|
|
|
|
arraysize = 0; /* silence gcc */
|
2009-09-06 18:09:25 +00:00
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah->state == SADB_SASTATE_DEAD)
|
|
|
|
continue;
|
2003-09-01 05:35:55 +00:00
|
|
|
if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) {
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_key_preferred_oldsa) {
|
2004-05-03 03:29:21 +00:00
|
|
|
state_valid = saorder_state_valid_prefer_old;
|
|
|
|
arraysize = N(saorder_state_valid_prefer_old);
|
|
|
|
} else {
|
|
|
|
state_valid = saorder_state_valid_prefer_new;
|
|
|
|
arraysize = N(saorder_state_valid_prefer_new);
|
|
|
|
}
|
2009-09-06 07:32:16 +00:00
|
|
|
break;
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2009-09-06 07:32:16 +00:00
|
|
|
if (sah == NULL)
|
|
|
|
return NULL;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* search valid state */
|
2004-05-03 03:29:21 +00:00
|
|
|
for (stateidx = 0; stateidx < arraysize; stateidx++) {
|
|
|
|
sav = key_do_allocsa_policy(sah, state_valid[stateidx]);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sav != NULL)
|
|
|
|
return sav;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2004-05-03 03:29:21 +00:00
|
|
|
#undef N
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* searching SAD with direction, protocol, mode and state.
|
|
|
|
* called by key_allocsa_policy().
|
|
|
|
* OUT:
|
|
|
|
* NULL : not found
|
|
|
|
* others : found, pointer to a SA.
|
|
|
|
*/
|
|
|
|
static struct secasvar *
|
|
|
|
key_do_allocsa_policy(struct secashead *sah, u_int state)
|
|
|
|
{
|
|
|
|
struct secasvar *sav, *nextsav, *candidate, *d;
|
|
|
|
|
|
|
|
/* initilize */
|
|
|
|
candidate = NULL;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
for (sav = LIST_FIRST(&sah->savtree[state]);
|
|
|
|
sav != NULL;
|
|
|
|
sav = nextsav) {
|
|
|
|
|
|
|
|
nextsav = LIST_NEXT(sav, chain);
|
|
|
|
|
|
|
|
/* sanity check */
|
2003-09-29 22:57:43 +00:00
|
|
|
KEY_CHKSASTATE(sav->state, state, __func__);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* initialize */
|
|
|
|
if (candidate == NULL) {
|
|
|
|
candidate = sav;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Which SA is the better ? */
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(candidate->lft_c != NULL,
|
|
|
|
("null candidate lifetime"));
|
|
|
|
IPSEC_ASSERT(sav->lft_c != NULL, ("null sav lifetime"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* What the best method is to compare ? */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_key_preferred_oldsa) {
|
2006-03-25 13:38:52 +00:00
|
|
|
if (candidate->lft_c->addtime >
|
|
|
|
sav->lft_c->addtime) {
|
2002-10-16 02:10:08 +00:00
|
|
|
candidate = sav;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
2004-02-16 17:09:53 +00:00
|
|
|
/* preferred new sa rather than old sa */
|
2006-03-25 13:38:52 +00:00
|
|
|
if (candidate->lft_c->addtime <
|
|
|
|
sav->lft_c->addtime) {
|
2002-10-16 02:10:08 +00:00
|
|
|
d = candidate;
|
|
|
|
candidate = sav;
|
|
|
|
} else
|
|
|
|
d = sav;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* prepared to delete the SA when there is more
|
|
|
|
* suitable candidate and the lifetime of the SA is not
|
|
|
|
* permanent.
|
|
|
|
*/
|
2008-03-24 14:55:09 +00:00
|
|
|
if (d->lft_h->addtime != 0) {
|
2002-10-16 02:10:08 +00:00
|
|
|
struct mbuf *m, *result;
|
2004-02-05 23:19:17 +00:00
|
|
|
u_int8_t satype;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
key_sa_chgstate(d, SADB_SASTATE_DEAD);
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(d->refcnt > 0, ("bogus ref count"));
|
2004-02-05 23:19:17 +00:00
|
|
|
|
|
|
|
satype = key_proto2satype(d->sah->saidx.proto);
|
|
|
|
if (satype == 0)
|
|
|
|
goto msgfail;
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
m = key_setsadbmsg(SADB_DELETE, 0,
|
2004-02-05 23:19:17 +00:00
|
|
|
satype, 0, 0, d->refcnt - 1);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (!m)
|
|
|
|
goto msgfail;
|
|
|
|
result = m;
|
|
|
|
|
|
|
|
/* set sadb_address for saidx's. */
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
|
|
|
|
&d->sah->saidx.src.sa,
|
|
|
|
d->sah->saidx.src.sa.sa_len << 3,
|
|
|
|
IPSEC_ULPROTO_ANY);
|
|
|
|
if (!m)
|
|
|
|
goto msgfail;
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
/* set sadb_address for saidx's. */
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
|
2004-05-03 05:15:53 +00:00
|
|
|
&d->sah->saidx.dst.sa,
|
|
|
|
d->sah->saidx.dst.sa.sa_len << 3,
|
2002-10-16 02:10:08 +00:00
|
|
|
IPSEC_ULPROTO_ANY);
|
|
|
|
if (!m)
|
|
|
|
goto msgfail;
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
/* create SA extension */
|
|
|
|
m = key_setsadbsa(d);
|
|
|
|
if (!m)
|
|
|
|
goto msgfail;
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
if (result->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
result = m_pullup(result,
|
|
|
|
sizeof(struct sadb_msg));
|
|
|
|
if (result == NULL)
|
|
|
|
goto msgfail;
|
|
|
|
}
|
|
|
|
|
|
|
|
result->m_pkthdr.len = 0;
|
|
|
|
for (m = result; m; m = m->m_next)
|
|
|
|
result->m_pkthdr.len += m->m_len;
|
|
|
|
mtod(result, struct sadb_msg *)->sadb_msg_len =
|
|
|
|
PFKEY_UNIT64(result->m_pkthdr.len);
|
|
|
|
|
|
|
|
if (key_sendup_mbuf(NULL, result,
|
|
|
|
KEY_SENDUP_REGISTERED))
|
|
|
|
goto msgfail;
|
|
|
|
msgfail:
|
|
|
|
KEY_FREESAV(&d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (candidate) {
|
2006-05-20 15:35:36 +00:00
|
|
|
sa_addref(candidate);
|
2002-10-16 02:10:08 +00:00
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s cause refcnt++:%d SA:%p\n",
|
|
|
|
__func__, candidate->refcnt, candidate));
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2003-09-01 05:35:55 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
return candidate;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* allocating a usable SA entry for a *INBOUND* packet.
|
|
|
|
* Must call key_freesav() later.
|
|
|
|
* OUT: positive: pointer to a usable sav (i.e. MATURE or DYING state).
|
|
|
|
* NULL: not found, or error occured.
|
|
|
|
*
|
|
|
|
* In the comparison, no source address is used--for RFC2401 conformance.
|
|
|
|
* To quote, from section 4.1:
|
|
|
|
* A security association is uniquely identified by a triple consisting
|
|
|
|
* of a Security Parameter Index (SPI), an IP Destination Address, and a
|
|
|
|
* security protocol (AH or ESP) identifier.
|
|
|
|
* Note that, however, we do need to keep source address in IPsec SA.
|
|
|
|
* IKE specification and PF_KEY specification do assume that we
|
|
|
|
* keep source address in IPsec SA. We see a tricky situation here.
|
|
|
|
*/
|
|
|
|
struct secasvar *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_allocsa(union sockaddr_union *dst, u_int proto, u_int32_t spi,
|
|
|
|
const char* where, int tag)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secashead *sah;
|
|
|
|
struct secasvar *sav;
|
2004-05-03 03:29:21 +00:00
|
|
|
u_int stateidx, arraysize, state;
|
|
|
|
const u_int *saorder_state_valid;
|
2014-05-24 09:29:23 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
int natt_chkport;
|
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(dst != NULL, ("null dst address"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s from %s:%u\n", __func__, where, tag));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
2014-05-24 09:29:23 +00:00
|
|
|
natt_chkport = (dst->sa.sa_family == AF_INET &&
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
dst->sa.sa_len == sizeof(struct sockaddr_in) &&
|
|
|
|
dst->sin.sin_port != 0);
|
|
|
|
#endif
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* searching SAD.
|
|
|
|
* XXX: to be checked internal IP header somewhere. Also when
|
|
|
|
* IPsec tunnel packet is received. But ESP tunnel mode is
|
|
|
|
* encrypted so we can't check internal IP header.
|
|
|
|
*/
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_key_preferred_oldsa) {
|
2004-05-03 03:29:21 +00:00
|
|
|
saorder_state_valid = saorder_state_valid_prefer_old;
|
|
|
|
arraysize = _ARRAYLEN(saorder_state_valid_prefer_old);
|
|
|
|
} else {
|
|
|
|
saorder_state_valid = saorder_state_valid_prefer_new;
|
|
|
|
arraysize = _ARRAYLEN(saorder_state_valid_prefer_new);
|
|
|
|
}
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2014-05-24 09:29:23 +00:00
|
|
|
int checkport;
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* search valid state */
|
2004-05-03 03:29:21 +00:00
|
|
|
for (stateidx = 0; stateidx < arraysize; stateidx++) {
|
2002-10-16 02:10:08 +00:00
|
|
|
state = saorder_state_valid[stateidx];
|
|
|
|
LIST_FOREACH(sav, &sah->savtree[state], chain) {
|
|
|
|
/* sanity check */
|
2003-09-29 22:57:43 +00:00
|
|
|
KEY_CHKSASTATE(sav->state, state, __func__);
|
2002-10-16 02:10:08 +00:00
|
|
|
/* do not return entries w/ unusable state */
|
|
|
|
if (sav->state != SADB_SASTATE_MATURE &&
|
|
|
|
sav->state != SADB_SASTATE_DYING)
|
|
|
|
continue;
|
|
|
|
if (proto != sav->sah->saidx.proto)
|
|
|
|
continue;
|
|
|
|
if (spi != sav->spi)
|
|
|
|
continue;
|
2014-05-24 09:29:23 +00:00
|
|
|
checkport = 0;
|
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Really only check ports when this is a NAT-T
|
|
|
|
* SA. Otherwise other lookups providing ports
|
|
|
|
* might suffer.
|
|
|
|
*/
|
|
|
|
if (sav->natt_type && natt_chkport)
|
|
|
|
checkport = 1;
|
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
#if 0 /* don't check src */
|
|
|
|
/* check src address */
|
2014-05-24 09:29:23 +00:00
|
|
|
if (key_sockaddrcmp(&src->sa,
|
|
|
|
&sav->sah->saidx.src.sa, checkport) != 0)
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
/* check dst address */
|
2014-05-24 09:29:23 +00:00
|
|
|
if (key_sockaddrcmp(&dst->sa,
|
|
|
|
&sav->sah->saidx.dst.sa, checkport) != 0)
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
2006-05-20 15:35:36 +00:00
|
|
|
sa_addref(sav);
|
2002-10-16 02:10:08 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sav = NULL;
|
|
|
|
done:
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s return SA:%p; refcnt %u\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
sav, sav ? sav->refcnt : 0));
|
|
|
|
return sav;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Must be called after calling key_allocsp().
|
|
|
|
* For both the packet without socket and key_freeso().
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
_key_freesp(struct secpolicy **spp, const char* where, int tag)
|
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
struct ipsecrequest *isr, *nextisr;
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secpolicy *sp = *spp;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sp != NULL, ("null sp"));
|
2002-10-16 02:10:08 +00:00
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s SP:%p (ID=%u) from %s:%u; refcnt now %u\n",
|
|
|
|
__func__, sp, sp->id, where, tag, sp->refcnt));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
if (SP_DELREF(sp) == 0)
|
|
|
|
return;
|
|
|
|
*spp = NULL;
|
|
|
|
for (isr = sp->req; isr != NULL; isr = nextisr) {
|
|
|
|
if (isr->sav != NULL) {
|
|
|
|
KEY_FREESAV(&isr->sav);
|
|
|
|
isr->sav = NULL;
|
|
|
|
}
|
|
|
|
nextisr = isr->next;
|
|
|
|
ipsec_delisr(isr);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2014-12-24 18:34:56 +00:00
|
|
|
free(sp, M_IPSEC_SP);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
key_unlink(struct secpolicy *sp)
|
|
|
|
{
|
|
|
|
|
|
|
|
IPSEC_ASSERT(sp != NULL, ("null sp"));
|
|
|
|
IPSEC_ASSERT(sp->spidx.dir == IPSEC_DIR_INBOUND ||
|
|
|
|
sp->spidx.dir == IPSEC_DIR_OUTBOUND,
|
|
|
|
("invalid direction %u", sp->spidx.dir));
|
|
|
|
SPTREE_UNLOCK_ASSERT();
|
|
|
|
|
|
|
|
SPTREE_WLOCK();
|
|
|
|
TAILQ_REMOVE(&V_sptree[sp->spidx.dir], sp, chain);
|
|
|
|
SPTREE_WUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Must be called after calling key_allocsp().
|
|
|
|
* For the packet with socket.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
key_freeso(struct socket *so)
|
|
|
|
{
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null so"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
switch (so->so_proto->pr_domain->dom_family) {
|
Another step assimilating IPv[46] PCB code - directly use
the inpcb names rather than the following IPv6 compat macros:
in6pcb,in6p_sp, in6p_ip6_nxt,in6p_flowinfo,in6p_vflag,
in6p_flags,in6p_socket,in6p_lport,in6p_fport,in6p_ppcb and
sotoin6pcb().
Apart from removing duplicate code in netipsec, this is a pure
whitespace, not a functional change.
Discussed with: rwatson
Reviewed by: rwatson (version before review requested changes)
MFC after: 4 weeks (set the timer and see then)
2008-12-15 21:50:54 +00:00
|
|
|
#if defined(INET) || defined(INET6)
|
2002-10-16 02:10:08 +00:00
|
|
|
#ifdef INET
|
|
|
|
case PF_INET:
|
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case PF_INET6:
|
Another step assimilating IPv[46] PCB code - directly use
the inpcb names rather than the following IPv6 compat macros:
in6pcb,in6p_sp, in6p_ip6_nxt,in6p_flowinfo,in6p_vflag,
in6p_flags,in6p_socket,in6p_lport,in6p_fport,in6p_ppcb and
sotoin6pcb().
Apart from removing duplicate code in netipsec, this is a pure
whitespace, not a functional change.
Discussed with: rwatson
Reviewed by: rwatson (version before review requested changes)
MFC after: 4 weeks (set the timer and see then)
2008-12-15 21:50:54 +00:00
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
Another step assimilating IPv[46] PCB code - directly use
the inpcb names rather than the following IPv6 compat macros:
in6pcb,in6p_sp, in6p_ip6_nxt,in6p_flowinfo,in6p_vflag,
in6p_flags,in6p_socket,in6p_lport,in6p_fport,in6p_ppcb and
sotoin6pcb().
Apart from removing duplicate code in netipsec, this is a pure
whitespace, not a functional change.
Discussed with: rwatson
Reviewed by: rwatson (version before review requested changes)
MFC after: 4 weeks (set the timer and see then)
2008-12-15 21:50:54 +00:00
|
|
|
struct inpcb *pcb = sotoinpcb(so);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* Does it have a PCB ? */
|
|
|
|
if (pcb == NULL)
|
|
|
|
return;
|
|
|
|
key_freesp_so(&pcb->inp_sp->sp_in);
|
|
|
|
key_freesp_so(&pcb->inp_sp->sp_out);
|
|
|
|
}
|
|
|
|
break;
|
Another step assimilating IPv[46] PCB code - directly use
the inpcb names rather than the following IPv6 compat macros:
in6pcb,in6p_sp, in6p_ip6_nxt,in6p_flowinfo,in6p_vflag,
in6p_flags,in6p_socket,in6p_lport,in6p_fport,in6p_ppcb and
sotoin6pcb().
Apart from removing duplicate code in netipsec, this is a pure
whitespace, not a functional change.
Discussed with: rwatson
Reviewed by: rwatson (version before review requested changes)
MFC after: 4 weeks (set the timer and see then)
2008-12-15 21:50:54 +00:00
|
|
|
#endif /* INET || INET6 */
|
2002-10-16 02:10:08 +00:00
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: unknown address family=%d.\n",
|
|
|
|
__func__, so->so_proto->pr_domain->dom_family));
|
2002-10-16 02:10:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
key_freesp_so(struct secpolicy **sp)
|
|
|
|
{
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sp != NULL && *sp != NULL, ("null sp"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if ((*sp)->policy == IPSEC_POLICY_ENTRUST ||
|
|
|
|
(*sp)->policy == IPSEC_POLICY_BYPASS)
|
|
|
|
return;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT((*sp)->policy == IPSEC_POLICY_IPSEC,
|
|
|
|
("invalid policy %u", (*sp)->policy));
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(sp);
|
|
|
|
}
|
|
|
|
|
2011-03-31 15:23:32 +00:00
|
|
|
void
|
|
|
|
key_addrefsa(struct secasvar *sav, const char* where, int tag)
|
|
|
|
{
|
|
|
|
|
|
|
|
IPSEC_ASSERT(sav != NULL, ("null sav"));
|
|
|
|
IPSEC_ASSERT(sav->refcnt > 0, ("refcount must exist"));
|
|
|
|
|
|
|
|
sa_addref(sav);
|
|
|
|
}
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* Must be called after calling key_allocsa().
|
|
|
|
* This function is called by key_freesp() to free some SA allocated
|
|
|
|
* for a policy.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
key_freesav(struct secasvar **psav, const char* where, int tag)
|
|
|
|
{
|
|
|
|
struct secasvar *sav = *psav;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sav != NULL, ("null sav"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2006-05-20 15:35:36 +00:00
|
|
|
if (sa_delref(sav)) {
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
|
|
|
printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
|
|
|
|
__func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
|
2002-10-16 02:10:08 +00:00
|
|
|
*psav = NULL;
|
|
|
|
key_delsav(sav);
|
2006-05-20 15:35:36 +00:00
|
|
|
} else {
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
|
|
|
printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
|
|
|
|
__func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* %%% SPD management */
|
|
|
|
/*
|
|
|
|
* search SPD
|
|
|
|
* OUT: NULL : not found
|
|
|
|
* others : found, pointer to a SP.
|
|
|
|
*/
|
|
|
|
static struct secpolicy *
|
|
|
|
key_getsp(struct secpolicyindex *spidx)
|
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK_TRACKER;
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secpolicy *sp;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(spidx != NULL, ("null spidx"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK();
|
|
|
|
TAILQ_FOREACH(sp, &V_sptree[spidx->dir], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (key_cmpspidx_exactly(spidx, &sp->spidx)) {
|
|
|
|
SP_ADDREF(sp);
|
2003-09-01 05:35:55 +00:00
|
|
|
break;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
return sp;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get SP by index.
|
|
|
|
* OUT: NULL : not found
|
|
|
|
* others : found, pointer to a SP.
|
|
|
|
*/
|
|
|
|
static struct secpolicy *
|
|
|
|
key_getspbyid(u_int32_t id)
|
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK_TRACKER;
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secpolicy *sp;
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK();
|
|
|
|
TAILQ_FOREACH(sp, &V_sptree[IPSEC_DIR_INBOUND], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sp->id == id) {
|
|
|
|
SP_ADDREF(sp);
|
2003-09-01 05:35:55 +00:00
|
|
|
goto done;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_FOREACH(sp, &V_sptree[IPSEC_DIR_OUTBOUND], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sp->id == id) {
|
|
|
|
SP_ADDREF(sp);
|
2003-09-01 05:35:55 +00:00
|
|
|
goto done;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
2003-09-01 05:35:55 +00:00
|
|
|
done:
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
return sp;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct secpolicy *
|
|
|
|
key_newsp(const char* where, int tag)
|
|
|
|
{
|
|
|
|
struct secpolicy *newsp = NULL;
|
|
|
|
|
|
|
|
newsp = (struct secpolicy *)
|
2003-09-01 05:35:55 +00:00
|
|
|
malloc(sizeof(struct secpolicy), M_IPSEC_SP, M_NOWAIT|M_ZERO);
|
2014-12-24 18:34:56 +00:00
|
|
|
if (newsp)
|
|
|
|
refcount_init(&newsp->refcnt, 1);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s from %s:%u return SP:%p\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
where, tag, newsp));
|
|
|
|
return newsp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* create secpolicy structure from sadb_x_policy structure.
|
|
|
|
* NOTE: `state', `secpolicyindex' in secpolicy structure are not set,
|
|
|
|
* so must be set properly later.
|
|
|
|
*/
|
|
|
|
struct secpolicy *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secpolicy *newsp;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(xpl0 != NULL, ("null xpl0"));
|
2004-04-07 00:19:02 +00:00
|
|
|
IPSEC_ASSERT(len >= sizeof(*xpl0), ("policy too short: %zu", len));
|
2003-09-29 22:57:43 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
if (len != PFKEY_EXTLEN(xpl0)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: Invalid msg length.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
*error = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((newsp = KEY_NEWSP()) == NULL) {
|
|
|
|
*error = ENOBUFS;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
newsp->spidx.dir = xpl0->sadb_x_policy_dir;
|
|
|
|
newsp->policy = xpl0->sadb_x_policy_type;
|
|
|
|
|
|
|
|
/* check policy */
|
|
|
|
switch (xpl0->sadb_x_policy_type) {
|
|
|
|
case IPSEC_POLICY_DISCARD:
|
|
|
|
case IPSEC_POLICY_NONE:
|
|
|
|
case IPSEC_POLICY_ENTRUST:
|
|
|
|
case IPSEC_POLICY_BYPASS:
|
|
|
|
newsp->req = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IPSEC_POLICY_IPSEC:
|
|
|
|
{
|
|
|
|
int tlen;
|
|
|
|
struct sadb_x_ipsecrequest *xisr;
|
|
|
|
struct ipsecrequest **p_isr = &newsp->req;
|
|
|
|
|
|
|
|
/* validity check */
|
|
|
|
if (PFKEY_EXTLEN(xpl0) < sizeof(*xpl0)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: Invalid msg length.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
tlen = PFKEY_EXTLEN(xpl0) - sizeof(*xpl0);
|
|
|
|
xisr = (struct sadb_x_ipsecrequest *)(xpl0 + 1);
|
|
|
|
|
|
|
|
while (tlen > 0) {
|
|
|
|
/* length check */
|
|
|
|
if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid ipsecrequest "
|
|
|
|
"length.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate request buffer */
|
2003-09-01 05:35:55 +00:00
|
|
|
/* NB: data structure is zero'd */
|
|
|
|
*p_isr = ipsec_newisr();
|
2002-10-16 02:10:08 +00:00
|
|
|
if ((*p_isr) == NULL) {
|
|
|
|
ipseclog((LOG_DEBUG,
|
2003-09-29 22:57:43 +00:00
|
|
|
"%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = ENOBUFS;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set values */
|
|
|
|
switch (xisr->sadb_x_ipsecrequest_proto) {
|
|
|
|
case IPPROTO_ESP:
|
|
|
|
case IPPROTO_AH:
|
|
|
|
case IPPROTO_IPCOMP:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ipseclog((LOG_DEBUG,
|
2003-09-29 22:57:43 +00:00
|
|
|
"%s: invalid proto type=%u\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
xisr->sadb_x_ipsecrequest_proto));
|
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = EPROTONOSUPPORT;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
(*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto;
|
|
|
|
|
|
|
|
switch (xisr->sadb_x_ipsecrequest_mode) {
|
|
|
|
case IPSEC_MODE_TRANSPORT:
|
|
|
|
case IPSEC_MODE_TUNNEL:
|
|
|
|
break;
|
|
|
|
case IPSEC_MODE_ANY:
|
|
|
|
default:
|
|
|
|
ipseclog((LOG_DEBUG,
|
2003-09-29 22:57:43 +00:00
|
|
|
"%s: invalid mode=%u\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
xisr->sadb_x_ipsecrequest_mode));
|
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
(*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode;
|
|
|
|
|
|
|
|
switch (xisr->sadb_x_ipsecrequest_level) {
|
|
|
|
case IPSEC_LEVEL_DEFAULT:
|
|
|
|
case IPSEC_LEVEL_USE:
|
|
|
|
case IPSEC_LEVEL_REQUIRE:
|
|
|
|
break;
|
|
|
|
case IPSEC_LEVEL_UNIQUE:
|
|
|
|
/* validity check */
|
|
|
|
/*
|
|
|
|
* If range violation of reqid, kernel will
|
|
|
|
* update it, don't refuse it.
|
|
|
|
*/
|
|
|
|
if (xisr->sadb_x_ipsecrequest_reqid
|
|
|
|
> IPSEC_MANUAL_REQID_MAX) {
|
|
|
|
ipseclog((LOG_DEBUG,
|
2003-09-29 22:57:43 +00:00
|
|
|
"%s: reqid=%d range "
|
2002-10-16 02:10:08 +00:00
|
|
|
"violation, updated by kernel.\n",
|
2003-09-29 22:57:43 +00:00
|
|
|
__func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
xisr->sadb_x_ipsecrequest_reqid));
|
|
|
|
xisr->sadb_x_ipsecrequest_reqid = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate new reqid id if reqid is zero. */
|
|
|
|
if (xisr->sadb_x_ipsecrequest_reqid == 0) {
|
|
|
|
u_int32_t reqid;
|
|
|
|
if ((reqid = key_newreqid()) == 0) {
|
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = ENOBUFS;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
(*p_isr)->saidx.reqid = reqid;
|
|
|
|
xisr->sadb_x_ipsecrequest_reqid = reqid;
|
|
|
|
} else {
|
|
|
|
/* set it for manual keying. */
|
|
|
|
(*p_isr)->saidx.reqid =
|
|
|
|
xisr->sadb_x_ipsecrequest_reqid;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid level=%u\n",
|
|
|
|
__func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
xisr->sadb_x_ipsecrequest_level));
|
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
(*p_isr)->level = xisr->sadb_x_ipsecrequest_level;
|
|
|
|
|
|
|
|
/* set IP addresses if there */
|
|
|
|
if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
|
|
|
|
struct sockaddr *paddr;
|
|
|
|
|
|
|
|
paddr = (struct sockaddr *)(xisr + 1);
|
|
|
|
|
|
|
|
/* validity check */
|
|
|
|
if (paddr->sa_len
|
|
|
|
> sizeof((*p_isr)->saidx.src)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid "
|
|
|
|
"request address length.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
bcopy(paddr, &(*p_isr)->saidx.src,
|
|
|
|
paddr->sa_len);
|
|
|
|
|
|
|
|
paddr = (struct sockaddr *)((caddr_t)paddr
|
|
|
|
+ paddr->sa_len);
|
|
|
|
|
|
|
|
/* validity check */
|
|
|
|
if (paddr->sa_len
|
|
|
|
> sizeof((*p_isr)->saidx.dst)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid "
|
|
|
|
"request address length.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
bcopy(paddr, &(*p_isr)->saidx.dst,
|
|
|
|
paddr->sa_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
(*p_isr)->sp = newsp;
|
|
|
|
|
|
|
|
/* initialization for the next. */
|
|
|
|
p_isr = &(*p_isr)->next;
|
|
|
|
tlen -= xisr->sadb_x_ipsecrequest_len;
|
|
|
|
|
|
|
|
/* validity check */
|
|
|
|
if (tlen < 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: becoming tlen < 0.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr
|
|
|
|
+ xisr->sadb_x_ipsecrequest_len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid policy type.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
*error = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
*error = 0;
|
|
|
|
return newsp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u_int32_t
|
|
|
|
key_newreqid()
|
|
|
|
{
|
|
|
|
static u_int32_t auto_reqid = IPSEC_MANUAL_REQID_MAX + 1;
|
|
|
|
|
|
|
|
auto_reqid = (auto_reqid == ~0
|
|
|
|
? IPSEC_MANUAL_REQID_MAX + 1 : auto_reqid + 1);
|
|
|
|
|
|
|
|
/* XXX should be unique check */
|
|
|
|
|
|
|
|
return auto_reqid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* copy secpolicy struct to sadb_x_policy structure indicated.
|
|
|
|
*/
|
|
|
|
struct mbuf *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_sp2msg(struct secpolicy *sp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_x_policy *xpl;
|
|
|
|
int tlen;
|
|
|
|
caddr_t p;
|
|
|
|
struct mbuf *m;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sp != NULL, ("null policy"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
tlen = key_getspreqmsglen(sp);
|
|
|
|
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(tlen, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (m == NULL)
|
|
|
|
return (NULL);
|
|
|
|
m_align(m, tlen);
|
2002-10-16 02:10:08 +00:00
|
|
|
m->m_len = tlen;
|
|
|
|
xpl = mtod(m, struct sadb_x_policy *);
|
|
|
|
bzero(xpl, tlen);
|
|
|
|
|
|
|
|
xpl->sadb_x_policy_len = PFKEY_UNIT64(tlen);
|
|
|
|
xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
|
|
|
|
xpl->sadb_x_policy_type = sp->policy;
|
|
|
|
xpl->sadb_x_policy_dir = sp->spidx.dir;
|
|
|
|
xpl->sadb_x_policy_id = sp->id;
|
|
|
|
p = (caddr_t)xpl + sizeof(*xpl);
|
|
|
|
|
|
|
|
/* if is the policy for ipsec ? */
|
|
|
|
if (sp->policy == IPSEC_POLICY_IPSEC) {
|
|
|
|
struct sadb_x_ipsecrequest *xisr;
|
|
|
|
struct ipsecrequest *isr;
|
|
|
|
|
|
|
|
for (isr = sp->req; isr != NULL; isr = isr->next) {
|
|
|
|
|
|
|
|
xisr = (struct sadb_x_ipsecrequest *)p;
|
|
|
|
|
|
|
|
xisr->sadb_x_ipsecrequest_proto = isr->saidx.proto;
|
|
|
|
xisr->sadb_x_ipsecrequest_mode = isr->saidx.mode;
|
|
|
|
xisr->sadb_x_ipsecrequest_level = isr->level;
|
|
|
|
xisr->sadb_x_ipsecrequest_reqid = isr->saidx.reqid;
|
|
|
|
|
|
|
|
p += sizeof(*xisr);
|
|
|
|
bcopy(&isr->saidx.src, p, isr->saidx.src.sa.sa_len);
|
|
|
|
p += isr->saidx.src.sa.sa_len;
|
|
|
|
bcopy(&isr->saidx.dst, p, isr->saidx.dst.sa.sa_len);
|
|
|
|
p += isr->saidx.src.sa.sa_len;
|
|
|
|
|
|
|
|
xisr->sadb_x_ipsecrequest_len =
|
|
|
|
PFKEY_ALIGN8(sizeof(*xisr)
|
|
|
|
+ isr->saidx.src.sa.sa_len
|
|
|
|
+ isr->saidx.dst.sa.sa_len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* m will not be freed nor modified */
|
|
|
|
static struct mbuf *
|
|
|
|
key_gather_mbuf(struct mbuf *m, const struct sadb_msghdr *mhp,
|
2014-12-03 03:50:54 +00:00
|
|
|
int ndeep, int nitem, ...)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
int idx;
|
|
|
|
int i;
|
|
|
|
struct mbuf *result = NULL, *n;
|
|
|
|
int len;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
va_start(ap, nitem);
|
|
|
|
for (i = 0; i < nitem; i++) {
|
|
|
|
idx = va_arg(ap, int);
|
|
|
|
if (idx < 0 || idx > SADB_EXT_MAX)
|
|
|
|
goto fail;
|
|
|
|
/* don't attempt to pull empty extension */
|
|
|
|
if (idx == SADB_EXT_RESERVED && mhp->msg == NULL)
|
|
|
|
continue;
|
|
|
|
if (idx != SADB_EXT_RESERVED &&
|
|
|
|
(mhp->ext[idx] == NULL || mhp->extlen[idx] == 0))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (idx == SADB_EXT_RESERVED) {
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
|
2003-09-29 22:57:43 +00:00
|
|
|
|
|
|
|
IPSEC_ASSERT(len <= MHLEN, ("header too big %u", len));
|
|
|
|
|
2012-12-05 08:04:20 +00:00
|
|
|
MGETHDR(n, M_NOWAIT, MT_DATA);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (!n)
|
|
|
|
goto fail;
|
|
|
|
n->m_len = len;
|
|
|
|
n->m_next = NULL;
|
|
|
|
m_copydata(m, 0, sizeof(struct sadb_msg),
|
|
|
|
mtod(n, caddr_t));
|
|
|
|
} else if (i < ndeep) {
|
|
|
|
len = mhp->extlen[idx];
|
2013-03-15 10:20:15 +00:00
|
|
|
n = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (n == NULL)
|
2002-10-16 02:10:08 +00:00
|
|
|
goto fail;
|
2013-03-15 10:20:15 +00:00
|
|
|
m_align(n, len);
|
|
|
|
n->m_len = len;
|
2002-10-16 02:10:08 +00:00
|
|
|
m_copydata(m, mhp->extoff[idx], mhp->extlen[idx],
|
|
|
|
mtod(n, caddr_t));
|
|
|
|
} else {
|
|
|
|
n = m_copym(m, mhp->extoff[idx], mhp->extlen[idx],
|
2012-12-05 08:04:20 +00:00
|
|
|
M_NOWAIT);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
if (n == NULL)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
m_cat(result, n);
|
|
|
|
else
|
|
|
|
result = n;
|
|
|
|
}
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if ((result->m_flags & M_PKTHDR) != 0) {
|
|
|
|
result->m_pkthdr.len = 0;
|
|
|
|
for (n = result; n; n = n->m_next)
|
|
|
|
result->m_pkthdr.len += n->m_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
m_freem(result);
|
2011-10-07 21:00:26 +00:00
|
|
|
va_end(ap);
|
2002-10-16 02:10:08 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_X_SPDADD, SADB_X_SPDSETIDX or SADB_X_SPDUPDATE processing
|
2003-01-01 18:49:04 +00:00
|
|
|
* add an entry to SP database, when received
|
2002-10-16 02:10:08 +00:00
|
|
|
* <base, address(SD), (lifetime(H),) policy>
|
|
|
|
* from the user(?).
|
|
|
|
* Adding to SP database,
|
|
|
|
* and send
|
|
|
|
* <base, address(SD), (lifetime(H),) policy>
|
|
|
|
* to the socket which was send.
|
|
|
|
*
|
|
|
|
* SPDADD set a unique policy entry.
|
|
|
|
* SPDSETIDX like SPDADD without a part of policy requests.
|
|
|
|
* SPDUPDATE replace a unique policy entry.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_address *src0, *dst0;
|
|
|
|
struct sadb_x_policy *xpl0, *xpl;
|
|
|
|
struct sadb_lifetime *lft = NULL;
|
|
|
|
struct secpolicyindex spidx;
|
|
|
|
struct secpolicy *newsp;
|
|
|
|
int error;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
|
|
|
|
mhp->ext[SADB_X_EXT_POLICY] == NULL) {
|
|
|
|
ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n"));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL) {
|
|
|
|
if (mhp->extlen[SADB_EXT_LIFETIME_HARD]
|
|
|
|
< sizeof(struct sadb_lifetime)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
lft = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD];
|
|
|
|
}
|
|
|
|
|
|
|
|
src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
|
|
|
|
dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
|
|
|
|
xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY];
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Note: do not parse SADB_X_EXT_NAT_T_* here:
|
|
|
|
* we are processing traffic endpoints.
|
|
|
|
*/
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* make secindex */
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir,
|
|
|
|
src0 + 1,
|
|
|
|
dst0 + 1,
|
|
|
|
src0->sadb_address_prefixlen,
|
|
|
|
dst0->sadb_address_prefixlen,
|
|
|
|
src0->sadb_address_proto,
|
|
|
|
&spidx);
|
|
|
|
|
|
|
|
/* checking the direciton. */
|
|
|
|
switch (xpl0->sadb_x_policy_dir) {
|
|
|
|
case IPSEC_DIR_INBOUND:
|
|
|
|
case IPSEC_DIR_OUTBOUND:
|
|
|
|
break;
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: Invalid SP direction.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
mhp->msg->sadb_msg_errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check policy */
|
|
|
|
/* key_spdadd() accepts DISCARD, NONE and IPSEC. */
|
|
|
|
if (xpl0->sadb_x_policy_type == IPSEC_POLICY_ENTRUST
|
|
|
|
|| xpl0->sadb_x_policy_type == IPSEC_POLICY_BYPASS) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: Invalid policy type.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* policy requests are mandatory when action is ipsec. */
|
|
|
|
if (mhp->msg->sadb_msg_type != SADB_X_SPDSETIDX
|
|
|
|
&& xpl0->sadb_x_policy_type == IPSEC_POLICY_IPSEC
|
|
|
|
&& mhp->extlen[SADB_X_EXT_POLICY] <= sizeof(*xpl0)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: some policy requests part required\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* checking there is SP already or not.
|
|
|
|
* SPDUPDATE doesn't depend on whether there is a SP or not.
|
|
|
|
* If the type is either SPDADD or SPDSETIDX AND a SP is found,
|
|
|
|
* then error.
|
|
|
|
*/
|
|
|
|
newsp = key_getsp(&spidx);
|
|
|
|
if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
|
|
|
|
if (newsp) {
|
2014-12-24 18:34:56 +00:00
|
|
|
key_unlink(newsp);
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&newsp);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (newsp != NULL) {
|
|
|
|
KEY_FREESP(&newsp);
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: a SP entry exists already.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EEXIST);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
/* XXX: there is race between key_getsp and key_msg2sp. */
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* allocation new SP entry */
|
|
|
|
if ((newsp = key_msg2sp(xpl0, PFKEY_EXTLEN(xpl0), &error)) == NULL) {
|
|
|
|
return key_senderror(so, m, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((newsp->id = key_getnewspid()) == 0) {
|
2014-12-24 18:34:56 +00:00
|
|
|
KEY_FREESP(&newsp);
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir,
|
|
|
|
src0 + 1,
|
|
|
|
dst0 + 1,
|
|
|
|
src0->sadb_address_prefixlen,
|
|
|
|
dst0->sadb_address_prefixlen,
|
|
|
|
src0->sadb_address_proto,
|
|
|
|
&newsp->spidx);
|
|
|
|
|
|
|
|
/* sanity check on addr pair */
|
|
|
|
if (((struct sockaddr *)(src0 + 1))->sa_family !=
|
|
|
|
((struct sockaddr *)(dst0+ 1))->sa_family) {
|
2014-12-24 18:34:56 +00:00
|
|
|
KEY_FREESP(&newsp);
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (((struct sockaddr *)(src0 + 1))->sa_len !=
|
|
|
|
((struct sockaddr *)(dst0+ 1))->sa_len) {
|
2014-12-24 18:34:56 +00:00
|
|
|
KEY_FREESP(&newsp);
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
#if 1
|
2014-12-24 18:34:56 +00:00
|
|
|
if (newsp->req && newsp->req->saidx.src.sa.sa_family &&
|
|
|
|
newsp->req->saidx.dst.sa.sa_family) {
|
|
|
|
if (newsp->req->saidx.src.sa.sa_family !=
|
|
|
|
newsp->req->saidx.dst.sa.sa_family) {
|
|
|
|
KEY_FREESP(&newsp);
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
newsp->created = time_second;
|
|
|
|
newsp->lastused = newsp->created;
|
|
|
|
newsp->lifetime = lft ? lft->sadb_lifetime_addtime : 0;
|
|
|
|
newsp->validtime = lft ? lft->sadb_lifetime_usetime : 0;
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_WLOCK();
|
|
|
|
TAILQ_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, chain);
|
|
|
|
SPTREE_WUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* delete the entry in spacqtree */
|
|
|
|
if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
|
2003-09-01 05:35:55 +00:00
|
|
|
struct secspacq *spacq = key_getspacq(&spidx);
|
|
|
|
if (spacq != NULL) {
|
2002-10-16 02:10:08 +00:00
|
|
|
/* reset counter in order to deletion by timehandler. */
|
|
|
|
spacq->created = time_second;
|
|
|
|
spacq->count = 0;
|
2003-09-29 22:57:43 +00:00
|
|
|
SPACQ_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct mbuf *n, *mpolicy;
|
|
|
|
struct sadb_msg *newmsg;
|
|
|
|
int off;
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Note: do not send SADB_X_EXT_NAT_T_* here:
|
|
|
|
* we are sending traffic endpoints.
|
|
|
|
*/
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* create new sadb_msg to reply. */
|
|
|
|
if (lft) {
|
|
|
|
n = key_gather_mbuf(m, mhp, 2, 5, SADB_EXT_RESERVED,
|
|
|
|
SADB_X_EXT_POLICY, SADB_EXT_LIFETIME_HARD,
|
|
|
|
SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
|
|
|
|
} else {
|
|
|
|
n = key_gather_mbuf(m, mhp, 2, 4, SADB_EXT_RESERVED,
|
|
|
|
SADB_X_EXT_POLICY,
|
|
|
|
SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
|
|
|
|
}
|
|
|
|
if (!n)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
|
|
|
|
if (n->m_len < sizeof(*newmsg)) {
|
|
|
|
n = m_pullup(n, sizeof(*newmsg));
|
|
|
|
if (!n)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
newmsg = mtod(n, struct sadb_msg *);
|
|
|
|
newmsg->sadb_msg_errno = 0;
|
|
|
|
newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
|
|
|
|
|
|
|
|
off = 0;
|
|
|
|
mpolicy = m_pulldown(n, PFKEY_ALIGN8(sizeof(struct sadb_msg)),
|
|
|
|
sizeof(*xpl), &off);
|
|
|
|
if (mpolicy == NULL) {
|
|
|
|
/* n is already freed */
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
xpl = (struct sadb_x_policy *)(mtod(mpolicy, caddr_t) + off);
|
|
|
|
if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) {
|
|
|
|
m_freem(n);
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
xpl->sadb_x_policy_id = newsp->id;
|
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get new policy id.
|
|
|
|
* OUT:
|
|
|
|
* 0: failure.
|
|
|
|
* others: success.
|
|
|
|
*/
|
|
|
|
static u_int32_t
|
|
|
|
key_getnewspid()
|
|
|
|
{
|
|
|
|
u_int32_t newid = 0;
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
int count = V_key_spi_trycnt; /* XXX */
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secpolicy *sp;
|
|
|
|
|
|
|
|
/* when requesting to allocate spi ranged */
|
|
|
|
while (count--) {
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
newid = (V_policy_id = (V_policy_id == ~0 ? 1 : V_policy_id + 1));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if ((sp = key_getspbyid(newid)) == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
KEY_FREESP(&sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count == 0 || newid == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: to allocate policy id is failed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return newid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_SPDDELETE processing
|
|
|
|
* receive
|
|
|
|
* <base, address(SD), policy(*)>
|
|
|
|
* from the user(?), and set SADB_SASTATE_DEAD,
|
|
|
|
* and send,
|
|
|
|
* <base, address(SD), policy(*)>
|
|
|
|
* to the ikmpd.
|
|
|
|
* policy(*) including direction of policy.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_spddelete(struct socket *so, struct mbuf *m,
|
|
|
|
const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_address *src0, *dst0;
|
|
|
|
struct sadb_x_policy *xpl0;
|
|
|
|
struct secpolicyindex spidx;
|
|
|
|
struct secpolicy *sp;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null so"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
|
|
|
|
mhp->ext[SADB_X_EXT_POLICY] == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
|
|
|
|
dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
|
|
|
|
xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY];
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Note: do not parse SADB_X_EXT_NAT_T_* here:
|
|
|
|
* we are processing traffic endpoints.
|
|
|
|
*/
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* make secindex */
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir,
|
|
|
|
src0 + 1,
|
|
|
|
dst0 + 1,
|
|
|
|
src0->sadb_address_prefixlen,
|
|
|
|
dst0->sadb_address_prefixlen,
|
|
|
|
src0->sadb_address_proto,
|
|
|
|
&spidx);
|
|
|
|
|
|
|
|
/* checking the direciton. */
|
|
|
|
switch (xpl0->sadb_x_policy_dir) {
|
|
|
|
case IPSEC_DIR_INBOUND:
|
|
|
|
case IPSEC_DIR_OUTBOUND:
|
|
|
|
break;
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: Invalid SP direction.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Is there SP in SPD ? */
|
|
|
|
if ((sp = key_getsp(&spidx)) == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: no SP found.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save policy id to buffer to be returned. */
|
|
|
|
xpl0->sadb_x_policy_id = sp->id;
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
key_unlink(sp);
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&sp);
|
|
|
|
|
|
|
|
{
|
|
|
|
struct mbuf *n;
|
|
|
|
struct sadb_msg *newmsg;
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Note: do not send SADB_X_EXT_NAT_T_* here:
|
|
|
|
* we are sending traffic endpoints.
|
|
|
|
*/
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* create new sadb_msg to reply. */
|
|
|
|
n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED,
|
|
|
|
SADB_X_EXT_POLICY, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
|
|
|
|
if (!n)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
|
|
|
|
newmsg = mtod(n, struct sadb_msg *);
|
|
|
|
newmsg->sadb_msg_errno = 0;
|
|
|
|
newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
|
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_SPDDELETE2 processing
|
|
|
|
* receive
|
|
|
|
* <base, policy(*)>
|
|
|
|
* from the user(?), and set SADB_SASTATE_DEAD,
|
|
|
|
* and send,
|
|
|
|
* <base, policy(*)>
|
|
|
|
* to the ikmpd.
|
|
|
|
* policy(*) including direction of policy.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_spddelete2(struct socket *so, struct mbuf *m,
|
|
|
|
const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
u_int32_t id;
|
|
|
|
struct secpolicy *sp;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
|
|
|
|
mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", __func__));
|
2007-06-15 23:45:39 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id;
|
|
|
|
|
|
|
|
/* Is there SP in SPD ? */
|
|
|
|
if ((sp = key_getspbyid(id)) == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: no SP found id:%u.\n", __func__, id));
|
2007-06-15 23:45:39 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
key_unlink(sp);
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESP(&sp);
|
|
|
|
|
|
|
|
{
|
|
|
|
struct mbuf *n, *nn;
|
|
|
|
struct sadb_msg *newmsg;
|
|
|
|
int off, len;
|
|
|
|
|
|
|
|
/* create new sadb_msg to reply. */
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
|
|
|
|
|
2012-12-05 08:04:20 +00:00
|
|
|
MGETHDR(n, M_NOWAIT, MT_DATA);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (n && len > MHLEN) {
|
2015-01-06 12:59:37 +00:00
|
|
|
if (!(MCLGET(n, M_NOWAIT))) {
|
2002-10-16 02:10:08 +00:00
|
|
|
m_freem(n);
|
|
|
|
n = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!n)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
|
|
|
|
n->m_len = len;
|
|
|
|
n->m_next = NULL;
|
|
|
|
off = 0;
|
|
|
|
|
|
|
|
m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off);
|
|
|
|
off += PFKEY_ALIGN8(sizeof(struct sadb_msg));
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(off == len, ("length inconsistency (off %u len %u)",
|
|
|
|
off, len));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
n->m_next = m_copym(m, mhp->extoff[SADB_X_EXT_POLICY],
|
2012-12-05 08:04:20 +00:00
|
|
|
mhp->extlen[SADB_X_EXT_POLICY], M_NOWAIT);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (!n->m_next) {
|
|
|
|
m_freem(n);
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
n->m_pkthdr.len = 0;
|
|
|
|
for (nn = n; nn; nn = nn->m_next)
|
|
|
|
n->m_pkthdr.len += nn->m_len;
|
|
|
|
|
|
|
|
newmsg = mtod(n, struct sadb_msg *);
|
|
|
|
newmsg->sadb_msg_errno = 0;
|
|
|
|
newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
|
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_X_GET processing
|
|
|
|
* receive
|
|
|
|
* <base, policy(*)>
|
|
|
|
* from the user(?),
|
|
|
|
* and send,
|
|
|
|
* <base, address(SD), policy>
|
|
|
|
* to the ikmpd.
|
|
|
|
* policy(*) including direction of policy.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_spdget(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
u_int32_t id;
|
|
|
|
struct secpolicy *sp;
|
|
|
|
struct mbuf *n;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
|
|
|
|
mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id;
|
|
|
|
|
|
|
|
/* Is there SP in SPD ? */
|
|
|
|
if ((sp = key_getspbyid(id)) == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: no SP found id:%u.\n", __func__, id));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid);
|
2011-05-09 13:16:21 +00:00
|
|
|
KEY_FREESP(&sp);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (n != NULL) {
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
|
|
|
|
} else
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_X_SPDACQUIRE processing.
|
|
|
|
* Acquire policy and SA(s) for a *OUTBOUND* packet.
|
|
|
|
* send
|
|
|
|
* <base, policy(*)>
|
|
|
|
* to KMD, and expect to receive
|
|
|
|
* <base> with SADB_X_SPDACQUIRE if error occured,
|
|
|
|
* or
|
|
|
|
* <base, policy>
|
|
|
|
* with SADB_X_SPDUPDATE from KMD by PF_KEY.
|
|
|
|
* policy(*) is without policy requests.
|
|
|
|
*
|
|
|
|
* 0 : succeed
|
|
|
|
* others: error number
|
|
|
|
*/
|
|
|
|
int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_spdacquire(struct secpolicy *sp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *result = NULL, *m;
|
|
|
|
struct secspacq *newspacq;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sp != NULL, ("null secpolicy"));
|
|
|
|
IPSEC_ASSERT(sp->req == NULL, ("policy exists"));
|
|
|
|
IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC,
|
|
|
|
("policy not IPSEC %u", sp->policy));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-01-01 18:49:04 +00:00
|
|
|
/* Get an entry to check whether sent message or not. */
|
2003-09-01 05:35:55 +00:00
|
|
|
newspacq = key_getspacq(&sp->spidx);
|
|
|
|
if (newspacq != NULL) {
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_key_blockacq_count < newspacq->count) {
|
2002-10-16 02:10:08 +00:00
|
|
|
/* reset counter and do send message. */
|
|
|
|
newspacq->count = 0;
|
|
|
|
} else {
|
|
|
|
/* increment counter and do nothing. */
|
|
|
|
newspacq->count++;
|
2014-12-07 06:47:00 +00:00
|
|
|
SPACQ_UNLOCK();
|
|
|
|
return (0);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SPACQ_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
} else {
|
|
|
|
/* make new entry for blocking to send SADB_ACQUIRE. */
|
2003-09-01 05:35:55 +00:00
|
|
|
newspacq = key_newspacq(&sp->spidx);
|
|
|
|
if (newspacq == NULL)
|
2002-10-16 02:10:08 +00:00
|
|
|
return ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create new sadb_msg to reply. */
|
|
|
|
m = key_setsadbmsg(SADB_X_SPDACQUIRE, 0, 0, 0, 0, 0);
|
2007-06-16 00:15:14 +00:00
|
|
|
if (!m)
|
|
|
|
return ENOBUFS;
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
result = m;
|
|
|
|
|
|
|
|
result->m_pkthdr.len = 0;
|
|
|
|
for (m = result; m; m = m->m_next)
|
|
|
|
result->m_pkthdr.len += m->m_len;
|
|
|
|
|
|
|
|
mtod(result, struct sadb_msg *)->sadb_msg_len =
|
|
|
|
PFKEY_UNIT64(result->m_pkthdr.len);
|
|
|
|
|
|
|
|
return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_SPDFLUSH processing
|
|
|
|
* receive
|
|
|
|
* <base>
|
|
|
|
* from the user, and free all entries in secpctree.
|
|
|
|
* and send,
|
|
|
|
* <base>
|
|
|
|
* to the user.
|
|
|
|
* NOTE: what to do is only marking SADB_SASTATE_DEAD.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_spdflush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_HEAD(, secpolicy) drainq;
|
2002-10-16 02:10:08 +00:00
|
|
|
struct sadb_msg *newmsg;
|
2014-12-24 18:34:56 +00:00
|
|
|
struct secpolicy *sp, *nextsp;
|
2002-10-16 02:10:08 +00:00
|
|
|
u_int dir;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg)))
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_INIT(&drainq);
|
|
|
|
SPTREE_WLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_CONCAT(&drainq, &V_sptree[dir], chain);
|
|
|
|
}
|
|
|
|
SPTREE_WUNLOCK();
|
|
|
|
sp = TAILQ_FIRST(&drainq);
|
|
|
|
while (sp != NULL) {
|
|
|
|
nextsp = TAILQ_NEXT(sp, chain);
|
|
|
|
KEY_FREESP(&sp);
|
|
|
|
sp = nextsp;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m->m_next)
|
|
|
|
m_freem(m->m_next);
|
|
|
|
m->m_next = NULL;
|
|
|
|
m->m_pkthdr.len = m->m_len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
|
|
|
|
newmsg = mtod(m, struct sadb_msg *);
|
|
|
|
newmsg->sadb_msg_errno = 0;
|
|
|
|
newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
|
|
|
|
|
|
|
|
return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_SPDDUMP processing
|
|
|
|
* receive
|
|
|
|
* <base>
|
|
|
|
* from the user, and dump all SP leaves
|
|
|
|
* and send,
|
|
|
|
* <base> .....
|
|
|
|
* to the ikmpd.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_spddump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK_TRACKER;
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secpolicy *sp;
|
|
|
|
int cnt;
|
|
|
|
u_int dir;
|
|
|
|
struct mbuf *n;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* search SPD entry and get buffer size. */
|
|
|
|
cnt = 0;
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-27 09:44:14 +00:00
|
|
|
if (cnt == 0) {
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOENT);
|
2009-05-27 09:44:14 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
--cnt;
|
|
|
|
n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt,
|
|
|
|
mhp->msg->sadb_msg_pid);
|
|
|
|
|
|
|
|
if (n)
|
|
|
|
key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
m_freem(m);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct mbuf *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_setdumpsp(struct secpolicy *sp, u_int8_t type, u_int32_t seq,
|
|
|
|
u_int32_t pid)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *result = NULL, *m;
|
2008-08-05 15:36:50 +00:00
|
|
|
struct seclifetime lt;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
result = m;
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Note: do not send SADB_X_EXT_NAT_T_* here:
|
|
|
|
* we are sending traffic endpoints.
|
|
|
|
*/
|
2002-10-16 02:10:08 +00:00
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
|
|
|
|
&sp->spidx.src.sa, sp->spidx.prefs,
|
|
|
|
sp->spidx.ul_proto);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
|
|
|
|
&sp->spidx.dst.sa, sp->spidx.prefd,
|
|
|
|
sp->spidx.ul_proto);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
m = key_sp2msg(sp);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
m_cat(result, m);
|
|
|
|
|
2008-08-05 15:36:50 +00:00
|
|
|
if(sp->lifetime){
|
|
|
|
lt.addtime=sp->created;
|
|
|
|
lt.usetime= sp->lastused;
|
|
|
|
m = key_setlifetime(<, SADB_EXT_LIFETIME_CURRENT);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
lt.addtime=sp->lifetime;
|
|
|
|
lt.usetime= sp->validtime;
|
|
|
|
m = key_setlifetime(<, SADB_EXT_LIFETIME_HARD);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
m_cat(result, m);
|
|
|
|
}
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
if ((result->m_flags & M_PKTHDR) == 0)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (result->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
result = m_pullup(result, sizeof(struct sadb_msg));
|
|
|
|
if (result == NULL)
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
result->m_pkthdr.len = 0;
|
|
|
|
for (m = result; m; m = m->m_next)
|
|
|
|
result->m_pkthdr.len += m->m_len;
|
|
|
|
|
|
|
|
mtod(result, struct sadb_msg *)->sadb_msg_len =
|
|
|
|
PFKEY_UNIT64(result->m_pkthdr.len);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
m_freem(result);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get PFKEY message length for security policy and request.
|
|
|
|
*/
|
|
|
|
static u_int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getspreqmsglen(struct secpolicy *sp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
u_int tlen;
|
|
|
|
|
|
|
|
tlen = sizeof(struct sadb_x_policy);
|
|
|
|
|
|
|
|
/* if is the policy for ipsec ? */
|
|
|
|
if (sp->policy != IPSEC_POLICY_IPSEC)
|
|
|
|
return tlen;
|
|
|
|
|
|
|
|
/* get length of ipsec requests */
|
|
|
|
{
|
|
|
|
struct ipsecrequest *isr;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
for (isr = sp->req; isr != NULL; isr = isr->next) {
|
|
|
|
len = sizeof(struct sadb_x_ipsecrequest)
|
|
|
|
+ isr->saidx.src.sa.sa_len
|
|
|
|
+ isr->saidx.dst.sa.sa_len;
|
|
|
|
|
|
|
|
tlen += PFKEY_ALIGN8(len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_SPDEXPIRE processing
|
|
|
|
* send
|
|
|
|
* <base, address(SD), lifetime(CH), policy>
|
|
|
|
* to KMD by PF_KEY.
|
|
|
|
*
|
|
|
|
* OUT: 0 : succeed
|
|
|
|
* others : error number
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_spdexpire(struct secpolicy *sp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *result = NULL, *m;
|
|
|
|
int len;
|
|
|
|
int error = -1;
|
|
|
|
struct sadb_lifetime *lt;
|
|
|
|
|
|
|
|
/* XXX: Why do we lock ? */
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sp != NULL, ("null secpolicy"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* set msg header */
|
|
|
|
m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
result = m;
|
|
|
|
|
|
|
|
/* create lifetime extension (current and hard) */
|
|
|
|
len = PFKEY_ALIGN8(sizeof(*lt)) * 2;
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (m == NULL) {
|
2002-10-16 02:10:08 +00:00
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
2013-03-15 10:20:15 +00:00
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
2002-10-16 02:10:08 +00:00
|
|
|
bzero(mtod(m, caddr_t), len);
|
|
|
|
lt = mtod(m, struct sadb_lifetime *);
|
|
|
|
lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
|
|
|
|
lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
|
|
|
|
lt->sadb_lifetime_allocations = 0;
|
|
|
|
lt->sadb_lifetime_bytes = 0;
|
|
|
|
lt->sadb_lifetime_addtime = sp->created;
|
|
|
|
lt->sadb_lifetime_usetime = sp->lastused;
|
|
|
|
lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2);
|
|
|
|
lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
|
|
|
|
lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
|
|
|
|
lt->sadb_lifetime_allocations = 0;
|
|
|
|
lt->sadb_lifetime_bytes = 0;
|
|
|
|
lt->sadb_lifetime_addtime = sp->lifetime;
|
|
|
|
lt->sadb_lifetime_usetime = sp->validtime;
|
|
|
|
m_cat(result, m);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Note: do not send SADB_X_EXT_NAT_T_* here:
|
|
|
|
* we are sending traffic endpoints.
|
|
|
|
*/
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* set sadb_address for source */
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
|
|
|
|
&sp->spidx.src.sa,
|
|
|
|
sp->spidx.prefs, sp->spidx.ul_proto);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
/* set sadb_address for destination */
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
|
|
|
|
&sp->spidx.dst.sa,
|
|
|
|
sp->spidx.prefd, sp->spidx.ul_proto);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
/* set secpolicy */
|
|
|
|
m = key_sp2msg(sp);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
if ((result->m_flags & M_PKTHDR) == 0) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
result = m_pullup(result, sizeof(struct sadb_msg));
|
|
|
|
if (result == NULL) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
result->m_pkthdr.len = 0;
|
|
|
|
for (m = result; m; m = m->m_next)
|
|
|
|
result->m_pkthdr.len += m->m_len;
|
|
|
|
|
|
|
|
mtod(result, struct sadb_msg *)->sadb_msg_len =
|
|
|
|
PFKEY_UNIT64(result->m_pkthdr.len);
|
|
|
|
|
|
|
|
return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
|
|
|
|
|
|
|
|
fail:
|
|
|
|
if (result)
|
|
|
|
m_freem(result);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* %%% SAD management */
|
|
|
|
/*
|
|
|
|
* allocating a memory for new SA head, and copy from the values of mhp.
|
|
|
|
* OUT: NULL : failure due to the lack of memory.
|
|
|
|
* others : pointer to new SA head.
|
|
|
|
*/
|
|
|
|
static struct secashead *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_newsah(struct secasindex *saidx)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secashead *newsah;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(saidx != NULL, ("null saidx"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
newsah = malloc(sizeof(struct secashead), M_IPSEC_SAH, M_NOWAIT|M_ZERO);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (newsah != NULL) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(newsah->savtree)/sizeof(newsah->savtree[0]); i++)
|
|
|
|
LIST_INIT(&newsah->savtree[i]);
|
|
|
|
newsah->saidx = *saidx;
|
|
|
|
|
|
|
|
/* add to saidxtree */
|
|
|
|
newsah->state = SADB_SASTATE_MATURE;
|
2003-09-01 05:35:55 +00:00
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_INSERT_HEAD(&V_sahtree, newsah, chain);
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
return(newsah);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* delete SA index and all SA registerd.
|
|
|
|
*/
|
|
|
|
static void
|
2014-12-03 03:50:54 +00:00
|
|
|
key_delsah(struct secashead *sah)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secasvar *sav, *nextsav;
|
2003-09-29 22:57:43 +00:00
|
|
|
u_int stateidx;
|
2002-10-16 02:10:08 +00:00
|
|
|
int zombie = 0;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sah != NULL, ("NULL sah"));
|
|
|
|
SAHTREE_LOCK_ASSERT();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* searching all SA registerd in the secindex. */
|
|
|
|
for (stateidx = 0;
|
2008-11-26 22:32:07 +00:00
|
|
|
stateidx < _ARRAYLEN(saorder_state_any);
|
2002-10-16 02:10:08 +00:00
|
|
|
stateidx++) {
|
2008-11-26 22:32:07 +00:00
|
|
|
u_int state = saorder_state_any[stateidx];
|
2003-09-29 22:57:43 +00:00
|
|
|
LIST_FOREACH_SAFE(sav, &sah->savtree[state], chain, nextsav) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sav->refcnt == 0) {
|
|
|
|
/* sanity check */
|
2003-09-29 22:57:43 +00:00
|
|
|
KEY_CHKSASTATE(state, sav->state, __func__);
|
2009-03-19 15:44:13 +00:00
|
|
|
/*
|
|
|
|
* do NOT call KEY_FREESAV here:
|
|
|
|
* it will only delete the sav if refcnt == 1,
|
2009-03-18 14:01:41 +00:00
|
|
|
* where we already know that refcnt == 0
|
|
|
|
*/
|
|
|
|
key_delsav(sav);
|
2002-10-16 02:10:08 +00:00
|
|
|
} else {
|
|
|
|
/* give up to delete this sa */
|
|
|
|
zombie++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
if (!zombie) { /* delete only if there are savs */
|
|
|
|
/* remove from tree of SA index */
|
|
|
|
if (__LIST_CHAINED(sah))
|
|
|
|
LIST_REMOVE(sah, chain);
|
|
|
|
free(sah, M_IPSEC_SAH);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* allocating a new SA with LARVAL state. key_add() and key_getspi() call,
|
|
|
|
* and copy the values of mhp into new buffer.
|
|
|
|
* When SAD message type is GETSPI:
|
|
|
|
* to set sequence number from acq_seq++,
|
|
|
|
* to set zero to SPI.
|
|
|
|
* not to call key_setsava().
|
|
|
|
* OUT: NULL : fail
|
|
|
|
* others : pointer to new secasvar.
|
|
|
|
*
|
|
|
|
* does not modify mbuf. does not free mbuf on error.
|
|
|
|
*/
|
|
|
|
static struct secasvar *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_newsav(struct mbuf *m, const struct sadb_msghdr *mhp,
|
|
|
|
struct secashead *sah, int *errp, const char *where, int tag)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secasvar *newsav;
|
|
|
|
const struct sadb_sa *xsa;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
|
|
|
IPSEC_ASSERT(sah != NULL, ("null secashead"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
newsav = malloc(sizeof(struct secasvar), M_IPSEC_SA, M_NOWAIT|M_ZERO);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (newsav == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
*errp = ENOBUFS;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mhp->msg->sadb_msg_type) {
|
|
|
|
case SADB_GETSPI:
|
|
|
|
newsav->spi = 0;
|
|
|
|
|
|
|
|
#ifdef IPSEC_DOSEQCHECK
|
|
|
|
/* sync sequence number */
|
|
|
|
if (mhp->msg->sadb_msg_seq == 0)
|
|
|
|
newsav->seq =
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
(V_acq_seq = (V_acq_seq == ~0 ? 1 : ++V_acq_seq));
|
2002-10-16 02:10:08 +00:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
newsav->seq = mhp->msg->sadb_msg_seq;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_ADD:
|
|
|
|
/* sanity check */
|
|
|
|
if (mhp->ext[SADB_EXT_SA] == NULL) {
|
2003-09-01 05:35:55 +00:00
|
|
|
free(newsav, M_IPSEC_SA);
|
|
|
|
newsav = NULL;
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
*errp = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
xsa = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA];
|
|
|
|
newsav->spi = xsa->sadb_sa_spi;
|
|
|
|
newsav->seq = mhp->msg->sadb_msg_seq;
|
|
|
|
break;
|
|
|
|
default:
|
2003-09-01 05:35:55 +00:00
|
|
|
free(newsav, M_IPSEC_SA);
|
|
|
|
newsav = NULL;
|
2002-10-16 02:10:08 +00:00
|
|
|
*errp = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* copy sav values */
|
|
|
|
if (mhp->msg->sadb_msg_type != SADB_GETSPI) {
|
|
|
|
*errp = key_setsaval(newsav, m, mhp);
|
|
|
|
if (*errp) {
|
2003-09-01 05:35:55 +00:00
|
|
|
free(newsav, M_IPSEC_SA);
|
|
|
|
newsav = NULL;
|
2002-10-16 02:10:08 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
SECASVAR_LOCK_INIT(newsav);
|
2003-09-01 05:35:55 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* reset created */
|
|
|
|
newsav->created = time_second;
|
|
|
|
newsav->pid = mhp->msg->sadb_msg_pid;
|
|
|
|
|
|
|
|
/* add to satree */
|
|
|
|
newsav->sah = sah;
|
2006-05-20 15:35:36 +00:00
|
|
|
sa_initref(newsav);
|
2002-10-16 02:10:08 +00:00
|
|
|
newsav->state = SADB_SASTATE_LARVAL;
|
2003-09-01 05:35:55 +00:00
|
|
|
|
2009-11-17 16:00:41 +00:00
|
|
|
SAHTREE_LOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav,
|
|
|
|
secasvar, chain);
|
2009-11-17 16:00:41 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
done:
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s from %s:%u return SP:%p\n", __func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
where, tag, newsav));
|
|
|
|
|
|
|
|
return newsav;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* free() SA variable entry.
|
|
|
|
*/
|
|
|
|
static void
|
2003-09-01 05:35:55 +00:00
|
|
|
key_cleansav(struct secasvar *sav)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2003-06-29 23:58:38 +00:00
|
|
|
/*
|
|
|
|
* Cleanup xform state. Note that zeroize'ing causes the
|
|
|
|
* keys to be cleared; otherwise we must do it ourself.
|
|
|
|
*/
|
|
|
|
if (sav->tdb_xform != NULL) {
|
|
|
|
sav->tdb_xform->xf_zeroize(sav);
|
|
|
|
sav->tdb_xform = NULL;
|
|
|
|
} else {
|
2003-09-29 22:57:43 +00:00
|
|
|
KASSERT(sav->iv == NULL, ("iv but no xform"));
|
2003-06-29 23:58:38 +00:00
|
|
|
if (sav->key_auth != NULL)
|
2006-03-25 13:38:52 +00:00
|
|
|
bzero(sav->key_auth->key_data, _KEYLEN(sav->key_auth));
|
2003-06-29 23:58:38 +00:00
|
|
|
if (sav->key_enc != NULL)
|
2006-03-25 13:38:52 +00:00
|
|
|
bzero(sav->key_enc->key_data, _KEYLEN(sav->key_enc));
|
2003-06-29 23:58:38 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sav->key_auth != NULL) {
|
2006-03-25 13:38:52 +00:00
|
|
|
if (sav->key_auth->key_data != NULL)
|
|
|
|
free(sav->key_auth->key_data, M_IPSEC_MISC);
|
2003-09-01 05:35:55 +00:00
|
|
|
free(sav->key_auth, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
sav->key_auth = NULL;
|
|
|
|
}
|
|
|
|
if (sav->key_enc != NULL) {
|
2006-03-25 13:38:52 +00:00
|
|
|
if (sav->key_enc->key_data != NULL)
|
|
|
|
free(sav->key_enc->key_data, M_IPSEC_MISC);
|
2003-09-01 05:35:55 +00:00
|
|
|
free(sav->key_enc, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
sav->key_enc = NULL;
|
|
|
|
}
|
|
|
|
if (sav->sched) {
|
|
|
|
bzero(sav->sched, sav->schedlen);
|
2003-09-01 05:35:55 +00:00
|
|
|
free(sav->sched, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
sav->sched = NULL;
|
|
|
|
}
|
|
|
|
if (sav->replay != NULL) {
|
2003-09-01 05:35:55 +00:00
|
|
|
free(sav->replay, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
sav->replay = NULL;
|
|
|
|
}
|
|
|
|
if (sav->lft_c != NULL) {
|
2003-09-01 05:35:55 +00:00
|
|
|
free(sav->lft_c, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
sav->lft_c = NULL;
|
|
|
|
}
|
|
|
|
if (sav->lft_h != NULL) {
|
2003-09-01 05:35:55 +00:00
|
|
|
free(sav->lft_h, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
sav->lft_h = NULL;
|
|
|
|
}
|
|
|
|
if (sav->lft_s != NULL) {
|
2003-09-01 05:35:55 +00:00
|
|
|
free(sav->lft_s, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
sav->lft_s = NULL;
|
|
|
|
}
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
/*
|
|
|
|
* free() SA variable entry.
|
|
|
|
*/
|
|
|
|
static void
|
2014-12-03 03:50:54 +00:00
|
|
|
key_delsav(struct secasvar *sav)
|
2003-09-01 05:35:55 +00:00
|
|
|
{
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sav != NULL, ("null sav"));
|
|
|
|
IPSEC_ASSERT(sav->refcnt == 0, ("reference count %u > 0", sav->refcnt));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
/* remove from SA header */
|
|
|
|
if (__LIST_CHAINED(sav))
|
|
|
|
LIST_REMOVE(sav, chain);
|
|
|
|
key_cleansav(sav);
|
2003-09-29 22:57:43 +00:00
|
|
|
SECASVAR_LOCK_DESTROY(sav);
|
2003-09-01 05:35:55 +00:00
|
|
|
free(sav, M_IPSEC_SA);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* search SAD.
|
|
|
|
* OUT:
|
|
|
|
* NULL : not found
|
|
|
|
* others : found, pointer to a SA.
|
|
|
|
*/
|
|
|
|
static struct secashead *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getsah(struct secasindex *saidx)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secashead *sah;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah->state == SADB_SASTATE_DEAD)
|
|
|
|
continue;
|
|
|
|
if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID))
|
2003-09-01 05:35:55 +00:00
|
|
|
break;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
return sah;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check not to be duplicated SPI.
|
|
|
|
* NOTE: this function is too slow due to searching all SAD.
|
|
|
|
* OUT:
|
|
|
|
* NULL : not found
|
|
|
|
* others : found, pointer to a SA.
|
|
|
|
*/
|
|
|
|
static struct secasvar *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_checkspidup(struct secasindex *saidx, u_int32_t spi)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secashead *sah;
|
|
|
|
struct secasvar *sav;
|
|
|
|
|
|
|
|
/* check address family */
|
|
|
|
if (saidx->src.sa.sa_family != saidx->dst.sa.sa_family) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: address family mismatched.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
sav = NULL;
|
2002-10-16 02:10:08 +00:00
|
|
|
/* check all SAD */
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst))
|
|
|
|
continue;
|
|
|
|
sav = key_getsavbyspi(sah, spi);
|
|
|
|
if (sav != NULL)
|
2003-09-01 05:35:55 +00:00
|
|
|
break;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
return sav;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* search SAD litmited alive SA, protocol, SPI.
|
|
|
|
* OUT:
|
|
|
|
* NULL : not found
|
|
|
|
* others : found, pointer to a SA.
|
|
|
|
*/
|
|
|
|
static struct secasvar *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getsavbyspi(struct secashead *sah, u_int32_t spi)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secasvar *sav;
|
|
|
|
u_int stateidx, state;
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
sav = NULL;
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK_ASSERT();
|
2002-10-16 02:10:08 +00:00
|
|
|
/* search all status */
|
|
|
|
for (stateidx = 0;
|
2008-11-26 22:32:07 +00:00
|
|
|
stateidx < _ARRAYLEN(saorder_state_alive);
|
2002-10-16 02:10:08 +00:00
|
|
|
stateidx++) {
|
|
|
|
|
2008-11-26 22:32:07 +00:00
|
|
|
state = saorder_state_alive[stateidx];
|
2002-10-16 02:10:08 +00:00
|
|
|
LIST_FOREACH(sav, &sah->savtree[state], chain) {
|
|
|
|
|
|
|
|
/* sanity check */
|
|
|
|
if (sav->state != state) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: "
|
2002-10-16 02:10:08 +00:00
|
|
|
"invalid sav->state (queue: %d SA: %d)\n",
|
2003-09-29 22:57:43 +00:00
|
|
|
__func__, state, sav->state));
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sav->spi == spi)
|
2004-05-03 05:11:40 +00:00
|
|
|
return sav;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-03 05:11:40 +00:00
|
|
|
return NULL;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* copy SA values from PF_KEY message except *SPI, SEQ, PID, STATE and TYPE*.
|
|
|
|
* You must update these if need.
|
|
|
|
* OUT: 0: success.
|
|
|
|
* !0: failure.
|
|
|
|
*
|
|
|
|
* does not modify mbuf. does not free mbuf on error.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_setsaval(struct secasvar *sav, struct mbuf *m,
|
|
|
|
const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* initialization */
|
|
|
|
sav->replay = NULL;
|
|
|
|
sav->key_auth = NULL;
|
|
|
|
sav->key_enc = NULL;
|
|
|
|
sav->sched = NULL;
|
|
|
|
sav->schedlen = 0;
|
|
|
|
sav->iv = NULL;
|
|
|
|
sav->lft_c = NULL;
|
|
|
|
sav->lft_h = NULL;
|
|
|
|
sav->lft_s = NULL;
|
|
|
|
sav->tdb_xform = NULL; /* transform */
|
|
|
|
sav->tdb_encalgxform = NULL; /* encoding algorithm */
|
|
|
|
sav->tdb_authalgxform = NULL; /* authentication algorithm */
|
|
|
|
sav->tdb_compalgxform = NULL; /* compression algorithm */
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/* Initialize even if NAT-T not compiled in: */
|
|
|
|
sav->natt_type = 0;
|
|
|
|
sav->natt_esp_frag_len = 0;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* SA */
|
|
|
|
if (mhp->ext[SADB_EXT_SA] != NULL) {
|
|
|
|
const struct sadb_sa *sa0;
|
|
|
|
|
|
|
|
sa0 = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA];
|
|
|
|
if (mhp->extlen[SADB_EXT_SA] < sizeof(*sa0)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
sav->alg_auth = sa0->sadb_sa_auth;
|
|
|
|
sav->alg_enc = sa0->sadb_sa_encrypt;
|
|
|
|
sav->flags = sa0->sadb_sa_flags;
|
|
|
|
|
|
|
|
/* replay window */
|
|
|
|
if ((sa0->sadb_sa_flags & SADB_X_EXT_OLD) == 0) {
|
|
|
|
sav->replay = (struct secreplay *)
|
2003-09-01 05:35:55 +00:00
|
|
|
malloc(sizeof(struct secreplay)+sa0->sadb_sa_replay, M_IPSEC_MISC, M_NOWAIT|M_ZERO);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sav->replay == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
if (sa0->sadb_sa_replay != 0)
|
|
|
|
sav->replay->bitmap = (caddr_t)(sav->replay+1);
|
|
|
|
sav->replay->wsize = sa0->sadb_sa_replay;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Authentication keys */
|
|
|
|
if (mhp->ext[SADB_EXT_KEY_AUTH] != NULL) {
|
|
|
|
const struct sadb_key *key0;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_AUTH];
|
|
|
|
len = mhp->extlen[SADB_EXT_KEY_AUTH];
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
if (len < sizeof(*key0)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
switch (mhp->msg->sadb_msg_satype) {
|
|
|
|
case SADB_SATYPE_AH:
|
|
|
|
case SADB_SATYPE_ESP:
|
Initial import of RFC 2385 (TCP-MD5) digest support.
This is the first of two commits; bringing in the kernel support first.
This can be enabled by compiling a kernel with options TCP_SIGNATURE
and FAST_IPSEC.
For the uninitiated, this is a TCP option which provides for a means of
authenticating TCP sessions which came into being before IPSEC. It is
still relevant today, however, as it is used by many commercial router
vendors, particularly with BGP, and as such has become a requirement for
interconnect at many major Internet points of presence.
Several parts of the TCP and IP headers, including the segment payload,
are digested with MD5, including a shared secret. The PF_KEY interface
is used to manage the secrets using security associations in the SADB.
There is a limitation here in that as there is no way to map a TCP flow
per-port back to an SPI without polluting tcpcb or using the SPD; the
code to do the latter is unstable at this time. Therefore this code only
supports per-host keying granularity.
Whilst FAST_IPSEC is mutually exclusive with KAME IPSEC (and thus IPv6),
TCP_SIGNATURE applies only to IPv4. For the vast majority of prospective
users of this feature, this will not pose any problem.
This implementation is output-only; that is, the option is honoured when
responding to a host initiating a TCP session, but no effort is made
[yet] to authenticate inbound traffic. This is, however, sufficient to
interwork with Cisco equipment.
Tested with a Cisco 2501 running IOS 12.0(27), and Quagga 0.96.4 with
local patches. Patches for tcpdump to validate TCP-MD5 sessions are also
available from me upon request.
Sponsored by: sentex.net
2004-02-11 04:26:04 +00:00
|
|
|
case SADB_X_SATYPE_TCPSIGNATURE:
|
2002-10-16 02:10:08 +00:00
|
|
|
if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) &&
|
|
|
|
sav->alg_auth != SADB_X_AALG_NULL)
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
case SADB_X_SATYPE_IPCOMP:
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (error) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid key_auth values.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2006-03-25 13:38:52 +00:00
|
|
|
sav->key_auth = (struct seckey *)key_dup_keymsg(key0, len,
|
|
|
|
M_IPSEC_MISC);
|
|
|
|
if (sav->key_auth == NULL ) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Encryption key */
|
|
|
|
if (mhp->ext[SADB_EXT_KEY_ENCRYPT] != NULL) {
|
|
|
|
const struct sadb_key *key0;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_ENCRYPT];
|
|
|
|
len = mhp->extlen[SADB_EXT_KEY_ENCRYPT];
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
if (len < sizeof(*key0)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
switch (mhp->msg->sadb_msg_satype) {
|
|
|
|
case SADB_SATYPE_ESP:
|
|
|
|
if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) &&
|
|
|
|
sav->alg_enc != SADB_EALG_NULL) {
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
2006-03-25 13:38:52 +00:00
|
|
|
sav->key_enc = (struct seckey *)key_dup_keymsg(key0,
|
|
|
|
len,
|
|
|
|
M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sav->key_enc == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SADB_X_SATYPE_IPCOMP:
|
|
|
|
if (len != PFKEY_ALIGN8(sizeof(struct sadb_key)))
|
|
|
|
error = EINVAL;
|
|
|
|
sav->key_enc = NULL; /*just in case*/
|
|
|
|
break;
|
|
|
|
case SADB_SATYPE_AH:
|
Initial import of RFC 2385 (TCP-MD5) digest support.
This is the first of two commits; bringing in the kernel support first.
This can be enabled by compiling a kernel with options TCP_SIGNATURE
and FAST_IPSEC.
For the uninitiated, this is a TCP option which provides for a means of
authenticating TCP sessions which came into being before IPSEC. It is
still relevant today, however, as it is used by many commercial router
vendors, particularly with BGP, and as such has become a requirement for
interconnect at many major Internet points of presence.
Several parts of the TCP and IP headers, including the segment payload,
are digested with MD5, including a shared secret. The PF_KEY interface
is used to manage the secrets using security associations in the SADB.
There is a limitation here in that as there is no way to map a TCP flow
per-port back to an SPI without polluting tcpcb or using the SPD; the
code to do the latter is unstable at this time. Therefore this code only
supports per-host keying granularity.
Whilst FAST_IPSEC is mutually exclusive with KAME IPSEC (and thus IPv6),
TCP_SIGNATURE applies only to IPv4. For the vast majority of prospective
users of this feature, this will not pose any problem.
This implementation is output-only; that is, the option is honoured when
responding to a host initiating a TCP session, but no effort is made
[yet] to authenticate inbound traffic. This is, however, sufficient to
interwork with Cisco equipment.
Tested with a Cisco 2501 running IOS 12.0(27), and Quagga 0.96.4 with
local patches. Patches for tcpdump to validate TCP-MD5 sessions are also
available from me upon request.
Sponsored by: sentex.net
2004-02-11 04:26:04 +00:00
|
|
|
case SADB_X_SATYPE_TCPSIGNATURE:
|
2002-10-16 02:10:08 +00:00
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (error) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid key_enc value.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set iv */
|
|
|
|
sav->ivlen = 0;
|
|
|
|
|
|
|
|
switch (mhp->msg->sadb_msg_satype) {
|
|
|
|
case SADB_SATYPE_AH:
|
|
|
|
error = xform_init(sav, XF_AH);
|
|
|
|
break;
|
|
|
|
case SADB_SATYPE_ESP:
|
|
|
|
error = xform_init(sav, XF_ESP);
|
|
|
|
break;
|
|
|
|
case SADB_X_SATYPE_IPCOMP:
|
|
|
|
error = xform_init(sav, XF_IPCOMP);
|
|
|
|
break;
|
Initial import of RFC 2385 (TCP-MD5) digest support.
This is the first of two commits; bringing in the kernel support first.
This can be enabled by compiling a kernel with options TCP_SIGNATURE
and FAST_IPSEC.
For the uninitiated, this is a TCP option which provides for a means of
authenticating TCP sessions which came into being before IPSEC. It is
still relevant today, however, as it is used by many commercial router
vendors, particularly with BGP, and as such has become a requirement for
interconnect at many major Internet points of presence.
Several parts of the TCP and IP headers, including the segment payload,
are digested with MD5, including a shared secret. The PF_KEY interface
is used to manage the secrets using security associations in the SADB.
There is a limitation here in that as there is no way to map a TCP flow
per-port back to an SPI without polluting tcpcb or using the SPD; the
code to do the latter is unstable at this time. Therefore this code only
supports per-host keying granularity.
Whilst FAST_IPSEC is mutually exclusive with KAME IPSEC (and thus IPv6),
TCP_SIGNATURE applies only to IPv4. For the vast majority of prospective
users of this feature, this will not pose any problem.
This implementation is output-only; that is, the option is honoured when
responding to a host initiating a TCP session, but no effort is made
[yet] to authenticate inbound traffic. This is, however, sufficient to
interwork with Cisco equipment.
Tested with a Cisco 2501 running IOS 12.0(27), and Quagga 0.96.4 with
local patches. Patches for tcpdump to validate TCP-MD5 sessions are also
available from me upon request.
Sponsored by: sentex.net
2004-02-11 04:26:04 +00:00
|
|
|
case SADB_X_SATYPE_TCPSIGNATURE:
|
|
|
|
error = xform_init(sav, XF_TCPSIGNATURE);
|
|
|
|
break;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
if (error) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: unable to initialize SA type %u.\n",
|
|
|
|
__func__, mhp->msg->sadb_msg_satype));
|
2002-10-16 02:10:08 +00:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset created */
|
|
|
|
sav->created = time_second;
|
|
|
|
|
|
|
|
/* make lifetime for CURRENT */
|
2008-03-02 17:12:28 +00:00
|
|
|
sav->lft_c = malloc(sizeof(struct seclifetime), M_IPSEC_MISC, M_NOWAIT);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sav->lft_c == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2006-03-25 13:38:52 +00:00
|
|
|
sav->lft_c->allocations = 0;
|
|
|
|
sav->lft_c->bytes = 0;
|
|
|
|
sav->lft_c->addtime = time_second;
|
|
|
|
sav->lft_c->usetime = 0;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* lifetimes for HARD and SOFT */
|
|
|
|
{
|
|
|
|
const struct sadb_lifetime *lft0;
|
|
|
|
|
|
|
|
lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD];
|
|
|
|
if (lft0 != NULL) {
|
|
|
|
if (mhp->extlen[SADB_EXT_LIFETIME_HARD] < sizeof(*lft0)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
2006-03-25 13:38:52 +00:00
|
|
|
sav->lft_h = key_dup_lifemsg(lft0, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sav->lft_h == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* to be initialize ? */
|
|
|
|
}
|
|
|
|
|
|
|
|
lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_SOFT];
|
|
|
|
if (lft0 != NULL) {
|
|
|
|
if (mhp->extlen[SADB_EXT_LIFETIME_SOFT] < sizeof(*lft0)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
2006-03-25 13:38:52 +00:00
|
|
|
sav->lft_s = key_dup_lifemsg(lft0, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sav->lft_s == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* to be initialize ? */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
/* initialization */
|
2003-09-01 05:35:55 +00:00
|
|
|
key_cleansav(sav);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* validation with a secasvar entry, and set SADB_SATYPE_MATURE.
|
|
|
|
* OUT: 0: valid
|
|
|
|
* other: errno
|
|
|
|
*/
|
|
|
|
static int
|
2003-09-01 05:35:55 +00:00
|
|
|
key_mature(struct secasvar *sav)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
/* check SPI value */
|
|
|
|
switch (sav->sah->saidx.proto) {
|
|
|
|
case IPPROTO_ESP:
|
|
|
|
case IPPROTO_AH:
|
2007-06-16 09:25:23 +00:00
|
|
|
/*
|
|
|
|
* RFC 4302, 2.4. Security Parameters Index (SPI), SPI values
|
|
|
|
* 1-255 reserved by IANA for future use,
|
|
|
|
* 0 for implementation specific, local use.
|
|
|
|
*/
|
|
|
|
if (ntohl(sav->spi) <= 255) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: illegal range of SPI %u.\n",
|
|
|
|
__func__, (u_int32_t)ntohl(sav->spi)));
|
2002-10-16 02:10:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check satype */
|
|
|
|
switch (sav->sah->saidx.proto) {
|
|
|
|
case IPPROTO_ESP:
|
|
|
|
/* check flags */
|
|
|
|
if ((sav->flags & (SADB_X_EXT_OLD|SADB_X_EXT_DERIV)) ==
|
|
|
|
(SADB_X_EXT_OLD|SADB_X_EXT_DERIV)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid flag (derived) "
|
|
|
|
"given to old-esp.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
error = xform_init(sav, XF_ESP);
|
|
|
|
break;
|
|
|
|
case IPPROTO_AH:
|
|
|
|
/* check flags */
|
|
|
|
if (sav->flags & SADB_X_EXT_DERIV) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid flag (derived) "
|
|
|
|
"given to AH SA.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
if (sav->alg_enc != SADB_EALG_NONE) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: protocol and algorithm "
|
|
|
|
"mismated.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return(EINVAL);
|
|
|
|
}
|
|
|
|
error = xform_init(sav, XF_AH);
|
|
|
|
break;
|
|
|
|
case IPPROTO_IPCOMP:
|
|
|
|
if (sav->alg_auth != SADB_AALG_NONE) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: protocol and algorithm "
|
|
|
|
"mismated.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return(EINVAL);
|
|
|
|
}
|
|
|
|
if ((sav->flags & SADB_X_EXT_RAWCPI) == 0
|
|
|
|
&& ntohl(sav->spi) >= 0x10000) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid cpi for IPComp.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return(EINVAL);
|
|
|
|
}
|
|
|
|
error = xform_init(sav, XF_IPCOMP);
|
|
|
|
break;
|
Initial import of RFC 2385 (TCP-MD5) digest support.
This is the first of two commits; bringing in the kernel support first.
This can be enabled by compiling a kernel with options TCP_SIGNATURE
and FAST_IPSEC.
For the uninitiated, this is a TCP option which provides for a means of
authenticating TCP sessions which came into being before IPSEC. It is
still relevant today, however, as it is used by many commercial router
vendors, particularly with BGP, and as such has become a requirement for
interconnect at many major Internet points of presence.
Several parts of the TCP and IP headers, including the segment payload,
are digested with MD5, including a shared secret. The PF_KEY interface
is used to manage the secrets using security associations in the SADB.
There is a limitation here in that as there is no way to map a TCP flow
per-port back to an SPI without polluting tcpcb or using the SPD; the
code to do the latter is unstable at this time. Therefore this code only
supports per-host keying granularity.
Whilst FAST_IPSEC is mutually exclusive with KAME IPSEC (and thus IPv6),
TCP_SIGNATURE applies only to IPv4. For the vast majority of prospective
users of this feature, this will not pose any problem.
This implementation is output-only; that is, the option is honoured when
responding to a host initiating a TCP session, but no effort is made
[yet] to authenticate inbound traffic. This is, however, sufficient to
interwork with Cisco equipment.
Tested with a Cisco 2501 running IOS 12.0(27), and Quagga 0.96.4 with
local patches. Patches for tcpdump to validate TCP-MD5 sessions are also
available from me upon request.
Sponsored by: sentex.net
2004-02-11 04:26:04 +00:00
|
|
|
case IPPROTO_TCP:
|
|
|
|
if (sav->alg_enc != SADB_EALG_NONE) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: protocol and algorithm "
|
|
|
|
"mismated.\n", __func__));
|
|
|
|
return(EINVAL);
|
|
|
|
}
|
|
|
|
error = xform_init(sav, XF_TCPSIGNATURE);
|
|
|
|
break;
|
2002-10-16 02:10:08 +00:00
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: Invalid satype.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EPROTONOSUPPORT;
|
|
|
|
break;
|
|
|
|
}
|
2003-09-01 05:35:55 +00:00
|
|
|
if (error == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
key_sa_chgstate(sav, SADB_SASTATE_MATURE);
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* subroutine for SADB_GET and SADB_DUMP.
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2009-02-24 18:09:31 +00:00
|
|
|
key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype,
|
|
|
|
u_int32_t seq, u_int32_t pid)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *result = NULL, *tres = NULL, *m;
|
|
|
|
int i;
|
|
|
|
int dumporder[] = {
|
|
|
|
SADB_EXT_SA, SADB_X_EXT_SA2,
|
|
|
|
SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT,
|
|
|
|
SADB_EXT_LIFETIME_CURRENT, SADB_EXT_ADDRESS_SRC,
|
|
|
|
SADB_EXT_ADDRESS_DST, SADB_EXT_ADDRESS_PROXY, SADB_EXT_KEY_AUTH,
|
|
|
|
SADB_EXT_KEY_ENCRYPT, SADB_EXT_IDENTITY_SRC,
|
|
|
|
SADB_EXT_IDENTITY_DST, SADB_EXT_SENSITIVITY,
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
SADB_X_EXT_NAT_T_TYPE,
|
|
|
|
SADB_X_EXT_NAT_T_SPORT, SADB_X_EXT_NAT_T_DPORT,
|
|
|
|
SADB_X_EXT_NAT_T_OAI, SADB_X_EXT_NAT_T_OAR,
|
|
|
|
SADB_X_EXT_NAT_T_FRAG,
|
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
m = key_setsadbmsg(type, 0, satype, seq, pid, sav->refcnt);
|
|
|
|
if (m == NULL)
|
|
|
|
goto fail;
|
|
|
|
result = m;
|
|
|
|
|
|
|
|
for (i = sizeof(dumporder)/sizeof(dumporder[0]) - 1; i >= 0; i--) {
|
|
|
|
m = NULL;
|
|
|
|
switch (dumporder[i]) {
|
|
|
|
case SADB_EXT_SA:
|
|
|
|
m = key_setsadbsa(sav);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_X_EXT_SA2:
|
|
|
|
m = key_setsadbxsa2(sav->sah->saidx.mode,
|
|
|
|
sav->replay ? sav->replay->count : 0,
|
|
|
|
sav->sah->saidx.reqid);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_EXT_ADDRESS_SRC:
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
|
|
|
|
&sav->sah->saidx.src.sa,
|
|
|
|
FULLMASK, IPSEC_ULPROTO_ANY);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_EXT_ADDRESS_DST:
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
|
|
|
|
&sav->sah->saidx.dst.sa,
|
|
|
|
FULLMASK, IPSEC_ULPROTO_ANY);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_EXT_KEY_AUTH:
|
|
|
|
if (!sav->key_auth)
|
|
|
|
continue;
|
2006-03-25 13:38:52 +00:00
|
|
|
m = key_setkey(sav->key_auth, SADB_EXT_KEY_AUTH);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_EXT_KEY_ENCRYPT:
|
|
|
|
if (!sav->key_enc)
|
|
|
|
continue;
|
2006-03-25 13:38:52 +00:00
|
|
|
m = key_setkey(sav->key_enc, SADB_EXT_KEY_ENCRYPT);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_EXT_LIFETIME_CURRENT:
|
|
|
|
if (!sav->lft_c)
|
|
|
|
continue;
|
2006-03-25 13:38:52 +00:00
|
|
|
m = key_setlifetime(sav->lft_c,
|
|
|
|
SADB_EXT_LIFETIME_CURRENT);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_EXT_LIFETIME_HARD:
|
|
|
|
if (!sav->lft_h)
|
|
|
|
continue;
|
2006-03-25 13:38:52 +00:00
|
|
|
m = key_setlifetime(sav->lft_h,
|
|
|
|
SADB_EXT_LIFETIME_HARD);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_EXT_LIFETIME_SOFT:
|
|
|
|
if (!sav->lft_s)
|
|
|
|
continue;
|
2008-03-24 15:01:20 +00:00
|
|
|
m = key_setlifetime(sav->lft_s,
|
2006-03-25 13:38:52 +00:00
|
|
|
SADB_EXT_LIFETIME_SOFT);
|
|
|
|
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
case SADB_X_EXT_NAT_T_TYPE:
|
|
|
|
m = key_setsadbxtype(sav->natt_type);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_X_EXT_NAT_T_DPORT:
|
|
|
|
m = key_setsadbxport(
|
|
|
|
KEY_PORTFROMSADDR(&sav->sah->saidx.dst),
|
|
|
|
SADB_X_EXT_NAT_T_DPORT);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_X_EXT_NAT_T_SPORT:
|
|
|
|
m = key_setsadbxport(
|
|
|
|
KEY_PORTFROMSADDR(&sav->sah->saidx.src),
|
|
|
|
SADB_X_EXT_NAT_T_SPORT);
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SADB_X_EXT_NAT_T_OAI:
|
|
|
|
case SADB_X_EXT_NAT_T_OAR:
|
|
|
|
case SADB_X_EXT_NAT_T_FRAG:
|
|
|
|
/* We do not (yet) support those. */
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
case SADB_EXT_ADDRESS_PROXY:
|
|
|
|
case SADB_EXT_IDENTITY_SRC:
|
|
|
|
case SADB_EXT_IDENTITY_DST:
|
|
|
|
/* XXX: should we brought from SPD ? */
|
|
|
|
case SADB_EXT_SENSITIVITY:
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-03-25 13:38:52 +00:00
|
|
|
if (!m)
|
2002-10-16 02:10:08 +00:00
|
|
|
goto fail;
|
|
|
|
if (tres)
|
|
|
|
m_cat(m, tres);
|
|
|
|
tres = m;
|
2006-03-25 13:38:52 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_cat(result, tres);
|
|
|
|
if (result->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
result = m_pullup(result, sizeof(struct sadb_msg));
|
|
|
|
if (result == NULL)
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
result->m_pkthdr.len = 0;
|
|
|
|
for (m = result; m; m = m->m_next)
|
|
|
|
result->m_pkthdr.len += m->m_len;
|
|
|
|
|
|
|
|
mtod(result, struct sadb_msg *)->sadb_msg_len =
|
|
|
|
PFKEY_UNIT64(result->m_pkthdr.len);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
m_freem(result);
|
|
|
|
m_freem(tres);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set data into sadb_msg.
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2009-02-24 18:09:31 +00:00
|
|
|
key_setsadbmsg(u_int8_t type, u_int16_t tlen, u_int8_t satype, u_int32_t seq,
|
|
|
|
pid_t pid, u_int16_t reserved)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
struct sadb_msg *p;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
|
|
|
|
if (len > MCLBYTES)
|
|
|
|
return NULL;
|
2012-12-05 08:04:20 +00:00
|
|
|
MGETHDR(m, M_NOWAIT, MT_DATA);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (m && len > MHLEN) {
|
2015-01-06 12:59:37 +00:00
|
|
|
if (!(MCLGET(m, M_NOWAIT))) {
|
2002-10-16 02:10:08 +00:00
|
|
|
m_freem(m);
|
|
|
|
m = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!m)
|
|
|
|
return NULL;
|
|
|
|
m->m_pkthdr.len = m->m_len = len;
|
|
|
|
m->m_next = NULL;
|
|
|
|
|
|
|
|
p = mtod(m, struct sadb_msg *);
|
|
|
|
|
|
|
|
bzero(p, len);
|
|
|
|
p->sadb_msg_version = PF_KEY_V2;
|
|
|
|
p->sadb_msg_type = type;
|
|
|
|
p->sadb_msg_errno = 0;
|
|
|
|
p->sadb_msg_satype = satype;
|
|
|
|
p->sadb_msg_len = PFKEY_UNIT64(tlen);
|
|
|
|
p->sadb_msg_reserved = reserved;
|
|
|
|
p->sadb_msg_seq = seq;
|
|
|
|
p->sadb_msg_pid = (u_int32_t)pid;
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* copy secasvar data into sadb_address.
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_setsadbsa(struct secasvar *sav)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
struct sadb_sa *p;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_sa));
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (m == NULL)
|
|
|
|
return (NULL);
|
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
2002-10-16 02:10:08 +00:00
|
|
|
p = mtod(m, struct sadb_sa *);
|
|
|
|
bzero(p, len);
|
|
|
|
p->sadb_sa_len = PFKEY_UNIT64(len);
|
|
|
|
p->sadb_sa_exttype = SADB_EXT_SA;
|
|
|
|
p->sadb_sa_spi = sav->spi;
|
|
|
|
p->sadb_sa_replay = (sav->replay != NULL ? sav->replay->wsize : 0);
|
|
|
|
p->sadb_sa_state = sav->state;
|
|
|
|
p->sadb_sa_auth = sav->alg_auth;
|
|
|
|
p->sadb_sa_encrypt = sav->alg_enc;
|
|
|
|
p->sadb_sa_flags = sav->flags;
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set data into sadb_address.
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_setsadbaddr(u_int16_t exttype, const struct sockaddr *saddr,
|
|
|
|
u_int8_t prefixlen, u_int16_t ul_proto)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
struct sadb_address *p;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_address)) +
|
|
|
|
PFKEY_ALIGN8(saddr->sa_len);
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (m == NULL)
|
|
|
|
return (NULL);
|
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
2002-10-16 02:10:08 +00:00
|
|
|
p = mtod(m, struct sadb_address *);
|
|
|
|
|
|
|
|
bzero(p, len);
|
|
|
|
p->sadb_address_len = PFKEY_UNIT64(len);
|
|
|
|
p->sadb_address_exttype = exttype;
|
|
|
|
p->sadb_address_proto = ul_proto;
|
|
|
|
if (prefixlen == FULLMASK) {
|
|
|
|
switch (saddr->sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
prefixlen = sizeof(struct in_addr) << 3;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
prefixlen = sizeof(struct in6_addr) << 3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
; /*XXX*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p->sadb_address_prefixlen = prefixlen;
|
|
|
|
p->sadb_address_reserved = 0;
|
|
|
|
|
|
|
|
bcopy(saddr,
|
|
|
|
mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_address)),
|
|
|
|
saddr->sa_len);
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set data into sadb_x_sa2.
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2009-02-24 18:09:31 +00:00
|
|
|
key_setsadbxsa2(u_int8_t mode, u_int32_t seq, u_int32_t reqid)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
struct sadb_x_sa2 *p;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_x_sa2));
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (m == NULL)
|
|
|
|
return (NULL);
|
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
2002-10-16 02:10:08 +00:00
|
|
|
p = mtod(m, struct sadb_x_sa2 *);
|
|
|
|
|
|
|
|
bzero(p, len);
|
|
|
|
p->sadb_x_sa2_len = PFKEY_UNIT64(len);
|
|
|
|
p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
|
|
|
|
p->sadb_x_sa2_mode = mode;
|
|
|
|
p->sadb_x_sa2_reserved1 = 0;
|
|
|
|
p->sadb_x_sa2_reserved2 = 0;
|
|
|
|
p->sadb_x_sa2_sequence = seq;
|
|
|
|
p->sadb_x_sa2_reqid = reqid;
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Set a type in sadb_x_nat_t_type.
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
|
|
|
key_setsadbxtype(u_int16_t type)
|
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
size_t len;
|
|
|
|
struct sadb_x_nat_t_type *p;
|
|
|
|
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_type));
|
|
|
|
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (m == NULL)
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
return (NULL);
|
2013-03-15 10:20:15 +00:00
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
p = mtod(m, struct sadb_x_nat_t_type *);
|
|
|
|
|
|
|
|
bzero(p, len);
|
|
|
|
p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
|
|
|
|
p->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
|
|
|
|
p->sadb_x_nat_t_type_type = type;
|
|
|
|
|
|
|
|
return (m);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Set a port in sadb_x_nat_t_port.
|
|
|
|
* In contrast to default RFC 2367 behaviour, port is in network byte order.
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
|
|
|
key_setsadbxport(u_int16_t port, u_int16_t type)
|
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
size_t len;
|
|
|
|
struct sadb_x_nat_t_port *p;
|
|
|
|
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_port));
|
|
|
|
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (m == NULL)
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
return (NULL);
|
2013-03-15 10:20:15 +00:00
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
p = mtod(m, struct sadb_x_nat_t_port *);
|
|
|
|
|
|
|
|
bzero(p, len);
|
|
|
|
p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
|
|
|
|
p->sadb_x_nat_t_port_exttype = type;
|
|
|
|
p->sadb_x_nat_t_port_port = port;
|
|
|
|
|
|
|
|
return (m);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get port from sockaddr. Port is in network byte order.
|
|
|
|
*/
|
2014-12-03 03:50:54 +00:00
|
|
|
u_int16_t
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
key_portfromsaddr(struct sockaddr *sa)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (sa->sa_family) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
|
|
|
return ((struct sockaddr_in *)sa)->sin_port;
|
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
return ((struct sockaddr_in6 *)sa)->sin6_port;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
|
|
|
printf("DP %s unexpected address family %d\n",
|
|
|
|
__func__, sa->sa_family));
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
#endif /* IPSEC_NAT_T */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set port in struct sockaddr. Port is in network byte order.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
key_porttosaddr(struct sockaddr *sa, u_int16_t port)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (sa->sa_family) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
|
|
|
((struct sockaddr_in *)sa)->sin_port = port;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
((struct sockaddr_in6 *)sa)->sin6_port = port;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
ipseclog((LOG_DEBUG, "%s: unexpected address family %d.\n",
|
|
|
|
__func__, sa->sa_family));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* set data into sadb_x_policy
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2009-02-24 18:09:31 +00:00
|
|
|
key_setsadbxpolicy(u_int16_t type, u_int8_t dir, u_int32_t id)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
struct sadb_x_policy *p;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_x_policy));
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (m == NULL)
|
|
|
|
return (NULL);
|
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
2002-10-16 02:10:08 +00:00
|
|
|
p = mtod(m, struct sadb_x_policy *);
|
|
|
|
|
|
|
|
bzero(p, len);
|
|
|
|
p->sadb_x_policy_len = PFKEY_UNIT64(len);
|
|
|
|
p->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
|
|
|
|
p->sadb_x_policy_type = type;
|
|
|
|
p->sadb_x_policy_dir = dir;
|
|
|
|
p->sadb_x_policy_id = id;
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* %%% utilities */
|
2006-03-25 13:38:52 +00:00
|
|
|
/* Take a key message (sadb_key) from the socket and turn it into one
|
|
|
|
* of the kernel's key structures (seckey).
|
|
|
|
*
|
|
|
|
* IN: pointer to the src
|
|
|
|
* OUT: NULL no more memory
|
2002-10-16 02:10:08 +00:00
|
|
|
*/
|
2006-03-25 13:38:52 +00:00
|
|
|
struct seckey *
|
|
|
|
key_dup_keymsg(const struct sadb_key *src, u_int len,
|
2014-12-03 03:50:54 +00:00
|
|
|
struct malloc_type *type)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2006-03-25 13:38:52 +00:00
|
|
|
struct seckey *dst;
|
|
|
|
dst = (struct seckey *)malloc(sizeof(struct seckey), type, M_NOWAIT);
|
|
|
|
if (dst != NULL) {
|
|
|
|
dst->bits = src->sadb_key_bits;
|
|
|
|
dst->key_data = (char *)malloc(len, type, M_NOWAIT);
|
|
|
|
if (dst->key_data != NULL) {
|
|
|
|
bcopy((const char *)src + sizeof(struct sadb_key),
|
|
|
|
dst->key_data, len);
|
|
|
|
} else {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n",
|
|
|
|
__func__));
|
|
|
|
free(dst, type);
|
|
|
|
dst = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2006-03-25 13:38:52 +00:00
|
|
|
}
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Take a lifetime message (sadb_lifetime) passed in on a socket and
|
|
|
|
* turn it into one of the kernel's lifetime structures (seclifetime).
|
|
|
|
*
|
|
|
|
* IN: pointer to the destination, source and malloc type
|
|
|
|
* OUT: NULL, no more memory
|
|
|
|
*/
|
|
|
|
|
|
|
|
static struct seclifetime *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_dup_lifemsg(const struct sadb_lifetime *src, struct malloc_type *type)
|
2006-03-25 13:38:52 +00:00
|
|
|
{
|
|
|
|
struct seclifetime *dst = NULL;
|
|
|
|
|
|
|
|
dst = (struct seclifetime *)malloc(sizeof(struct seclifetime),
|
|
|
|
type, M_NOWAIT);
|
|
|
|
if (dst == NULL) {
|
2003-09-01 05:35:55 +00:00
|
|
|
/* XXX counter */
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2006-03-25 13:38:52 +00:00
|
|
|
} else {
|
|
|
|
dst->allocations = src->sadb_lifetime_allocations;
|
|
|
|
dst->bytes = src->sadb_lifetime_bytes;
|
|
|
|
dst->addtime = src->sadb_lifetime_addtime;
|
|
|
|
dst->usetime = src->sadb_lifetime_usetime;
|
|
|
|
}
|
|
|
|
return dst;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* compare my own address
|
|
|
|
* OUT: 1: true, i.e. my address.
|
|
|
|
* 0: false
|
|
|
|
*/
|
|
|
|
int
|
2014-10-31 12:19:22 +00:00
|
|
|
key_ismyaddr(struct sockaddr *sa)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sa != NULL, ("null sockaddr"));
|
2002-10-16 02:10:08 +00:00
|
|
|
switch (sa->sa_family) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
2014-10-31 12:19:22 +00:00
|
|
|
return (in_localip(satosin(sa)->sin_addr));
|
2002-10-16 02:10:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
return key_ismyaddr6((struct sockaddr_in6 *)sa);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef INET6
|
|
|
|
/*
|
|
|
|
* compare my own address for IPv6.
|
|
|
|
* 1: ours
|
|
|
|
* 0: other
|
|
|
|
* NOTE: derived ip6_input() in KAME. This is necessary to modify more.
|
|
|
|
*/
|
|
|
|
#include <netinet6/in6_var.h>
|
|
|
|
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_ismyaddr6(struct sockaddr_in6 *sin6)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct in6_ifaddr *ia;
|
2009-04-29 11:15:58 +00:00
|
|
|
#if 0
|
2002-10-16 02:10:08 +00:00
|
|
|
struct in6_multi *in6m;
|
2009-04-29 11:15:58 +00:00
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2009-06-25 16:35:28 +00:00
|
|
|
IN6_IFADDR_RLOCK();
|
2009-06-24 21:00:25 +00:00
|
|
|
TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (key_sockaddrcmp((struct sockaddr *)&sin6,
|
2009-06-25 16:35:28 +00:00
|
|
|
(struct sockaddr *)&ia->ia_addr, 0) == 0) {
|
|
|
|
IN6_IFADDR_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
return 1;
|
2009-06-25 16:35:28 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2009-04-29 11:15:58 +00:00
|
|
|
#if 0
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* XXX Multicast
|
|
|
|
* XXX why do we care about multlicast here while we don't care
|
|
|
|
* about IPv4 multicast??
|
|
|
|
* XXX scope
|
|
|
|
*/
|
|
|
|
in6m = NULL;
|
|
|
|
IN6_LOOKUP_MULTI(sin6->sin6_addr, ia->ia_ifp, in6m);
|
2009-06-25 16:35:28 +00:00
|
|
|
if (in6m) {
|
|
|
|
IN6_IFADDR_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
return 1;
|
2009-06-25 16:35:28 +00:00
|
|
|
}
|
2009-04-29 11:15:58 +00:00
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2009-06-25 16:35:28 +00:00
|
|
|
IN6_IFADDR_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* loopback, just for safety */
|
|
|
|
if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /*INET6*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* compare two secasindex structure.
|
|
|
|
* flag can specify to compare 2 saidxes.
|
|
|
|
* compare two secasindex structure without both mode and reqid.
|
|
|
|
* don't compare port.
|
|
|
|
* IN:
|
|
|
|
* saidx0: source, it can be in SAD.
|
|
|
|
* saidx1: object.
|
|
|
|
* OUT:
|
|
|
|
* 1 : equal
|
|
|
|
* 0 : not equal
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_cmpsaidx(const struct secasindex *saidx0, const struct secasindex *saidx1,
|
|
|
|
int flag)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
int chkport = 0;
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* sanity */
|
|
|
|
if (saidx0 == NULL && saidx1 == NULL)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (saidx0 == NULL || saidx1 == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (saidx0->proto != saidx1->proto)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (flag == CMP_EXACTLY) {
|
|
|
|
if (saidx0->mode != saidx1->mode)
|
|
|
|
return 0;
|
|
|
|
if (saidx0->reqid != saidx1->reqid)
|
|
|
|
return 0;
|
|
|
|
if (bcmp(&saidx0->src, &saidx1->src, saidx0->src.sa.sa_len) != 0 ||
|
|
|
|
bcmp(&saidx0->dst, &saidx1->dst, saidx0->dst.sa.sa_len) != 0)
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* CMP_MODE_REQID, CMP_REQID, CMP_HEAD */
|
|
|
|
if (flag == CMP_MODE_REQID
|
|
|
|
||flag == CMP_REQID) {
|
|
|
|
/*
|
|
|
|
* If reqid of SPD is non-zero, unique SA is required.
|
|
|
|
* The result must be of same reqid in this case.
|
|
|
|
*/
|
|
|
|
if (saidx1->reqid != 0 && saidx0->reqid != saidx1->reqid)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag == CMP_MODE_REQID) {
|
|
|
|
if (saidx0->mode != IPSEC_MODE_ANY
|
|
|
|
&& saidx0->mode != saidx1->mode)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* If NAT-T is enabled, check ports for tunnel mode.
|
|
|
|
* Do not check ports if they are set to zero in the SPD.
|
2012-09-12 12:14:50 +00:00
|
|
|
* Also do not do it for native transport mode, as there
|
|
|
|
* is no port information available in the SP.
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
*/
|
2012-09-12 12:14:50 +00:00
|
|
|
if ((saidx1->mode == IPSEC_MODE_TUNNEL ||
|
|
|
|
(saidx1->mode == IPSEC_MODE_TRANSPORT &&
|
|
|
|
saidx1->proto == IPPROTO_ESP)) &&
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
saidx1->src.sa.sa_family == AF_INET &&
|
|
|
|
saidx1->dst.sa.sa_family == AF_INET &&
|
|
|
|
((const struct sockaddr_in *)(&saidx1->src))->sin_port &&
|
|
|
|
((const struct sockaddr_in *)(&saidx1->dst))->sin_port)
|
|
|
|
chkport = 1;
|
|
|
|
#endif /* IPSEC_NAT_T */
|
|
|
|
|
|
|
|
if (key_sockaddrcmp(&saidx0->src.sa, &saidx1->src.sa, chkport) != 0) {
|
2002-10-16 02:10:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
if (key_sockaddrcmp(&saidx0->dst.sa, &saidx1->dst.sa, chkport) != 0) {
|
2002-10-16 02:10:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* compare two secindex structure exactly.
|
|
|
|
* IN:
|
|
|
|
* spidx0: source, it is often in SPD.
|
|
|
|
* spidx1: object, it is often from PFKEY message.
|
|
|
|
* OUT:
|
|
|
|
* 1 : equal
|
|
|
|
* 0 : not equal
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_cmpspidx_exactly(struct secpolicyindex *spidx0,
|
|
|
|
struct secpolicyindex *spidx1)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
/* sanity */
|
|
|
|
if (spidx0 == NULL && spidx1 == NULL)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (spidx0 == NULL || spidx1 == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (spidx0->prefs != spidx1->prefs
|
|
|
|
|| spidx0->prefd != spidx1->prefd
|
|
|
|
|| spidx0->ul_proto != spidx1->ul_proto)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return key_sockaddrcmp(&spidx0->src.sa, &spidx1->src.sa, 1) == 0 &&
|
|
|
|
key_sockaddrcmp(&spidx0->dst.sa, &spidx1->dst.sa, 1) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* compare two secindex structure with mask.
|
|
|
|
* IN:
|
|
|
|
* spidx0: source, it is often in SPD.
|
|
|
|
* spidx1: object, it is often from IP header.
|
|
|
|
* OUT:
|
|
|
|
* 1 : equal
|
|
|
|
* 0 : not equal
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_cmpspidx_withmask(struct secpolicyindex *spidx0,
|
|
|
|
struct secpolicyindex *spidx1)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
/* sanity */
|
|
|
|
if (spidx0 == NULL && spidx1 == NULL)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (spidx0 == NULL || spidx1 == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (spidx0->src.sa.sa_family != spidx1->src.sa.sa_family ||
|
|
|
|
spidx0->dst.sa.sa_family != spidx1->dst.sa.sa_family ||
|
|
|
|
spidx0->src.sa.sa_len != spidx1->src.sa.sa_len ||
|
|
|
|
spidx0->dst.sa.sa_len != spidx1->dst.sa.sa_len)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* if spidx.ul_proto == IPSEC_ULPROTO_ANY, ignore. */
|
|
|
|
if (spidx0->ul_proto != (u_int16_t)IPSEC_ULPROTO_ANY
|
|
|
|
&& spidx0->ul_proto != spidx1->ul_proto)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (spidx0->src.sa.sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (spidx0->src.sin.sin_port != IPSEC_PORT_ANY
|
|
|
|
&& spidx0->src.sin.sin_port != spidx1->src.sin.sin_port)
|
|
|
|
return 0;
|
|
|
|
if (!key_bbcmp(&spidx0->src.sin.sin_addr,
|
|
|
|
&spidx1->src.sin.sin_addr, spidx0->prefs))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (spidx0->src.sin6.sin6_port != IPSEC_PORT_ANY
|
|
|
|
&& spidx0->src.sin6.sin6_port != spidx1->src.sin6.sin6_port)
|
|
|
|
return 0;
|
|
|
|
/*
|
|
|
|
* scope_id check. if sin6_scope_id is 0, we regard it
|
|
|
|
* as a wildcard scope, which matches any scope zone ID.
|
|
|
|
*/
|
|
|
|
if (spidx0->src.sin6.sin6_scope_id &&
|
|
|
|
spidx1->src.sin6.sin6_scope_id &&
|
|
|
|
spidx0->src.sin6.sin6_scope_id != spidx1->src.sin6.sin6_scope_id)
|
|
|
|
return 0;
|
|
|
|
if (!key_bbcmp(&spidx0->src.sin6.sin6_addr,
|
|
|
|
&spidx1->src.sin6.sin6_addr, spidx0->prefs))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* XXX */
|
|
|
|
if (bcmp(&spidx0->src, &spidx1->src, spidx0->src.sa.sa_len) != 0)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (spidx0->dst.sa.sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (spidx0->dst.sin.sin_port != IPSEC_PORT_ANY
|
|
|
|
&& spidx0->dst.sin.sin_port != spidx1->dst.sin.sin_port)
|
|
|
|
return 0;
|
|
|
|
if (!key_bbcmp(&spidx0->dst.sin.sin_addr,
|
|
|
|
&spidx1->dst.sin.sin_addr, spidx0->prefd))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (spidx0->dst.sin6.sin6_port != IPSEC_PORT_ANY
|
|
|
|
&& spidx0->dst.sin6.sin6_port != spidx1->dst.sin6.sin6_port)
|
|
|
|
return 0;
|
|
|
|
/*
|
|
|
|
* scope_id check. if sin6_scope_id is 0, we regard it
|
|
|
|
* as a wildcard scope, which matches any scope zone ID.
|
|
|
|
*/
|
2004-06-22 17:17:44 +00:00
|
|
|
if (spidx0->dst.sin6.sin6_scope_id &&
|
|
|
|
spidx1->dst.sin6.sin6_scope_id &&
|
2002-10-16 02:10:08 +00:00
|
|
|
spidx0->dst.sin6.sin6_scope_id != spidx1->dst.sin6.sin6_scope_id)
|
|
|
|
return 0;
|
|
|
|
if (!key_bbcmp(&spidx0->dst.sin6.sin6_addr,
|
|
|
|
&spidx1->dst.sin6.sin6_addr, spidx0->prefd))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* XXX */
|
|
|
|
if (bcmp(&spidx0->dst, &spidx1->dst, spidx0->dst.sa.sa_len) != 0)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX Do we check other field ? e.g. flowinfo */
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns 0 on match */
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_sockaddrcmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
|
|
|
|
int port)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
#ifdef satosin
|
|
|
|
#undef satosin
|
|
|
|
#endif
|
|
|
|
#define satosin(s) ((const struct sockaddr_in *)s)
|
|
|
|
#ifdef satosin6
|
|
|
|
#undef satosin6
|
|
|
|
#endif
|
|
|
|
#define satosin6(s) ((const struct sockaddr_in6 *)s)
|
|
|
|
if (sa1->sa_family != sa2->sa_family || sa1->sa_len != sa2->sa_len)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
switch (sa1->sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (sa1->sa_len != sizeof(struct sockaddr_in))
|
|
|
|
return 1;
|
|
|
|
if (satosin(sa1)->sin_addr.s_addr !=
|
|
|
|
satosin(sa2)->sin_addr.s_addr) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (port && satosin(sa1)->sin_port != satosin(sa2)->sin_port)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (sa1->sa_len != sizeof(struct sockaddr_in6))
|
|
|
|
return 1; /*EINVAL*/
|
|
|
|
if (satosin6(sa1)->sin6_scope_id !=
|
|
|
|
satosin6(sa2)->sin6_scope_id) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (!IN6_ARE_ADDR_EQUAL(&satosin6(sa1)->sin6_addr,
|
|
|
|
&satosin6(sa2)->sin6_addr)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (port &&
|
|
|
|
satosin6(sa1)->sin6_port != satosin6(sa2)->sin6_port) {
|
|
|
|
return 1;
|
|
|
|
}
|
2007-05-29 22:18:44 +00:00
|
|
|
break;
|
2002-10-16 02:10:08 +00:00
|
|
|
default:
|
|
|
|
if (bcmp(sa1, sa2, sa1->sa_len) != 0)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
#undef satosin
|
|
|
|
#undef satosin6
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* compare two buffers with mask.
|
|
|
|
* IN:
|
|
|
|
* addr1: source
|
|
|
|
* addr2: object
|
|
|
|
* bits: Number of bits to compare
|
|
|
|
* OUT:
|
|
|
|
* 1 : equal
|
|
|
|
* 0 : not equal
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
key_bbcmp(const void *a1, const void *a2, u_int bits)
|
|
|
|
{
|
|
|
|
const unsigned char *p1 = a1;
|
|
|
|
const unsigned char *p2 = a2;
|
|
|
|
|
|
|
|
/* XXX: This could be considerably faster if we compare a word
|
|
|
|
* at a time, but it is complicated on LSB Endian machines */
|
|
|
|
|
|
|
|
/* Handle null pointers */
|
|
|
|
if (p1 == NULL || p2 == NULL)
|
|
|
|
return (p1 == p2);
|
|
|
|
|
|
|
|
while (bits >= 8) {
|
|
|
|
if (*p1++ != *p2++)
|
|
|
|
return 0;
|
|
|
|
bits -= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bits > 0) {
|
|
|
|
u_int8_t mask = ~((1<<(8-bits))-1);
|
|
|
|
if ((*p1 & mask) != (*p2 & mask))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1; /* Match! */
|
|
|
|
}
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
static void
|
|
|
|
key_flush_spd(time_t now)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK_TRACKER;
|
2003-09-29 22:57:43 +00:00
|
|
|
struct secpolicy *sp;
|
2002-10-16 02:10:08 +00:00
|
|
|
u_int dir;
|
|
|
|
|
|
|
|
/* SPD */
|
|
|
|
for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
|
2003-09-29 22:57:43 +00:00
|
|
|
restart:
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RLOCK();
|
|
|
|
TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sp->lifetime == 0 && sp->validtime == 0)
|
|
|
|
continue;
|
2014-12-24 18:34:56 +00:00
|
|
|
if ((sp->lifetime &&
|
|
|
|
now - sp->created > sp->lifetime) ||
|
|
|
|
(sp->validtime &&
|
|
|
|
now - sp->lastused > sp->validtime)) {
|
|
|
|
SPTREE_RUNLOCK();
|
|
|
|
key_unlink(sp);
|
2002-10-16 02:10:08 +00:00
|
|
|
key_spdexpire(sp);
|
2014-12-24 18:34:56 +00:00
|
|
|
KEY_FREESP(&sp);
|
2003-09-29 22:57:43 +00:00
|
|
|
goto restart;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-24 18:34:56 +00:00
|
|
|
SPTREE_RUNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
static void
|
|
|
|
key_flush_sad(time_t now)
|
|
|
|
{
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secashead *sah, *nextsah;
|
|
|
|
struct secasvar *sav, *nextsav;
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
/* SAD */
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH_SAFE(sah, &V_sahtree, chain, nextsah) {
|
2002-10-16 02:10:08 +00:00
|
|
|
/* if sah has been dead, then delete it and process next sah. */
|
|
|
|
if (sah->state == SADB_SASTATE_DEAD) {
|
|
|
|
key_delsah(sah);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if LARVAL entry doesn't become MATURE, delete it. */
|
2003-09-29 22:57:43 +00:00
|
|
|
LIST_FOREACH_SAFE(sav, &sah->savtree[SADB_SASTATE_LARVAL], chain, nextsav) {
|
2009-03-19 15:44:13 +00:00
|
|
|
/* Need to also check refcnt for a larval SA ??? */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (now - sav->created > V_key_larval_lifetime)
|
2002-10-16 02:10:08 +00:00
|
|
|
KEY_FREESAV(&sav);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check MATURE entry to start to send expire message
|
|
|
|
* whether or not.
|
|
|
|
*/
|
2003-09-29 22:57:43 +00:00
|
|
|
LIST_FOREACH_SAFE(sav, &sah->savtree[SADB_SASTATE_MATURE], chain, nextsav) {
|
2002-10-16 02:10:08 +00:00
|
|
|
/* we don't need to check. */
|
|
|
|
if (sav->lft_s == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* sanity check */
|
|
|
|
if (sav->lft_c == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG,"%s: there is no CURRENT "
|
|
|
|
"time, why?\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check SOFT lifetime */
|
2006-03-25 13:38:52 +00:00
|
|
|
if (sav->lft_s->addtime != 0 &&
|
|
|
|
now - sav->created > sav->lft_s->addtime) {
|
2009-03-05 16:22:32 +00:00
|
|
|
key_sa_chgstate(sav, SADB_SASTATE_DYING);
|
2009-03-19 15:50:45 +00:00
|
|
|
/*
|
2009-03-23 16:20:39 +00:00
|
|
|
* Actually, only send expire message if
|
|
|
|
* SA has been used, as it was done before,
|
|
|
|
* but should we always send such message,
|
|
|
|
* and let IKE daemon decide if it should be
|
|
|
|
* renegotiated or not ?
|
|
|
|
* XXX expire message will actually NOT be
|
|
|
|
* sent if SA is only used after soft
|
|
|
|
* lifetime has been reached, see below
|
|
|
|
* (DYING state)
|
2002-10-16 02:10:08 +00:00
|
|
|
*/
|
2009-03-05 16:22:32 +00:00
|
|
|
if (sav->lft_c->usetime != 0)
|
2002-10-16 02:10:08 +00:00
|
|
|
key_expire(sav);
|
|
|
|
}
|
|
|
|
/* check SOFT lifetime by bytes */
|
|
|
|
/*
|
|
|
|
* XXX I don't know the way to delete this SA
|
|
|
|
* when new SA is installed. Caution when it's
|
|
|
|
* installed too big lifetime by time.
|
|
|
|
*/
|
2006-03-25 13:38:52 +00:00
|
|
|
else if (sav->lft_s->bytes != 0 &&
|
|
|
|
sav->lft_s->bytes < sav->lft_c->bytes) {
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
key_sa_chgstate(sav, SADB_SASTATE_DYING);
|
|
|
|
/*
|
|
|
|
* XXX If we keep to send expire
|
|
|
|
* message in the status of
|
|
|
|
* DYING. Do remove below code.
|
|
|
|
*/
|
|
|
|
key_expire(sav);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check DYING entry to change status to DEAD. */
|
2003-09-29 22:57:43 +00:00
|
|
|
LIST_FOREACH_SAFE(sav, &sah->savtree[SADB_SASTATE_DYING], chain, nextsav) {
|
2002-10-16 02:10:08 +00:00
|
|
|
/* we don't need to check. */
|
|
|
|
if (sav->lft_h == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* sanity check */
|
|
|
|
if (sav->lft_c == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: there is no CURRENT "
|
|
|
|
"time, why?\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-03-25 13:38:52 +00:00
|
|
|
if (sav->lft_h->addtime != 0 &&
|
|
|
|
now - sav->created > sav->lft_h->addtime) {
|
2002-10-16 02:10:08 +00:00
|
|
|
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
|
|
|
|
KEY_FREESAV(&sav);
|
|
|
|
}
|
|
|
|
#if 0 /* XXX Should we keep to send expire message until HARD lifetime ? */
|
|
|
|
else if (sav->lft_s != NULL
|
2006-03-25 13:38:52 +00:00
|
|
|
&& sav->lft_s->addtime != 0
|
|
|
|
&& now - sav->created > sav->lft_s->addtime) {
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* XXX: should be checked to be
|
|
|
|
* installed the valid SA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there is no SA then sending
|
|
|
|
* expire message.
|
|
|
|
*/
|
|
|
|
key_expire(sav);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* check HARD lifetime by bytes */
|
2006-03-25 13:38:52 +00:00
|
|
|
else if (sav->lft_h->bytes != 0 &&
|
|
|
|
sav->lft_h->bytes < sav->lft_c->bytes) {
|
2002-10-16 02:10:08 +00:00
|
|
|
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
|
|
|
|
KEY_FREESAV(&sav);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* delete entry in DEAD */
|
2003-09-29 22:57:43 +00:00
|
|
|
LIST_FOREACH_SAFE(sav, &sah->savtree[SADB_SASTATE_DEAD], chain, nextsav) {
|
2002-10-16 02:10:08 +00:00
|
|
|
/* sanity check */
|
|
|
|
if (sav->state != SADB_SASTATE_DEAD) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid sav->state "
|
|
|
|
"(queue: %d SA: %d): kill it anyway\n",
|
|
|
|
__func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
SADB_SASTATE_DEAD, sav->state));
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* do not call key_freesav() here.
|
|
|
|
* sav should already be freed, and sav->refcnt
|
|
|
|
* shows other references to sav
|
|
|
|
* (such as from SPD).
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
static void
|
|
|
|
key_flush_acq(time_t now)
|
|
|
|
{
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secacq *acq, *nextacq;
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
/* ACQ tree */
|
2003-09-29 22:57:43 +00:00
|
|
|
ACQ_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
for (acq = LIST_FIRST(&V_acqtree); acq != NULL; acq = nextacq) {
|
2002-10-16 02:10:08 +00:00
|
|
|
nextacq = LIST_NEXT(acq, chain);
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (now - acq->created > V_key_blockacq_lifetime
|
2002-10-16 02:10:08 +00:00
|
|
|
&& __LIST_CHAINED(acq)) {
|
|
|
|
LIST_REMOVE(acq, chain);
|
2003-09-01 05:35:55 +00:00
|
|
|
free(acq, M_IPSEC_SAQ);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
ACQ_UNLOCK();
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
static void
|
|
|
|
key_flush_spacq(time_t now)
|
|
|
|
{
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secspacq *acq, *nextacq;
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
/* SP ACQ tree */
|
2003-09-29 22:57:43 +00:00
|
|
|
SPACQ_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
for (acq = LIST_FIRST(&V_spacqtree); acq != NULL; acq = nextacq) {
|
2002-10-16 02:10:08 +00:00
|
|
|
nextacq = LIST_NEXT(acq, chain);
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (now - acq->created > V_key_blockacq_lifetime
|
2002-10-16 02:10:08 +00:00
|
|
|
&& __LIST_CHAINED(acq)) {
|
|
|
|
LIST_REMOVE(acq, chain);
|
2003-09-01 05:35:55 +00:00
|
|
|
free(acq, M_IPSEC_SAQ);
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SPACQ_UNLOCK();
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
/*
|
|
|
|
* time handler.
|
|
|
|
* scanning SPD and SAD to check status for each entries,
|
|
|
|
* and do to remove or to expire.
|
|
|
|
* XXX: year 2038 problem may remain.
|
|
|
|
*/
|
2014-10-23 20:43:16 +00:00
|
|
|
static void
|
|
|
|
key_timehandler(void *arg)
|
2003-09-01 05:35:55 +00:00
|
|
|
{
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
VNET_ITERATOR_DECL(vnet_iter);
|
2003-09-01 05:35:55 +00:00
|
|
|
time_t now = time_second;
|
|
|
|
|
2009-07-19 14:20:53 +00:00
|
|
|
VNET_LIST_RLOCK_NOSLEEP();
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
VNET_FOREACH(vnet_iter) {
|
|
|
|
CURVNET_SET(vnet_iter);
|
|
|
|
key_flush_spd(now);
|
|
|
|
key_flush_sad(now);
|
|
|
|
key_flush_acq(now);
|
|
|
|
key_flush_spacq(now);
|
|
|
|
CURVNET_RESTORE();
|
|
|
|
}
|
2009-07-19 14:20:53 +00:00
|
|
|
VNET_LIST_RUNLOCK_NOSLEEP();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
#ifndef IPSEC_DEBUG2
|
|
|
|
/* do exchange to tick time !! */
|
2014-10-23 20:43:16 +00:00
|
|
|
callout_schedule(&key_timer, hz);
|
2002-10-16 02:10:08 +00:00
|
|
|
#endif /* IPSEC_DEBUG2 */
|
|
|
|
}
|
|
|
|
|
|
|
|
u_long
|
|
|
|
key_random()
|
|
|
|
{
|
|
|
|
u_long value;
|
|
|
|
|
|
|
|
key_randomfill(&value, sizeof(value));
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-12-03 03:50:54 +00:00
|
|
|
key_randomfill(void *p, size_t l)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
size_t n;
|
|
|
|
u_long v;
|
|
|
|
static int warn = 1;
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
n = (size_t)read_random(p, (u_int)l);
|
|
|
|
/* last resort */
|
|
|
|
while (n < l) {
|
|
|
|
v = random();
|
|
|
|
bcopy(&v, (u_int8_t *)p + n,
|
|
|
|
l - n < sizeof(v) ? l - n : sizeof(v));
|
|
|
|
n += sizeof(v);
|
|
|
|
|
|
|
|
if (warn) {
|
|
|
|
printf("WARNING: pseudo-random number generator "
|
|
|
|
"used for IPsec processing\n");
|
|
|
|
warn = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* map SADB_SATYPE_* to IPPROTO_*.
|
|
|
|
* if satype == SADB_SATYPE then satype is mapped to ~0.
|
|
|
|
* OUT:
|
|
|
|
* 0: invalid satype.
|
|
|
|
*/
|
|
|
|
static u_int16_t
|
2009-02-24 18:09:31 +00:00
|
|
|
key_satype2proto(u_int8_t satype)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
switch (satype) {
|
|
|
|
case SADB_SATYPE_UNSPEC:
|
|
|
|
return IPSEC_PROTO_ANY;
|
|
|
|
case SADB_SATYPE_AH:
|
|
|
|
return IPPROTO_AH;
|
|
|
|
case SADB_SATYPE_ESP:
|
|
|
|
return IPPROTO_ESP;
|
|
|
|
case SADB_X_SATYPE_IPCOMP:
|
|
|
|
return IPPROTO_IPCOMP;
|
Initial import of RFC 2385 (TCP-MD5) digest support.
This is the first of two commits; bringing in the kernel support first.
This can be enabled by compiling a kernel with options TCP_SIGNATURE
and FAST_IPSEC.
For the uninitiated, this is a TCP option which provides for a means of
authenticating TCP sessions which came into being before IPSEC. It is
still relevant today, however, as it is used by many commercial router
vendors, particularly with BGP, and as such has become a requirement for
interconnect at many major Internet points of presence.
Several parts of the TCP and IP headers, including the segment payload,
are digested with MD5, including a shared secret. The PF_KEY interface
is used to manage the secrets using security associations in the SADB.
There is a limitation here in that as there is no way to map a TCP flow
per-port back to an SPI without polluting tcpcb or using the SPD; the
code to do the latter is unstable at this time. Therefore this code only
supports per-host keying granularity.
Whilst FAST_IPSEC is mutually exclusive with KAME IPSEC (and thus IPv6),
TCP_SIGNATURE applies only to IPv4. For the vast majority of prospective
users of this feature, this will not pose any problem.
This implementation is output-only; that is, the option is honoured when
responding to a host initiating a TCP session, but no effort is made
[yet] to authenticate inbound traffic. This is, however, sufficient to
interwork with Cisco equipment.
Tested with a Cisco 2501 running IOS 12.0(27), and Quagga 0.96.4 with
local patches. Patches for tcpdump to validate TCP-MD5 sessions are also
available from me upon request.
Sponsored by: sentex.net
2004-02-11 04:26:04 +00:00
|
|
|
case SADB_X_SATYPE_TCPSIGNATURE:
|
|
|
|
return IPPROTO_TCP;
|
2002-10-16 02:10:08 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* map IPPROTO_* to SADB_SATYPE_*
|
|
|
|
* OUT:
|
|
|
|
* 0: invalid protocol type.
|
|
|
|
*/
|
|
|
|
static u_int8_t
|
2009-02-24 18:09:31 +00:00
|
|
|
key_proto2satype(u_int16_t proto)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
switch (proto) {
|
|
|
|
case IPPROTO_AH:
|
|
|
|
return SADB_SATYPE_AH;
|
|
|
|
case IPPROTO_ESP:
|
|
|
|
return SADB_SATYPE_ESP;
|
|
|
|
case IPPROTO_IPCOMP:
|
|
|
|
return SADB_X_SATYPE_IPCOMP;
|
Initial import of RFC 2385 (TCP-MD5) digest support.
This is the first of two commits; bringing in the kernel support first.
This can be enabled by compiling a kernel with options TCP_SIGNATURE
and FAST_IPSEC.
For the uninitiated, this is a TCP option which provides for a means of
authenticating TCP sessions which came into being before IPSEC. It is
still relevant today, however, as it is used by many commercial router
vendors, particularly with BGP, and as such has become a requirement for
interconnect at many major Internet points of presence.
Several parts of the TCP and IP headers, including the segment payload,
are digested with MD5, including a shared secret. The PF_KEY interface
is used to manage the secrets using security associations in the SADB.
There is a limitation here in that as there is no way to map a TCP flow
per-port back to an SPI without polluting tcpcb or using the SPD; the
code to do the latter is unstable at this time. Therefore this code only
supports per-host keying granularity.
Whilst FAST_IPSEC is mutually exclusive with KAME IPSEC (and thus IPv6),
TCP_SIGNATURE applies only to IPv4. For the vast majority of prospective
users of this feature, this will not pose any problem.
This implementation is output-only; that is, the option is honoured when
responding to a host initiating a TCP session, but no effort is made
[yet] to authenticate inbound traffic. This is, however, sufficient to
interwork with Cisco equipment.
Tested with a Cisco 2501 running IOS 12.0(27), and Quagga 0.96.4 with
local patches. Patches for tcpdump to validate TCP-MD5 sessions are also
available from me upon request.
Sponsored by: sentex.net
2004-02-11 04:26:04 +00:00
|
|
|
case IPPROTO_TCP:
|
|
|
|
return SADB_X_SATYPE_TCPSIGNATURE;
|
2002-10-16 02:10:08 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* %%% PF_KEY */
|
|
|
|
/*
|
|
|
|
* SADB_GETSPI processing is to receive
|
|
|
|
* <base, (SA2), src address, dst address, (SPI range)>
|
|
|
|
* from the IKMPd, to assign a unique spi value, to hang on the INBOUND
|
|
|
|
* tree with the status of LARVAL, and send
|
|
|
|
* <base, SA(*), address(SD)>
|
|
|
|
* to the IKMPd.
|
|
|
|
*
|
|
|
|
* IN: mhp: pointer to the pointer to each header.
|
|
|
|
* OUT: NULL if fail.
|
|
|
|
* other if success, return pointer to the message to send.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getspi(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_address *src0, *dst0;
|
|
|
|
struct secasindex saidx;
|
|
|
|
struct secashead *newsah;
|
|
|
|
struct secasvar *newsav;
|
|
|
|
u_int8_t proto;
|
|
|
|
u_int32_t spi;
|
|
|
|
u_int8_t mode;
|
|
|
|
u_int32_t reqid;
|
|
|
|
int error;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
|
|
|
|
mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
|
|
|
|
reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid;
|
|
|
|
} else {
|
|
|
|
mode = IPSEC_MODE_ANY;
|
|
|
|
reqid = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
|
|
|
|
dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
|
|
|
|
|
|
|
|
/* map satype to proto */
|
|
|
|
if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Make sure the port numbers are zero.
|
|
|
|
* In case of NAT-T we will update them later if needed.
|
|
|
|
*/
|
2002-10-16 02:10:08 +00:00
|
|
|
switch (((struct sockaddr *)(src0 + 1))->sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (((struct sockaddr *)(src0 + 1))->sa_len !=
|
|
|
|
sizeof(struct sockaddr_in))
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
((struct sockaddr_in *)(src0 + 1))->sin_port = 0;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (((struct sockaddr *)(src0 + 1))->sa_len !=
|
|
|
|
sizeof(struct sockaddr_in6))
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
((struct sockaddr_in6 *)(src0 + 1))->sin6_port = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
; /*???*/
|
|
|
|
}
|
|
|
|
switch (((struct sockaddr *)(dst0 + 1))->sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (((struct sockaddr *)(dst0 + 1))->sa_len !=
|
|
|
|
sizeof(struct sockaddr_in))
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
((struct sockaddr_in *)(dst0 + 1))->sin_port = 0;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (((struct sockaddr *)(dst0 + 1))->sa_len !=
|
|
|
|
sizeof(struct sockaddr_in6))
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
((struct sockaddr_in6 *)(dst0 + 1))->sin6_port = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
; /*???*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Handle NAT-T info if present.
|
|
|
|
* We made sure the port numbers are zero above, so we do
|
|
|
|
* not have to worry in case we do not update them.
|
|
|
|
*/
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL)
|
|
|
|
ipseclog((LOG_DEBUG, "%s: NAT-T OAi present\n", __func__));
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL)
|
|
|
|
ipseclog((LOG_DEBUG, "%s: NAT-T OAr present\n", __func__));
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) {
|
|
|
|
struct sadb_x_nat_t_type *type;
|
|
|
|
struct sadb_x_nat_t_port *sport, *dport;
|
|
|
|
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid nat-t message "
|
|
|
|
"passed.\n", __func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
sport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT];
|
|
|
|
dport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT];
|
|
|
|
|
|
|
|
if (sport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.src, sport->sadb_x_nat_t_port_port);
|
|
|
|
if (dport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst, dport->sadb_x_nat_t_port_port);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* SPI allocation */
|
|
|
|
spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE],
|
|
|
|
&saidx);
|
|
|
|
if (spi == 0)
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
|
|
|
|
/* get a SA index */
|
|
|
|
if ((newsah = key_getsah(&saidx)) == NULL) {
|
|
|
|
/* create a new SA index */
|
|
|
|
if ((newsah = key_newsah(&saidx)) == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get a new SA */
|
|
|
|
/* XXX rewrite */
|
|
|
|
newsav = KEY_NEWSAV(m, mhp, newsah, &error);
|
|
|
|
if (newsav == NULL) {
|
|
|
|
/* XXX don't free new SA index allocated in above. */
|
|
|
|
return key_senderror(so, m, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set spi */
|
|
|
|
newsav->spi = htonl(spi);
|
|
|
|
|
|
|
|
/* delete the entry in acqtree */
|
|
|
|
if (mhp->msg->sadb_msg_seq != 0) {
|
|
|
|
struct secacq *acq;
|
|
|
|
if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) != NULL) {
|
|
|
|
/* reset counter in order to deletion by timehandler. */
|
|
|
|
acq->created = time_second;
|
|
|
|
acq->count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct mbuf *n, *nn;
|
|
|
|
struct sadb_sa *m_sa;
|
|
|
|
struct sadb_msg *newmsg;
|
|
|
|
int off, len;
|
|
|
|
|
|
|
|
/* create new sadb_msg to reply. */
|
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_msg)) +
|
|
|
|
PFKEY_ALIGN8(sizeof(struct sadb_sa));
|
|
|
|
|
2012-12-05 08:04:20 +00:00
|
|
|
MGETHDR(n, M_NOWAIT, MT_DATA);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (len > MHLEN) {
|
2015-01-06 12:59:37 +00:00
|
|
|
if (!(MCLGET(n, M_NOWAIT))) {
|
2002-10-16 02:10:08 +00:00
|
|
|
m_freem(n);
|
|
|
|
n = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!n)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
|
|
|
|
n->m_len = len;
|
|
|
|
n->m_next = NULL;
|
|
|
|
off = 0;
|
|
|
|
|
|
|
|
m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off);
|
|
|
|
off += PFKEY_ALIGN8(sizeof(struct sadb_msg));
|
|
|
|
|
|
|
|
m_sa = (struct sadb_sa *)(mtod(n, caddr_t) + off);
|
|
|
|
m_sa->sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa));
|
|
|
|
m_sa->sadb_sa_exttype = SADB_EXT_SA;
|
|
|
|
m_sa->sadb_sa_spi = htonl(spi);
|
|
|
|
off += PFKEY_ALIGN8(sizeof(struct sadb_sa));
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(off == len,
|
|
|
|
("length inconsistency (off %u len %u)", off, len));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
n->m_next = key_gather_mbuf(m, mhp, 0, 2, SADB_EXT_ADDRESS_SRC,
|
|
|
|
SADB_EXT_ADDRESS_DST);
|
|
|
|
if (!n->m_next) {
|
|
|
|
m_freem(n);
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
n = m_pullup(n, sizeof(struct sadb_msg));
|
|
|
|
if (n == NULL)
|
|
|
|
return key_sendup_mbuf(so, m, KEY_SENDUP_ONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
n->m_pkthdr.len = 0;
|
|
|
|
for (nn = n; nn; nn = nn->m_next)
|
|
|
|
n->m_pkthdr.len += nn->m_len;
|
|
|
|
|
|
|
|
newmsg = mtod(n, struct sadb_msg *);
|
|
|
|
newmsg->sadb_msg_seq = newsav->seq;
|
|
|
|
newmsg->sadb_msg_errno = 0;
|
|
|
|
newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
|
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* allocating new SPI
|
|
|
|
* called by key_getspi().
|
|
|
|
* OUT:
|
|
|
|
* 0: failure.
|
|
|
|
* others: success.
|
|
|
|
*/
|
|
|
|
static u_int32_t
|
2014-12-03 03:50:54 +00:00
|
|
|
key_do_getnewspi(struct sadb_spirange *spirange, struct secasindex *saidx)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
u_int32_t newspi;
|
|
|
|
u_int32_t min, max;
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
int count = V_key_spi_trycnt;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* set spi range to allocate */
|
|
|
|
if (spirange != NULL) {
|
|
|
|
min = spirange->sadb_spirange_min;
|
|
|
|
max = spirange->sadb_spirange_max;
|
|
|
|
} else {
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
min = V_key_spi_minval;
|
|
|
|
max = V_key_spi_maxval;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
/* IPCOMP needs 2-byte SPI */
|
|
|
|
if (saidx->proto == IPPROTO_IPCOMP) {
|
|
|
|
u_int32_t t;
|
|
|
|
if (min >= 0x10000)
|
|
|
|
min = 0xffff;
|
|
|
|
if (max >= 0x10000)
|
|
|
|
max = 0xffff;
|
|
|
|
if (min > max) {
|
|
|
|
t = min; min = max; max = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (min == max) {
|
|
|
|
if (key_checkspidup(saidx, min) != NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: SPI %u exists already.\n",
|
|
|
|
__func__, min));
|
2002-10-16 02:10:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
count--; /* taking one cost. */
|
|
|
|
newspi = min;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* init SPI */
|
|
|
|
newspi = 0;
|
|
|
|
|
|
|
|
/* when requesting to allocate spi ranged */
|
|
|
|
while (count--) {
|
|
|
|
/* generate pseudo-random SPI value ranged. */
|
|
|
|
newspi = min + (key_random() % (max - min + 1));
|
|
|
|
|
|
|
|
if (key_checkspidup(saidx, newspi) == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count == 0 || newspi == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: to allocate spi is failed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* statistics */
|
|
|
|
keystat.getspi_count =
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
(keystat.getspi_count + V_key_spi_trycnt - count) / 2;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
return newspi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_UPDATE processing
|
|
|
|
* receive
|
|
|
|
* <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),)
|
|
|
|
* key(AE), (identity(SD),) (sensitivity)>
|
|
|
|
* from the ikmpd, and update a secasvar entry whose status is SADB_SASTATE_LARVAL.
|
|
|
|
* and send
|
|
|
|
* <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),)
|
|
|
|
* (identity(SD),) (sensitivity)>
|
|
|
|
* to the ikmpd.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_update(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_sa *sa0;
|
|
|
|
struct sadb_address *src0, *dst0;
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
struct sadb_x_nat_t_type *type;
|
2009-06-19 21:01:55 +00:00
|
|
|
struct sadb_x_nat_t_port *sport, *dport;
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
struct sadb_address *iaddr, *raddr;
|
|
|
|
struct sadb_x_nat_t_frag *frag;
|
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secasindex saidx;
|
|
|
|
struct secashead *sah;
|
|
|
|
struct secasvar *sav;
|
|
|
|
u_int16_t proto;
|
|
|
|
u_int8_t mode;
|
|
|
|
u_int32_t reqid;
|
|
|
|
int error;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* map satype to proto */
|
|
|
|
if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_SA] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
|
|
|
|
(mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP &&
|
|
|
|
mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) ||
|
|
|
|
(mhp->msg->sadb_msg_satype == SADB_SATYPE_AH &&
|
|
|
|
mhp->ext[SADB_EXT_KEY_AUTH] == NULL) ||
|
|
|
|
(mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL &&
|
|
|
|
mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) ||
|
|
|
|
(mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL &&
|
|
|
|
mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
|
|
|
|
mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
|
|
|
|
reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid;
|
|
|
|
} else {
|
|
|
|
mode = IPSEC_MODE_ANY;
|
|
|
|
reqid = 0;
|
|
|
|
}
|
|
|
|
/* XXX boundary checking for other extensions */
|
|
|
|
|
|
|
|
sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA];
|
|
|
|
src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
|
|
|
|
dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
|
|
|
|
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Make sure the port numbers are zero.
|
|
|
|
* In case of NAT-T we will update them later if needed.
|
|
|
|
*/
|
|
|
|
KEY_PORTTOSADDR(&saidx.src, 0);
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst, 0);
|
|
|
|
|
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Handle NAT-T info if present.
|
|
|
|
*/
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) {
|
|
|
|
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message.\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
type = (struct sadb_x_nat_t_type *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_TYPE];
|
|
|
|
sport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT];
|
|
|
|
dport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT];
|
|
|
|
} else {
|
|
|
|
type = 0;
|
2009-06-19 21:01:55 +00:00
|
|
|
sport = dport = 0;
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
}
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) {
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
iaddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAI];
|
|
|
|
raddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAR];
|
|
|
|
ipseclog((LOG_DEBUG, "%s: NAT-T OAi/r present\n", __func__));
|
|
|
|
} else {
|
|
|
|
iaddr = raddr = NULL;
|
|
|
|
}
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_FRAG] != NULL) {
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_FRAG] < sizeof(*frag)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
frag = (struct sadb_x_nat_t_frag *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_FRAG];
|
|
|
|
} else {
|
|
|
|
frag = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* get a SA header */
|
|
|
|
if ((sah = key_getsah(&saidx)) == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: no SA index found.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set spidx if there */
|
|
|
|
/* XXX rewrite */
|
|
|
|
error = key_setident(sah, m, mhp);
|
|
|
|
if (error)
|
|
|
|
return key_senderror(so, m, error);
|
|
|
|
|
|
|
|
/* find a SA with sequence number. */
|
|
|
|
#ifdef IPSEC_DOSEQCHECK
|
|
|
|
if (mhp->msg->sadb_msg_seq != 0
|
|
|
|
&& (sav = key_getsavbyseq(sah, mhp->msg->sadb_msg_seq)) == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: no larval SA with sequence %u "
|
|
|
|
"exists.\n", __func__, mhp->msg->sadb_msg_seq));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOENT);
|
|
|
|
}
|
|
|
|
#else
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
|
|
|
sav = key_getsavbyspi(sah, sa0->sadb_sa_spi);
|
|
|
|
SAHTREE_UNLOCK();
|
|
|
|
if (sav == NULL) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: no such a SA found (spi:%u)\n",
|
|
|
|
__func__, (u_int32_t)ntohl(sa0->sadb_sa_spi)));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* validity check */
|
|
|
|
if (sav->sah->saidx.proto != proto) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: protocol mismatched "
|
|
|
|
"(DB=%u param=%u)\n", __func__,
|
|
|
|
sav->sah->saidx.proto, proto));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
#ifdef IPSEC_DOSEQCHECK
|
|
|
|
if (sav->spi != sa0->sadb_sa_spi) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: SPI mismatched (DB:%u param:%u)\n",
|
|
|
|
__func__,
|
2002-10-16 02:10:08 +00:00
|
|
|
(u_int32_t)ntohl(sav->spi),
|
|
|
|
(u_int32_t)ntohl(sa0->sadb_sa_spi)));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (sav->pid != mhp->msg->sadb_msg_pid) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: pid mismatched (DB:%u param:%u)\n",
|
|
|
|
__func__, sav->pid, mhp->msg->sadb_msg_pid));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy sav values */
|
|
|
|
error = key_setsaval(sav, m, mhp);
|
|
|
|
if (error) {
|
|
|
|
KEY_FREESAV(&sav);
|
|
|
|
return key_senderror(so, m, error);
|
|
|
|
}
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Handle more NAT-T info if present,
|
|
|
|
* now that we have a sav to fill.
|
|
|
|
*/
|
|
|
|
if (type)
|
|
|
|
sav->natt_type = type->sadb_x_nat_t_type_type;
|
|
|
|
|
2009-06-19 21:01:55 +00:00
|
|
|
if (sport)
|
|
|
|
KEY_PORTTOSADDR(&sav->sah->saidx.src,
|
|
|
|
sport->sadb_x_nat_t_port_port);
|
|
|
|
if (dport)
|
|
|
|
KEY_PORTTOSADDR(&sav->sah->saidx.dst,
|
|
|
|
dport->sadb_x_nat_t_port_port);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* In case SADB_X_EXT_NAT_T_FRAG was not given, leave it at 0.
|
|
|
|
* We should actually check for a minimum MTU here, if we
|
|
|
|
* want to support it in ip_output.
|
|
|
|
*/
|
|
|
|
if (frag)
|
|
|
|
sav->natt_esp_frag_len = frag->sadb_x_nat_t_frag_fraglen;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2010-05-05 08:55:26 +00:00
|
|
|
/* check SA values to be mature. */
|
|
|
|
if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) {
|
|
|
|
KEY_FREESAV(&sav);
|
|
|
|
return key_senderror(so, m, 0);
|
|
|
|
}
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *n;
|
|
|
|
|
|
|
|
/* set msg buf from mhp */
|
|
|
|
n = key_getmsgbuf_x1(m, mhp);
|
|
|
|
if (n == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* search SAD with sequence for a SA which state is SADB_SASTATE_LARVAL.
|
|
|
|
* only called by key_update().
|
|
|
|
* OUT:
|
|
|
|
* NULL : not found
|
|
|
|
* others : found, pointer to a SA.
|
|
|
|
*/
|
|
|
|
#ifdef IPSEC_DOSEQCHECK
|
|
|
|
static struct secasvar *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getsavbyseq(struct secashead *sah, u_int32_t seq)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secasvar *sav;
|
|
|
|
u_int state;
|
|
|
|
|
|
|
|
state = SADB_SASTATE_LARVAL;
|
|
|
|
|
|
|
|
/* search SAD with sequence number ? */
|
|
|
|
LIST_FOREACH(sav, &sah->savtree[state], chain) {
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
KEY_CHKSASTATE(state, sav->state, __func__);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if (sav->seq == seq) {
|
2006-05-20 15:35:36 +00:00
|
|
|
sa_addref(sav);
|
2002-10-16 02:10:08 +00:00
|
|
|
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
printf("DP %s cause refcnt++:%d SA:%p\n",
|
|
|
|
__func__, sav->refcnt, sav));
|
2002-10-16 02:10:08 +00:00
|
|
|
return sav;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_ADD processing
|
2003-01-01 18:49:04 +00:00
|
|
|
* add an entry to SA database, when received
|
2002-10-16 02:10:08 +00:00
|
|
|
* <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),)
|
|
|
|
* key(AE), (identity(SD),) (sensitivity)>
|
|
|
|
* from the ikmpd,
|
|
|
|
* and send
|
|
|
|
* <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),)
|
|
|
|
* (identity(SD),) (sensitivity)>
|
|
|
|
* to the ikmpd.
|
|
|
|
*
|
|
|
|
* IGNORE identity and sensitivity messages.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_add(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_sa *sa0;
|
|
|
|
struct sadb_address *src0, *dst0;
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
struct sadb_x_nat_t_type *type;
|
|
|
|
struct sadb_address *iaddr, *raddr;
|
|
|
|
struct sadb_x_nat_t_frag *frag;
|
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
struct secasindex saidx;
|
|
|
|
struct secashead *newsah;
|
|
|
|
struct secasvar *newsav;
|
|
|
|
u_int16_t proto;
|
|
|
|
u_int8_t mode;
|
|
|
|
u_int32_t reqid;
|
|
|
|
int error;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* map satype to proto */
|
|
|
|
if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_SA] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
|
|
|
|
(mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP &&
|
|
|
|
mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) ||
|
|
|
|
(mhp->msg->sadb_msg_satype == SADB_SATYPE_AH &&
|
|
|
|
mhp->ext[SADB_EXT_KEY_AUTH] == NULL) ||
|
|
|
|
(mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL &&
|
|
|
|
mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) ||
|
|
|
|
(mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL &&
|
|
|
|
mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
|
|
|
|
/* XXX need more */
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
|
|
|
|
mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
|
|
|
|
reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid;
|
|
|
|
} else {
|
|
|
|
mode = IPSEC_MODE_ANY;
|
|
|
|
reqid = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA];
|
|
|
|
src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
|
|
|
|
dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
|
|
|
|
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Make sure the port numbers are zero.
|
|
|
|
* In case of NAT-T we will update them later if needed.
|
|
|
|
*/
|
|
|
|
KEY_PORTTOSADDR(&saidx.src, 0);
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst, 0);
|
|
|
|
|
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Handle NAT-T info if present.
|
|
|
|
*/
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) {
|
|
|
|
struct sadb_x_nat_t_port *sport, *dport;
|
|
|
|
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message.\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
type = (struct sadb_x_nat_t_type *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_TYPE];
|
|
|
|
sport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT];
|
|
|
|
dport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT];
|
|
|
|
|
|
|
|
if (sport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.src,
|
|
|
|
sport->sadb_x_nat_t_port_port);
|
|
|
|
if (dport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst,
|
|
|
|
dport->sadb_x_nat_t_port_port);
|
|
|
|
} else {
|
|
|
|
type = 0;
|
|
|
|
}
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) {
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
iaddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAI];
|
|
|
|
raddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAR];
|
|
|
|
ipseclog((LOG_DEBUG, "%s: NAT-T OAi/r present\n", __func__));
|
|
|
|
} else {
|
|
|
|
iaddr = raddr = NULL;
|
|
|
|
}
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_FRAG] != NULL) {
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_FRAG] < sizeof(*frag)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
frag = (struct sadb_x_nat_t_frag *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_FRAG];
|
|
|
|
} else {
|
|
|
|
frag = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* get a SA header */
|
|
|
|
if ((newsah = key_getsah(&saidx)) == NULL) {
|
|
|
|
/* create a new SA header */
|
|
|
|
if ((newsah = key_newsah(&saidx)) == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set spidx if there */
|
|
|
|
/* XXX rewrite */
|
|
|
|
error = key_setident(newsah, m, mhp);
|
|
|
|
if (error) {
|
|
|
|
return key_senderror(so, m, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create new SA entry. */
|
|
|
|
/* We can create new SA only if SPI is differenct. */
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
|
|
|
newsav = key_getsavbyspi(newsah, sa0->sadb_sa_spi);
|
|
|
|
SAHTREE_UNLOCK();
|
|
|
|
if (newsav != NULL) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: SA already exists.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EEXIST);
|
|
|
|
}
|
|
|
|
newsav = KEY_NEWSAV(m, mhp, newsah, &error);
|
|
|
|
if (newsav == NULL) {
|
|
|
|
return key_senderror(so, m, error);
|
|
|
|
}
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Handle more NAT-T info if present,
|
|
|
|
* now that we have a sav to fill.
|
|
|
|
*/
|
|
|
|
if (type)
|
|
|
|
newsav->natt_type = type->sadb_x_nat_t_type_type;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* In case SADB_X_EXT_NAT_T_FRAG was not given, leave it at 0.
|
|
|
|
* We should actually check for a minimum MTU here, if we
|
|
|
|
* want to support it in ip_output.
|
|
|
|
*/
|
|
|
|
if (frag)
|
|
|
|
newsav->natt_esp_frag_len = frag->sadb_x_nat_t_frag_fraglen;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2010-05-05 08:58:58 +00:00
|
|
|
/* check SA values to be mature. */
|
|
|
|
if ((error = key_mature(newsav)) != 0) {
|
|
|
|
KEY_FREESAV(&newsav);
|
|
|
|
return key_senderror(so, m, error);
|
|
|
|
}
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/*
|
|
|
|
* don't call key_freesav() here, as we would like to keep the SA
|
|
|
|
* in the database on success.
|
|
|
|
*/
|
|
|
|
|
|
|
|
{
|
|
|
|
struct mbuf *n;
|
|
|
|
|
|
|
|
/* set msg buf from mhp */
|
|
|
|
n = key_getmsgbuf_x1(m, mhp);
|
|
|
|
if (n == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* m is retained */
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_setident(struct secashead *sah, struct mbuf *m,
|
|
|
|
const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
const struct sadb_ident *idsrc, *iddst;
|
|
|
|
int idsrclen, iddstlen;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sah != NULL, ("null secashead"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* don't make buffer if not there */
|
|
|
|
if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL &&
|
|
|
|
mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) {
|
|
|
|
sah->idents = NULL;
|
|
|
|
sah->identd = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid identity.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
idsrc = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_SRC];
|
|
|
|
iddst = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_DST];
|
|
|
|
idsrclen = mhp->extlen[SADB_EXT_IDENTITY_SRC];
|
|
|
|
iddstlen = mhp->extlen[SADB_EXT_IDENTITY_DST];
|
|
|
|
|
|
|
|
/* validity check */
|
|
|
|
if (idsrc->sadb_ident_type != iddst->sadb_ident_type) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: ident type mismatch.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (idsrc->sadb_ident_type) {
|
|
|
|
case SADB_IDENTTYPE_PREFIX:
|
|
|
|
case SADB_IDENTTYPE_FQDN:
|
|
|
|
case SADB_IDENTTYPE_USERFQDN:
|
|
|
|
default:
|
|
|
|
/* XXX do nothing */
|
|
|
|
sah->idents = NULL;
|
|
|
|
sah->identd = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make structure */
|
2006-03-25 13:38:52 +00:00
|
|
|
sah->idents = malloc(sizeof(struct secident), M_IPSEC_MISC, M_NOWAIT);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah->idents == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return ENOBUFS;
|
|
|
|
}
|
2006-03-25 13:38:52 +00:00
|
|
|
sah->identd = malloc(sizeof(struct secident), M_IPSEC_MISC, M_NOWAIT);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah->identd == NULL) {
|
2003-09-01 05:35:55 +00:00
|
|
|
free(sah->idents, M_IPSEC_MISC);
|
2002-10-16 02:10:08 +00:00
|
|
|
sah->idents = NULL;
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return ENOBUFS;
|
|
|
|
}
|
2006-03-25 13:38:52 +00:00
|
|
|
sah->idents->type = idsrc->sadb_ident_type;
|
|
|
|
sah->idents->id = idsrc->sadb_ident_id;
|
|
|
|
|
|
|
|
sah->identd->type = iddst->sadb_ident_type;
|
|
|
|
sah->identd->id = iddst->sadb_ident_id;
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* m will not be freed on return.
|
|
|
|
* it is caller's responsibility to free the result.
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getmsgbuf_x1(struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *n;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* create new sadb_msg to reply. */
|
|
|
|
n = key_gather_mbuf(m, mhp, 1, 9, SADB_EXT_RESERVED,
|
|
|
|
SADB_EXT_SA, SADB_X_EXT_SA2,
|
|
|
|
SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST,
|
|
|
|
SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT,
|
|
|
|
SADB_EXT_IDENTITY_SRC, SADB_EXT_IDENTITY_DST);
|
|
|
|
if (!n)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (n->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
n = m_pullup(n, sizeof(struct sadb_msg));
|
|
|
|
if (n == NULL)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
mtod(n, struct sadb_msg *)->sadb_msg_errno = 0;
|
|
|
|
mtod(n, struct sadb_msg *)->sadb_msg_len =
|
|
|
|
PFKEY_UNIT64(n->m_pkthdr.len);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_DELETE processing
|
|
|
|
* receive
|
|
|
|
* <base, SA(*), address(SD)>
|
|
|
|
* from the ikmpd, and set SADB_SASTATE_DEAD,
|
|
|
|
* and send,
|
|
|
|
* <base, SA(*), address(SD)>
|
|
|
|
* to the ikmpd.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_delete(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_sa *sa0;
|
|
|
|
struct sadb_address *src0, *dst0;
|
|
|
|
struct secasindex saidx;
|
|
|
|
struct secashead *sah;
|
|
|
|
struct secasvar *sav = NULL;
|
|
|
|
u_int16_t proto;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* map satype to proto */
|
|
|
|
if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_SA] == NULL) {
|
|
|
|
/*
|
|
|
|
* Caller wants us to delete all non-LARVAL SAs
|
|
|
|
* that match the src/dst. This is used during
|
|
|
|
* IKE INITIAL-CONTACT.
|
|
|
|
*/
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: doing delete all.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_delete_all(so, m, mhp, proto);
|
|
|
|
} else if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA];
|
|
|
|
src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
|
|
|
|
dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
|
|
|
|
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Make sure the port numbers are zero.
|
|
|
|
* In case of NAT-T we will update them later if needed.
|
|
|
|
*/
|
|
|
|
KEY_PORTTOSADDR(&saidx.src, 0);
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst, 0);
|
|
|
|
|
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Handle NAT-T info if present.
|
|
|
|
*/
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) {
|
|
|
|
struct sadb_x_nat_t_port *sport, *dport;
|
|
|
|
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message.\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
sport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT];
|
|
|
|
dport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT];
|
|
|
|
|
|
|
|
if (sport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.src,
|
|
|
|
sport->sadb_x_nat_t_port_port);
|
|
|
|
if (dport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst,
|
|
|
|
dport->sadb_x_nat_t_port_port);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* get a SA header */
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah->state == SADB_SASTATE_DEAD)
|
|
|
|
continue;
|
|
|
|
if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* get a SA with SPI. */
|
|
|
|
sav = key_getsavbyspi(sah, sa0->sadb_sa_spi);
|
|
|
|
if (sav)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (sah == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
|
|
|
ipseclog((LOG_DEBUG, "%s: no SA found.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
|
|
|
|
KEY_FREESAV(&sav);
|
2009-11-17 16:00:41 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
struct mbuf *n;
|
|
|
|
struct sadb_msg *newmsg;
|
|
|
|
|
|
|
|
/* create new sadb_msg to reply. */
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/* XXX-BZ NAT-T extensions? */
|
2002-10-16 02:10:08 +00:00
|
|
|
n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED,
|
|
|
|
SADB_EXT_SA, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
|
|
|
|
if (!n)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
|
|
|
|
if (n->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
n = m_pullup(n, sizeof(struct sadb_msg));
|
|
|
|
if (n == NULL)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
newmsg = mtod(n, struct sadb_msg *);
|
|
|
|
newmsg->sadb_msg_errno = 0;
|
|
|
|
newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
|
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* delete all SAs for src/dst. Called from key_delete().
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_delete_all(struct socket *so, struct mbuf *m,
|
|
|
|
const struct sadb_msghdr *mhp, u_int16_t proto)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_address *src0, *dst0;
|
|
|
|
struct secasindex saidx;
|
|
|
|
struct secashead *sah;
|
|
|
|
struct secasvar *sav, *nextsav;
|
|
|
|
u_int stateidx, state;
|
|
|
|
|
|
|
|
src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
|
|
|
|
dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
|
|
|
|
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Make sure the port numbers are zero.
|
|
|
|
* In case of NAT-T we will update them later if needed.
|
|
|
|
*/
|
|
|
|
KEY_PORTTOSADDR(&saidx.src, 0);
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst, 0);
|
|
|
|
|
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Handle NAT-T info if present.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) {
|
|
|
|
struct sadb_x_nat_t_port *sport, *dport;
|
|
|
|
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message.\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
sport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT];
|
|
|
|
dport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT];
|
|
|
|
|
|
|
|
if (sport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.src,
|
|
|
|
sport->sadb_x_nat_t_port_port);
|
|
|
|
if (dport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst,
|
|
|
|
dport->sadb_x_nat_t_port_port);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah->state == SADB_SASTATE_DEAD)
|
|
|
|
continue;
|
|
|
|
if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Delete all non-LARVAL SAs. */
|
|
|
|
for (stateidx = 0;
|
2008-11-26 22:32:07 +00:00
|
|
|
stateidx < _ARRAYLEN(saorder_state_alive);
|
2002-10-16 02:10:08 +00:00
|
|
|
stateidx++) {
|
2008-11-26 22:32:07 +00:00
|
|
|
state = saorder_state_alive[stateidx];
|
2002-10-16 02:10:08 +00:00
|
|
|
if (state == SADB_SASTATE_LARVAL)
|
|
|
|
continue;
|
|
|
|
for (sav = LIST_FIRST(&sah->savtree[state]);
|
|
|
|
sav != NULL; sav = nextsav) {
|
|
|
|
nextsav = LIST_NEXT(sav, chain);
|
|
|
|
/* sanity check */
|
|
|
|
if (sav->state != state) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid "
|
|
|
|
"sav->state (queue %d SA %d)\n",
|
|
|
|
__func__, state, sav->state));
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
|
|
|
|
KEY_FREESAV(&sav);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *n;
|
|
|
|
struct sadb_msg *newmsg;
|
|
|
|
|
|
|
|
/* create new sadb_msg to reply. */
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/* XXX-BZ NAT-T extensions? */
|
2002-10-16 02:10:08 +00:00
|
|
|
n = key_gather_mbuf(m, mhp, 1, 3, SADB_EXT_RESERVED,
|
|
|
|
SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
|
|
|
|
if (!n)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
|
|
|
|
if (n->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
n = m_pullup(n, sizeof(struct sadb_msg));
|
|
|
|
if (n == NULL)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
newmsg = mtod(n, struct sadb_msg *);
|
|
|
|
newmsg->sadb_msg_errno = 0;
|
|
|
|
newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
|
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_GET processing
|
|
|
|
* receive
|
|
|
|
* <base, SA(*), address(SD)>
|
|
|
|
* from the ikmpd, and get a SP and a SA to respond,
|
|
|
|
* and send,
|
|
|
|
* <base, SA, (lifetime(HSC),) address(SD), (address(P),) key(AE),
|
|
|
|
* (identity(SD),) (sensitivity)>
|
|
|
|
* to the ikmpd.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_get(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_sa *sa0;
|
|
|
|
struct sadb_address *src0, *dst0;
|
|
|
|
struct secasindex saidx;
|
|
|
|
struct secashead *sah;
|
|
|
|
struct secasvar *sav = NULL;
|
|
|
|
u_int16_t proto;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* map satype to proto */
|
|
|
|
if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_SA] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA];
|
|
|
|
src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
|
|
|
|
dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
|
|
|
|
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Make sure the port numbers are zero.
|
|
|
|
* In case of NAT-T we will update them later if needed.
|
|
|
|
*/
|
|
|
|
KEY_PORTTOSADDR(&saidx.src, 0);
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst, 0);
|
|
|
|
|
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Handle NAT-T info if present.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) {
|
|
|
|
struct sadb_x_nat_t_port *sport, *dport;
|
|
|
|
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message.\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
sport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT];
|
|
|
|
dport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT];
|
|
|
|
|
|
|
|
if (sport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.src,
|
|
|
|
sport->sadb_x_nat_t_port_port);
|
|
|
|
if (dport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst,
|
|
|
|
dport->sadb_x_nat_t_port_port);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* get a SA header */
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah->state == SADB_SASTATE_DEAD)
|
|
|
|
continue;
|
|
|
|
if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* get a SA with SPI. */
|
|
|
|
sav = key_getsavbyspi(sah, sa0->sadb_sa_spi);
|
|
|
|
if (sav)
|
|
|
|
break;
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: no SA found.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct mbuf *n;
|
|
|
|
u_int8_t satype;
|
|
|
|
|
|
|
|
/* map proto to satype */
|
|
|
|
if ((satype = key_proto2satype(sah->saidx.proto)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: there was invalid proto in SAD.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create new sadb_msg to reply. */
|
|
|
|
n = key_setdumpsa(sav, SADB_GET, satype, mhp->msg->sadb_msg_seq,
|
|
|
|
mhp->msg->sadb_msg_pid);
|
|
|
|
if (!n)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX make it sysctl-configurable? */
|
|
|
|
static void
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getcomb_setlifetime(struct sadb_comb *comb)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
comb->sadb_comb_soft_allocations = 1;
|
|
|
|
comb->sadb_comb_hard_allocations = 1;
|
|
|
|
comb->sadb_comb_soft_bytes = 0;
|
|
|
|
comb->sadb_comb_hard_bytes = 0;
|
|
|
|
comb->sadb_comb_hard_addtime = 86400; /* 1 day */
|
|
|
|
comb->sadb_comb_soft_addtime = comb->sadb_comb_soft_addtime * 80 / 100;
|
|
|
|
comb->sadb_comb_soft_usetime = 28800; /* 8 hours */
|
|
|
|
comb->sadb_comb_hard_usetime = comb->sadb_comb_hard_usetime * 80 / 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX reorder combinations by preference
|
|
|
|
* XXX no idea if the user wants ESP authentication or not
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
|
|
|
key_getcomb_esp()
|
|
|
|
{
|
|
|
|
struct sadb_comb *comb;
|
|
|
|
struct enc_xform *algo;
|
|
|
|
struct mbuf *result = NULL, *m, *n;
|
|
|
|
int encmin;
|
|
|
|
int i, off, o;
|
|
|
|
int totlen;
|
|
|
|
const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb));
|
|
|
|
|
|
|
|
m = NULL;
|
|
|
|
for (i = 1; i <= SADB_EALG_MAX; i++) {
|
|
|
|
algo = esp_algorithm_lookup(i);
|
|
|
|
if (algo == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* discard algorithms with key size smaller than system min */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (_BITS(algo->maxkey) < V_ipsec_esp_keymin)
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (_BITS(algo->minkey) < V_ipsec_esp_keymin)
|
|
|
|
encmin = V_ipsec_esp_keymin;
|
2002-10-16 02:10:08 +00:00
|
|
|
else
|
|
|
|
encmin = _BITS(algo->minkey);
|
|
|
|
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_ipsec_esp_auth)
|
2002-10-16 02:10:08 +00:00
|
|
|
m = key_getcomb_ah();
|
|
|
|
else {
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(l <= MLEN,
|
|
|
|
("l=%u > MLEN=%lu", l, (u_long) MLEN));
|
2012-12-05 08:04:20 +00:00
|
|
|
MGET(m, M_NOWAIT, MT_DATA);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (m) {
|
|
|
|
M_ALIGN(m, l);
|
|
|
|
m->m_len = l;
|
|
|
|
m->m_next = NULL;
|
|
|
|
bzero(mtod(m, caddr_t), m->m_len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!m)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
totlen = 0;
|
|
|
|
for (n = m; n; n = n->m_next)
|
|
|
|
totlen += n->m_len;
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT((totlen % l) == 0, ("totlen=%u, l=%u", totlen, l));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
for (off = 0; off < totlen; off += l) {
|
|
|
|
n = m_pulldown(m, off, l, &o);
|
|
|
|
if (!n) {
|
|
|
|
/* m is already freed */
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
comb = (struct sadb_comb *)(mtod(n, caddr_t) + o);
|
|
|
|
bzero(comb, sizeof(*comb));
|
|
|
|
key_getcomb_setlifetime(comb);
|
|
|
|
comb->sadb_comb_encrypt = i;
|
|
|
|
comb->sadb_comb_encrypt_minbits = encmin;
|
|
|
|
comb->sadb_comb_encrypt_maxbits = _BITS(algo->maxkey);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
result = m;
|
|
|
|
else
|
|
|
|
m_cat(result, m);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
if (result)
|
|
|
|
m_freem(result);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getsizes_ah(const struct auth_hash *ah, int alg, u_int16_t* min,
|
|
|
|
u_int16_t* max)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
Step 1.5 of importing the network stack virtualization infrastructure
from the vimage project, as per plan established at devsummit 08/08:
http://wiki.freebsd.org/Image/Notes200808DevSummit
Introduce INIT_VNET_*() initializer macros, VNET_FOREACH() iterator
macros, and CURVNET_SET() context setting macros, all currently
resolving to NOPs.
Prepare for virtualization of selected SYSCTL objects by introducing a
family of SYSCTL_V_*() macros, currently resolving to their global
counterparts, i.e. SYSCTL_V_INT() == SYSCTL_INT().
Move selected #defines from sys/sys/vimage.h to newly introduced header
files specific to virtualized subsystems (sys/net/vnet.h,
sys/netinet/vinet.h etc.).
All the changes are verified to have zero functional impact at this
point in time by doing MD5 comparision between pre- and post-change
object files(*).
(*) netipsec/keysock.c did not validate depending on compile time options.
Implemented by: julian, bz, brooks, zec
Reviewed by: julian, bz, brooks, kris, rwatson, ...
Approved by: julian (mentor)
Obtained from: //depot/projects/vimage-commit2/...
X-MFC after: never
Sponsored by: NLnet Foundation, The FreeBSD Foundation
2008-10-02 15:37:58 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
*min = *max = ah->keysize;
|
|
|
|
if (ah->keysize == 0) {
|
|
|
|
/*
|
|
|
|
* Transform takes arbitrary key size but algorithm
|
|
|
|
* key size is restricted. Enforce this here.
|
|
|
|
*/
|
|
|
|
switch (alg) {
|
|
|
|
case SADB_X_AALG_MD5: *min = *max = 16; break;
|
|
|
|
case SADB_X_AALG_SHA: *min = *max = 20; break;
|
|
|
|
case SADB_X_AALG_NULL: *min = 1; *max = 256; break;
|
2011-02-18 09:40:13 +00:00
|
|
|
case SADB_X_AALG_SHA2_256: *min = *max = 32; break;
|
|
|
|
case SADB_X_AALG_SHA2_384: *min = *max = 48; break;
|
|
|
|
case SADB_X_AALG_SHA2_512: *min = *max = 64; break;
|
2002-10-16 02:10:08 +00:00
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
DPRINTF(("%s: unknown AH algorithm %u\n",
|
|
|
|
__func__, alg));
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX reorder combinations by preference
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
|
|
|
key_getcomb_ah()
|
|
|
|
{
|
|
|
|
struct sadb_comb *comb;
|
|
|
|
struct auth_hash *algo;
|
|
|
|
struct mbuf *m;
|
|
|
|
u_int16_t minkeysize, maxkeysize;
|
|
|
|
int i;
|
|
|
|
const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb));
|
|
|
|
|
|
|
|
m = NULL;
|
|
|
|
for (i = 1; i <= SADB_AALG_MAX; i++) {
|
|
|
|
#if 1
|
|
|
|
/* we prefer HMAC algorithms, not old algorithms */
|
2011-02-18 09:40:13 +00:00
|
|
|
if (i != SADB_AALG_SHA1HMAC &&
|
|
|
|
i != SADB_AALG_MD5HMAC &&
|
|
|
|
i != SADB_X_AALG_SHA2_256 &&
|
|
|
|
i != SADB_X_AALG_SHA2_384 &&
|
|
|
|
i != SADB_X_AALG_SHA2_512)
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
algo = ah_algorithm_lookup(i);
|
|
|
|
if (!algo)
|
|
|
|
continue;
|
|
|
|
key_getsizes_ah(algo, i, &minkeysize, &maxkeysize);
|
|
|
|
/* discard algorithms with key size smaller than system min */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (_BITS(minkeysize) < V_ipsec_ah_keymin)
|
2002-10-16 02:10:08 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!m) {
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(l <= MLEN,
|
|
|
|
("l=%u > MLEN=%lu", l, (u_long) MLEN));
|
2012-12-05 08:04:20 +00:00
|
|
|
MGET(m, M_NOWAIT, MT_DATA);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (m) {
|
|
|
|
M_ALIGN(m, l);
|
|
|
|
m->m_len = l;
|
|
|
|
m->m_next = NULL;
|
|
|
|
}
|
|
|
|
} else
|
2012-12-05 08:04:20 +00:00
|
|
|
M_PREPEND(m, l, M_NOWAIT);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (!m)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
comb = mtod(m, struct sadb_comb *);
|
|
|
|
bzero(comb, sizeof(*comb));
|
|
|
|
key_getcomb_setlifetime(comb);
|
|
|
|
comb->sadb_comb_auth = i;
|
|
|
|
comb->sadb_comb_auth_minbits = _BITS(minkeysize);
|
|
|
|
comb->sadb_comb_auth_maxbits = _BITS(maxkeysize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* not really an official behavior. discussed in pf_key@inner.net in Sep2000.
|
|
|
|
* XXX reorder combinations by preference
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
|
|
|
key_getcomb_ipcomp()
|
|
|
|
{
|
|
|
|
struct sadb_comb *comb;
|
|
|
|
struct comp_algo *algo;
|
|
|
|
struct mbuf *m;
|
|
|
|
int i;
|
|
|
|
const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb));
|
|
|
|
|
|
|
|
m = NULL;
|
|
|
|
for (i = 1; i <= SADB_X_CALG_MAX; i++) {
|
|
|
|
algo = ipcomp_algorithm_lookup(i);
|
|
|
|
if (!algo)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!m) {
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(l <= MLEN,
|
|
|
|
("l=%u > MLEN=%lu", l, (u_long) MLEN));
|
2012-12-05 08:04:20 +00:00
|
|
|
MGET(m, M_NOWAIT, MT_DATA);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (m) {
|
|
|
|
M_ALIGN(m, l);
|
|
|
|
m->m_len = l;
|
|
|
|
m->m_next = NULL;
|
|
|
|
}
|
|
|
|
} else
|
2012-12-05 08:04:20 +00:00
|
|
|
M_PREPEND(m, l, M_NOWAIT);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (!m)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
comb = mtod(m, struct sadb_comb *);
|
|
|
|
bzero(comb, sizeof(*comb));
|
|
|
|
key_getcomb_setlifetime(comb);
|
|
|
|
comb->sadb_comb_encrypt = i;
|
|
|
|
/* what should we set into sadb_comb_*_{min,max}bits? */
|
|
|
|
}
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX no way to pass mode (transport/tunnel) to userland
|
|
|
|
* XXX replay checking?
|
|
|
|
* XXX sysctl interface to ipsec_{ah,esp}_keymin
|
|
|
|
*/
|
|
|
|
static struct mbuf *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getprop(const struct secasindex *saidx)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_prop *prop;
|
|
|
|
struct mbuf *m, *n;
|
|
|
|
const int l = PFKEY_ALIGN8(sizeof(struct sadb_prop));
|
|
|
|
int totlen;
|
|
|
|
|
|
|
|
switch (saidx->proto) {
|
|
|
|
case IPPROTO_ESP:
|
|
|
|
m = key_getcomb_esp();
|
|
|
|
break;
|
|
|
|
case IPPROTO_AH:
|
|
|
|
m = key_getcomb_ah();
|
|
|
|
break;
|
|
|
|
case IPPROTO_IPCOMP:
|
|
|
|
m = key_getcomb_ipcomp();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m)
|
|
|
|
return NULL;
|
2012-12-05 08:04:20 +00:00
|
|
|
M_PREPEND(m, l, M_NOWAIT);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (!m)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
totlen = 0;
|
|
|
|
for (n = m; n; n = n->m_next)
|
|
|
|
totlen += n->m_len;
|
|
|
|
|
|
|
|
prop = mtod(m, struct sadb_prop *);
|
|
|
|
bzero(prop, sizeof(*prop));
|
|
|
|
prop->sadb_prop_len = PFKEY_UNIT64(totlen);
|
|
|
|
prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
|
|
|
|
prop->sadb_prop_replay = 32; /* XXX */
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_ACQUIRE processing called by key_checkrequest() and key_acquire2().
|
|
|
|
* send
|
|
|
|
* <base, SA, address(SD), (address(P)), x_policy,
|
|
|
|
* (identity(SD),) (sensitivity,) proposal>
|
|
|
|
* to KMD, and expect to receive
|
|
|
|
* <base> with SADB_ACQUIRE if error occured,
|
|
|
|
* or
|
|
|
|
* <base, src address, dst address, (SPI range)> with SADB_GETSPI
|
|
|
|
* from KMD by PF_KEY.
|
|
|
|
*
|
|
|
|
* XXX x_policy is outside of RFC2367 (KAME extension).
|
|
|
|
* XXX sensitivity is not supported.
|
|
|
|
* XXX for ipcomp, RFC2367 does not define how to fill in proposal.
|
|
|
|
* see comment for key_getcomb_ipcomp().
|
|
|
|
*
|
|
|
|
* OUT:
|
|
|
|
* 0 : succeed
|
|
|
|
* others: error number
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
key_acquire(const struct secasindex *saidx, struct secpolicy *sp)
|
|
|
|
{
|
|
|
|
struct mbuf *result = NULL, *m;
|
|
|
|
struct secacq *newacq;
|
|
|
|
u_int8_t satype;
|
|
|
|
int error = -1;
|
|
|
|
u_int32_t seq;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(saidx != NULL, ("null saidx"));
|
2002-10-16 02:10:08 +00:00
|
|
|
satype = key_proto2satype(saidx->proto);
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(satype != 0, ("null satype, protocol %u", saidx->proto));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We never do anything about acquirng SA. There is anather
|
|
|
|
* solution that kernel blocks to send SADB_ACQUIRE message until
|
|
|
|
* getting something message from IKEd. In later case, to be
|
|
|
|
* managed with ACQUIRING list.
|
|
|
|
*/
|
2003-01-01 18:49:04 +00:00
|
|
|
/* Get an entry to check whether sending message or not. */
|
2002-10-16 02:10:08 +00:00
|
|
|
if ((newacq = key_getacq(saidx)) != NULL) {
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (V_key_blockacq_count < newacq->count) {
|
2002-10-16 02:10:08 +00:00
|
|
|
/* reset counter and do send message. */
|
|
|
|
newacq->count = 0;
|
|
|
|
} else {
|
|
|
|
/* increment counter and do nothing. */
|
|
|
|
newacq->count++;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* make new entry for blocking to send SADB_ACQUIRE. */
|
|
|
|
if ((newacq = key_newacq(saidx)) == NULL)
|
|
|
|
return ENOBUFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
seq = newacq->seq;
|
|
|
|
m = key_setsadbmsg(SADB_ACQUIRE, 0, satype, seq, 0, 0);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
result = m;
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* No SADB_X_EXT_NAT_T_* here: we do not know
|
|
|
|
* anything related to NAT-T at this time.
|
|
|
|
*/
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* set sadb_address for saidx's. */
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
|
|
|
|
&saidx->src.sa, FULLMASK, IPSEC_ULPROTO_ANY);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
|
|
|
|
&saidx->dst.sa, FULLMASK, IPSEC_ULPROTO_ANY);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
/* XXX proxy address (optional) */
|
|
|
|
|
|
|
|
/* set sadb_x_policy */
|
|
|
|
if (sp) {
|
|
|
|
m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX identity (optional) */
|
|
|
|
#if 0
|
|
|
|
if (idexttype && fqdn) {
|
|
|
|
/* create identity extension (FQDN) */
|
|
|
|
struct sadb_ident *id;
|
|
|
|
int fqdnlen;
|
|
|
|
|
|
|
|
fqdnlen = strlen(fqdn) + 1; /* +1 for terminating-NUL */
|
|
|
|
id = (struct sadb_ident *)p;
|
|
|
|
bzero(id, sizeof(*id) + PFKEY_ALIGN8(fqdnlen));
|
|
|
|
id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(fqdnlen));
|
|
|
|
id->sadb_ident_exttype = idexttype;
|
|
|
|
id->sadb_ident_type = SADB_IDENTTYPE_FQDN;
|
|
|
|
bcopy(fqdn, id + 1, fqdnlen);
|
|
|
|
p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(fqdnlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idexttype) {
|
|
|
|
/* create identity extension (USERFQDN) */
|
|
|
|
struct sadb_ident *id;
|
|
|
|
int userfqdnlen;
|
|
|
|
|
|
|
|
if (userfqdn) {
|
|
|
|
/* +1 for terminating-NUL */
|
|
|
|
userfqdnlen = strlen(userfqdn) + 1;
|
|
|
|
} else
|
|
|
|
userfqdnlen = 0;
|
|
|
|
id = (struct sadb_ident *)p;
|
|
|
|
bzero(id, sizeof(*id) + PFKEY_ALIGN8(userfqdnlen));
|
|
|
|
id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(userfqdnlen));
|
|
|
|
id->sadb_ident_exttype = idexttype;
|
|
|
|
id->sadb_ident_type = SADB_IDENTTYPE_USERFQDN;
|
|
|
|
/* XXX is it correct? */
|
|
|
|
if (curproc && curproc->p_cred)
|
|
|
|
id->sadb_ident_id = curproc->p_cred->p_ruid;
|
|
|
|
if (userfqdn && userfqdnlen)
|
|
|
|
bcopy(userfqdn, id + 1, userfqdnlen);
|
|
|
|
p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(userfqdnlen);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* XXX sensitivity (optional) */
|
|
|
|
|
|
|
|
/* create proposal/combination extension */
|
|
|
|
m = key_getprop(saidx);
|
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* spec conformant: always attach proposal/combination extension,
|
|
|
|
* the problem is that we have no way to attach it for ipcomp,
|
|
|
|
* due to the way sadb_comb is declared in RFC2367.
|
|
|
|
*/
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* outside of spec; make proposal/combination extension optional.
|
|
|
|
*/
|
|
|
|
if (m)
|
|
|
|
m_cat(result, m);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ((result->m_flags & M_PKTHDR) == 0) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
result = m_pullup(result, sizeof(struct sadb_msg));
|
|
|
|
if (result == NULL) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
result->m_pkthdr.len = 0;
|
|
|
|
for (m = result; m; m = m->m_next)
|
|
|
|
result->m_pkthdr.len += m->m_len;
|
|
|
|
|
|
|
|
mtod(result, struct sadb_msg *)->sadb_msg_len =
|
|
|
|
PFKEY_UNIT64(result->m_pkthdr.len);
|
|
|
|
|
|
|
|
return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
|
|
|
|
|
|
|
|
fail:
|
|
|
|
if (result)
|
|
|
|
m_freem(result);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct secacq *
|
|
|
|
key_newacq(const struct secasindex *saidx)
|
|
|
|
{
|
|
|
|
struct secacq *newacq;
|
|
|
|
|
|
|
|
/* get new entry */
|
2003-09-01 05:35:55 +00:00
|
|
|
newacq = malloc(sizeof(struct secacq), M_IPSEC_SAQ, M_NOWAIT|M_ZERO);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (newacq == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy secindex */
|
|
|
|
bcopy(saidx, &newacq->saidx, sizeof(newacq->saidx));
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
newacq->seq = (V_acq_seq == ~0 ? 1 : ++V_acq_seq);
|
2002-10-16 02:10:08 +00:00
|
|
|
newacq->created = time_second;
|
|
|
|
newacq->count = 0;
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
/* add to acqtree */
|
2003-09-29 22:57:43 +00:00
|
|
|
ACQ_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_INSERT_HEAD(&V_acqtree, newacq, chain);
|
2003-09-29 22:57:43 +00:00
|
|
|
ACQ_UNLOCK();
|
2003-09-01 05:35:55 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
return newacq;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct secacq *
|
|
|
|
key_getacq(const struct secasindex *saidx)
|
|
|
|
{
|
|
|
|
struct secacq *acq;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
ACQ_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(acq, &V_acqtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY))
|
2003-09-01 05:35:55 +00:00
|
|
|
break;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
ACQ_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
return acq;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct secacq *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getacqbyseq(u_int32_t seq)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secacq *acq;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
ACQ_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(acq, &V_acqtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (acq->seq == seq)
|
2003-09-01 05:35:55 +00:00
|
|
|
break;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
ACQ_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
return acq;
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct secspacq *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_newspacq(struct secpolicyindex *spidx)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secspacq *acq;
|
|
|
|
|
|
|
|
/* get new entry */
|
2003-09-01 05:35:55 +00:00
|
|
|
acq = malloc(sizeof(struct secspacq), M_IPSEC_SAQ, M_NOWAIT|M_ZERO);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (acq == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy secindex */
|
|
|
|
bcopy(spidx, &acq->spidx, sizeof(acq->spidx));
|
|
|
|
acq->created = time_second;
|
|
|
|
acq->count = 0;
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
/* add to spacqtree */
|
2003-09-29 22:57:43 +00:00
|
|
|
SPACQ_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_INSERT_HEAD(&V_spacqtree, acq, chain);
|
2003-09-29 22:57:43 +00:00
|
|
|
SPACQ_UNLOCK();
|
2003-09-01 05:35:55 +00:00
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
return acq;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct secspacq *
|
2014-12-03 03:50:54 +00:00
|
|
|
key_getspacq(struct secpolicyindex *spidx)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secspacq *acq;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
SPACQ_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(acq, &V_spacqtree, chain) {
|
2003-09-01 05:35:55 +00:00
|
|
|
if (key_cmpspidx_exactly(spidx, &acq->spidx)) {
|
|
|
|
/* NB: return holding spacq_lock */
|
2002-10-16 02:10:08 +00:00
|
|
|
return acq;
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SPACQ_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_ACQUIRE processing,
|
|
|
|
* in first situation, is receiving
|
|
|
|
* <base>
|
|
|
|
* from the ikmpd, and clear sequence of its secasvar entry.
|
|
|
|
*
|
|
|
|
* In second situation, is receiving
|
|
|
|
* <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal>
|
|
|
|
* from a user land process, and return
|
|
|
|
* <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal>
|
|
|
|
* to the socket.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_acquire2(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
const struct sadb_address *src0, *dst0;
|
|
|
|
struct secasindex saidx;
|
|
|
|
struct secashead *sah;
|
|
|
|
u_int16_t proto;
|
|
|
|
int error;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Error message from KMd.
|
|
|
|
* We assume that if error was occured in IKEd, the length of PFKEY
|
|
|
|
* message is equal to the size of sadb_msg structure.
|
|
|
|
* We do not raise error even if error occured in this function.
|
|
|
|
*/
|
|
|
|
if (mhp->msg->sadb_msg_len == PFKEY_UNIT64(sizeof(struct sadb_msg))) {
|
|
|
|
struct secacq *acq;
|
|
|
|
|
|
|
|
/* check sequence number */
|
|
|
|
if (mhp->msg->sadb_msg_seq == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: must specify sequence "
|
|
|
|
"number.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
m_freem(m);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) == NULL) {
|
|
|
|
/*
|
|
|
|
* the specified larval SA is already gone, or we got
|
|
|
|
* a bogus sequence number. we can silently ignore it.
|
|
|
|
*/
|
|
|
|
m_freem(m);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset acq counter in order to deletion by timehander. */
|
|
|
|
acq->created = time_second;
|
|
|
|
acq->count = 0;
|
|
|
|
m_freem(m);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This message is from user land.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* map satype to proto */
|
|
|
|
if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
|
|
|
|
mhp->ext[SADB_EXT_PROPOSAL] == NULL) {
|
|
|
|
/* error */
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) ||
|
|
|
|
mhp->extlen[SADB_EXT_PROPOSAL] < sizeof(struct sadb_prop)) {
|
|
|
|
/* error */
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
|
|
|
|
dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
|
|
|
|
|
|
|
|
/* XXX boundary check against sa_len */
|
|
|
|
KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* Make sure the port numbers are zero.
|
|
|
|
* In case of NAT-T we will update them later if needed.
|
|
|
|
*/
|
|
|
|
KEY_PORTTOSADDR(&saidx.src, 0);
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst, 0);
|
|
|
|
|
|
|
|
#ifndef IPSEC_NAT_T
|
|
|
|
/*
|
|
|
|
* Handle NAT-T info if present.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL &&
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) {
|
|
|
|
struct sadb_x_nat_t_port *sport, *dport;
|
|
|
|
|
|
|
|
if (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) ||
|
|
|
|
mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) {
|
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message.\n",
|
|
|
|
__func__));
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
sport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_SPORT];
|
|
|
|
dport = (struct sadb_x_nat_t_port *)
|
|
|
|
mhp->ext[SADB_X_EXT_NAT_T_DPORT];
|
|
|
|
|
|
|
|
if (sport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.src,
|
|
|
|
sport->sadb_x_nat_t_port_port);
|
|
|
|
if (dport)
|
|
|
|
KEY_PORTTOSADDR(&saidx.dst,
|
|
|
|
dport->sadb_x_nat_t_port_port);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
/* get a SA index */
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah->state == SADB_SASTATE_DEAD)
|
|
|
|
continue;
|
|
|
|
if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE_REQID))
|
|
|
|
break;
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
if (sah != NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: a SA exists already.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EEXIST);
|
|
|
|
}
|
|
|
|
|
|
|
|
error = key_acquire(&saidx, NULL);
|
|
|
|
if (error != 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: error %d returned from key_acquire\n",
|
|
|
|
__func__, mhp->msg->sadb_msg_errno));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_REGISTER processing.
|
|
|
|
* If SATYPE_UNSPEC has been passed as satype, only return sabd_supported.
|
|
|
|
* receive
|
|
|
|
* <base>
|
|
|
|
* from the ikmpd, and register a socket to send PF_KEY messages,
|
|
|
|
* and send
|
|
|
|
* <base, supported>
|
|
|
|
* to KMD by PF_KEY.
|
|
|
|
* If socket is detached, must free from regnode.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_register(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secreg *reg, *newreg = 0;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* check for invalid register message */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
if (mhp->msg->sadb_msg_satype >= sizeof(V_regtree)/sizeof(V_regtree[0]))
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
|
|
|
|
/* When SATYPE_UNSPEC is specified, only return sabd_supported. */
|
|
|
|
if (mhp->msg->sadb_msg_satype == SADB_SATYPE_UNSPEC)
|
|
|
|
goto setmsg;
|
|
|
|
|
|
|
|
/* check whether existing or not */
|
2003-09-29 22:57:43 +00:00
|
|
|
REGTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(reg, &V_regtree[mhp->msg->sadb_msg_satype], chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (reg->so == so) {
|
2003-09-29 22:57:43 +00:00
|
|
|
REGTREE_UNLOCK();
|
|
|
|
ipseclog((LOG_DEBUG, "%s: socket exists already.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EEXIST);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create regnode */
|
2003-09-01 05:35:55 +00:00
|
|
|
newreg = malloc(sizeof(struct secreg), M_IPSEC_SAR, M_NOWAIT|M_ZERO);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (newreg == NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
REGTREE_UNLOCK();
|
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
newreg->so = so;
|
|
|
|
((struct keycb *)sotorawcb(so))->kp_registered++;
|
|
|
|
|
|
|
|
/* add regnode to regtree. */
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_INSERT_HEAD(&V_regtree[mhp->msg->sadb_msg_satype], newreg, chain);
|
2003-09-29 22:57:43 +00:00
|
|
|
REGTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
setmsg:
|
|
|
|
{
|
|
|
|
struct mbuf *n;
|
|
|
|
struct sadb_msg *newmsg;
|
|
|
|
struct sadb_supported *sup;
|
|
|
|
u_int len, alen, elen;
|
|
|
|
int off;
|
|
|
|
int i;
|
|
|
|
struct sadb_alg *alg;
|
|
|
|
|
|
|
|
/* create new sadb_msg to reply. */
|
|
|
|
alen = 0;
|
|
|
|
for (i = 1; i <= SADB_AALG_MAX; i++) {
|
|
|
|
if (ah_algorithm_lookup(i))
|
|
|
|
alen += sizeof(struct sadb_alg);
|
|
|
|
}
|
|
|
|
if (alen)
|
|
|
|
alen += sizeof(struct sadb_supported);
|
|
|
|
elen = 0;
|
|
|
|
for (i = 1; i <= SADB_EALG_MAX; i++) {
|
|
|
|
if (esp_algorithm_lookup(i))
|
|
|
|
elen += sizeof(struct sadb_alg);
|
|
|
|
}
|
|
|
|
if (elen)
|
|
|
|
elen += sizeof(struct sadb_supported);
|
|
|
|
|
|
|
|
len = sizeof(struct sadb_msg) + alen + elen;
|
|
|
|
|
|
|
|
if (len > MCLBYTES)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
|
2012-12-05 08:04:20 +00:00
|
|
|
MGETHDR(n, M_NOWAIT, MT_DATA);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (len > MHLEN) {
|
2015-01-06 12:59:37 +00:00
|
|
|
if (!(MCLGET(n, M_NOWAIT))) {
|
2002-10-16 02:10:08 +00:00
|
|
|
m_freem(n);
|
|
|
|
n = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!n)
|
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
|
|
|
|
n->m_pkthdr.len = n->m_len = len;
|
|
|
|
n->m_next = NULL;
|
|
|
|
off = 0;
|
|
|
|
|
|
|
|
m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off);
|
|
|
|
newmsg = mtod(n, struct sadb_msg *);
|
|
|
|
newmsg->sadb_msg_errno = 0;
|
|
|
|
newmsg->sadb_msg_len = PFKEY_UNIT64(len);
|
|
|
|
off += PFKEY_ALIGN8(sizeof(struct sadb_msg));
|
|
|
|
|
|
|
|
/* for authentication algorithm */
|
|
|
|
if (alen) {
|
|
|
|
sup = (struct sadb_supported *)(mtod(n, caddr_t) + off);
|
|
|
|
sup->sadb_supported_len = PFKEY_UNIT64(alen);
|
|
|
|
sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH;
|
|
|
|
off += PFKEY_ALIGN8(sizeof(*sup));
|
|
|
|
|
|
|
|
for (i = 1; i <= SADB_AALG_MAX; i++) {
|
|
|
|
struct auth_hash *aalgo;
|
|
|
|
u_int16_t minkeysize, maxkeysize;
|
|
|
|
|
|
|
|
aalgo = ah_algorithm_lookup(i);
|
|
|
|
if (!aalgo)
|
|
|
|
continue;
|
|
|
|
alg = (struct sadb_alg *)(mtod(n, caddr_t) + off);
|
|
|
|
alg->sadb_alg_id = i;
|
|
|
|
alg->sadb_alg_ivlen = 0;
|
|
|
|
key_getsizes_ah(aalgo, i, &minkeysize, &maxkeysize);
|
|
|
|
alg->sadb_alg_minbits = _BITS(minkeysize);
|
|
|
|
alg->sadb_alg_maxbits = _BITS(maxkeysize);
|
|
|
|
off += PFKEY_ALIGN8(sizeof(*alg));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* for encryption algorithm */
|
|
|
|
if (elen) {
|
|
|
|
sup = (struct sadb_supported *)(mtod(n, caddr_t) + off);
|
|
|
|
sup->sadb_supported_len = PFKEY_UNIT64(elen);
|
|
|
|
sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT;
|
|
|
|
off += PFKEY_ALIGN8(sizeof(*sup));
|
|
|
|
|
|
|
|
for (i = 1; i <= SADB_EALG_MAX; i++) {
|
|
|
|
struct enc_xform *ealgo;
|
|
|
|
|
|
|
|
ealgo = esp_algorithm_lookup(i);
|
|
|
|
if (!ealgo)
|
|
|
|
continue;
|
|
|
|
alg = (struct sadb_alg *)(mtod(n, caddr_t) + off);
|
|
|
|
alg->sadb_alg_id = i;
|
|
|
|
alg->sadb_alg_ivlen = ealgo->blocksize;
|
|
|
|
alg->sadb_alg_minbits = _BITS(ealgo->minkey);
|
|
|
|
alg->sadb_alg_maxbits = _BITS(ealgo->maxkey);
|
|
|
|
off += PFKEY_ALIGN8(sizeof(struct sadb_alg));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(off == len,
|
|
|
|
("length assumption failed (off %u len %u)", off, len));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* free secreg entry registered.
|
|
|
|
* XXX: I want to do free a socket marked done SADB_RESIGER to socket.
|
|
|
|
*/
|
|
|
|
void
|
2003-09-01 05:35:55 +00:00
|
|
|
key_freereg(struct socket *so)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secreg *reg;
|
|
|
|
int i;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("NULL so"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* check whether existing or not.
|
|
|
|
* check all type of SA, because there is a potential that
|
|
|
|
* one socket is registered to multiple type of SA.
|
|
|
|
*/
|
2003-09-29 22:57:43 +00:00
|
|
|
REGTREE_LOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
for (i = 0; i <= SADB_SATYPE_MAX; i++) {
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(reg, &V_regtree[i], chain) {
|
2003-09-01 05:35:55 +00:00
|
|
|
if (reg->so == so && __LIST_CHAINED(reg)) {
|
2002-10-16 02:10:08 +00:00
|
|
|
LIST_REMOVE(reg, chain);
|
2003-09-01 05:35:55 +00:00
|
|
|
free(reg, M_IPSEC_SAR);
|
2002-10-16 02:10:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
REGTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_EXPIRE processing
|
|
|
|
* send
|
|
|
|
* <base, SA, SA2, lifetime(C and one of HS), address(SD)>
|
|
|
|
* to KMD by PF_KEY.
|
|
|
|
* NOTE: We send only soft lifetime extension.
|
|
|
|
*
|
|
|
|
* OUT: 0 : succeed
|
|
|
|
* others : error number
|
|
|
|
*/
|
|
|
|
static int
|
2003-09-01 05:35:55 +00:00
|
|
|
key_expire(struct secasvar *sav)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
int satype;
|
|
|
|
struct mbuf *result = NULL, *m;
|
|
|
|
int len;
|
|
|
|
int error = -1;
|
|
|
|
struct sadb_lifetime *lt;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT (sav != NULL, ("null sav"));
|
|
|
|
IPSEC_ASSERT (sav->sah != NULL, ("null sa header"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* set msg header */
|
2003-09-29 22:57:43 +00:00
|
|
|
satype = key_proto2satype(sav->sah->saidx.proto);
|
|
|
|
IPSEC_ASSERT(satype != 0, ("invalid proto, satype %u", satype));
|
2002-10-16 02:10:08 +00:00
|
|
|
m = key_setsadbmsg(SADB_EXPIRE, 0, satype, sav->seq, 0, sav->refcnt);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
result = m;
|
|
|
|
|
|
|
|
/* create SA extension */
|
|
|
|
m = key_setsadbsa(sav);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
/* create SA extension */
|
|
|
|
m = key_setsadbxsa2(sav->sah->saidx.mode,
|
|
|
|
sav->replay ? sav->replay->count : 0,
|
|
|
|
sav->sah->saidx.reqid);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
/* create lifetime extension (current and soft) */
|
|
|
|
len = PFKEY_ALIGN8(sizeof(*lt)) * 2;
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
|
|
|
if (m == NULL) {
|
2002-10-16 02:10:08 +00:00
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
2013-03-15 10:20:15 +00:00
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
2002-10-16 02:10:08 +00:00
|
|
|
bzero(mtod(m, caddr_t), len);
|
|
|
|
lt = mtod(m, struct sadb_lifetime *);
|
|
|
|
lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
|
|
|
|
lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
|
2006-03-25 13:38:52 +00:00
|
|
|
lt->sadb_lifetime_allocations = sav->lft_c->allocations;
|
|
|
|
lt->sadb_lifetime_bytes = sav->lft_c->bytes;
|
|
|
|
lt->sadb_lifetime_addtime = sav->lft_c->addtime;
|
|
|
|
lt->sadb_lifetime_usetime = sav->lft_c->usetime;
|
2002-10-16 02:10:08 +00:00
|
|
|
lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2);
|
2008-03-02 17:12:28 +00:00
|
|
|
lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
|
|
|
|
lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
|
|
|
|
lt->sadb_lifetime_allocations = sav->lft_s->allocations;
|
|
|
|
lt->sadb_lifetime_bytes = sav->lft_s->bytes;
|
|
|
|
lt->sadb_lifetime_addtime = sav->lft_s->addtime;
|
|
|
|
lt->sadb_lifetime_usetime = sav->lft_s->usetime;
|
2002-10-16 02:10:08 +00:00
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
/* set sadb_address for source */
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
|
|
|
|
&sav->sah->saidx.src.sa,
|
|
|
|
FULLMASK, IPSEC_ULPROTO_ANY);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
|
|
|
|
/* set sadb_address for destination */
|
|
|
|
m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
|
|
|
|
&sav->sah->saidx.dst.sa,
|
|
|
|
FULLMASK, IPSEC_ULPROTO_ANY);
|
|
|
|
if (!m) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
m_cat(result, m);
|
|
|
|
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
/*
|
|
|
|
* XXX-BZ Handle NAT-T extensions here.
|
|
|
|
*/
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
if ((result->m_flags & M_PKTHDR) == 0) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
result = m_pullup(result, sizeof(struct sadb_msg));
|
|
|
|
if (result == NULL) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
result->m_pkthdr.len = 0;
|
|
|
|
for (m = result; m; m = m->m_next)
|
|
|
|
result->m_pkthdr.len += m->m_len;
|
|
|
|
|
|
|
|
mtod(result, struct sadb_msg *)->sadb_msg_len =
|
|
|
|
PFKEY_UNIT64(result->m_pkthdr.len);
|
|
|
|
|
|
|
|
return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
|
|
|
|
|
|
|
|
fail:
|
|
|
|
if (result)
|
|
|
|
m_freem(result);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_FLUSH processing
|
|
|
|
* receive
|
|
|
|
* <base>
|
|
|
|
* from the ikmpd, and free all entries in secastree.
|
|
|
|
* and send,
|
|
|
|
* <base>
|
|
|
|
* to the ikmpd.
|
|
|
|
* NOTE: to do is only marking SADB_SASTATE_DEAD.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_flush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_msg *newmsg;
|
|
|
|
struct secashead *sah, *nextsah;
|
|
|
|
struct secasvar *sav, *nextsav;
|
|
|
|
u_int16_t proto;
|
|
|
|
u_int8_t state;
|
|
|
|
u_int stateidx;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* map satype to proto */
|
|
|
|
if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no SATYPE specified, i.e. flushing all SA. */
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
for (sah = LIST_FIRST(&V_sahtree);
|
2002-10-16 02:10:08 +00:00
|
|
|
sah != NULL;
|
|
|
|
sah = nextsah) {
|
|
|
|
nextsah = LIST_NEXT(sah, chain);
|
|
|
|
|
|
|
|
if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC
|
|
|
|
&& proto != sah->saidx.proto)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (stateidx = 0;
|
2008-11-26 22:32:07 +00:00
|
|
|
stateidx < _ARRAYLEN(saorder_state_alive);
|
2002-10-16 02:10:08 +00:00
|
|
|
stateidx++) {
|
2008-11-26 22:32:07 +00:00
|
|
|
state = saorder_state_any[stateidx];
|
2002-10-16 02:10:08 +00:00
|
|
|
for (sav = LIST_FIRST(&sah->savtree[state]);
|
|
|
|
sav != NULL;
|
|
|
|
sav = nextsav) {
|
|
|
|
|
|
|
|
nextsav = LIST_NEXT(sav, chain);
|
|
|
|
|
|
|
|
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
|
|
|
|
KEY_FREESAV(&sav);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sah->state = SADB_SASTATE_DEAD;
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
if (m->m_len < sizeof(struct sadb_msg) ||
|
|
|
|
sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOBUFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m->m_next)
|
|
|
|
m_freem(m->m_next);
|
|
|
|
m->m_next = NULL;
|
|
|
|
m->m_pkthdr.len = m->m_len = sizeof(struct sadb_msg);
|
|
|
|
newmsg = mtod(m, struct sadb_msg *);
|
|
|
|
newmsg->sadb_msg_errno = 0;
|
|
|
|
newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
|
|
|
|
|
|
|
|
return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_DUMP processing
|
|
|
|
* dump all entries including status of DEAD in SAD.
|
|
|
|
* receive
|
|
|
|
* <base>
|
|
|
|
* from the ikmpd, and dump all secasvar leaves
|
|
|
|
* and send,
|
|
|
|
* <base> .....
|
|
|
|
* to the ikmpd.
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_dump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct secashead *sah;
|
|
|
|
struct secasvar *sav;
|
|
|
|
u_int16_t proto;
|
|
|
|
u_int stateidx;
|
|
|
|
u_int8_t satype;
|
|
|
|
u_int8_t state;
|
|
|
|
int cnt;
|
|
|
|
struct sadb_msg *newmsg;
|
|
|
|
struct mbuf *n;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* map satype to proto */
|
|
|
|
if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n",
|
|
|
|
__func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* count sav entries to be sent to the userland. */
|
|
|
|
cnt = 0;
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_LOCK();
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC
|
|
|
|
&& proto != sah->saidx.proto)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (stateidx = 0;
|
2008-11-26 22:32:07 +00:00
|
|
|
stateidx < _ARRAYLEN(saorder_state_any);
|
2002-10-16 02:10:08 +00:00
|
|
|
stateidx++) {
|
2008-11-26 22:32:07 +00:00
|
|
|
state = saorder_state_any[stateidx];
|
2002-10-16 02:10:08 +00:00
|
|
|
LIST_FOREACH(sav, &sah->savtree[state], chain) {
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
if (cnt == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOENT);
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* send this to the userland, one at a time. */
|
|
|
|
newmsg = NULL;
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_FOREACH(sah, &V_sahtree, chain) {
|
2002-10-16 02:10:08 +00:00
|
|
|
if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC
|
|
|
|
&& proto != sah->saidx.proto)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* map proto to satype */
|
|
|
|
if ((satype = key_proto2satype(sah->saidx.proto)) == 0) {
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
|
|
|
ipseclog((LOG_DEBUG, "%s: there was invalid proto in "
|
|
|
|
"SAD.\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (stateidx = 0;
|
2008-11-26 22:32:07 +00:00
|
|
|
stateidx < _ARRAYLEN(saorder_state_any);
|
2002-10-16 02:10:08 +00:00
|
|
|
stateidx++) {
|
2008-11-26 22:32:07 +00:00
|
|
|
state = saorder_state_any[stateidx];
|
2002-10-16 02:10:08 +00:00
|
|
|
LIST_FOREACH(sav, &sah->savtree[state], chain) {
|
|
|
|
n = key_setdumpsa(sav, SADB_DUMP, satype,
|
|
|
|
--cnt, mhp->msg->sadb_msg_pid);
|
2003-09-01 05:35:55 +00:00
|
|
|
if (!n) {
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
return key_senderror(so, m, ENOBUFS);
|
2003-09-01 05:35:55 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-29 22:57:43 +00:00
|
|
|
SAHTREE_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
m_freem(m);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SADB_X_PROMISC processing
|
|
|
|
*
|
|
|
|
* m will always be freed.
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_promisc(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
int olen;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
olen = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len);
|
|
|
|
|
|
|
|
if (olen < sizeof(struct sadb_msg)) {
|
|
|
|
#if 1
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
#else
|
|
|
|
m_freem(m);
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
} else if (olen == sizeof(struct sadb_msg)) {
|
|
|
|
/* enable/disable promisc mode */
|
|
|
|
struct keycb *kp;
|
|
|
|
|
|
|
|
if ((kp = (struct keycb *)sotorawcb(so)) == NULL)
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
mhp->msg->sadb_msg_errno = 0;
|
|
|
|
switch (mhp->msg->sadb_msg_satype) {
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
kp->kp_promisc = mhp->msg->sadb_msg_satype;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return key_senderror(so, m, EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* send the original message back to everyone */
|
|
|
|
mhp->msg->sadb_msg_errno = 0;
|
|
|
|
return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
|
|
|
|
} else {
|
|
|
|
/* send packet as is */
|
|
|
|
|
|
|
|
m_adj(m, PFKEY_ALIGN8(sizeof(struct sadb_msg)));
|
|
|
|
|
|
|
|
/* TODO: if sadb_msg_seq is specified, send to specific pid */
|
|
|
|
return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-03 04:08:41 +00:00
|
|
|
static int (*key_typesw[])(struct socket *, struct mbuf *,
|
|
|
|
const struct sadb_msghdr *) = {
|
2002-10-16 02:10:08 +00:00
|
|
|
NULL, /* SADB_RESERVED */
|
|
|
|
key_getspi, /* SADB_GETSPI */
|
|
|
|
key_update, /* SADB_UPDATE */
|
|
|
|
key_add, /* SADB_ADD */
|
|
|
|
key_delete, /* SADB_DELETE */
|
|
|
|
key_get, /* SADB_GET */
|
|
|
|
key_acquire2, /* SADB_ACQUIRE */
|
|
|
|
key_register, /* SADB_REGISTER */
|
|
|
|
NULL, /* SADB_EXPIRE */
|
|
|
|
key_flush, /* SADB_FLUSH */
|
|
|
|
key_dump, /* SADB_DUMP */
|
|
|
|
key_promisc, /* SADB_X_PROMISC */
|
|
|
|
NULL, /* SADB_X_PCHANGE */
|
|
|
|
key_spdadd, /* SADB_X_SPDUPDATE */
|
|
|
|
key_spdadd, /* SADB_X_SPDADD */
|
|
|
|
key_spddelete, /* SADB_X_SPDDELETE */
|
|
|
|
key_spdget, /* SADB_X_SPDGET */
|
|
|
|
NULL, /* SADB_X_SPDACQUIRE */
|
|
|
|
key_spddump, /* SADB_X_SPDDUMP */
|
|
|
|
key_spdflush, /* SADB_X_SPDFLUSH */
|
|
|
|
key_spdadd, /* SADB_X_SPDSETIDX */
|
|
|
|
NULL, /* SADB_X_SPDEXPIRE */
|
|
|
|
key_spddelete2, /* SADB_X_SPDDELETE2 */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* parse sadb_msg buffer to process PFKEYv2,
|
|
|
|
* and create a data to response if needed.
|
|
|
|
* I think to be dealed with mbuf directly.
|
|
|
|
* IN:
|
|
|
|
* msgp : pointer to pointer to a received buffer pulluped.
|
|
|
|
* This is rewrited to response.
|
|
|
|
* so : pointer to socket.
|
|
|
|
* OUT:
|
|
|
|
* length for buffer to send to user process.
|
|
|
|
*/
|
|
|
|
int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_parse(struct mbuf *m, struct socket *so)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_msg *msg;
|
|
|
|
struct sadb_msghdr mh;
|
|
|
|
u_int orglen;
|
|
|
|
int error;
|
|
|
|
int target;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(so != NULL, ("null socket"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
#if 0 /*kdebug_sadb assumes msg in linear buffer*/
|
|
|
|
KEYDEBUG(KEYDEBUG_KEY_DUMP,
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: passed sadb_msg\n", __func__));
|
2002-10-16 02:10:08 +00:00
|
|
|
kdebug_sadb(msg));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (m->m_len < sizeof(struct sadb_msg)) {
|
|
|
|
m = m_pullup(m, sizeof(struct sadb_msg));
|
|
|
|
if (!m)
|
|
|
|
return ENOBUFS;
|
|
|
|
}
|
|
|
|
msg = mtod(m, struct sadb_msg *);
|
|
|
|
orglen = PFKEY_UNUNIT64(msg->sadb_msg_len);
|
|
|
|
target = KEY_SENDUP_ONE;
|
|
|
|
|
|
|
|
if ((m->m_flags & M_PKTHDR) == 0 ||
|
|
|
|
m->m_pkthdr.len != m->m_pkthdr.len) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid message length.\n",__func__));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invlen);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg->sadb_msg_version != PF_KEY_V2) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: PF_KEY version %u is mismatched.\n",
|
|
|
|
__func__, msg->sadb_msg_version));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invver);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg->sadb_msg_type > SADB_MAX) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid type %u is passed.\n",
|
|
|
|
__func__, msg->sadb_msg_type));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invmsgtype);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* for old-fashioned code - should be nuked */
|
|
|
|
if (m->m_pkthdr.len > MCLBYTES) {
|
|
|
|
m_freem(m);
|
|
|
|
return ENOBUFS;
|
|
|
|
}
|
|
|
|
if (m->m_next) {
|
|
|
|
struct mbuf *n;
|
|
|
|
|
2012-12-05 08:04:20 +00:00
|
|
|
MGETHDR(n, M_NOWAIT, MT_DATA);
|
2002-10-16 02:10:08 +00:00
|
|
|
if (n && m->m_pkthdr.len > MHLEN) {
|
2015-01-06 12:59:37 +00:00
|
|
|
if (!(MCLGET(n, M_NOWAIT))) {
|
2002-10-16 02:10:08 +00:00
|
|
|
m_free(n);
|
|
|
|
n = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!n) {
|
|
|
|
m_freem(m);
|
|
|
|
return ENOBUFS;
|
|
|
|
}
|
|
|
|
m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
|
|
|
|
n->m_pkthdr.len = n->m_len = m->m_pkthdr.len;
|
|
|
|
n->m_next = NULL;
|
|
|
|
m_freem(m);
|
|
|
|
m = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* align the mbuf chain so that extensions are in contiguous region. */
|
|
|
|
error = key_align(m, &mh);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
msg = mh.msg;
|
|
|
|
|
|
|
|
/* check SA type */
|
|
|
|
switch (msg->sadb_msg_satype) {
|
|
|
|
case SADB_SATYPE_UNSPEC:
|
|
|
|
switch (msg->sadb_msg_type) {
|
|
|
|
case SADB_GETSPI:
|
|
|
|
case SADB_UPDATE:
|
|
|
|
case SADB_ADD:
|
|
|
|
case SADB_DELETE:
|
|
|
|
case SADB_GET:
|
|
|
|
case SADB_ACQUIRE:
|
|
|
|
case SADB_EXPIRE:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: must specify satype "
|
|
|
|
"when msg type=%u.\n", __func__,
|
|
|
|
msg->sadb_msg_type));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invsatype);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SADB_SATYPE_AH:
|
|
|
|
case SADB_SATYPE_ESP:
|
|
|
|
case SADB_X_SATYPE_IPCOMP:
|
Initial import of RFC 2385 (TCP-MD5) digest support.
This is the first of two commits; bringing in the kernel support first.
This can be enabled by compiling a kernel with options TCP_SIGNATURE
and FAST_IPSEC.
For the uninitiated, this is a TCP option which provides for a means of
authenticating TCP sessions which came into being before IPSEC. It is
still relevant today, however, as it is used by many commercial router
vendors, particularly with BGP, and as such has become a requirement for
interconnect at many major Internet points of presence.
Several parts of the TCP and IP headers, including the segment payload,
are digested with MD5, including a shared secret. The PF_KEY interface
is used to manage the secrets using security associations in the SADB.
There is a limitation here in that as there is no way to map a TCP flow
per-port back to an SPI without polluting tcpcb or using the SPD; the
code to do the latter is unstable at this time. Therefore this code only
supports per-host keying granularity.
Whilst FAST_IPSEC is mutually exclusive with KAME IPSEC (and thus IPv6),
TCP_SIGNATURE applies only to IPv4. For the vast majority of prospective
users of this feature, this will not pose any problem.
This implementation is output-only; that is, the option is honoured when
responding to a host initiating a TCP session, but no effort is made
[yet] to authenticate inbound traffic. This is, however, sufficient to
interwork with Cisco equipment.
Tested with a Cisco 2501 running IOS 12.0(27), and Quagga 0.96.4 with
local patches. Patches for tcpdump to validate TCP-MD5 sessions are also
available from me upon request.
Sponsored by: sentex.net
2004-02-11 04:26:04 +00:00
|
|
|
case SADB_X_SATYPE_TCPSIGNATURE:
|
2002-10-16 02:10:08 +00:00
|
|
|
switch (msg->sadb_msg_type) {
|
|
|
|
case SADB_X_SPDADD:
|
|
|
|
case SADB_X_SPDDELETE:
|
|
|
|
case SADB_X_SPDGET:
|
|
|
|
case SADB_X_SPDDUMP:
|
|
|
|
case SADB_X_SPDFLUSH:
|
|
|
|
case SADB_X_SPDSETIDX:
|
|
|
|
case SADB_X_SPDUPDATE:
|
|
|
|
case SADB_X_SPDDELETE2:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: illegal satype=%u\n",
|
|
|
|
__func__, msg->sadb_msg_type));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invsatype);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SADB_SATYPE_RSVP:
|
|
|
|
case SADB_SATYPE_OSPFV2:
|
|
|
|
case SADB_SATYPE_RIPV2:
|
|
|
|
case SADB_SATYPE_MIP:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: type %u isn't supported.\n",
|
|
|
|
__func__, msg->sadb_msg_satype));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invsatype);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EOPNOTSUPP;
|
|
|
|
goto senderror;
|
|
|
|
case 1: /* XXX: What does it do? */
|
|
|
|
if (msg->sadb_msg_type == SADB_X_PROMISC)
|
|
|
|
break;
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid type %u is passed.\n",
|
|
|
|
__func__, msg->sadb_msg_satype));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invsatype);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check field of upper layer protocol and address family */
|
|
|
|
if (mh.ext[SADB_EXT_ADDRESS_SRC] != NULL
|
|
|
|
&& mh.ext[SADB_EXT_ADDRESS_DST] != NULL) {
|
|
|
|
struct sadb_address *src0, *dst0;
|
|
|
|
u_int plen;
|
|
|
|
|
|
|
|
src0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_SRC]);
|
|
|
|
dst0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_DST]);
|
|
|
|
|
|
|
|
/* check upper layer protocol */
|
|
|
|
if (src0->sadb_address_proto != dst0->sadb_address_proto) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: upper layer protocol "
|
|
|
|
"mismatched.\n", __func__));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invaddr);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check family */
|
|
|
|
if (PFKEY_ADDR_SADDR(src0)->sa_family !=
|
|
|
|
PFKEY_ADDR_SADDR(dst0)->sa_family) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: address family mismatched.\n",
|
|
|
|
__func__));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invaddr);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
if (PFKEY_ADDR_SADDR(src0)->sa_len !=
|
|
|
|
PFKEY_ADDR_SADDR(dst0)->sa_len) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: address struct size "
|
|
|
|
"mismatched.\n", __func__));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invaddr);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (PFKEY_ADDR_SADDR(src0)->sa_len !=
|
|
|
|
sizeof(struct sockaddr_in)) {
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invaddr);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if (PFKEY_ADDR_SADDR(src0)->sa_len !=
|
|
|
|
sizeof(struct sockaddr_in6)) {
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invaddr);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: unsupported address family\n",
|
|
|
|
__func__));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invaddr);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EAFNOSUPPORT;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
plen = sizeof(struct in_addr) << 3;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
plen = sizeof(struct in6_addr) << 3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
plen = 0; /*fool gcc*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check max prefix length */
|
|
|
|
if (src0->sadb_address_prefixlen > plen ||
|
|
|
|
dst0->sadb_address_prefixlen > plen) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: illegal prefixlen.\n",
|
|
|
|
__func__));
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invaddr);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* prefixlen == 0 is valid because there can be a case when
|
|
|
|
* all addresses are matched.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) ||
|
|
|
|
key_typesw[msg->sadb_msg_type] == NULL) {
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invmsgtype);
|
2002-10-16 02:10:08 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto senderror;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (*key_typesw[msg->sadb_msg_type])(so, m, &mh);
|
|
|
|
|
|
|
|
senderror:
|
|
|
|
msg->sadb_msg_errno = error;
|
|
|
|
return key_sendup_mbuf(so, m, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_senderror(struct socket *so, struct mbuf *m, int code)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct sadb_msg *msg;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(m->m_len >= sizeof(struct sadb_msg),
|
|
|
|
("mbuf too small, len %u", m->m_len));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
msg = mtod(m, struct sadb_msg *);
|
|
|
|
msg->sadb_msg_errno = code;
|
|
|
|
return key_sendup_mbuf(so, m, KEY_SENDUP_ONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set the pointer to each header into message buffer.
|
|
|
|
* m will be freed on error.
|
|
|
|
* XXX larger-than-MCLBYTES extension?
|
|
|
|
*/
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_align(struct mbuf *m, struct sadb_msghdr *mhp)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
struct mbuf *n;
|
|
|
|
struct sadb_ext *ext;
|
|
|
|
size_t off, end;
|
|
|
|
int extlen;
|
|
|
|
int toff;
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(m != NULL, ("null mbuf"));
|
|
|
|
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
|
|
|
|
IPSEC_ASSERT(m->m_len >= sizeof(struct sadb_msg),
|
|
|
|
("mbuf too small, len %u", m->m_len));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* initialize */
|
|
|
|
bzero(mhp, sizeof(*mhp));
|
|
|
|
|
|
|
|
mhp->msg = mtod(m, struct sadb_msg *);
|
|
|
|
mhp->ext[0] = (struct sadb_ext *)mhp->msg; /*XXX backward compat */
|
|
|
|
|
|
|
|
end = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len);
|
|
|
|
extlen = end; /*just in case extlen is not updated*/
|
|
|
|
for (off = sizeof(struct sadb_msg); off < end; off += extlen) {
|
|
|
|
n = m_pulldown(m, off, sizeof(struct sadb_ext), &toff);
|
|
|
|
if (!n) {
|
|
|
|
/* m is already freed */
|
|
|
|
return ENOBUFS;
|
|
|
|
}
|
|
|
|
ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff);
|
|
|
|
|
|
|
|
/* set pointer */
|
|
|
|
switch (ext->sadb_ext_type) {
|
|
|
|
case SADB_EXT_SA:
|
|
|
|
case SADB_EXT_ADDRESS_SRC:
|
|
|
|
case SADB_EXT_ADDRESS_DST:
|
|
|
|
case SADB_EXT_ADDRESS_PROXY:
|
|
|
|
case SADB_EXT_LIFETIME_CURRENT:
|
|
|
|
case SADB_EXT_LIFETIME_HARD:
|
|
|
|
case SADB_EXT_LIFETIME_SOFT:
|
|
|
|
case SADB_EXT_KEY_AUTH:
|
|
|
|
case SADB_EXT_KEY_ENCRYPT:
|
|
|
|
case SADB_EXT_IDENTITY_SRC:
|
|
|
|
case SADB_EXT_IDENTITY_DST:
|
|
|
|
case SADB_EXT_SENSITIVITY:
|
|
|
|
case SADB_EXT_PROPOSAL:
|
|
|
|
case SADB_EXT_SUPPORTED_AUTH:
|
|
|
|
case SADB_EXT_SUPPORTED_ENCRYPT:
|
|
|
|
case SADB_EXT_SPIRANGE:
|
|
|
|
case SADB_X_EXT_POLICY:
|
|
|
|
case SADB_X_EXT_SA2:
|
Added support for NAT-Traversal (RFC 3948) in IPsec stack.
Thanks to (no special order) Emmanuel Dreyfus (manu@netbsd.org), Larry
Baird (lab@gta.com), gnn, bz, and other FreeBSD devs, Julien Vanherzeele
(julien.vanherzeele@netasq.com, for years of bug reporting), the PFSense
team, and all people who used / tried the NAT-T patch for years and
reported bugs, patches, etc...
X-MFC: never
Reviewed by: bz
Approved by: gnn(mentor)
Obtained from: NETASQ
2009-06-12 15:44:35 +00:00
|
|
|
#ifdef IPSEC_NAT_T
|
|
|
|
case SADB_X_EXT_NAT_T_TYPE:
|
|
|
|
case SADB_X_EXT_NAT_T_SPORT:
|
|
|
|
case SADB_X_EXT_NAT_T_DPORT:
|
|
|
|
case SADB_X_EXT_NAT_T_OAI:
|
|
|
|
case SADB_X_EXT_NAT_T_OAR:
|
|
|
|
case SADB_X_EXT_NAT_T_FRAG:
|
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
/* duplicate check */
|
|
|
|
/*
|
|
|
|
* XXX Are there duplication payloads of either
|
|
|
|
* KEY_AUTH or KEY_ENCRYPT ?
|
|
|
|
*/
|
|
|
|
if (mhp->ext[ext->sadb_ext_type] != NULL) {
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: duplicate ext_type "
|
|
|
|
"%u\n", __func__, ext->sadb_ext_type));
|
2002-10-16 02:10:08 +00:00
|
|
|
m_freem(m);
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_dupext);
|
2002-10-16 02:10:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2003-09-29 22:57:43 +00:00
|
|
|
ipseclog((LOG_DEBUG, "%s: invalid ext_type %u\n",
|
|
|
|
__func__, ext->sadb_ext_type));
|
2002-10-16 02:10:08 +00:00
|
|
|
m_freem(m);
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invexttype);
|
2002-10-16 02:10:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
extlen = PFKEY_UNUNIT64(ext->sadb_ext_len);
|
|
|
|
|
|
|
|
if (key_validate_ext(ext, extlen)) {
|
|
|
|
m_freem(m);
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invlen);
|
2002-10-16 02:10:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
n = m_pulldown(m, off, extlen, &toff);
|
|
|
|
if (!n) {
|
|
|
|
/* m is already freed */
|
|
|
|
return ENOBUFS;
|
|
|
|
}
|
|
|
|
ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff);
|
|
|
|
|
|
|
|
mhp->ext[ext->sadb_ext_type] = ext;
|
|
|
|
mhp->extoff[ext->sadb_ext_type] = off;
|
|
|
|
mhp->extlen[ext->sadb_ext_type] = extlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (off != end) {
|
|
|
|
m_freem(m);
|
2013-06-20 11:44:16 +00:00
|
|
|
PFKEYSTAT_INC(out_invlen);
|
2002-10-16 02:10:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_validate_ext(const struct sadb_ext *ext, int len)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
const struct sockaddr *sa;
|
|
|
|
enum { NONE, ADDR } checktype = NONE;
|
|
|
|
int baselen = 0;
|
|
|
|
const int sal = offsetof(struct sockaddr, sa_len) + sizeof(sa->sa_len);
|
|
|
|
|
|
|
|
if (len != PFKEY_UNUNIT64(ext->sadb_ext_len))
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
/* if it does not match minimum/maximum length, bail */
|
|
|
|
if (ext->sadb_ext_type >= sizeof(minsize) / sizeof(minsize[0]) ||
|
|
|
|
ext->sadb_ext_type >= sizeof(maxsize) / sizeof(maxsize[0]))
|
|
|
|
return EINVAL;
|
|
|
|
if (!minsize[ext->sadb_ext_type] || len < minsize[ext->sadb_ext_type])
|
|
|
|
return EINVAL;
|
|
|
|
if (maxsize[ext->sadb_ext_type] && len > maxsize[ext->sadb_ext_type])
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
/* more checks based on sadb_ext_type XXX need more */
|
|
|
|
switch (ext->sadb_ext_type) {
|
|
|
|
case SADB_EXT_ADDRESS_SRC:
|
|
|
|
case SADB_EXT_ADDRESS_DST:
|
|
|
|
case SADB_EXT_ADDRESS_PROXY:
|
|
|
|
baselen = PFKEY_ALIGN8(sizeof(struct sadb_address));
|
|
|
|
checktype = ADDR;
|
|
|
|
break;
|
|
|
|
case SADB_EXT_IDENTITY_SRC:
|
|
|
|
case SADB_EXT_IDENTITY_DST:
|
|
|
|
if (((const struct sadb_ident *)ext)->sadb_ident_type ==
|
|
|
|
SADB_X_IDENTTYPE_ADDR) {
|
|
|
|
baselen = PFKEY_ALIGN8(sizeof(struct sadb_ident));
|
|
|
|
checktype = ADDR;
|
|
|
|
} else
|
|
|
|
checktype = NONE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
checktype = NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (checktype) {
|
|
|
|
case NONE:
|
|
|
|
break;
|
|
|
|
case ADDR:
|
|
|
|
sa = (const struct sockaddr *)(((const u_int8_t*)ext)+baselen);
|
|
|
|
if (len < baselen + sal)
|
|
|
|
return EINVAL;
|
|
|
|
if (baselen + PFKEY_ALIGN8(sa->sa_len) != len)
|
|
|
|
return EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-06-29 00:49:50 +00:00
|
|
|
key_init(void)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
for (i = 0; i < IPSEC_DIR_MAX; i++)
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_INIT(&V_sptree[i]);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_INIT(&V_sahtree);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
for (i = 0; i <= SADB_SATYPE_MAX; i++)
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_INIT(&V_regtree[i]);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
Commit step 1 of the vimage project, (network stack)
virtualization work done by Marko Zec (zec@).
This is the first in a series of commits over the course
of the next few weeks.
Mark all uses of global variables to be virtualized
with a V_ prefix.
Use macros to map them back to their global names for
now, so this is a NOP change only.
We hope to have caught at least 85-90% of what is needed
so we do not invalidate a lot of outstanding patches again.
Obtained from: //depot/projects/vimage-commit2/...
Reviewed by: brooks, des, ed, mav, julian,
jamie, kris, rwatson, zec, ...
(various people I forgot, different versions)
md5 (with a bit of help)
Sponsored by: NLnet Foundation, The FreeBSD Foundation
X-MFC after: never
V_Commit_Message_Reviewed_By: more people than the patch
2008-08-17 23:27:27 +00:00
|
|
|
LIST_INIT(&V_acqtree);
|
|
|
|
LIST_INIT(&V_spacqtree);
|
2002-10-16 02:10:08 +00:00
|
|
|
|
First pass at separating per-vnet initializer functions
from existing functions for initializing global state.
At this stage, the new per-vnet initializer functions are
directly called from the existing global initialization code,
which should in most cases result in compiler inlining those
new functions, hence yielding a near-zero functional change.
Modify the existing initializer functions which are invoked via
protosw, like ip_init() et. al., to allow them to be invoked
multiple times, i.e. per each vnet. Global state, if any,
is initialized only if such functions are called within the
context of vnet0, which will be determined via the
IS_DEFAULT_VNET(curvnet) check (currently always true).
While here, V_irtualize a few remaining global UMA zones
used by net/netinet/netipsec networking code. While it is
not yet clear to me or anybody else whether this is the right
thing to do, at this stage this makes the code more readable,
and makes it easier to track uncollected UMA-zone-backed
objects on vnet removal. In the long run, it's quite possible
that some form of shared use of UMA zone pools among multiple
vnets should be considered.
Bump __FreeBSD_version due to changes in layout of structs
vnet_ipfw, vnet_inet and vnet_net.
Approved by: julian (mentor)
2009-04-06 22:29:41 +00:00
|
|
|
if (!IS_DEFAULT_VNET(curvnet))
|
|
|
|
return;
|
|
|
|
|
|
|
|
SPTREE_LOCK_INIT();
|
|
|
|
REGTREE_LOCK_INIT();
|
|
|
|
SAHTREE_LOCK_INIT();
|
|
|
|
ACQ_LOCK_INIT();
|
|
|
|
SPACQ_LOCK_INIT();
|
|
|
|
|
2002-10-16 02:10:08 +00:00
|
|
|
#ifndef IPSEC_DEBUG2
|
2014-10-23 20:43:16 +00:00
|
|
|
callout_init(&key_timer, CALLOUT_MPSAFE);
|
|
|
|
callout_reset(&key_timer, hz, key_timehandler, NULL);
|
2002-10-16 02:10:08 +00:00
|
|
|
#endif /*IPSEC_DEBUG2*/
|
|
|
|
|
|
|
|
/* initialize key statistics */
|
|
|
|
keystat.getspi_count = 1;
|
|
|
|
|
2008-03-14 16:25:40 +00:00
|
|
|
printf("IPsec: Initialized Security Association Processing.\n");
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef VIMAGE
|
|
|
|
void
|
|
|
|
key_destroy(void)
|
|
|
|
{
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_HEAD(, secpolicy) drainq;
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
struct secpolicy *sp, *nextsp;
|
2010-03-28 06:51:50 +00:00
|
|
|
struct secacq *acq, *nextacq;
|
|
|
|
struct secspacq *spacq, *nextspacq;
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
struct secashead *sah, *nextsah;
|
|
|
|
struct secreg *reg;
|
|
|
|
int i;
|
|
|
|
|
2014-12-24 18:34:56 +00:00
|
|
|
TAILQ_INIT(&drainq);
|
|
|
|
SPTREE_WLOCK();
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
for (i = 0; i < IPSEC_DIR_MAX; i++) {
|
2014-12-25 13:38:51 +00:00
|
|
|
TAILQ_CONCAT(&drainq, &V_sptree[i], chain);
|
2014-12-24 18:34:56 +00:00
|
|
|
}
|
|
|
|
SPTREE_WUNLOCK();
|
|
|
|
sp = TAILQ_FIRST(&drainq);
|
|
|
|
while (sp != NULL) {
|
|
|
|
nextsp = TAILQ_NEXT(sp, chain);
|
|
|
|
KEY_FREESP(&sp);
|
|
|
|
sp = nextsp;
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
SAHTREE_LOCK();
|
|
|
|
for (sah = LIST_FIRST(&V_sahtree); sah != NULL; sah = nextsah) {
|
|
|
|
nextsah = LIST_NEXT(sah, chain);
|
|
|
|
if (__LIST_CHAINED(sah)) {
|
|
|
|
LIST_REMOVE(sah, chain);
|
|
|
|
free(sah, M_IPSEC_SAH);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SAHTREE_UNLOCK();
|
|
|
|
|
|
|
|
REGTREE_LOCK();
|
|
|
|
for (i = 0; i <= SADB_SATYPE_MAX; i++) {
|
|
|
|
LIST_FOREACH(reg, &V_regtree[i], chain) {
|
|
|
|
if (__LIST_CHAINED(reg)) {
|
|
|
|
LIST_REMOVE(reg, chain);
|
|
|
|
free(reg, M_IPSEC_SAR);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
REGTREE_UNLOCK();
|
|
|
|
|
|
|
|
ACQ_LOCK();
|
2010-03-28 06:51:50 +00:00
|
|
|
for (acq = LIST_FIRST(&V_acqtree); acq != NULL; acq = nextacq) {
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
nextacq = LIST_NEXT(acq, chain);
|
|
|
|
if (__LIST_CHAINED(acq)) {
|
|
|
|
LIST_REMOVE(acq, chain);
|
|
|
|
free(acq, M_IPSEC_SAQ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ACQ_UNLOCK();
|
|
|
|
|
|
|
|
SPACQ_LOCK();
|
2010-03-28 06:51:50 +00:00
|
|
|
for (spacq = LIST_FIRST(&V_spacqtree); spacq != NULL;
|
|
|
|
spacq = nextspacq) {
|
|
|
|
nextspacq = LIST_NEXT(spacq, chain);
|
|
|
|
if (__LIST_CHAINED(spacq)) {
|
|
|
|
LIST_REMOVE(spacq, chain);
|
|
|
|
free(spacq, M_IPSEC_SAQ);
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
SPACQ_UNLOCK();
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
Introduce an infrastructure for dismantling vnet instances.
Vnet modules and protocol domains may now register destructor
functions to clean up and release per-module state. The destructor
mechanisms can be triggered by invoking "vimage -d", or a future
equivalent command which will be provided via the new jail framework.
While this patch introduces numerous placeholder destructor functions,
many of those are currently incomplete, thus leaking memory or (even
worse) failing to stop all running timers. Many of such issues are
already known and will be incrementaly fixed over the next weeks in
smaller incremental commits.
Apart from introducing new fields in structs ifnet, domain, protosw
and vnet_net, which requires the kernel and modules to be rebuilt, this
change should have no impact on nooptions VIMAGE builds, since vnet
destructors can only be called in VIMAGE kernels. Moreover,
destructor functions should be in general compiled in only in
options VIMAGE builds, except for kernel modules which can be safely
kldunloaded at run time.
Bump __FreeBSD_version to 800097.
Reviewed by: bz, julian
Approved by: rwatson, kib (re), julian (mentor)
2009-06-08 17:15:40 +00:00
|
|
|
#endif
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX: maybe This function is called after INBOUND IPsec processing.
|
|
|
|
*
|
|
|
|
* Special check for tunnel-mode packets.
|
|
|
|
* We must make some checks for consistency between inner and outer IP header.
|
|
|
|
*
|
|
|
|
* xxx more checks to be provided
|
|
|
|
*/
|
|
|
|
int
|
2014-12-03 03:50:54 +00:00
|
|
|
key_checktunnelsanity(struct secasvar *sav, u_int family, caddr_t src,
|
|
|
|
caddr_t dst)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sav->sah != NULL, ("null SA header"));
|
2002-10-16 02:10:08 +00:00
|
|
|
|
|
|
|
/* XXX: check inner IP header */
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* record data transfer on SA, and update timestamps */
|
|
|
|
void
|
2014-12-03 03:50:54 +00:00
|
|
|
key_sa_recordxfer(struct secasvar *sav, struct mbuf *m)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sav != NULL, ("Null secasvar"));
|
|
|
|
IPSEC_ASSERT(m != NULL, ("Null mbuf"));
|
2002-10-16 02:10:08 +00:00
|
|
|
if (!sav->lft_c)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX Currently, there is a difference of bytes size
|
|
|
|
* between inbound and outbound processing.
|
|
|
|
*/
|
2006-03-25 13:38:52 +00:00
|
|
|
sav->lft_c->bytes += m->m_pkthdr.len;
|
2002-10-16 02:10:08 +00:00
|
|
|
/* to check bytes lifetime is done in key_timehandler(). */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We use the number of packets as the unit of
|
2006-03-25 13:38:52 +00:00
|
|
|
* allocations. We increment the variable
|
2002-10-16 02:10:08 +00:00
|
|
|
* whenever {esp,ah}_{in,out}put is called.
|
|
|
|
*/
|
2006-03-25 13:38:52 +00:00
|
|
|
sav->lft_c->allocations++;
|
2002-10-16 02:10:08 +00:00
|
|
|
/* XXX check for expires? */
|
|
|
|
|
|
|
|
/*
|
2006-03-25 13:38:52 +00:00
|
|
|
* NOTE: We record CURRENT usetime by using wall clock,
|
2002-10-16 02:10:08 +00:00
|
|
|
* in seconds. HARD and SOFT lifetime are measured by the time
|
2006-03-25 13:38:52 +00:00
|
|
|
* difference (again in seconds) from usetime.
|
2002-10-16 02:10:08 +00:00
|
|
|
*
|
|
|
|
* usetime
|
|
|
|
* v expire expire
|
|
|
|
* -----+-----+--------+---> t
|
|
|
|
* <--------------> HARD
|
|
|
|
* <-----> SOFT
|
|
|
|
*/
|
2006-03-25 13:38:52 +00:00
|
|
|
sav->lft_c->usetime = time_second;
|
2002-10-16 02:10:08 +00:00
|
|
|
/* XXX check for expires? */
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-02-24 18:09:31 +00:00
|
|
|
key_sa_chgstate(struct secasvar *sav, u_int8_t state)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sav != NULL, ("NULL sav"));
|
|
|
|
SAHTREE_LOCK_ASSERT();
|
2002-10-16 02:10:08 +00:00
|
|
|
|
2003-09-01 05:35:55 +00:00
|
|
|
if (sav->state != state) {
|
|
|
|
if (__LIST_CHAINED(sav))
|
|
|
|
LIST_REMOVE(sav, chain);
|
|
|
|
sav->state = state;
|
|
|
|
LIST_INSERT_HEAD(&sav->sah->savtree[state], sav, chain);
|
|
|
|
}
|
2002-10-16 02:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-12-03 03:50:54 +00:00
|
|
|
key_sa_stir_iv(struct secasvar *sav)
|
2002-10-16 02:10:08 +00:00
|
|
|
{
|
|
|
|
|
2003-09-29 22:57:43 +00:00
|
|
|
IPSEC_ASSERT(sav->iv != NULL, ("null IV"));
|
2002-10-16 02:10:08 +00:00
|
|
|
key_randomfill(sav->iv, sav->ivlen);
|
|
|
|
}
|
|
|
|
|
2006-03-25 13:38:52 +00:00
|
|
|
/*
|
|
|
|
* Take one of the kernel's security keys and convert it into a PF_KEY
|
|
|
|
* structure within an mbuf, suitable for sending up to a waiting
|
|
|
|
* application in user land.
|
|
|
|
*
|
|
|
|
* IN:
|
|
|
|
* src: A pointer to a kernel security key.
|
|
|
|
* exttype: Which type of key this is. Refer to the PF_KEY data structures.
|
|
|
|
* OUT:
|
|
|
|
* a valid mbuf or NULL indicating an error
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static struct mbuf *
|
|
|
|
key_setkey(struct seckey *src, u_int16_t exttype)
|
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
struct sadb_key *p;
|
2007-06-15 22:35:59 +00:00
|
|
|
int len;
|
2006-03-25 13:38:52 +00:00
|
|
|
|
|
|
|
if (src == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2007-06-15 22:35:59 +00:00
|
|
|
len = PFKEY_ALIGN8(sizeof(struct sadb_key) + _KEYLEN(src));
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
2006-03-25 13:38:52 +00:00
|
|
|
if (m == NULL)
|
|
|
|
return NULL;
|
2013-03-15 10:20:15 +00:00
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
2006-03-25 13:38:52 +00:00
|
|
|
p = mtod(m, struct sadb_key *);
|
|
|
|
bzero(p, len);
|
|
|
|
p->sadb_key_len = PFKEY_UNIT64(len);
|
|
|
|
p->sadb_key_exttype = exttype;
|
|
|
|
p->sadb_key_bits = src->bits;
|
|
|
|
bcopy(src->key_data, _KEYBUF(p), _KEYLEN(src));
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Take one of the kernel's lifetime data structures and convert it
|
|
|
|
* into a PF_KEY structure within an mbuf, suitable for sending up to
|
|
|
|
* a waiting application in user land.
|
|
|
|
*
|
|
|
|
* IN:
|
|
|
|
* src: A pointer to a kernel lifetime structure.
|
|
|
|
* exttype: Which type of lifetime this is. Refer to the PF_KEY
|
|
|
|
* data structures for more information.
|
|
|
|
* OUT:
|
|
|
|
* a valid mbuf or NULL indicating an error
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static struct mbuf *
|
|
|
|
key_setlifetime(struct seclifetime *src, u_int16_t exttype)
|
|
|
|
{
|
|
|
|
struct mbuf *m = NULL;
|
|
|
|
struct sadb_lifetime *p;
|
|
|
|
int len = PFKEY_ALIGN8(sizeof(struct sadb_lifetime));
|
|
|
|
|
|
|
|
if (src == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2013-03-15 10:20:15 +00:00
|
|
|
m = m_get2(len, M_NOWAIT, MT_DATA, 0);
|
2006-03-25 13:38:52 +00:00
|
|
|
if (m == NULL)
|
|
|
|
return m;
|
2013-03-15 10:20:15 +00:00
|
|
|
m_align(m, len);
|
|
|
|
m->m_len = len;
|
2006-03-25 13:38:52 +00:00
|
|
|
p = mtod(m, struct sadb_lifetime *);
|
|
|
|
|
|
|
|
bzero(p, len);
|
|
|
|
p->sadb_lifetime_len = PFKEY_UNIT64(len);
|
|
|
|
p->sadb_lifetime_exttype = exttype;
|
|
|
|
p->sadb_lifetime_allocations = src->allocations;
|
|
|
|
p->sadb_lifetime_bytes = src->bytes;
|
|
|
|
p->sadb_lifetime_addtime = src->addtime;
|
|
|
|
p->sadb_lifetime_usetime = src->usetime;
|
|
|
|
|
|
|
|
return m;
|
|
|
|
|
|
|
|
}
|