/* routines that interface with the kernel's IPsec mechanism
* Copyright (C) 1997 Angelos D. Keromytis.
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
* 2005/03/25 13:47 zqqa <zqqa@163.com> modify
* RCSID $Id: kernel.c,v 1.149 2002/04/01 08:46:54 dhr Exp $
*/
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <freeswan.h>
#ifdef KLIPS
#include <sys/time.h> /* for select(2) */
#include <sys/types.h> /* for select(2) */
# include <signal.h>
# include <pfkeyv2.h>
# include <pfkey.h>
#endif /* KLIPS */
#include <linux/config.h>
#ifdef CONFIG_LEDMAN
#include <linux/ledman.h>
#endif
#include "constants.h"
#include "defs.h"
#include "rnd.h"
#include "id.h"
#include "x509.h"
#include "connections.h" /* needs id.h */
#include "state.h"
#include "timer.h"
#include "kernel.h"
#include "log.h"
#include "server.h"
#include "whack.h" /* for RC_LOG_SERIOUS */
#include "alg_info.h"
#include "kernel_alg.h"
#ifdef NAT_TRAVERSAL
#include "packet.h" /* for pb_stream in nat_traversal.h */
#include "nat_traversal.h"
#endif
bool can_do_IPcomp = TRUE; /* can system actually perform IPCOMP? */
/* How far can IPsec messages arrive out of order before the anti-replay
* logic loses track and swats them? 64 is the best KLIPS can do.
*/
#define REPLAY_WINDOW 64
static bool route_and_eroute(struct connection *c
, struct state *st); /* forward declaration */
static bool onlyeroute(struct connection *c
, struct state *st); /* zqqa modified ,forward declaration */
/* test if the routes required for two different connections agree
* It is assumed that the destination subnets agree; we are only
* testing that the interfaces and nexthops match.
*/
#define routes_agree(c, d) ((c)->interface == (d)->interface \
&& sameaddr(&(c)->this.host_nexthop, &(d)->this.host_nexthop))
#ifndef KLIPS
bool no_klips = TRUE; /* don't actually use KLIPS */
#else /* !KLIPS */
/* Declare eroute things early enough for uses.
*
* Flags are encoded above the low-order byte of verbs.
* "real" eroutes are only outbound. Inbound eroutes don't exist,
* but an addflow with an INBOUND flag allows IPIP tunnels to be
* limited to appropriate source and destination addresses.
*/
#define ERO_MASK 0xFF
#define ERO_FLAG_SHIFT 8
#define ERO_DELETE SADB_X_DELFLOW
#define ERO_ADD SADB_X_ADDFLOW
#define ERO_REPLACE (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT))
#define ERO_ADD_INBOUND (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
/* bare (connectionless) shunt (eroute) table
*
* Bare shunts are those that don't "belong" to a connection.
* This happens because some %trapped traffic hasn't yet or cannot be
* assigned to a connection. The usual reason is that we cannot discover
* the peer SG. Another is that even when the peer has been discovered,
* it may be that no connection matches all the particulars.
* Bare shunts are either %hold or %pass.
* We record them so that, with scanning, we can discover
* which %holds are news and which %passes should expire.
*/
#define SHUNT_SCAN_INTERVAL (60 * 2) /* time between scans of eroutes */
/* SHUNT_PATIENCE only has resolution down to a multiple of the sample rate,
* SHUNT_SCAN_INTERVAL.
* By making SHUNT_PATIENCE an odd multiple of half of SHUNT_SCAN_INTERVAL,
* we minimize the effects of jitter.
*/
#define SHUNT_PATIENCE (SHUNT_SCAN_INTERVAL * 15 / 2) /* inactivity timeout */
struct bare_shunt {
ip_subnet ours;
ip_subnet his;
ip_said said;
unsigned long count;
time_t last_activity;
struct bare_shunt *next;
};
static struct bare_shunt *bare_shunts = NULL;
#ifdef DEBUG
static void
DBG_bare_shunt(const char *op, const struct bare_shunt *bs)
{
DBG(DBG_KLIPS,
{
char ourst[SUBNETTOT_BUF];
char hist[SUBNETTOT_BUF];
char sat[SATOT_BUF];
subnettot(&(bs)->ours, 0, ourst, sizeof(ourst));
subnettot(&(bs)->his, 0, hist, sizeof(hist));
satot(&(bs)->said, 0, sat, sizeof(sat));
DBG_log("%s bare shunt %p %s -> %s => %s"
, op, (const void *)(bs), ourst, hist, sat);
});
}
#else /* !DEBUG */
#define DBG_bare_shunt(op, bs) {}
#endif /* !DEBUG */
/* information from /proc/net/ipsec_eroute */
struct eroute_info {
unsigned long count;
ip_subnet ours;
ip_subnet his;
ip_address dst;
ip_said said;
struct eroute_info *next;
};
/* The orphaned_holds table records %holds for which we
* scan_proc_shunts found no representation of in any connection.
* The corresponding ACQUIRE message might have been lost.
*/
struct eroute_info *orphaned_holds = NULL;
static bool shunt_eroute(struct connection *c
, unsigned int op, const char *opname); /* forward declaration */
bool no_klips = FALSE; /* don't actually use KLIPS */
int pfkeyfd = NULL_FD;
typedef u_int32_t pfkey_seq_t;
static pfkey_seq_t pfkey_seq = 0; /* sequence number for our PF_KEY messages */
static pid_t pid;
static void pfkey_register(void);
#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */
static sparse_names pfkey_type_names = {
NE(SADB_RESERVED),
NE(SADB_GETSPI),
NE(SADB_UPDATE),
NE(SADB_ADD),
NE(SADB_DELETE),
NE(SADB_GET),
NE(SADB_ACQUIRE),
NE(SADB_REGISTER),
NE(SADB_EXPIRE),
NE(SADB_FLUSH),
NE(SADB_DUMP),
NE(SADB_X_PROMISC),
NE(SADB_X_PCHANGE),
NE(SADB_X_GRPSA),
NE(SADB_X_ADDFLOW),
NE(SADB_X_DELFLOW),
NE(SADB_X_DEBUG),
#ifdef NAT_TRAVERSAL
NE(SADB_X_NAT_T_NEW_MAPPING),
#endif
NE(SADB_MAX),
{ 0, sparse_end }
};
#ifdef NEVER /* not needed yet */
static sparse_names pfkey_ext_names = {
NE(SADB_EXT_RESERVED),
NE(SADB_EXT_SA),
NE(SADB_EXT_LIFETIME_CURRENT),
NE(SADB_EXT_LIFETIME_HARD),
NE(SADB_EXT_LIFETIME_SOFT),
NE(SADB_EXT_ADDRESS_SRC),
NE(SADB_EXT_ADDRESS_DST),
NE(SADB_EXT_ADDRESS_PROXY),
NE(SADB_EXT_KEY_AUTH),
NE(SADB_EXT_KEY_ENCRYPT),
NE(SADB_EXT_IDENTITY_SRC),
NE(SADB_EXT_IDENTITY_DST),
NE(SADB_EXT_SENSITIVITY),
NE(SADB_EXT_PROPOSAL),
NE(SADB_EXT_SUPPORTED_AUTH),
NE(SADB_EXT_SUPPORTED_ENCRYPT),
NE(SADB_EXT_SPIRANGE),
NE(SADB_X_EXT_KMPRIVATE),
NE(SADB_X_EXT_SATYPE2),
NE(SADB_X_EXT_SA2),
NE(SADB_X_EXT_ADDRESS_DST2),
NE(SADB_X_EXT_ADDRESS_SRC_FLOW),
NE(SADB_X_EXT_ADDRESS_DST_FLOW),
NE(SADB_X_EXT_ADDRESS_SRC_MASK),
NE(SADB_X_EXT_ADDRESS_DST_MASK),
NE(SADB_X_EXT_DEBUG),
{ 0, sparse_end }
};
#endif /* NEVER */
#undef NE
static void
init_pfkey(void)
{
pid = getpid();
/* open PF_KEY socket */
pfkeyfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
if (pfkeyfd == -1)
exit_log_errno((e, "socket() in init_pfkeyfd()"));
#ifdef NEVER /* apparently unsupported! */
if (fcntl(pfkeyfd, F_SETFL, O_NONBLOCK) != 0)
exit_log_errno((e, "fcntl() in init_pfkeyfd()"));
#endif
DBG(DBG_KLIPS,
DBG_log("process %u listening for PF_KEY_V2 on file descriptor %d", (unsigned)pid, pfkeyfd));
pfkey_register(); /* register SA types that we can negotiate */
}
/* Kinds of PF_KEY message from the kernel:
* - response to a request from us
* + ACK/NAK
* + Register: indicates transforms supported by kernel
* + SPI requested by getspi
* - Acquire, requesting us to deal with trapped clear packet
* - expiration of of one of our SAs
* - messages to other processes
*
* To minimize the effect on the event-driven structure of Pluto,
* responses are dealt with synchronously. We hope that the Kernel
* produces them synchronously. We must "read ahead" in the PF_KEY
* stream, saving Acquire and Expiry messages that are encountered.
* We ignore messages to other processes.
*/
typedef union {
unsigned char bytes[PFKEYv2_MAX_MSGSIZE];
struct sadb_msg msg;
} pfkey_buf;
/* queue of unprocessed PF_KEY messages input from kernel
* Note that the pfkey_buf may be partly allocated, reflecting
* the variable length nature of the messages. So the link field
* must come first.
*/
typedef struct pfkey_item {
struct pfkey_item *next;
pfkey_buf buf;
} pfkey_item;
static pfkey_item *pfkey_iq_head = NULL; /* oldest */
static pfkey_item *pfkey_iq_tail; /* youngest */
static bool
pfkey_input_ready(void)
{
fd_set readfds;
int ndes;
struct timeval tm;
tm.tv_sec = 0; /* don't wait at all */
tm.tv_usec = 0;
FD_ZERO(&readfds); /* we only care about pfkeyfd */
FD_SET(pfkeyfd, &readfds);
do {
ndes = select(pfkeyfd + 1, &readfds, NULL, NULL, &tm);
} while (ndes == -1 && errno == EINTR);
if (ndes < 0)
{
log_errno((e, "select() failed in pfkey_get()"));
return FALSE;
}
if (ndes == 0)
return FALSE; /* nothing to read */
passert(ndes == 1 && FD_ISSET(pfkeyfd, &readfds));
return TRUE;
}
/* get a PF_KEY message from kernel.
* Returns TRUE is message found, FALSE if no message pending,
* and aborts or keeps trying when an error is encountered.
* The only validation of the message is that the message length
* received matches that in the message header, and that the message
* is for this process.
*/
static bool
pfkey_get(pfkey_buf *buf)
{
for (;;)
{
ssize_t len;
if (!pfkey_input_ready())
return FALSE;
len = read(pfkeyfd, buf->bytes, sizeof(buf->bytes));
if (len < 0)
{
if (errno == EAGAIN)
return FALSE;
log_errno((e, "read() failed in pfkey_get()"));
return FALSE;
}
else if ((size_t) len < sizeof(buf->msg))
{
log("pfkey_get read truncated PF_KEY message: %d bytes; ignoring message", len);
}
else if ((size_t) len != buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN)
{
log("pfkey_get read PF_KEY message with length %d that doesn't equal sadb_msg_len %u * %d; ignoring message"
, len, (unsigned) buf->msg.sadb_msg_len, IPSEC_PFKEYv2_ALIGN);
}
/* for now, unsolicited messages can be:
* SADB_ACQUIRE, SADB_REGISTER
*/
else if (!(buf->msg.sadb_msg_pid == (unsigned)pid
|| (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_ACQUIRE)
#ifdef NAT_TRAVERSAL
|| (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING)
#endif
|| (buf->msg.sadb_msg_type == SADB_REGISTER)))
{
/* not for us: ignore */
DBG(DBG_KLIPS,
DBG_log("pfkey_get: ignoring PF_KEY %s message %u for process %u"
, sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
, buf->msg.sadb_msg_seq
, buf->msg.sadb_msg_pid));
}
else
{
DBG(DBG_KLIPS,
DBG_log("pfkey_get: %s message %u"
, sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
, buf->msg.sadb_msg_seq));
return TRUE;
}
}
}
/* get a response to a specific message */
static bool
pfkey_get_response(pfkey_buf *buf, pfkey_seq_t seq)
{
while (pfkey_get(buf))
{
if (buf->msg.sadb_msg_pid == (unsigned)pid
&& buf->msg.sadb_msg_seq == seq)
{
return TRUE;
}
else
{
/* Not for us: queue it. */
size_t bl = buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN;
pfkey_item *it = alloc_bytes(offsetof(pfkey_item, buf) + bl, "pfkey_item");
memcpy(&it->buf, buf, bl);
it->next = NULL;
if (pfkey_iq_head == NULL)
{
pfkey_iq_head = it;
}
else
{
pfkey_iq_tail->next = it;
}
pfkey_iq_tail = it;
}
}
return FALSE;
}
/* Process a SADB_REGISTER message from KLIPS.
* This will be a response to one of ours, but it may be asynchronous
* (if KLIPS modules are loaded and unloaded).
* Some sanity checking has already been performed.
*/
static void
process_pfkey_register_response(pfkey_buf *buf)
{
/* Find out what the kernel can support.
* In fact, the only question at the moment
* is whether it can support IPcomp.
* So we ignore the rest.
* ??? we really should pay attention to what transforms are supported.
*/
switch (buf->msg.sadb_msg_satype)
{
case SADB_SATYPE_AH:
break;
case SADB_SATYPE_ESP:
#ifndef NO_KERNEL_ALG
kernel_alg_register_pfkey(buf, sizeof (pfkey_buf));
#endif
break;
case SADB_X_SATYPE_COMP:
/* ??? There ought to be an extension to list the
* supported algorithms, but RFC 2367 doesn't
* list one for IPcomp. KLIPS uses SADB_X_CALG_DEFLATE.
* Since we only implement deflate, we'll assume this.
*/
can_do_IPcomp = TRUE;
break;
case SADB_X_SATYPE_IPIP:
break;
default:
break;
}
}
/* Create ip_address out of sockaddr. Ignore port! */
static err_t
sockaddr_to_ip_address(const struct sockaddr *src, ip_address *dest)
{
switch (src->sa_family)
{
case AF_INET:
initaddr((const void *) &((const struct sockaddr_in *)src)->sin_addr
, sizeof(((const struct sockaddr_in *)src)->sin_addr)
, src->sa_family, dest);
return NULL;
case AF_INET6:
initaddr((const void *) &((const struct sockaddr_in6 *)src)->sin6_addr
, sizeof(((const struct sockaddr_in6 *)src)->sin6_addr)
, src->sa_family, dest);
return NULL;
default:
return "unknown address family";
}
}
static void
record_and_initiate_opportunistic(ip_subnet *ours, ip_subnet *his)
{
passert(samesubnettype(ours, his));
/* Add to bare shunt list.
* We need to do this because the shunt was installed by KLIPS
* which can't do this itself.
*/
{
struct bare_shunt *bs = alloc_thing(struct bare_shunt, "bare shunt");
bs->ours = *ours;
bs->his = *his;
bs->said.proto = SA_INT;
bs->said.spi = htonl(SPI_HOLD);
bs->said.dst = *aftoinfo(subnettypeof(ours))->any;
bs->count = 0;
bs->last_activity = now();
bs->next = bare_shunts;
bare_shunts = bs;
DBG_bare_shunt("add", bs);
}
/* actually initiate opportunism */
{
ip_address src, dst;
networkof(ours, &src);
networkof(his, &dst);
initiate_opportunistic(&src, &dst, TRUE, NULL_FD);
}
/* if present, remove from orphaned_holds list.
* NOTE: we do this last in case ours or his is a pointer into a member.
*/
{
struct eroute_info **pp, *p;
for (pp = &orphaned_holds; (p = *pp) != NULL; pp = &p->next)
{
if (samesubnet(ours, &p->ours) && samesubnet(his, &p->his))
{
*pp = p->next;
pfree(p);
break;
}
}
}
}
/* Processs a SADB_ACQUIRE message from KLIPS.
* Try to build an opportunistic connection!
* See RFC 2367 "PF_KEY Key Management API, Version 2" 3.1.6
* <base, address(SD), (address(P)), (identity(SD),) (sensitivity,) proposal>
* - extensions for source and data IP addresses
* - optional extensions for identity [not useful for us?]
* - optional extension for sensitivity [not useful for us?]
* - expension for proposal [not useful for us?]
*
* ??? We must use the sequence number in creating an SA.
* We actually need to create up to 4 SAs each way. Which one?
* I guess it depends on the protocol present in the sadb_msg_satype.
* For now, we'll ignore this requirement.
*
* ??? We need some mechanism to make sure that multiple ACQUIRE messages
* don't cause a whole bunch of redundant negotiations.
*/
static void
process_pfkey_acquire(pfkey_buf *buf, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];
struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];
ip_address src, dst;
ip_subnet ours, his;
err_t ugh = NULL;
/* assumption: we're only catching our own outgoing packets
* so source is our end and destination is the other end.
* Verifying this is not actually convenient.
*
* This stylized control structure yields a complaint or
* desired results. For compactness, a pointer value is
* treated as a boolean. Logically, the structure is:
* keep going as long as things are OK.
*/
if (buf->msg.sadb_msg_pid == 0 /* we only wish to hear from kernel */
&& !(ugh = sockaddr_to_ip_address((struct sockaddr *)(void *)&srcx[1], &src))
&& !(ugh = sockaddr_to_ip_address((struct sockaddr *)(void *)&dstx[1], &dst))
&& !(ugh = addrtypeof(&src) == addrtypeof(&dst)? NULL : "conflicting address types")
&& !(ugh = addrtosubnet(&src, &ours))
&& !(ugh = addrtosubnet(&dst, &his)))
record_and_initiate_opportunistic(&ours, &his);
if (ugh != NULL)
log("SADB_ACQUIRE message from KLIPS malformed: %s", ugh);
}
/* Handle PF_KEY messages from the kernel that are not dealt with
* synchronously. In other words, all but responses to PF_KEY messages
* that we sent.
*/
static void
pfkey_async(pfkey_buf *buf)
{
struct sadb_ext *extensions[SADB_EXT_MAX + 1];
if (pfkey_msg_parse(&buf->msg, NULL, extensions, EXT_BITS_OUT))
{
log("pfkey_async:"
" unparseable PF_KEY message:"
" %s len=%d, errno=%d, seq=%d, pid=%d; message ignored"
, sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
, buf->msg.sadb_msg_len
, buf->msg.sadb_msg_errno
, buf->msg.sadb_msg_seq
, buf->msg.sadb_msg_pid);
}
else
{
DBG(DBG_CONTROL | DBG_KLIPS, DBG_log("pfkey_async:"
" %s len=%u, errno=%u, satype=%u, seq=%u, pid=%u"
, sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type)
, buf->msg.sadb_msg_len
, buf->msg.sadb_msg_errno
, buf->msg.sadb_msg_satype
, buf->msg.sadb_msg_seq
, buf->msg.sadb_msg_pid));
switch (buf->msg.sadb_msg_type)
{
case SADB_REGISTER:
process_pfkey_register_response(buf);
break;
case SADB_ACQUIRE:
/* to simulate loss of ACQUIRE, delete this call */
process_pfkey_acquire(buf, extensions);
break;
#ifdef NAT_TRAVERSAL
case SADB_X_NAT_T_NEW_MAPPING:
process_pfkey_nat_t_new_mapping(&(buf->msg), extensions);
break;
#endif
default:
/* ignored */
break;
}
}
}
/* asynchronous messages from our queue */
void
pfkey_dequeue(void)
{
while (pfkey_iq_head != NULL)
{
pfkey_item *it = pfkey_iq_head;
pfkey_async(&it->buf);
pfkey_iq_head = it->next;
pfree(it);
}
/* Handle any orphaned holds, but only if no pfkey input is pending.
* For each, we initiate Opportunistic.
* note: we don't need to advance the pointer because
* record_and_initiate_opportunistic will remove the current
* record each time we call it.
*/
while (orphaned_holds != NULL && !pfkey_input_ready())
record_and_initiate_opportunistic(&orphaned_holds->ours
, &orphaned_holds->his);
}
/* asynchronous messages directly from PF_KEY socket */
void
pfkey_event(void)
{
pfkey_buf buf;
if (pfkey_get(&buf))
pfkey_async(&buf);
}
#endif /* KLIPS */
/* Generate Unique SPI numbers.
*
* The specs say that the number must not be less than IPSEC_DOI_SPI_MIN.
* Pluto generates numbers not less than IPSEC_DOI_SPI_OUR_MIN,
* reserving numbers in between for manual keying (but we cannot so
* restrict numbers generated by our peer).
* XXX This should be replaced by a call to the kernel when
* XXX we get an API.
* The returned SPI is in network byte order.
* We use a random number as the initial SPI so that there is
* a good chance that different Pluto instances will choose
* different SPIs. This is good for two reasons.
* - the keying material for the initiator and responder only
* differs if the SPIs differ.
* - if Pluto is restarted, it would otherwise recycle the SPI
* numbers and confuse everything. When the kernel generates
* SPIs, this will no longer matter.
* We then allocate numbers sequentially. Thus we don't have to
* check if the number was previously used (assuming that no
* SPI lives longer than 4G of its successors).
*/
ipsec_spi_t
get_ipsec_spi(ipsec_spi_t avoid)
{
static ipsec_spi_t spi = 0; /* host order, so not returned directly! */
spi++;
while (spi < IPSEC_DOI_SPI_OUR_MIN || spi == ntohl(avoid))
get_rnd_bytes((u_char *)&spi, sizeof(spi));
DBG(DBG_CONTROL,
{
ipsec_spi_t spi_net = htonl(spi);
DBG_dump("generate SPI:", (u_char *)&spi_net, sizeof(spi_net));
});
return htonl(spi);
}
/* Generate Unique CPI numbers.
* The result is returned as an SPI (4 bytes) in network order!
* The real bits are in the nework-low-order 2 bytes.
* Modelled on get_ipsec_spi, but range is more limited:
* 256-61439.
* If we can't find one easily, return 0 (a bad SPI,
* no matter what order) indicating failure.
*/
ipsec_spi_t
get_my_cpi(void)
{
static cpi_t
first_busy_cpi = 0,
latest_cpi;
while (!(IPCOMP_FIRST_NEGOTIATED <= first_busy_cpi && first_busy_cpi < IPCOMP_LAST_NEGOTIATED))
{
get_rnd_bytes((u_char *)&first_busy_cpi, sizeof(first_busy_cpi));
latest_cpi = first_busy_cpi;
}
latest_cpi++;
if (latest_cpi == first_busy_cpi)
find_my_cpi_gap(&latest_cpi, &first_busy_cpi);
if (latest_cpi > IPCOMP_LAST_NEGOTIATED)
latest_cpi = IPCOMP_FIRST_NEGOTIATED;
return htonl((ipsec_spi_t)latest_cpi);
}
/* invoke the updown script to do the routing and firewall commands required
*
* The user-specified updown script is run. Parameters are fed to it in
* the form of environment variables. All such environment variables
* have names starting with "PLUTO_".
*
* The operation to be performed is specified by PLUTO_VERB. This
* verb has a suffix "-host" if the client on this end is just the
* host; otherwise the suffix is "-client". If the address family
* of the host is IPv6, an extra suffix of "-v6" is added.
*
* "prepare-host" and "prepare-client" are used to delete a route
* that may exist (due to forces outside of Pluto). It is used to
* prepare for pluto creating a route.
*
* "route-host" and "route-client" are used to install a route.
* Since routing is based only on destination, the PLUTO_MY_CLIENT_*
* values are probably of no use (using them may signify a bug).
*
* "unroute-host" and "unroute-client" are used to delete a route.
* Since routing is based only on destination, the PLUTO_MY_CLIENT_*
* values are probably of no use (using them may signify a bug).
*
* "up-host" and "up-client" are run when an eroute is added (not replaced).
* They are useful for adjusting a firewall: usually for adding a rule
* to let processed packets flow between clients. Note that only
* one eroute may exist for a pair of client subnets but inbound
* IPsec SAs may persist without an eroute.
*
* "down-host" and "down-client" are run when an eroute is deleted.
* They are useful for adjusting a firewall.
*/
#ifndef DEFAULT_UPDOWN
# define DEFAULT_UPDOWN "ipsec _updown"
#endif
static bool
do_command(struct connection *c, const char *verb)
{
char cmd[1536]; /* arbitrary limit on shell command length */
const char *verb_suffix;
/* figure out which verb suffix applies */
{
const char *hs, *cs;
switch (addrtypeof(&c->this.host_addr))
{
case AF_INET:
hs = "-host";
cs = "-client";
break;
case AF_INET6:
hs = "-host-v6";
cs = "-client-v6";
break;
default:
loglog(RC_LOG_SERIOUS, "unknown address family");
return FALSE;
}
verb_suffix = subnetishost(&c->this.client) && addrinsubnet(&c->this.host_addr, &c->this.client)
? hs : cs;
}
/* form the command string */
{
const ip_subnet *epc = EffectivePeerClient(c);
char
nexthop_str[ADDRTOT_BUF],
me_str[ADDRTOT_BUF],
myid_str[IDTOA_BUF],
myclient_str[SUBNETTOT_BUF],
myclientnet_str[ADDRTOT_BUF],
myclientmask_str[ADDRTOT_BUF],
peer_str[ADDRTOT_BUF],
peerid_str[IDTOA_BUF],
peerclient_str[SUBNETTOT_BUF],
peerclientnet_str[ADDRTOT_BUF],
peerclientmask_str[ADDRTOT_BUF];
ip_address ta;
addrtot(&c->this.host_nexthop, 0, nexthop_str, sizeof(nexthop_str));
addrtot(&c->this.host_addr, 0, me_str, sizeof(me_str));
idtoa(&c->this.id, myid_str, sizeof(myid_str));
subnettot(&c->this.client, 0, myclient_str, sizeof(myclientnet_str));
networkof(&c->this.client, &ta);
addrtot(&ta, 0, myclientnet_str, sizeof(myclientnet_str));
maskof(&c->this.client, &ta);
addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str));
addrtot(&c->that.host_addr, 0, peer_str, sizeof(peer_str));
idtoa(&c->that.id, peerid_str, sizeof(peerid_str));
subnettot(epc, 0, peerclient_str, sizeof(peerclientnet_str));
networkof(epc, &ta);
addrtot(&ta, 0, peerclientnet_str, sizeof(peerclientnet_str));
maskof(epc, &ta);
addrtot(&ta, 0, peerclientmask_str, sizeof(peerclientmask_str));
#ifdef SIMPLE_SCRIPTS
# define SE "setenv "
# define EQ " "
# define NL "\n"
#else
# define SE ""
# define EQ "="
# define NL " "
#endif
if (-1 == snprintf(cmd, sizeof(cmd),
#ifdef SIMPLE_SCRIPTS
"#!/bin/sh" NL
#endif
/* change VERSION when interface spec changes */
SE "PLUTO_VERSION" EQ "'1.1'" NL
SE "PLUTO_VERB" EQ "'%s%s'" NL
SE "PLUTO_CONNECTION" EQ "'%s'" NL
SE "PLUTO_NEXT_HOP" EQ "'%s'" NL
SE "PLUTO_INTERFACE" EQ "'%s'" NL
SE "PLUTO_ME" EQ "'%s'" NL
SE "PLUTO_MY_ID" EQ "'%s'" NL
SE "PLUTO_MY_CLIENT" EQ "'%s'" NL
SE "PLUTO_MY_CLIENT_NET" EQ "'%s'" NL
SE "PLUTO_MY_CLIENT_MASK" EQ "'%s'" NL
SE "PLUTO_MY_PORT" EQ "'%u'" NL
SE "PLUTO_MY_PROTOCOL" EQ "'%u'" NL
SE "PLUTO_PEER" EQ "'%s'" NL
SE "PLUTO_PEER_ID" EQ "'%s'" NL
SE "PLUTO_PEER_CLIENT" EQ "'%s'" NL
SE "PLUTO_PEER_CLIENT_NET" EQ "'%s'" NL
SE "PLUTO_PEER_CLIENT_MASK" EQ "'%s'" NL
SE "PLUTO_PEER_PORT" EQ "'%u'" NL
SE "PLUTO_PEER_PROTOCOL" EQ "'%u'" NL
"%s" NL /* actual script */
#ifndef SIMPLE_SCRIPTS
"2>&1 " /* capture stderr along with stdout */
#endif
, verb, verb_suffix
, c->name
, nexthop_str
, c->interface->vname
, me_str
, myid_str
, myclient_str
, myclientnet_str
, myclientmask_str
, c->this.port
, c->this.protocol
, peer_str
, peerid_str
, peerclient_str
, peerclientnet_str
, peerclientmask_str
, c->that.port
, c->that.protocol
, c->this.updown == NULL? DEFAULT_UPDOWN : c->this.updown))
{
loglog(RC_LOG_SERIOUS, "%s%s command too long!", verb, verb_suffix);
return FALSE;
}
}
DBG(DBG_CONTROL, DBG_log("executing %s%s: %s"
, verb, verb_suffix, cmd));
#ifdef KLIPS
#ifdef SIMPLE_SCRIPTS
if (!no_klips)
{
const char *temp_name = "/var/log/pluto_script";
int fd;
unlink(temp_name);
fd = open(temp_name, O_WRONLY|O_CREAT|O_TRUNC, 0777);
if (fd == -1) {
loglog(RC_LOG_SERIOUS, "unable to open %s", temp_name);
return FALSE;
}
if (write(fd, cmd, strlen(cmd)) != strlen(cmd)) {
loglog(RC_LOG_SERIOUS, "unable to write to %s", temp_name);
return FALSE;
}
if (close(fd) == -1) {
loglog(RC_LOG_SERIOUS, "unable to close %s", temp_name);
return FALSE;
}
strncpy(cmd, temp_name, sizeof(cmd));
}
#endif
if (!no_klips)
{
/* invoke the script, catching stderr and stdout
* It may be of concern that some file descriptors will
* be inherited. For the ones under our control, we
* have done fcntl(fd, F_SETFD, FD_CLOEXEC) to prevent this.
* Any used by library routines (perhaps the resolver or syslog)
* will remain.
*/
FILE *f = popen(cmd, "r");
if (f == NULL)
{
loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix);
#ifdef SIMPLE_SCRIPTS
unlink(cmd); /* don't need it now */
#endif
return FALSE;
}
/* log any output */
for (;;)
{
/* if response doesn't fit in this buffer, it will be folded */
char resp[256];
if (fgets(resp, sizeof(resp), f) == NULL)
{
if (ferror(f))
{
log_errno((e, "fgets failed on output of %s%s command"
, verb, verb_suffix));
#ifdef SIMPLE_SCRIPTS
unlink(cmd); /* don't need it now */
#endif
return FALSE;
}
else
{
passert(feof(f));
break;
}
}
else
{
char *e = resp + strlen(resp);
if (e > resp && e[-1] == '\n')
e[-1] = ''; /* trim trailing '\n' */
//log("%s%s output: %s", verb, verb_suffix, resp);
}
}
#ifdef SIMPLE_SCRIPTS
unlink(cmd); /* don't need it now */
#endif
/* report on and react to return code */
{
int r = pclose(f);
if (r == -1)
{
if (errno == ECHILD)
return TRUE;
log_errno((e, "pclose failed for %s%s command"
, verb, verb_suffix));
return FALSE;
}
else if (WIFEXITED(r))
{
if (WEXITSTATUS(r) != 0)
{
loglog(RC_LOG_SERIOUS, "%s%s command exited with status %d"
, verb, verb_suffix, WEXITSTATUS(r));
return FALSE;
}
}
else if (WIFSIGNALED(r))
{
loglog(RC_LOG_SERIOUS, "%s%s command exited with signal %d"
, verb, verb_suffix, WTERMSIG(r));
return FALSE;
}
else
{
loglog(RC_LOG_SERIOUS, "%s%s command exited with unknown status %d"
, verb, verb_suffix, r);
return FALSE;
}
}
}
#endif /* KLIPS */
return TRUE;
}
/* Check that we can route (and eroute). Diagnose if we cannot. */
static bool
could_route(struct connection *c)
{
struct connection *ero /* who, if anyone, owns our eroute? */
, *ro = route_owner(c, &ero); /* who owns our route? */
/* if this is a Road Warrior template, we cannot route.
* Opportunistic template is OK.
*/
if (c->kind == CK_TEMPLATE && !(c->policy & POLICY_OPPO))
{
loglog(RC_ROUTE, "cannot route Road Warrior template");
return FALSE;
}
/* if we don't know nexthop, we cannot route */
if (isanyaddr(&c->this.host_nexthop))
{
loglog(RC_ROUTE, "cannot route connection without knowing our nexthop");
return FALSE;
}
/* if routing would affect IKE messages, reject */
if (!no_klips
#ifdef NAT_TRAVERSAL
&& c->this.host_port != NAT_T_IKE_FLOAT_PORT
#endif
&& c->this.host_port != IKE_UDP_PORT
&& addrinsubnet(&c->that.host_addr, EffectivePeerClient(c)))
{
loglog(RC_LOG_SERIOUS, "cannot install route: peer is within its client");
return FALSE;
}
/* If there is already a route for peer's client subnet
* and it disagrees about interface or nexthop, we cannot steal it.
* Note: if this connection is already routed (perhaps for another
* state object), the route will agree.
* This is as it should be -- it will arise during rekeying.
*/
if (ro != NULL && !routes_agree(ro, c))
{
loglog(RC_LOG_SERIOUS, "cannot route -- route already in use for \"%s\""
, ro->name);
return FALSE; /* another connection already using the eroute */
}
#ifdef KLIPS
/* if there is an eroute for another connection, there is a problem */
if (ero != NULL && ero != c)
{
char inst[CONN_INST_BUF];
fmt_conn_instance(ero, inst);
loglog(RC_LOG_SERIOUS
, "cannot install eroute -- it is in use for \"%s\"%s #%lu"
, ero->name, inst, ero->eroute_owner);
return FALSE; /* another connection already using the eroute */
}
#endif /* KLIPS */
return TRUE;
}
bool
trap_connection(struct connection *c)
{
/* RT_ROUTED_TUNNEL is treated specially: we don't override
* because we don't want to lose track of the IPSEC_SAs etc.
*/
return could_route(c)
&& (c->routing == RT_ROUTED_TUNNEL || onlyeroute(c, NULL)); /*zqqa modified*/
}
/* delete any eroute for a connection and unroute it if route isn't shared */
void
unroute_connection(struct connection *c)
{
enum routing_t cr = c->routing;
if (erouted(cr))
{
passert(cr != RT_ROUTED_TUNNEL); /* cannot handle a live one */
#ifdef KLIPS
shunt_eroute(c, ERO_DELETE, "delete");
#endif
}
c->routing = RT_UNROUTED; /* do now so route_owner won't find us */
/* only unroute if no other connection shares it */
if (routed(cr)
&& route_owner(c, NULL) == NULL)
(void) do_command(c, "unroute");
}
#ifdef KLIPS
static void
set_text_said(char *text_said, const ip_address *dst, ipsec_spi_t spi, int proto)
{
ip_said said;
initsaid(dst, spi, proto, &said);
satot(&said, 0, text_said, SATOT_BUF);
}
static bool
pfkey_build(int error
, const char *description
, const char *text_said
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
if (error == 0)
{
return TRUE;
}
else
{
loglog(RC_LOG_SERIOUS, "building of %s %s failed, code %d"
, description, text_said, error);
pfkey_extensions_free(extensions);
return FALSE;
}
}
/* pfkey_extensions_init + pfkey_build + pfkey_msg_hdr_build */
static bool
pfkey_msg_start(u_int8_t msg_type
, u_int8_t satype
, const char *description
, const char *text_said
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
pfkey_extensions_init(extensions);
return pfkey_build(pfkey_msg_hdr_build(&extensions[0], msg_type
, satype, 0, ++pfkey_seq, pid)
, description, text_said, extensions);
}
/* pfkey_build + pfkey_address_build */
static bool
pfkeyext_address(u_int16_t exttype
, const ip_address *address
, const char *description
, const char *text_said
, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
{
/* the following variable is only needed to silence
* a warning caused by the fact that the argument
* to sockaddrof is NOT pointer to const!
*/
ip_address t = *address;
return pfkey_build(pfkey_address_build(extensions + exttype
, exttype, 0, 0, sockaddrof(&t))
, description, text_said, extensions);
}
/* Finish (building, sending, accepting response for) PF_KEY message.
* If response isn't NULL, the response from the kernel will be
* placed there (and its errno field will not be examined).
* Returns TRUE iff all appears well.
*/
static bool
finish_pfkey_msg(struct sadb_ext *extensions[SADB_EXT_MAX + 1]
, const char *description
, const char *text_said
, pfkey_buf *response)
{
struct sadb_msg *pfkey_msg;
bool success = TRUE;
int error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN);
if (error != 0)
{
loglog(RC_LOG_SERIOUS, "pfkey_msg_build of %s %s failed, code %d"
, description, text_said, error);
success = FALSE;
}
else
{
size_t len = pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN;
DBG(DBG_KLIPS,
DBG_log("finish_pfkey_msg: %s message %u for %s %s"
, sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
, pfkey_msg->sadb_msg_seq
, description, text_said);
DBG_dump(NULL, (void *) pfkey_msg, len));
if (!no_klips)
{
ssize_t r = write(pfkeyfd, pfkey_msg, len);
if (r != (ssize_t)len)
{
if (r < 0)
{
log("This connection is probably expecting a road warrior or the IP address"
" of the remote host's DNS hostname has changed");
log_errno((e
, "pfkey write() of %s message %u"
" for %s %s failed"
, sparse_val_show(pfkey_type_names
, pfkey_msg->sadb_msg_type)
, pfkey_msg->sadb_msg_seq
, description, text_said));
}
else
{
loglog(RC_LOG_SERIOUS
, "ERROR: pfkey write() of %s message %u"
" for %s %s truncated: %ld instead of %ld"
, sparse_val_show(pfkey_type_names
, pfkey_msg->sadb_msg_type)
, pfkey_msg->sadb_msg_seq
, description, text_said
, (long)r, (long)len);
}
success = FALSE;
/* if we were compiled with debugging, but we haven't already
* dumped the KLIPS command, do so.
*/
#ifdef DEBUG
if ((cur_debugging & DBG_KLIPS) == 0)
DBG_dump(NULL, (void *) pfkey_msg, len);
#endif
}
else
{
/* Check response from KLIPS.
* It ought to be an echo, perhaps with additional info.
* If the caller wants it, response will point to space.
*/
pfkey_buf b;
pfkey_buf *bp = response != NULL? response : &b;
if (!pfkey_get_response(bp, ((struct sadb_msg *) extensions[0])->sadb_msg_seq))
{
loglog(RC_LOG_SERIOUS
, "ERROR: no response to our PF_KEY %s message for %s %s"
, sparse