diff --git a/libreswan-3.19-configdir-compat.patch b/libreswan-3.19-configdir-compat.patch
new file mode 100644
index 0000000..e0b79d6
--- /dev/null
+++ b/libreswan-3.19-configdir-compat.patch
@@ -0,0 +1,66 @@
+diff -Naur libreswan-3.19-orig/programs/ipsec/ipsec.in libreswan-3.19/programs/ipsec/ipsec.in
+--- libreswan-3.19-orig/programs/ipsec/ipsec.in 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/ipsec/ipsec.in 2017-02-03 17:49:07.779187770 -0500
+@@ -38,7 +38,7 @@
+ PATH="${IPSEC_SBINDIR}":/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin
+ export PATH
+
+-# supress ElectricFence banner changing our reference testing output
++# suppress ElectricFence banner changing our reference testing output
+ export EF_DISABLE_BANNER=1
+
+ # things not to be listed in --help command list
+@@ -216,10 +216,14 @@
+ # A lot of nss commands use -d to specify NSS db location.
+ # We use --nssdir.
+ if [ "${2}" = "-d" -o \
++ "${2}" = "--configdir" -o \
+ "${2}" = "--nssdir" ]
+ then
+ if [ -d "${3}" ]; then
+ IPSEC_NSSDIR="${3}"
++ if [ "${2}" = "--configdir" ]; then
++ echo "ipsec import warning: --configdir is obsoleted, use --nssdir" >&2
++ fi
+ else
+ echo "usage: ipsec import [--nssdir ${IPSEC_NSSDIR}] /path/to/pkcs.12" >&2
+ exit 1
+@@ -251,10 +255,14 @@
+ # A lot of nss commands use -d to specify NSS db location.
+ # We use --nssdir.
+ if [ "${2}" = "-d" -o \
++ "${2}" = "--configdir" -o \
+ "${2}" = "--nssdir" ]
+ then
+ IPSEC_NSSDIR="${3}"
+ IPSEC_NSSDIR_SQL="sql:${IPSEC_NSSDIR}"
++ if [ "${2}" = "--configdir" ]; then
++ echo "ipsec initnss warning: --configdir is obsoleted, use --nssdir" >&2
++ fi
+ else
+ echo "usage: ipsec initnss [--nssdir ${IPSEC_NSSDIR}]" >&2
+ exit 1
+diff -Naur libreswan-3.19-orig/programs/newhostkey/newhostkey.in libreswan-3.19/programs/newhostkey/newhostkey.in
+--- libreswan-3.19-orig/programs/newhostkey/newhostkey.in 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/newhostkey/newhostkey.in 2017-02-03 17:49:16.131142346 -0500
+@@ -54,7 +54,7 @@
+ exit 0
+ ;;
+ --random)
+- echo "$me warning: --random is obsoleted, using --seeddev"
++ echo "$me warning: --random is obsoleted, using --seeddev" >&2
+ seeddev="--seeddev ${2}"
+ shift
+ ;;
+@@ -62,6 +62,11 @@
+ seeddev="--seeddev ${2}"
+ shift
+ ;;
++ --configdir)
++ echo "$me warning: --configdir is obsoleted, use --nssdir" >&2
++ nssdir="${2}"
++ shift
++ ;;
+ --nssdir)
+ nssdir="${2}"
+ shift
diff --git a/libreswan-3.19-suppress_delete.patch b/libreswan-3.19-suppress_delete.patch
new file mode 100644
index 0000000..ab3e073
--- /dev/null
+++ b/libreswan-3.19-suppress_delete.patch
@@ -0,0 +1,78 @@
+diff -Naur libreswan-3.19-orig/programs/pluto/connections.c libreswan-3.19/programs/pluto/connections.c
+--- libreswan-3.19-orig/programs/pluto/connections.c 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/pluto/connections.c 2017-02-03 17:44:29.009703914 -0500
+@@ -4334,3 +4334,27 @@
+ unroute_connection(c); /* --unroute */
+ }
+ }
++
++/*
++ * When replacing an old existing connection, suppress sending delete notify
++ */
++void suppress_delete(struct connection *c)
++{
++ struct state *pst = state_with_serialno(c->newest_isakmp_sa);
++ struct state *cst = state_with_serialno(c->newest_ipsec_sa);
++ if (pst != NULL) {
++ pst->st_ikev2_no_del = TRUE;
++ DBG(DBG_CONTROL, DBG_log("Marked IKE state #%lu to suppress sending delete notify",
++ c->newest_isakmp_sa));
++ } else {
++ libreswan_log("did not find old IKE state to mark for suppressing delete");
++ }
++
++ if (cst != NULL) {
++ cst->st_ikev2_no_del = TRUE;
++ DBG(DBG_CONTROL, DBG_log("Marked IPSEC state #%lu to suppress sending delete notify",
++ c->newest_ipsec_sa));
++ } else {
++ libreswan_log("did not find old IPsec state to mark for suppressing delete");
++ }
++}
+diff -Naur libreswan-3.19-orig/programs/pluto/connections.h libreswan-3.19/programs/pluto/connections.h
+--- libreswan-3.19-orig/programs/pluto/connections.h 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/pluto/connections.h 2017-02-03 17:44:29.009703914 -0500
+@@ -383,6 +383,7 @@
+ extern void terminate_connection(const char *name);
+ extern void release_connection(struct connection *c, bool relations);
+ extern void delete_connection(struct connection *c, bool relations);
++extern void suppress_delete(struct connection *c);
+ extern void delete_connections_by_name(const char *name, bool strict);
+ extern void delete_every_connection(void);
+ extern char *add_group_instance(struct connection *group,
+diff -Naur libreswan-3.19-orig/programs/pluto/initiate.c libreswan-3.19/programs/pluto/initiate.c
+--- libreswan-3.19-orig/programs/pluto/initiate.c 2017-02-03 17:41:48.704575766 -0500
++++ libreswan-3.19/programs/pluto/initiate.c 2017-02-03 17:44:34.470674213 -0500
+@@ -978,6 +978,7 @@
+ same_id(&c->spd.that.id, &d->spd.that.id)))
+ {
+ DBG(DBG_CONTROL, DBG_log("Unorienting old connection with same IDs"));
++ suppress_delete(d); /* don't send a delete */
+ release_connection(d, FALSE);
+ }
+ d = next;
+diff -Naur libreswan-3.19-orig/programs/pluto/state.c libreswan-3.19/programs/pluto/state.c
+--- libreswan-3.19-orig/programs/pluto/state.c 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/pluto/state.c 2017-02-03 17:44:34.471674208 -0500
+@@ -880,8 +880,8 @@
+ }
+
+ /* tell the other side of any IPSEC SAs that are going down */
+- if (IS_IPSEC_SA_ESTABLISHED(st->st_state) ||
+- IS_ISAKMP_SA_ESTABLISHED(st->st_state)) {
++ if (!st->st_ikev2_no_del && (IS_IPSEC_SA_ESTABLISHED(st->st_state) ||
++ IS_ISAKMP_SA_ESTABLISHED(st->st_state))) {
+ if (st->st_ikev2 && IS_CHILD_SA(st) &&
+ state_with_serialno(st->st_clonedfrom) == NULL) {
+ /* ??? in v2, there must be a parent */
+diff -Naur libreswan-3.19-orig/programs/pluto/state.h libreswan-3.19/programs/pluto/state.h
+--- libreswan-3.19-orig/programs/pluto/state.h 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/pluto/state.h 2017-02-03 17:44:34.471674208 -0500
+@@ -245,6 +245,7 @@
+ bool has_pam_thread; /* per state PAM thread flag */
+
+ bool st_ikev2; /* is this an IKEv2 state? */
++ bool st_ikev2_no_del; /* suppress sending DELETE - eg replaced conn */
+ bool st_rekeytov2; /* true if this IKEv1 is about
+ * to be replaced with IKEv2
+ */
diff --git a/libreswan-3.19-testbuf.patch b/libreswan-3.19-testbuf.patch
new file mode 100644
index 0000000..0c5795a
--- /dev/null
+++ b/libreswan-3.19-testbuf.patch
@@ -0,0 +1,21 @@
+diff -Naur libreswan-3.19-orig/programs/pluto/test_buffer.c libreswan-3.19/programs/pluto/test_buffer.c
+--- libreswan-3.19-orig/programs/pluto/test_buffer.c 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/pluto/test_buffer.c 2017-01-15 15:26:25.800866709 -0500
+@@ -67,7 +67,7 @@
+ if (i != 2) {
+ loglog(RC_INTERNALERR,
+ "unexpected space or NUL character at offset %zu in hex buffer \"%s\" at \"%s\"\n",
+- pos - string, string, pos);
++ (size_t)(pos - string), string, pos);
+ exit_pluto(PLUTO_EXIT_NSS_FAIL);
+ }
+ char *end;
+@@ -75,7 +75,7 @@
+ if (end - buf != 2) {
+ loglog(RC_INTERNALERR,
+ "invalid character at offset %zu in hex buffer \"%s\" at \"%s\"\n",
+- pos-string, string, pos);
++ (size_t)(pos-string), string, pos);
+ exit_pluto(PLUTO_EXIT_NSS_FAIL);
+ }
+ chunk.len++;
diff --git a/libreswan-3.19-uniqueid_replace.patch b/libreswan-3.19-uniqueid_replace.patch
new file mode 100644
index 0000000..14dae1c
--- /dev/null
+++ b/libreswan-3.19-uniqueid_replace.patch
@@ -0,0 +1,195 @@
+diff -Naur libreswan-3.19-orig/programs/configs/d.ipsec.conf/uniqueids.xml libreswan-3.19/programs/configs/d.ipsec.conf/uniqueids.xml
+--- libreswan-3.19-orig/programs/configs/d.ipsec.conf/uniqueids.xml 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/configs/d.ipsec.conf/uniqueids.xml 2017-02-03 17:41:48.703575771 -0500
+@@ -1,17 +1,20 @@
+
+ uniqueids
+
+-whether a particular participant ID should be kept unique,
+-with any new (automatically keyed)
+-connection using an ID from a different IP address
+-deemed to replace all old ones using that ID.
+-Acceptable values are yes
+-(the default)
+-and
+-no.
+-Participant IDs normally are unique,
+-so a new (automatically-keyed) connection using the same ID is
+-almost invariably intended to replace an old one.
+-
++ Whether IDs should be considered identifying remote parties
++uniquely. Acceptable values are yes (the
++default) and no. Participant IDs normally
++are unique, so a new connection instance using the same remote ID is
++almost invariably intended to replace an old existing connection.
++
++ When the connection is defined to be a server (using xauthserver=)
++and the connection policy is authby=secret, this option is ignored (as
++of 3.20) and old connections will never be replaced. This situation is
++commonly known as clients using a "Group ID".
++
++ This option may disappear in the near future. People using identical
++X.509 certificates on multiple devices are urged to upgrade to use seperate
++certificates per client and device.
++
+
+
+diff -Naur libreswan-3.19-orig/programs/pluto/ikev1_aggr.c libreswan-3.19/programs/pluto/ikev1_aggr.c
+--- libreswan-3.19-orig/programs/pluto/ikev1_aggr.c 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/pluto/ikev1_aggr.c 2017-02-03 17:41:42.320610486 -0500
+@@ -906,6 +906,9 @@
+ */
+ set_ph1_iv_from_new(st);
+ DBG(DBG_CONTROL, DBG_log("phase 1 complete"));
++
++ ISAKMP_SA_established(st->st_connection, st->st_serialno);
++
+ #ifdef USE_LINUX_AUDIT
+ linux_audit_conn(st, LAK_PARENT_START);
+ #endif
+@@ -1012,6 +1015,9 @@
+ */
+ set_ph1_iv_from_new(st);
+ DBG(DBG_CONTROL, DBG_log("phase 1 complete"));
++
++ ISAKMP_SA_established(st->st_connection, st->st_serialno);
++
+ #ifdef USE_LINUX_AUDIT
+ linux_audit_conn(st, LAK_PARENT_START);
+ #endif
+diff -Naur libreswan-3.19-orig/programs/pluto/ikev2_child.c libreswan-3.19/programs/pluto/ikev2_child.c
+--- libreswan-3.19-orig/programs/pluto/ikev2_child.c 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/pluto/ikev2_child.c 2017-02-03 17:41:37.984634068 -0500
+@@ -1271,6 +1271,9 @@
+
+ ikev2_derive_child_keys(cst, role);
+
++ /* Check to see if we need to release an old instance */
++ ISAKMP_SA_established(pst->st_connection, pst->st_serialno);
++
+ /* install inbound and outbound SPI info */
+ if (!install_ipsec_sa(cst, TRUE))
+ return STF_FATAL;
+diff -Naur libreswan-3.19-orig/programs/pluto/initiate.c libreswan-3.19/programs/pluto/initiate.c
+--- libreswan-3.19-orig/programs/pluto/initiate.c 2017-01-15 14:34:34.000000000 -0500
++++ libreswan-3.19/programs/pluto/initiate.c 2017-02-03 17:41:48.704575766 -0500
+@@ -929,73 +929,58 @@
+ bool uniqueIDs = FALSE; /* --uniqueids? */
+
+ /*
+- * Called by main_inI3_outR3_tail() and ikev2_child_sa_respond() which is called for
+- * initiator and responder alike! So this function should not be in initiate.c.
+- * It is also not called in IKEv1 Aggressive Mode!
++ * Called by IKEv1 and IKEv2 when the IKE SA is established.
++ * It checks if the freshly established connection needs is
++ * replacing an established version of itself.
++ *
++ * The use of uniqueIDs is mostly historic and might be removed
++ * in a future version. It is ignored for PSK based connections,
++ * which only act based on being a "server using PSK".
+ */
+ void ISAKMP_SA_established(struct connection *c, so_serial_t serial)
+ {
+ c->newest_isakmp_sa = serial;
+
+- if (uniqueIDs && !c->spd.this.xauth_server &&
+- (c->policy & POLICY_AUTH_NULL) == LEMPTY) {
+- /*
+- * for all connections: if the same Phase 1 IDs are used
+- * for different IP addresses, unorient that connection.
+- * We also check ports, since different Phase 1 ID's can
+- * exist for the same IP when NAT is involved.
+- */
+- struct connection *d;
+-
+- for (d = connections; d != NULL; ) {
+- /* might move underneath us */
+- struct connection *next = d->ac_next;
+-
+- /*
+- * We try to find duplicate instances of same
+- * connection to clean up old ones when uniqueids=yes
+- *
+- * We are testing for all of:
+- * 1: an appropriate kind to consider
+- * 2: same ids, left and right
+- * 3: same address family
+- * 4: same connection name
+- * 5: but different IP address or port
+- * 6: differing dnsnames (sort of)
+- *
+- * DHR (2014-10-29):
+- * Is the sense of the last clause inverted?
+- * The logic kind of suggests that in fact the
+- * same dnsnames should be the same, not different.
+- *
+- * Let's make 6 clearer:
+- * if BOTH have dnsnames, they must be unequal.
+- *
+- * I suspect that it should be:
+- * if BOTH have dnsnames, they must be equal.
+- *
+- * In other words the streq result should be negated.
+- */
+- if ((d->kind == CK_PERMANENT ||
+- d->kind == CK_INSTANCE ||
+- d->kind == CK_GOING_AWAY) &&
+- (c->name == d->name) &&
+- same_id(&c->spd.this.id, &d->spd.this.id) &&
+- same_id(&c->spd.that.id, &d->spd.that.id) &&
+- addrtypeof(&c->spd.that.host_addr) ==
+- addrtypeof(&d->spd.that.host_addr) &&
+- (!sameaddr(&c->spd.that.host_addr,
+- &d->spd.that.host_addr) ||
+- c->spd.that.host_port !=
+- d->spd.that.host_port) &&
+- !(c->dnshostname != NULL &&
+- d->dnshostname != NULL &&
+- streq(c->dnshostname,
+- d->dnshostname))) {
+- release_connection(d, FALSE);
+- }
+- d = next;
++ /* NULL authentication can never replaced - it is all anonnymous */
++ if (LIN(POLICY_AUTH_NULL, c->policy) ||
++ ( c->spd.that.authby == AUTH_NULL || c->spd.this.authby == AUTH_NULL)) {
++
++ DBG(DBG_CONTROL, DBG_log("NULL Authentication - all clients appear identical"));
++ return;
++ }
++
++ /*
++ * If we are a server and use PSK, all clients use the same group ID
++ * Note that "xauth_server" also refers to IKEv2 CP
++ */
++ if (c->spd.this.xauth_server && LIN(POLICY_PSK, c->policy)) {
++ DBG(DBG_CONTROL, DBG_log("We are a server using PSK and clients are using a group ID"));
++ return;
++ }
++
++ if (!uniqueIDs) {
++ DBG(DBG_CONTROL, DBG_log("uniqueIDs disabled, not contemplating releasing older self"));
++ return;
++ }
++
++ /*
++ * for all existing connections: if the same Phase 1 IDs are used,
++ * unorient that (old) connection - This is a replacement.
++ */
++ struct connection *d;
++
++ for (d = connections; d != NULL; ) {
++ /* might move underneath us */
++ struct connection *next = d->ac_next;
++
++ if (c != d && c->kind == d->kind && streq(c->name, d->name) &&
++ (same_id(&c->spd.this.id, &d->spd.this.id) &&
++ same_id(&c->spd.that.id, &d->spd.that.id)))
++ {
++ DBG(DBG_CONTROL, DBG_log("Unorienting old connection with same IDs"));
++ release_connection(d, FALSE);
+ }
++ d = next;
+ }
+ }
+
diff --git a/libreswan.spec b/libreswan.spec
index ff2686b..dc6fd35 100644
--- a/libreswan.spec
+++ b/libreswan.spec
@@ -28,6 +28,11 @@ Source1: https://download.libreswan.org/cavs/ikev1_dsa.fax.bz2
Source2: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2
Source3: https://download.libreswan.org/cavs/ikev2.fax.bz2
+Patch1: libreswan-3.19-configdir-compat.patch
+Patch2: libreswan-3.19-testbuf.patch
+Patch3: libreswan-3.19-uniqueid_replace.patch
+Patch4: libreswan-3.19-suppress_delete.patch
+
%endif
Group: System Environment/Daemons
BuildRequires: bison flex pkgconfig
@@ -96,6 +101,11 @@ Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04
%setup -q -n libreswan-%{version}%{?prever}
sed -i "s:/usr/bin/python:/usr/bin/python3:" programs/verify/verify.in
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+
%build
%if %{buildefence}
%global efence "-lefence"
@@ -232,6 +242,12 @@ OBJ.linux.*/programs/pluto/cavp -v1psk ikev1_psk.fax | \
%endif
%changelog
+* Fri Feb 03 2017 Paul Wouters - 3.19-2
+- Resolves: rhbz#1392191 libreswan: crash when OSX client connects
+- Improved uniqueid and session replacing support
+- Test Buffer warning fix on size_t
+- Re-introduce --configdir for backwards compatibility
+
* Sun Jan 15 2017 Paul Wouters - 3.19-1
- Updated to 3.19 (see download.libreswan.org/CHANGES)