summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorJason King <jason.king@joyent.com>2017-12-01 18:50:05 +0000
committerJason King <jason.king@joyent.com>2017-12-05 15:49:43 +0000
commit9ba45b30b3b7aaeb1b63f85670403e6ea3a550eb (patch)
tree8fc863c81e21701c683082713be3693e2ba8fd51 /usr/src
parentafa571e5c76063af71af626415191589b53d042f (diff)
downloadillumos-joyent-9ba45b30b3b7aaeb1b63f85670403e6ea3a550eb.tar.gz
OS-6480 Allow IKEV2 pf_key(7P) key management cookies to be updated after set
Reviewed by: Dan McDonald <danmcd@joyent.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/lib/libipsecutil/common/ipsec_util.c4
-rw-r--r--usr/src/test/os-tests/tests/pf_key/Makefile1
-rw-r--r--usr/src/test/os-tests/tests/pf_key/kmc-update.sh73
-rw-r--r--usr/src/test/os-tests/tests/pf_key/kmc-updater.c126
-rw-r--r--usr/src/uts/common/inet/ip/sadb.c4
-rw-r--r--usr/src/uts/common/net/pfkeyv2.h3
6 files changed, 179 insertions, 32 deletions
diff --git a/usr/src/lib/libipsecutil/common/ipsec_util.c b/usr/src/lib/libipsecutil/common/ipsec_util.c
index 343a4f0a1b..b983e75e37 100644
--- a/usr/src/lib/libipsecutil/common/ipsec_util.c
+++ b/usr/src/lib/libipsecutil/common/ipsec_util.c
@@ -2612,7 +2612,9 @@ print_kmc(FILE *file, char *prefix, struct sadb_x_kmc *kmc)
case SADB_X_KMP_MANUAL:
cookie_label = dgettext(TEXT_DOMAIN, "Manual SA with cookie:");
break;
- /* case SADB_X_KMP_IKEV2: */
+ case SADB_X_KMP_IKEV2:
+ cookie_label = dgettext(TEXT_DOMAIN, "IKEV2:");
+ break;
default:
cookie_label =
dgettext(TEXT_DOMAIN, "<unknown KM protocol>");
diff --git a/usr/src/test/os-tests/tests/pf_key/Makefile b/usr/src/test/os-tests/tests/pf_key/Makefile
index 1073ed7e5f..443cf4c1e1 100644
--- a/usr/src/test/os-tests/tests/pf_key/Makefile
+++ b/usr/src/test/os-tests/tests/pf_key/Makefile
@@ -32,6 +32,7 @@ CMDS = $(PROG:%=$(TESTDIR)/%)
$(CMDS) := FILEMODE = 0555
LDLIBS += -lsocket
+kmc-updater := LDLIBS += -lipsecutil
eacq-enabler:
$(LINK.c) eacq-enabler.c -o $@ $(LDLIBS)
diff --git a/usr/src/test/os-tests/tests/pf_key/kmc-update.sh b/usr/src/test/os-tests/tests/pf_key/kmc-update.sh
index 473a0b7d6b..a78df0f7dc 100644
--- a/usr/src/test/os-tests/tests/pf_key/kmc-update.sh
+++ b/usr/src/test/os-tests/tests/pf_key/kmc-update.sh
@@ -30,15 +30,23 @@ fi
# test (or not) cookie/cookie64 and the IKEv1 exception.
#
-# Add two simple SAs. Will delete them first, out of paranoia.
+SADB_X_KMP_KINK=2
+SADB_X_KMP_IKEV2=3
+COOKIE_IKEV2="0x111770171170"
+EINVAL=22
+
+# Add three simple SAs. Will delete them first, out of paranoia.
ipseckey 2>&1 >/dev/null <<EOF
delete ah spi 0x2112 dst 127.0.0.1
delete ah spi 0x5150 dst 127.0.0.1
+delete ah spi 0x6768 dst 127.0.0.1
add ah spi 0x2112 dst 127.0.0.1 authalg md5 authkey \
1234567890abcdeffedcba0987654321
add ah spi 0x5150 dst 127.0.0.1 authalg md5 authkey \
abcdef01234567890123456789abcdef
+add ah spi 0x6768 dst 127.0.0.1 authalg md5 authkey \
+ fedcbafedcba01234567890123456789
EOF
# Run programs to see if UPDATE on their KM cookies works. Both test
@@ -54,6 +62,22 @@ if [[ $? != 0 ]]; then
fi
echo "Passed IKEv1 32-bit KMC test."
+# Test that once set, an IKEv1 KMC cannot be changed once set
+$TESTPATH/kmc-updater -e $EINVAL -k 0x12345 0x2112
+if [[ $? != 0 ]]; then
+ echo "IKEv1 32-bit KMC update test failed."
+ exit 1
+fi
+echo "Passed IKEv1 32-bit KMC update test."
+
+# Test that IKEv1 KMCs once set, cannot be changed to a different type
+$TESTPATH/kmc-updater -e $EINVAL -p $SADB_X_KMP_IKEV2 0x2112
+if [[ $? != 0 ]]; then
+ echo "IKEv1 32-bit KMC protocol update test failed."
+ exit 1
+fi
+echo "Passed IKEv1 32-bit KMC protocol update test."
+
# Test a different one, using all 64-bits.
$TESTPATH/kmc-updater 0x5150 64
if [[ $? != 0 ]]; then
@@ -62,7 +86,54 @@ if [[ $? != 0 ]]; then
fi
echo "Passed 64-bit KMC test."
+# Test that non IKEv2 64-bit KMCs also cannot be changed once set
+$TESTPATH/kmc-updater -e $EINVAL -k "0x12345678abcdef" 0x5150 64
+if [[ $? != 0 ]]; then
+ echo "64-bit KMC update test failed."
+ exit 1
+fi
+echo "Passed 64-bit KMC update test."
+
+# Test that non-IKEv2 KMCs cannot be changed to a different type
+$TESTPATH/kmc-updater -e $EINVAL -p $SADB_X_KMP_IKEV2 0x5150 64
+if [[ $? != 0 ]]; then
+ echo "64-bit non-IKEv2 KMC protocol update test failed."
+ exit 1
+fi
+echo "Passed 64-bit non-IKEv2 KMC protocol update test."
+
+# Test allowing the update of IKEv2 KMCs
+$TESTPATH/kmc-updater -p $SADB_X_KMP_IKEV2 0x6768 64
+if [[ $? != 0 ]]; then
+ echo "Failed to set KMC for IKEV2 test."
+ exit 1
+fi
+$TESTPATH/kmc-updater -p $SADB_X_KMP_IKEV2 -k "$COOKIE_IKEV2" 0x6768 64
+if [[ $? != 0 ]]; then
+ echo "Failed to update IKEv2 KMC."
+ exit 1
+fi
+echo "Passed IKEv2 KMC test."
+
+# Test that IKEv2 KMCs cannot be changed to a different type
+$TESTPATH/kmc-updater -e $EINVAL -p $SADB_X_KMP_KINK -k "$COOKIE_IKEV2" \
+ 0x6768 64
+if [[ $? != 0 ]]; then
+ echo "64-bit IKEv2 KMC protocol update test failed."
+ exit 1
+fi
+echo "Passed 64-bit IKEv2 KMC protocol update test."
+
+# Test that IKEv2 KMCs cannot be changed to a different type even w/ new KMC
+$TESTPATH/kmc-updater -e $EINVAL -p $SADB_X_KMP_KINK 0x6768 64
+if [[ $? != 0 ]]; then
+ echo "64-bit IKEv2 KMC protocol + KMC update test failed."
+ exit 1
+fi
+echo "Passed 64-bit IKEv2 KMC protocol + KMC update test."
+
ipseckey delete ah spi 0x2112 dst 127.0.0.1
ipseckey delete ah spi 0x5150 dst 127.0.0.1
+ipseckey delete ah spi 0x6768 dst 127.0.0.1
exit 0
diff --git a/usr/src/test/os-tests/tests/pf_key/kmc-updater.c b/usr/src/test/os-tests/tests/pf_key/kmc-updater.c
index 2395eecb76..28fa3b36c4 100644
--- a/usr/src/test/os-tests/tests/pf_key/kmc-updater.c
+++ b/usr/src/test/os-tests/tests/pf_key/kmc-updater.c
@@ -21,6 +21,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#include <ipsec_util.h>
#define COOKIE64 0xc0ffee4afee01deaULL
#define COOKIE32 0x90125
@@ -35,7 +36,7 @@
*/
static void
write_and_read(int s, sadb_msg_t *samsg, uint64_t *readbuf, int readlen,
- char *msgtypestr)
+ int expected, char *msgtypestr)
{
ssize_t rc;
uint8_t msgtype = samsg->sadb_msg_type;
@@ -55,15 +56,24 @@ write_and_read(int s, sadb_msg_t *samsg, uint64_t *readbuf, int readlen,
} while (samsg->sadb_msg_seq != seq || samsg->sadb_msg_pid != pid ||
samsg->sadb_msg_type != msgtype);
- if (samsg->sadb_msg_errno != 0) {
+ if (samsg->sadb_msg_errno != expected) {
errno = samsg->sadb_msg_errno;
- err(EXIT_SETUP_FAIL, "%s reply has error (diag = %d)",
- msgtypestr, samsg->sadb_x_msg_diagnostic);
+ err(EXIT_SETUP_FAIL, "%s reply has error (diag = %d, %s)",
+ msgtypestr, samsg->sadb_x_msg_diagnostic,
+ keysock_diag(samsg->sadb_x_msg_diagnostic));
}
}
+static void
+usage(const char *progname)
+{
+ (void) fprintf(stderr, "Usage: %s [-e expected_error] [-k kmc_value] "
+ "[-p kmc_proto] <spi-value> [64]\n", progname);
+ exit(EXIT_SETUP_FAIL);
+}
+
int
-main(int argc, char *argv[])
+main(int argc, char * const argv[])
{
uint32_t spi;
sadb_ext_t *ext;
@@ -75,19 +85,72 @@ main(int argc, char *argv[])
uint64_t writebuf[20]; /* PF_KEY likes 64-bit alignment. */
uint64_t readbuf[128];
uint64_t *extptr, *endptr;
+ const char *cookiestr = NULL;
+ uint64_t cookie64 = COOKIE64;
+ uint32_t cookie32 = COOKIE32;
+ uint32_t reserved = RESERVED;
+ uint32_t proto = 0;
+ int experr = 0;
pid_t pid = getpid();
boolean_t do_64_test;
int s;
+ int c;
- if (argc != 2 && argc != 3) {
- (void) fprintf(stderr, "Usage: %s <spi-value> {64}\n",
- argv[0]);
- exit(EXIT_SETUP_FAIL);
+ while ((c = getopt(argc, argv, "e:k:p:")) != -1) {
+ switch (c) {
+ case 'e':
+ errno = 0;
+ experr = strtol(optarg, NULL, 0);
+ if (errno != 0) {
+ err(EXIT_SETUP_FAIL,
+ "Expected error value '%s' is not a "
+ "parsable number", optarg);
+ }
+ break;
+ case 'k':
+ cookiestr = optarg;
+ break;
+ case 'p':
+ errno = 0;
+ proto = strtoul(optarg, NULL, 0);
+ if (errno != 0) {
+ err(EXIT_SETUP_FAIL,
+ "KMC Protocol value '%s' is not a parsable"
+ " number", optarg);
+ }
+ break;
+ case '?':
+ (void) fprintf(stderr, "Invalid option -%c\n", optopt);
+ usage(argv[0]);
+ break;
+ }
}
- do_64_test = (argc == 3);
+
+ if (argc - optind != 1 && argc - optind != 2)
+ usage(argv[0]);
+
+ do_64_test = (argc - optind == 2);
+
+ if (cookiestr != NULL) {
+ errno = 0;
+
+ if (do_64_test)
+ cookie64 = strtoull(cookiestr, NULL, 0);
+ else
+ cookie32 = strtoul(cookiestr, NULL, 0);
+
+ if (errno != 0) {
+ err(EXIT_SETUP_FAIL,
+ "KMC '%s' is not a parsable number",
+ cookiestr);
+ }
+ }
+
+ if (proto == 0)
+ proto = do_64_test ? SADB_X_KMP_KINK : SADB_X_KMP_IKE;
errno = 0; /* Clear for strtoul() call. */
- spi = strtoul(argv[1], NULL, 0);
+ spi = strtoul(argv[optind], NULL, 0);
if (spi == 0) {
if (errno != 0) {
err(EXIT_SETUP_FAIL,
@@ -155,16 +218,21 @@ main(int argc, char *argv[])
kmcext->sadb_x_kmc_exttype = SADB_X_EXT_KM_COOKIE;
if (do_64_test) {
/* 64-bit cookie test. KINK is non-zero, and non-IKEv1. */
- kmcext->sadb_x_kmc_proto = SADB_X_KMP_KINK;
- kmcext->sadb_x_kmc_cookie64 = COOKIE64;
+ kmcext->sadb_x_kmc_proto = proto;
+ kmcext->sadb_x_kmc_cookie64 = cookie64;
} else {
/* IKEv1 32-bit cookie test. */
- kmcext->sadb_x_kmc_proto = SADB_X_KMP_IKE;
- kmcext->sadb_x_kmc_cookie = COOKIE32;
- kmcext->sadb_x_kmc_reserved = RESERVED;
+ kmcext->sadb_x_kmc_proto = proto;
+ kmcext->sadb_x_kmc_cookie = cookie32;
+ kmcext->sadb_x_kmc_reserved = reserved;
}
- write_and_read(s, samsg, readbuf, sizeof (readbuf), "SADB_UPDATE");
+ write_and_read(s, samsg, readbuf, sizeof (readbuf), experr,
+ "SADB_UPDATE");
+
+ /* If we expected to fail, we shouldn't try to verify anything */
+ if (experr != 0)
+ exit(EXIT_SUCCESS);
/*
* Okay, it worked! Now let's find the KMC reported back from the
@@ -174,7 +242,7 @@ main(int argc, char *argv[])
samsg->sadb_msg_len -= SADB_8TO64(sizeof (*kmcext));
/* Everything else in writebuf is good to go. */
- write_and_read(s, samsg, readbuf, sizeof (readbuf), "SADB_GET");
+ write_and_read(s, samsg, readbuf, sizeof (readbuf), 0, "SADB_GET");
/* Actually find the KMC extension. (expand for loop for readability) */
samsg = (sadb_msg_t *)readbuf;
@@ -195,26 +263,28 @@ main(int argc, char *argv[])
kmcext = (sadb_x_kmc_t *)extptr;
if (do_64_test) {
- if (kmcext->sadb_x_kmc_proto != SADB_X_KMP_KINK ||
- kmcext->sadb_x_kmc_cookie64 != COOKIE64) {
+ if (kmcext->sadb_x_kmc_proto != proto ||
+ kmcext->sadb_x_kmc_cookie64 != cookie64) {
(void) fprintf(stderr, "Unexpected 64-bit results: "
- "KMC received was %d, expecting %d,\n",
- kmcext->sadb_x_kmc_proto, SADB_X_KMP_KINK);
+ "KMC received was %" PRIu32
+ ", expecting %" PRIu32 ",\n",
+ kmcext->sadb_x_kmc_proto, proto);
(void) fprintf(stderr, "64-bit cookie recevied was "
"0x%"PRIx64", expecting 0x%"PRIx64"\n",
- kmcext->sadb_x_kmc_cookie64, COOKIE64);
+ kmcext->sadb_x_kmc_cookie64, cookie64);
exit(EXIT_TEST_FAIL);
}
} else {
- if (kmcext->sadb_x_kmc_proto != SADB_X_KMP_IKE ||
- kmcext->sadb_x_kmc_cookie != COOKIE32 ||
+ if (kmcext->sadb_x_kmc_proto != proto ||
+ kmcext->sadb_x_kmc_cookie != cookie32 ||
kmcext->sadb_x_kmc_reserved != 0) {
(void) fprintf(stderr, "Unexpected IKE/32-bit results:"
- " KMC received was %d, expecting %d,\n",
- kmcext->sadb_x_kmc_proto, SADB_X_KMP_IKE);
+ " KMC received was %" PRIu32
+ ", expecting %" PRIu32 ",\n",
+ kmcext->sadb_x_kmc_proto, proto);
(void) fprintf(stderr, "32-bit cookie recevied was "
"0x%"PRIx32", expecting 0x%"PRIx32"\n",
- kmcext->sadb_x_kmc_cookie64, COOKIE32);
+ kmcext->sadb_x_kmc_cookie64, cookie32);
(void) fprintf(stderr, "32-bit reserved recevied was "
"0x%"PRIx32", expecting 0\n",
kmcext->sadb_x_kmc_cookie64);
diff --git a/usr/src/uts/common/inet/ip/sadb.c b/usr/src/uts/common/inet/ip/sadb.c
index b56f09d029..a45f69c19e 100644
--- a/usr/src/uts/common/inet/ip/sadb.c
+++ b/usr/src/uts/common/inet/ip/sadb.c
@@ -4468,7 +4468,9 @@ sadb_check_kmc(ipsa_query_t *sq, ipsa_t *sa, int *diagnostic)
return (EINVAL);
}
- if ((kmc != 0) && (sa->ipsa_kmc != 0) && (sa->ipsa_kmc != kmc)) {
+ /* Allow IKEv2 KMCs to update the kmc value for rekeying */
+ if ((kmp != SADB_X_KMP_IKEV2) && (kmc != 0) && (sa->ipsa_kmc != 0) &&
+ (sa->ipsa_kmc != kmc)) {
*diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMC;
return (EINVAL);
}
diff --git a/usr/src/uts/common/net/pfkeyv2.h b/usr/src/uts/common/net/pfkeyv2.h
index 741de5007d..909c73414a 100644
--- a/usr/src/uts/common/net/pfkeyv2.h
+++ b/usr/src/uts/common/net/pfkeyv2.h
@@ -841,8 +841,9 @@ typedef struct sadb_x_edump {
#define SADB_X_KMP_MANUAL 0 /* Cookie is ignored. */
#define SADB_X_KMP_IKE 1
#define SADB_X_KMP_KINK 2
+#define SADB_X_KMP_IKEV2 3
-#define SADB_X_KMP_MAX 2
+#define SADB_X_KMP_MAX 3
/*
* Handy conversion macros. Not part of the PF_KEY spec...