diff options
author | Jason King <jason.king@joyent.com> | 2017-12-01 18:50:05 +0000 |
---|---|---|
committer | Jason King <jason.king@joyent.com> | 2017-12-05 15:49:43 +0000 |
commit | 9ba45b30b3b7aaeb1b63f85670403e6ea3a550eb (patch) | |
tree | 8fc863c81e21701c683082713be3693e2ba8fd51 /usr/src | |
parent | afa571e5c76063af71af626415191589b53d042f (diff) | |
download | illumos-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.c | 4 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/pf_key/Makefile | 1 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/pf_key/kmc-update.sh | 73 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/pf_key/kmc-updater.c | 126 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/sadb.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/net/pfkeyv2.h | 3 |
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... |