[prev in list] [next in list] [prev in thread] [next in thread]
List: ipsec-tools-devel
Subject: Re: [Ipsec-tools-devel] Ipsec-tools-0.7 and Cisco ASA 5520
From: "L. Gabriel Somlo" <somlo () cmu ! edu>
Date: 2008-06-25 19:04:28
Message-ID: 20080625190428.GA22515 () hedwig ! net ! cmu ! edu
[Download RAW message or body]
> Two of the three patches were committed to the head branch but are not yet
> included in a release. The third patch, a work around which prevented
> scripts from being executed more than once, was not committed. I had
> intended to do some work in IKE config mode to improve state tracking which
> would have made the patch irrelevant. Unfortunately, I never got around to
> it due to lack of time.
The third patch is unnecessary, as the phase1_up_down script can
easily perform those checks. I'm attaching my current linux and bsd
specific phase1_up_down scripts. I had a thread (with Manu, iirc)
about potentially including these in src/racoon/samples/roadwarrior/client/
but we got stuck trying to resolve whether having two scripts, one for
BSD and one for Linux was worse than having one script with a metric
ton of
case $OS in
bsd*)
foo
;;
linux*)
bar
;;
esac
So, if these scripts are accepted, the third patch Matthew mentions
becomes unecessary.
There was a later, fourth patch, which fixes the broken handling of
SADB_DELETE on Linux. I'm also re-attaching that one to this message.
Please consider applying this one to the head branch, as well.
Thanks,
Gabriel
["phase1-up-down-bsd.sh" (application/x-sh)]
#!/bin/sh
#
# manipulate IPSec SA database on behalf of the racoon daemon
# Gabriel Somlo <somlo at cmu edu>, 08/27/2007
#
#FIXME: read this from a config file
NAT_T="yes"
umask 0022
PATH=/bin:/sbin:/usr/bin:/usr/sbin
# set up NAT-T
case "${NAT_T}" in
yes|true|on|enable*|1)
LOCAL="${LOCAL_ADDR}[${LOCAL_PORT}]"
REMOTE="${REMOTE_ADDR}[${REMOTE_PORT}]"
;;
*)
LOCAL="${LOCAL_ADDR}"
REMOTE="${REMOTE_ADDR}"
;;
esac
# determine interface and next-hop for our default route
DFLT_RT=$(netstat -rn | awk '($1 == "default"){print $2 ";" $7}')
DFLT_IF=${DFLT_RT#*;}
DFLT_GW=${DFLT_RT%;*}
# bring up phase1
phase1_up() {
# check if VPN address already set up on default interface (dupe script call)
ifconfig ${DFLT_IF} | grep -q "${INTERNAL_ADDR4}" && {
echo "p1_up_down: phase1_up has already run !!!"
exit 4
}
# save current resolv.conf and create new one based on info from VPN server
[ -f /etc/resolv.conf.prevpn ] || cp /etc/resolv.conf /etc/resolv.conf.prevpn
{
echo "# Generated by racoon on $(date)"
echo "search ${DEFAULT_DOMAIN}"
for NS in ${INTERNAL_DNS4_LIST}; do
echo "nameserver ${NS}"
done
} > /etc/resolv.conf
# add VPN address to default interface
ifconfig ${DFLT_IF} alias ${INTERNAL_ADDR4} netmask 255.255.255.255
# set up host route to VPN server
route add ${REMOTE_ADDR} ${DEFAULT_GW}
if [ -n "${SPLIT_INCLUDE}" ]; then
# split tunnel: keep existing default, insert specific tunnel routes
for N in ${SPLIT_INCLUDE}; do
NETADDR=${N%/*}
NETMASK=${N#*/}
route add -net ${NETADDR} netmask ${NETMASK} gw ${DFLT_GW} -ifa ${INTERNAL_ADDR4}
done
else
# full tunnel: set up any applicable exceptions
for N in ${SPLIT_LOCAL}; do
NETADDR=${N%/*}
NETMASK=${N#*/}
route add -net ${NETADDR} netmask ${NETMASK} gw ${DFLT_GW}
done
# ... then replace default route with vpn tunnel
route delete default
route add default gw ${DFLT_GW} -ifa ${INTERNAL_ADDR4}
fi
# update SA database
setkey -c << EOT
spdadd ${INTERNAL_ADDR4}/32[any] 0.0.0.0/0[any] any -P out ipsec
esp/tunnel/${LOCAL}-${REMOTE}/require;
spdadd 0.0.0.0/0[any] ${INTERNAL_ADDR4}[any] any -P in ipsec
esp/tunnel/${REMOTE}-${LOCAL}/require;
EOT
}
# bring down phase1
phase1_down() {
# restore previous resolv.conf
[ -f /etc/resolv.conf.prevpn ] && mv /etc/resolv.conf.prevpn /etc/resolv.conf
if [ -n "${SPLIT_INCLUDE}" ]; then
# split tunnel: remove specific tunnel routes
for N in ${SPLIT_INCLUDE}; do
NETADDR=${N%/*}
NETMASK=${N#*/}
route del -net ${NETADDR} netmask ${NETMASK}
done
else
# full tunnel: remove any applicable exceptions
for N in ${SPLIT_LOCAL}; do
NETADDR=${N%/*}
NETMASK=${N#*/}
route del -net ${NETADDR} netmask ${NETMASK}
done
# ... then restore original default route
route delete default
route add default ${DFLT_GW} -ifa ${LOCAL_ADDR}
fi
# remove host route to VPN server
route delete ${REMOTE_ADDR}
# remove VPN address from default interface
ifconfig ${DFLT_IF} delete ${INTERNAL_ADDR4}
# clean up SA database
# (deleteall command may be broken on Linux, use 'flush esp' as workaround)
setkey -c << EOT
spddelete ${INTERNAL_ADDR4}/32[any] 0.0.0.0/0[any] any -P out ipsec
esp/tunnel/${LOCAL}-${REMOTE}/require;
spddelete 0.0.0.0/0[any] ${INTERNAL_ADDR4}[any] any -P in ipsec
esp/tunnel/${REMOTE}-${LOCAL}/require;
deleteall ${REMOTE_ADDR} ${LOCAL_ADDR} esp;
deleteall ${LOCAL_ADDR} ${REMOTE_ADDR} esp;
EOT
}
# print out parameters we received
echo "p1_up_down: $1 starting..."
echo "p1_up_down: LOCAL_ADDR = ${LOCAL_ADDR}"
echo "p1_up_down: LOCAL_PORT = ${LOCAL_PORT}"
echo "p1_up_down: REMOTE_ADDR = ${REMOTE_ADDR}"
echo "p1_up_down: REMOTE_PORT = ${REMOTE_PORT}"
echo "p1_up_down: DFLT_GW = ${DFLT_GW}"
echo "p1_up_down: DFLT_IF = ${DFLT_IF}"
echo "p1_up_down: INTERNAL_ADDR4 = ${INTERNAL_ADDR4}"
echo "p1_up_down: INTERNAL_DNS4 = ${INTERNAL_DNS4}"
echo "p1_up_down: DEFAULT_DOMAIN = ${DEFAULT_DOMAIN}"
echo "p1_up_down: SPLIT_INCLUDE = ${SPLIT_INCLUDE}"
echo "p1_up_down: SPLIT_LOCAL= ${SPLIT_LOCAL}"
# check for valid VPN address
echo ${INTERNAL_ADDR4} | grep -q '[0-9]' || {
echo "p1_up_down: error: invalid INTERNAL_ADDR4."
exit 1
}
# check for valid default nexthop
echo ${DFLT_GW} | grep -q '[0-9]' || {
echo "p1_up_down: error: invalid DFLT_GW."
exit 2
}
# main "program"
case "$1" in
phase1_up)
phase1_up
;;
phase1_down)
phase1_down
;;
*)
echo "p1_up_down: error: must be called by racoon w. arg=phase1_[up|down]"
exit 3
;;
esac
echo "p1_up_down: $1 completed successfully."
exit 0
["phase1-up-down-linux.sh" (application/x-sh)]
#!/bin/bash
#
# manipulate IPSec SA database on behalf of the racoon daemon
# Gabriel Somlo <somlo at cmu edu>, 08/27/2007
#
#FIXME: read this from a config file
NAT_T="yes"
umask 0022
PATH=/bin:/sbin:/usr/bin:/usr/sbin
# set up NAT-T
case "${NAT_T}" in
yes|true|on|enable*|1)
LOCAL="${LOCAL_ADDR}[${LOCAL_PORT}]"
REMOTE="${REMOTE_ADDR}[${REMOTE_PORT}]"
;;
*)
LOCAL="${LOCAL_ADDR}"
REMOTE="${REMOTE_ADDR}"
;;
esac
# determine interface and next-hop for our default route
DFLT_RT=$(ip route list | awk '($1 == "default"){print $3 ";" $5}')
DFLT_IF=${DFLT_RT#*;}
DFLT_GW=${DFLT_RT%;*}
# bring up phase1
phase1_up() {
# check if VPN address already set up on default interface (dupe script call)
ip addr list ${DFLT_IF} | grep -q "${INTERNAL_ADDR4}/32" && {
echo "p1_up_down: phase1_up has already run !!!"
exit 4
}
# save current resolv.conf and create new one based on info from VPN server
[ -f /etc/resolv.conf.prevpn ] || cp /etc/resolv.conf /etc/resolv.conf.prevpn
{
echo "# Generated by racoon on $(date)"
echo "search ${DEFAULT_DOMAIN}"
for NS in ${INTERNAL_DNS4_LIST}; do
echo "nameserver ${NS}"
done
} > /etc/resolv.conf
# add VPN address to default interface
ip addr add dev ${DFLT_IF} ${INTERNAL_ADDR4}/32
# set up host route to VPN server
ip route add ${REMOTE_ADDR} via ${DFLT_GW} dev ${DFLT_IF}
if [ -n "${SPLIT_INCLUDE_CIDR}" ]; then
# split tunnel: keep existing default, insert specific tunnel routes
for N in ${SPLIT_INCLUDE_CIDR}; do
ip route add ${N} via ${DFLT_GW} dev ${DFLT_IF} src ${INTERNAL_ADDR4}
done
else
# full tunnel: set up any applicable exceptions...
for N in ${SPLIT_LOCAL_CIDR}; do
ip route add ${N} via ${DFLT_GW} dev ${DFLT_IF}
done
# ... then replace default route with vpn tunnel
ip route del default
ip route add default via ${DFLT_GW} dev ${DFLT_IF} src ${INTERNAL_ADDR4}
fi
# update SA database
setkey -c << EOT
spdadd ${INTERNAL_ADDR4}/32[any] 0.0.0.0/0[any] any -P out ipsec
esp/tunnel/${LOCAL}-${REMOTE}/require;
spdadd 0.0.0.0/0[any] ${INTERNAL_ADDR4}[any] any -P in ipsec
esp/tunnel/${REMOTE}-${LOCAL}/require;
EOT
}
# bring down phase1
phase1_down() {
# restore previous resolv.conf
[ -f /etc/resolv.conf.prevpn ] && mv /etc/resolv.conf.prevpn /etc/resolv.conf
if [ -n "${SPLIT_INCLUDE_CIDR}" ]; then
# split tunnel: remove specific tunnel routes
for N in ${SPLIT_INCLUDE_CIDR}; do
ip route del ${N}
done
else
# full tunnel: remove any applicable exceptions...
for N in ${SPLIT_LOCAL_CIDR}; do
ip route del ${N}
done
# ... then restore original default route
ip route del default
ip route add default via ${DFLT_GW} dev ${DFLT_IF}
fi
# remove host route to VPN server
ip route del ${REMOTE_ADDR}
# remove VPN address from default interface
ip addr del dev ${DFLT_IF} ${INTERNAL_ADDR4}/32
# clean up SA database
# (deleteall command may be broken on Linux, use 'flush esp' as workaround)
setkey -c << EOT
spddelete ${INTERNAL_ADDR4}/32[any] 0.0.0.0/0[any] any -P out ipsec
esp/tunnel/${LOCAL}-${REMOTE}/require;
spddelete 0.0.0.0/0[any] ${INTERNAL_ADDR4}[any] any -P in ipsec
esp/tunnel/${REMOTE}-${LOCAL}/require;
deleteall ${REMOTE_ADDR} ${LOCAL_ADDR} esp;
deleteall ${LOCAL_ADDR} ${REMOTE_ADDR} esp;
EOT
}
# print out parameters we received
echo "p1_up_down: $1 starting..."
echo "p1_up_down: LOCAL_ADDR = ${LOCAL_ADDR}"
echo "p1_up_down: LOCAL_PORT = ${LOCAL_PORT}"
echo "p1_up_down: REMOTE_ADDR = ${REMOTE_ADDR}"
echo "p1_up_down: REMOTE_PORT = ${REMOTE_PORT}"
echo "p1_up_down: DFLT_GW = ${DFLT_GW}"
echo "p1_up_down: DFLT_IF = ${DFLT_IF}"
echo "p1_up_down: INTERNAL_ADDR4 = ${INTERNAL_ADDR4}"
echo "p1_up_down: INTERNAL_DNS4 = ${INTERNAL_DNS4}"
echo "p1_up_down: DEFAULT_DOMAIN = ${DEFAULT_DOMAIN}"
echo "p1_up_down: SPLIT_INCLUDE_CIDR = ${SPLIT_INCLUDE_CIDR}"
echo "p1_up_down: SPLIT_LOCAL_CIDR = ${SPLIT_LOCAL_CIDR}"
# check for valid VPN address
echo ${INTERNAL_ADDR4} | grep -q '[0-9]' || {
echo "p1_up_down: error: invalid INTERNAL_ADDR4."
exit 1
}
# check for valid default nexthop
echo ${DFLT_GW} | grep -q '[0-9]' || {
echo "p1_up_down: error: invalid DFLT_GW."
exit 2
}
# main "program"
case "$1" in
phase1_up)
phase1_up
;;
phase1_down)
phase1_down
;;
*)
echo "p1_up_down: error: must be called by racoon w. arg=phase1_[up|down]"
exit 3
;;
esac
echo "p1_up_down: $1 completed successfully."
exit 0
["ipsec-tools-0.7-cvs-deleteall.patch" (text/plain)]
diff -NarU5 ipsec-tools-0.7-cvs071026.orig/src/setkey/parse.y \
ipsec-tools-0.7-cvs071026/src/setkey/parse.y
--- ipsec-tools-0.7-cvs071026.orig/src/setkey/parse.y 2007-07-18 08:07:52.000000000 \
-0400
+++ ipsec-tools-0.7-cvs071026/src/setkey/parse.y 2007-10-26 22:44:18.000000000 -0400
@@ -209,15 +209,36 @@
/* deleteall command */
deleteall_command
: DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT
{
- int status;
-
- status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1);
- if (status < 0)
+#ifndef __linux__
+ if (setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1) < 0)
+ return -1;
+#else /* __linux__ */
+ /* linux strictly adheres to RFC2367, and returns an error when we
+ * send an SADB_DELETE request without an SPI. Therefore, we must
+ * first retrieve a list of SPIs for all matching SADB entries, and
+ * then delete each one separately.
+ */
+#define MAX_SPI 1024
+ u_int32_t spi[MAX_SPI];
+ int i, n;
+
+ n = sendkeymsg_spigrep($5, $3, $4, spi, MAX_SPI);
+ if (n < 0) {
+ yyerror("too many SPIs matched");
return -1;
+ }
+
+ for (i = 0; i < n; i++) {
+ p_spi = spi[i];
+ if (setkeymsg_addr(SADB_DELETE,
+ $5, $3, $4, 0) < 0)
+ return -1;
+ }
+#endif /* __linux__ */
}
;
/* get command */
get_command
diff -NarU5 ipsec-tools-0.7-cvs071026.orig/src/setkey/setkey.c \
ipsec-tools-0.7-cvs071026/src/setkey/setkey.c
--- ipsec-tools-0.7-cvs071026.orig/src/setkey/setkey.c 2007-07-18 08:07:52.000000000 \
-0400
+++ ipsec-tools-0.7-cvs071026/src/setkey/setkey.c 2007-10-26 22:42:40.000000000 -0400
@@ -443,10 +443,157 @@
fflush(stdout);
}
}
}
+/* Populate 'spi' array with SPIs matching 'satype', 'srcs', and 'dsts'
+ * Return value is the number of SPIs found.
+ * If maximum capacity of 'spi' (given by 'max_spi') is exceeded, return -1
+ * On any other error, return 0.
+ */
+int
+sendkeymsg_spigrep(satype, srcs, dsts, spi, max_spi)
+ unsigned int satype;
+ struct addrinfo *srcs;
+ struct addrinfo *dsts;
+ u_int32_t *spi;
+ int max_spi;
+{
+ struct sadb_msg msg, *m;
+ char *buf;
+ size_t len;
+ ssize_t l;
+ u_char rbuf[1024 * 32];
+ int n;
+ caddr_t mhp[SADB_EXT_MAX + 1];
+ struct sadb_address *saddr;
+ struct sockaddr *s;
+ struct addrinfo *a;
+ struct sadb_sa *sa;
+
+ if (f_notreally)
+ return 0;
+
+ {
+ struct timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+ perror("setsockopt");
+ return 0;
+ }
+ }
+
+ msg.sadb_msg_version = PF_KEY_V2;
+ msg.sadb_msg_type = SADB_DUMP;
+ msg.sadb_msg_errno = 0;
+ msg.sadb_msg_satype = satype;
+ msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
+ msg.sadb_msg_reserved = 0;
+ msg.sadb_msg_seq = 0;
+ msg.sadb_msg_pid = getpid();
+ buf = (char *)&msg;
+ len = sizeof(msg);
+
+ if (f_verbose) {
+ kdebug_sadb(&msg);
+ printf("\n");
+ }
+ if (f_hexdump) {
+ int i;
+ for (i = 0; i < len; i++) {
+ if (i % 16 == 0)
+ printf("%08x: ", i);
+ printf("%02x ", buf[i] & 0xff);
+ if (i % 16 == 15)
+ printf("\n");
+ }
+ if (len % 16)
+ printf("\n");
+ }
+
+ if ((l = send(so, buf, len, 0)) < 0) {
+ perror("send");
+ return 0;
+ }
+
+ m = (struct sadb_msg *)rbuf;
+ n = 0;
+ do {
+ if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
+ perror("recv");
+ return 0;
+ }
+
+ if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) {
+ warnx("invalid keymsg length");
+ return 0;
+ }
+
+ if (f_verbose) {
+ kdebug_sadb(m);
+ printf("\n");
+ }
+
+ if (m->sadb_msg_type != SADB_DUMP) {
+ warnx("unexpected message type");
+ return 0;
+ }
+
+ if (m->sadb_msg_errno != 0) {
+ warnx("error encountered");
+ return 0;
+ }
+
+ /* match satype */
+ if (m->sadb_msg_satype != satype)
+ continue;
+
+ pfkey_align(m, mhp);
+ pfkey_check(mhp);
+
+ /* match src */
+ saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+ if (saddr == NULL)
+ continue;
+ s = (struct sockaddr *)(saddr + 1);
+ for (a = srcs; a; a = a->ai_next)
+ if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
+ break;
+ if (a == NULL)
+ continue;
+
+ /* match dst */
+ saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+ if (saddr == NULL)
+ continue;
+ s = (struct sockaddr *)(saddr + 1);
+ for (a = dsts; a; a = a->ai_next)
+ if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
+ break;
+ if (a == NULL)
+ continue;
+
+ if (n < max_spi) {
+ sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+ if (sa != NULL)
+ spi[n++] = (u_int32_t)ntohl(sa->sadb_sa_spi);
+ } else
+ return -1;
+
+ m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len));
+
+ if (f_verbose) {
+ kdebug_sadb(m);
+ printf("\n");
+ }
+
+ } while (m->sadb_msg_seq);
+
+ return n;
+}
+
int
sendkeymsg(buf, len)
char *buf;
size_t len;
{
@@ -504,11 +651,11 @@
warnx("invalid keymsg length");
break;
}
if (f_verbose) {
- kdebug_sadb((struct sadb_msg *)rbuf);
+ kdebug_sadb(msg);
printf("\n");
}
if (postproc(msg, l) < 0)
break;
} while (msg->sadb_msg_errno || msg->sadb_msg_seq);
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Ipsec-tools-devel mailing list
Ipsec-tools-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ipsec-tools-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic