diff --git a/wolfProvider/README.md b/wolfProvider/README.md new file mode 100644 index 00000000..fc557b65 --- /dev/null +++ b/wolfProvider/README.md @@ -0,0 +1,50 @@ +# wolfProvider OSP patches + +Patches that adapt upstream open-source projects (curl, krb5, libssh2, +hostap, etc.) to test cleanly against `wolfProvider` (FIPS and non-FIPS). + +## Naming convention + +Every patch follows exactly one pattern (no exceptions): + + /--wolfprov.patch (non-FIPS) + /--wolfprov-fips.patch (FIPS) + /--wolfssl-X.Y.Z-wolfprov.patch (pinned snapshot) + /--wolfssl-X.Y.Z-wolfprov-fips.patch (pinned snapshot) + +Rules: +- FIPS is always the `-fips` suffix before `.patch` (never an + uppercase `-FIPS-` infix). +- The provider segment is always `-wolfprov` (never `-wolfprovider`). +- `` is the upstream version ref the patch targets and may be + empty for version-agnostic patches. + +- **Universal** name (no `-wolfssl-X.Y.Z-` infix) is the **latest** + patch content. By default a patch should be universal — it tracks + current wolfSSL master / latest stable and is reused unchanged across + wolfSSL version bumps. +- `-wolfssl-X.Y.Z-` infix marks a **pinned snapshot** for that wolfSSL + line. Add one only when the universal patch has diverged in a way + that breaks on an older wolfSSL release that is still supported. + +When you modify a patch for a new wolfSSL release in a way that breaks +an older line: + 1. Copy the pre-modification content as + `-wolfssl--wolfprov[-fips].patch`. + 2. Keep editing the universal file for the new wolfSSL release. + +## How workflows pick the right patch + +`wolfssl/wolfProvider` workflows resolve patches via +`scripts/resolve-osp-patch.sh`: + +| wolfssl_ref | order tried | +|---------------------|--------------------------------------------| +| `v5.8.X-stable` | `-wolfssl-5.8.4-` then universal | +| `v5.9.X-stable` | `-wolfssl-5.9.1-` then universal | +| `master` / other | universal only | + +For FIPS, the helper tries `-wolfprov-fips.patch` and falls back to the +non-FIPS patch when no FIPS-specific one exists. Because the naming is +uniform, the helper stays simple — one pattern, no per-project special +cases. diff --git a/wolfProvider/curl/README.md b/wolfProvider/curl/README.md index 91911fbd..a1be6eb2 100644 --- a/wolfProvider/curl/README.md +++ b/wolfProvider/curl/README.md @@ -1,4 +1,9 @@ -`wolfProvider/curl/curl-8_4_0-wolfprov.patch` adds support for testing curl -`8.4.0` with wolfProvider FIPS in Jenkins. This patch is only needed when -testing curl with Jenkins. It disables a non crypto related test that IDN -with different languages. +`wolfProvider/curl/curl-8_4_0-wolfprov.patch` and +`wolfProvider/curl/curl-7_88_1-wolfprov.patch` add support for testing the +respective curl versions with wolfProvider. Both patches disable test 1560 +(`[URL API]` libtest) — a non-crypto IDN-related test that fails under the +wolfProvider test-deps container regardless of IDN dependencies installed. + +These patches must be applied to the curl source tree (e.g. `patch -p1`) +before running `make test-ci`. If they are not applied, test 1560 will +appear as an unexpected failure in normal-mode runs. diff --git a/wolfProvider/curl/curl-7_88_1-wolfprov.patch b/wolfProvider/curl/curl-7_88_1-wolfprov.patch new file mode 100644 index 00000000..1a583580 --- /dev/null +++ b/wolfProvider/curl/curl-7_88_1-wolfprov.patch @@ -0,0 +1,11 @@ +diff --git a/tests/data/DISABLED b/tests/data/DISABLED +index 6edc0b4..98fa0ab 100644 +--- a/tests/data/DISABLED ++++ b/tests/data/DISABLED +@@ -106,3 +106,6 @@ + %if bearssl + 313 + %endif ++# test 1560 requires IDN support - wolfProvider works locally in Jenkins ++# this fails even with the dependency installed ++1560 diff --git a/wolfProvider/grpc/README.md b/wolfProvider/grpc/README.md index 3a4f80f2..e1a06549 100644 --- a/wolfProvider/grpc/README.md +++ b/wolfProvider/grpc/README.md @@ -1,3 +1,3 @@ -`grpc-FIPS-v1.60.0-wolfprov.patch` adds testing support for FIPS and non-FIPS +`grpc-v1.60.0-wolfprov-fips.patch` adds testing support for FIPS and non-FIPS grpc `v1.60.0`. The patch also adds support for the use of `WOLFPROV_FORCE_FAIL=1` env variable. diff --git a/wolfProvider/grpc/grpc-FIPS-v1.60.0-wolfprov.patch b/wolfProvider/grpc/grpc-v1.60.0-wolfprov-fips.patch similarity index 100% rename from wolfProvider/grpc/grpc-FIPS-v1.60.0-wolfprov.patch rename to wolfProvider/grpc/grpc-v1.60.0-wolfprov-fips.patch diff --git a/wolfProvider/hostap/README.md b/wolfProvider/hostap/README.md deleted file mode 100644 index 5d9ef0d5..00000000 --- a/wolfProvider/hostap/README.md +++ /dev/null @@ -1,11 +0,0 @@ -`wolfProvider/hostap/hostap-main-wolfprov.patch` adds support for testing hostap `main` -with wolfProvider. It is needed to test the full testing suite. - -The patch makes the following changes: -1. Replaces OpenSSL provider references in `src/crypto/crypto_openssl.c`: - - Changes "default" provider to "libwolfprov" - - Changes "legacy" provider to "libwolfprov" -2. Replaces OpenSSL provider reference in `src/crypto/tls_openssl.c`: - - Changes "pkcs11" provider to "libwolfprov" -3. Fixes crda command failure handling in `tests/hwsim/vm/inside.sh`: - - Adds `|| true` to handle crda command failure gracefully diff --git a/wolfProvider/hostap/hostap-hostap_2_11-wolfprov-fips.patch b/wolfProvider/hostap/hostap-hostap_2_11-wolfprov-fips.patch new file mode 100644 index 00000000..64a29828 --- /dev/null +++ b/wolfProvider/hostap/hostap-hostap_2_11-wolfprov-fips.patch @@ -0,0 +1,113 @@ +diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c +index 2d8ff60..1bb28b6 100644 +--- a/src/crypto/crypto_openssl.c ++++ b/src/crypto/crypto_openssl.c +@@ -196,7 +196,7 @@ void openssl_load_legacy_provider(void) + if (openssl_legacy_provider) + return; + +- openssl_legacy_provider = OSSL_PROVIDER_try_load(NULL, "legacy", 1); ++ openssl_legacy_provider = OSSL_PROVIDER_try_load(NULL, "libwolfprov", 1); + #endif /* OpenSSL version >= 3.0 */ + } + +diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py +index f8e75b5..3820ae0 100644 +--- a/tests/hwsim/test_ap_eap.py ++++ b/tests/hwsim/test_ap_eap.py +@@ -2000,16 +2000,6 @@ def test_ap_wpa2_eap_ttls_mschapv2_utf8(dev, apdev): + dev[2].request("REMOVE_NETWORK all") + dev[2].wait_disconnected() + +-def test_ap_wpa2_eap_ttls_eap_gtc(dev, apdev): +- """WPA2-Enterprise connection using EAP-TTLS/EAP-GTC""" +- params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") +- hapd = hostapd.add_ap(apdev[0], params) +- eap_connect(dev[0], hapd, "TTLS", "user", +- anonymous_identity="ttls", password="password", +- ca_cert="auth_serv/ca.pem", phase2="autheap=GTC") +- hwsim_utils.test_connectivity(dev[0], hapd) +- eap_reauth(dev[0], "TTLS") +- + def test_ap_wpa2_eap_ttls_eap_gtc_incorrect_password(dev, apdev): + """WPA2-Enterprise connection using EAP-TTLS/EAP-GTC - incorrect password""" + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") +@@ -2548,17 +2538,6 @@ def test_ap_wpa2_eap_peap_eap_gtc(dev, apdev, params): + anonymous_identity="peap", password="password", + ca_cert="auth_serv/ca.pem", phase2="auth=GTC") + +-def test_ap_wpa2_eap_peap_eap_tls(dev, apdev): +- """WPA2-Enterprise connection using EAP-PEAP/EAP-TLS""" +- params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") +- hapd = hostapd.add_ap(apdev[0], params) +- eap_connect(dev[0], hapd, "PEAP", "cert user", +- ca_cert="auth_serv/ca.pem", phase2="auth=TLS", +- ca_cert2="auth_serv/ca.pem", +- client_cert2="auth_serv/user.pem", +- private_key2="auth_serv/user.key") +- eap_reauth(dev[0], "PEAP") +- + def test_ap_wpa2_eap_peap_eap_vendor(dev, apdev): + """WPA2-Enterprise connection using EAP-PEAP/EAP-vendor""" + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") +@@ -2566,15 +2545,6 @@ def test_ap_wpa2_eap_peap_eap_vendor(dev, apdev): + eap_connect(dev[0], hapd, "PEAP", "vendor-test-2", + ca_cert="auth_serv/ca.pem", phase2="auth=VENDOR-TEST") + +-def test_ap_wpa2_eap_tls(dev, apdev): +- """WPA2-Enterprise connection using EAP-TLS""" +- params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") +- hapd = hostapd.add_ap(apdev[0], params) +- eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem", +- client_cert="auth_serv/user.pem", +- private_key="auth_serv/user.key") +- eap_reauth(dev[0], "TLS") +- + def test_eap_tls_pkcs8_pkcs5_v2_des3(dev, apdev): + """WPA2-Enterprise connection using EAP-TLS and PKCS #8, PKCS #5 v2 DES3 key""" + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") +diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py +index 9655093..82e5d5c 100644 +--- a/tests/hwsim/test_ap_psk.py ++++ b/tests/hwsim/test_ap_psk.py +@@ -35,27 +35,6 @@ def check_mib(dev, vals): + raise Exception("Unexpected {} = {} (expected {})".format(v[0], mib[v[0]], v[1])) + + @remote_compatible +-def test_ap_wpa2_psk(dev, apdev): +- """WPA2-PSK AP with PSK instead of passphrase""" +- ssid = "test-wpa2-psk" +- passphrase = 'qwertyuiop' +- psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' +- params = hostapd.wpa2_params(ssid=ssid) +- params['wpa_psk'] = psk +- hapd = hostapd.add_ap(apdev[0], params) +- key_mgmt = hapd.get_config()['key_mgmt'] +- if key_mgmt.split(' ')[0] != "WPA-PSK": +- raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt) +- dev[0].connect(ssid, raw_psk=psk, scan_freq="2412") +- dev[1].connect(ssid, psk=passphrase, scan_freq="2412") +- +- sig = dev[0].request("SIGNAL_POLL").splitlines() +- pkt = dev[0].request("PKTCNT_POLL").splitlines() +- if "FREQUENCY=2412" not in sig: +- raise Exception("Unexpected SIGNAL_POLL value: " + str(sig)) +- if "TXBAD=0" not in pkt: +- raise Exception("Unexpected TXBAD value: " + str(pkt)) +- + def test_ap_wpa2_psk_file(dev, apdev): + """WPA2-PSK AP with PSK from a file""" + ssid = "test-wpa2-psk" +diff --git a/tests/hwsim/vm/inside.sh b/tests/hwsim/vm/inside.sh +index 31dfb9d..424b48b 100755 +--- a/tests/hwsim/vm/inside.sh ++++ b/tests/hwsim/vm/inside.sh +@@ -163,7 +163,7 @@ else + # some tests need CRDA, install a simple uevent helper + # and preload the 00 domain it will have asked for already + echo $TESTDIR/vm/uevent.sh > /sys/kernel/uevent_helper +- COUNTRY=00 crda ++ COUNTRY=00 crda || true + + mkdir -p /var/run/dbus + touch /var/run/dbus/hwsim-test diff --git a/wolfProvider/hostap/hostap-hostap_2_11-wolfprov.patch b/wolfProvider/hostap/hostap-hostap_2_11-wolfprov.patch new file mode 100644 index 00000000..ac254f17 --- /dev/null +++ b/wolfProvider/hostap/hostap-hostap_2_11-wolfprov.patch @@ -0,0 +1,26 @@ +diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c +index 2d8ff60..1bb28b6 100644 +--- a/src/crypto/crypto_openssl.c ++++ b/src/crypto/crypto_openssl.c +@@ -196,7 +196,7 @@ void openssl_load_legacy_provider(void) + if (openssl_legacy_provider) + return; + +- openssl_legacy_provider = OSSL_PROVIDER_try_load(NULL, "legacy", 1); ++ openssl_legacy_provider = OSSL_PROVIDER_try_load(NULL, "libwolfprov", 1); + #endif /* OpenSSL version >= 3.0 */ + } + +diff --git a/tests/hwsim/vm/inside.sh b/tests/hwsim/vm/inside.sh +index 31dfb9d..424b48b 100755 +--- a/tests/hwsim/vm/inside.sh ++++ b/tests/hwsim/vm/inside.sh +@@ -163,7 +163,7 @@ else + # some tests need CRDA, install a simple uevent helper + # and preload the 00 domain it will have asked for already + echo $TESTDIR/vm/uevent.sh > /sys/kernel/uevent_helper +- COUNTRY=00 crda ++ COUNTRY=00 crda || true + + mkdir -p /var/run/dbus + touch /var/run/dbus/hwsim-test diff --git a/wolfProvider/krb5/krb5-1.20.1-final-wolfprov-fips.patch b/wolfProvider/krb5/krb5-1.20.1-final-wolfprov-fips.patch index 1d380ed0..d5c994f9 100644 --- a/wolfProvider/krb5/krb5-1.20.1-final-wolfprov-fips.patch +++ b/wolfProvider/krb5/krb5-1.20.1-final-wolfprov-fips.patch @@ -1626,6 +1626,64 @@ index e4b560fb8..4c25b9d42 100644 $(srcdir)/t_authdata.c \ $(srcdir)/t_cc_config.c \ $(srcdir)/t_copy_context.c \ +diff --git a/src/lib/krb5/krb/t_expire_warn.py b/src/lib/krb5/krb/t_expire_warn.py +index e163cc7..2b56d8f 100755 +--- a/src/lib/krb5/krb/t_expire_warn.py ++++ b/src/lib/krb5/krb/t_expire_warn.py +@@ -26,41 +26,41 @@ from k5test import * + realm = K5Realm(create_user=False, create_host=False) + + # Create principals with various password expirations. +-realm.run([kadminl, 'addprinc', '-pw', 'pass', 'noexpire']) +-realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '30 minutes', ++realm.run([kadminl, 'addprinc', '-pw', 'password-test12', 'noexpire']) ++realm.run([kadminl, 'addprinc', '-pw', 'password-test12', '-pwexpire', '30 minutes', + 'minutes']) +-realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '12 hours', ++realm.run([kadminl, 'addprinc', '-pw', 'password-test12', '-pwexpire', '12 hours', + 'hours']) +-realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '3 days', 'days']) ++realm.run([kadminl, 'addprinc', '-pw', 'password-test12', '-pwexpire', '3 days', 'days']) + + # Check for expected prompter warnings when no expire callback is used. +-output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '0', '0']) ++output = realm.run(['./t_expire_warn', 'noexpire', 'password-test12', '0', '0']) + if output: + fail('Unexpected output for noexpire') +-realm.run(['./t_expire_warn', 'minutes', 'pass', '0', '0'], ++realm.run(['./t_expire_warn', 'minutes', 'password-test12', '0', '0'], + expected_msg=' less than one hour on ') +-realm.run(['./t_expire_warn', 'hours', 'pass', '0', '0'], ++realm.run(['./t_expire_warn', 'hours', 'password-test12', '0', '0'], + expected_msg=' hours on ') +-realm.run(['./t_expire_warn', 'days', 'pass', '0', '0'], ++realm.run(['./t_expire_warn', 'days', 'password-test12', '0', '0'], + expected_msg=' days on ') + # Try one case with the stepwise interface. +-realm.run(['./t_expire_warn', 'days', 'pass', '0', '1'], ++realm.run(['./t_expire_warn', 'days', 'password-test12', '0', '1'], + expected_msg=' days on ') + + # Check for expected expire callback behavior. These tests are + # carefully agnostic about whether the KDC supports last_req fields, + # and could be made more specific if last_req support is added. +-output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '1', '0']) ++output = realm.run(['./t_expire_warn', 'noexpire', 'password-test12', '1', '0']) + if 'password_expiration = 0\n' not in output or \ + 'account_expiration = 0\n' not in output or \ + 'is_last_req = ' not in output: + fail('Expected callback output not seen for noexpire') +-output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '0']) ++output = realm.run(['./t_expire_warn', 'days', 'password-test12', '1', '0']) + if 'password_expiration = ' not in output or \ + 'password_expiration = 0\n' in output: + fail('Expected non-zero password expiration not seen for days') + # Try one case with the stepwise interface. +-output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '1']) ++output = realm.run(['./t_expire_warn', 'days', 'password-test12', '1', '1']) + if 'password_expiration = ' not in output or \ + 'password_expiration = 0\n' in output: + fail('Expected non-zero password expiration not seen for days') diff --git a/src/lib/krb5/krb/t_get_etype_info.py b/src/lib/krb5/krb/t_get_etype_info.py index 3c9168591..0529b6729 100644 --- a/src/lib/krb5/krb/t_get_etype_info.py diff --git a/wolfProvider/krb5/krb5-1.20.1-final-wolfssl-5.8.4-wolfprov-fips.patch b/wolfProvider/krb5/krb5-1.20.1-final-wolfssl-5.8.4-wolfprov-fips.patch new file mode 100644 index 00000000..d5c994f9 --- /dev/null +++ b/wolfProvider/krb5/krb5-1.20.1-final-wolfssl-5.8.4-wolfprov-fips.patch @@ -0,0 +1,4356 @@ +diff --git a/src/lib/crypto/crypto_tests/Makefile.in b/src/lib/crypto/crypto_tests/Makefile.in +index 1a3fe5966..eed0e1931 100644 +--- a/src/lib/crypto/crypto_tests/Makefile.in ++++ b/src/lib/crypto/crypto_tests/Makefile.in +@@ -36,7 +36,7 @@ check-unix: t_nfold t_encrypt t_decrypt t_prf t_cmac t_hmac \ + $(RUN_TEST) ./t_encrypt + $(RUN_TEST) ./t_decrypt + $(RUN_TEST) ./t_cmac +- $(RUN_TEST) ./t_hmac ++ #$(RUN_TEST) ./t_hmac + $(RUN_TEST) ./t_prf + $(RUN_TEST) ./t_cksums + $(RUN_TEST) ./t_cts +@@ -44,17 +44,13 @@ check-unix: t_nfold t_encrypt t_decrypt t_prf t_cmac t_hmac \ + cmp vk.txt $(srcdir)/expect-vk.txt + $(RUN_TEST) ./aes-test > vt.txt + cmp vt.txt $(srcdir)/expect-vt.txt +- $(RUN_TEST) ./camellia-test > camellia-vt.txt +- cmp camellia-vt.txt $(srcdir)/camellia-expect-vt.txt +- $(RUN_TEST) $(C)t_mddriver4 -x +- $(RUN_TEST) $(C)t_mddriver -x ++ #$(RUN_TEST) $(C)t_mddriver4 -x ++ #$(RUN_TEST) $(C)t_mddriver -x + $(RUN_TEST) ./t_sha2 + $(RUN_TEST) ./t_short + $(RUN_TEST) ./t_str2key + $(RUN_TEST) ./t_derive + $(RUN_TEST) ./t_fork +- $(RUN_TEST) ./t_cf2 <$(srcdir)/t_cf2.in >t_cf2.output +- diff t_cf2.output $(srcdir)/t_cf2.expected + # $(RUN_TEST) ./t_pkcs5 + + t_nfold$(EXEEXT): t_nfold.$(OBJEXT) $(KRB5_BASE_DEPLIBS) +diff --git a/src/lib/crypto/crypto_tests/camellia-test.c b/src/lib/crypto/crypto_tests/camellia-test.c +index 23d14667e..1e9d68708 100644 +--- a/src/lib/crypto/crypto_tests/camellia-test.c ++++ b/src/lib/crypto/crypto_tests/camellia-test.c +@@ -132,10 +132,6 @@ int main (int argc, char *argv[]) + argv[0], argv[0]); + return 1; + } +- init(); +- if (argc == 2) +- vk_test(); +- else +- vt_test(); ++ /* No camellia support in wolfProvider */ + return 0; + } +diff --git a/src/lib/crypto/crypto_tests/t_cksums.c b/src/lib/crypto/crypto_tests/t_cksums.c +index 557340ec5..0704e0305 100644 +--- a/src/lib/crypto/crypto_tests/t_cksums.c ++++ b/src/lib/crypto/crypto_tests/t_cksums.c +@@ -40,35 +40,6 @@ struct test { + krb5_data keybits; + krb5_data cksum; + } test_cases[] = { +- { +- { KV5M_DATA, 3, "one" }, +- CKSUMTYPE_RSA_MD4, 0, 0, { KV5M_DATA, 0, "" }, +- { KV5M_DATA, 16, +- "\x30\x5D\xCC\x2C\x0F\xDD\x53\x39\x96\x95\x52\xC7\xB8\x99\x63\x48" } +- }, +- { +- { KV5M_DATA, 19, "two three four five" }, +- CKSUMTYPE_RSA_MD5, 0, 0, { KV5M_DATA, 0, "" }, +- { KV5M_DATA, 16, +- "\xBA\xB5\x32\x15\x51\xE1\x08\x44\x90\x86\x96\x35\xB3\xC2\x68\x15" } +- }, +- { +- { KV5M_DATA, 0, "" }, +- CKSUMTYPE_SHA1, 0, 0, { KV5M_DATA, 0, "" }, +- { KV5M_DATA, 20, +- "\xDA\x39\xA3\xEE\x5E\x6B\x4B\x0D\x32\x55\xBF\xEF\x95\x60\x18\x90" +- "\xAF\xD8\x07\x09" } +- }, +- { +- { KV5M_DATA, 9, "six seven" }, +- CKSUMTYPE_HMAC_SHA1_DES3, ENCTYPE_DES3_CBC_SHA1, 2, +- { KV5M_DATA, 24, +- "\x7A\x25\xDF\x89\x92\x29\x6D\xCE\xDA\x0E\x13\x5B\xC4\x04\x6E\x23" +- "\x75\xB3\xC1\x4C\x98\xFB\xC1\x62" }, +- { KV5M_DATA, 20, +- "\x0E\xEF\xC9\xC3\xE0\x49\xAA\xBC\x1B\xA5\xC4\x01\x67\x7D\x9A\xB6" +- "\x99\x08\x2B\xB4" } +- }, + { + { KV5M_DATA, 37, "eight nine ten eleven twelve thirteen" }, + CKSUMTYPE_HMAC_SHA1_96_AES128, ENCTYPE_AES128_CTS_HMAC_SHA1_96, 3, +@@ -86,56 +57,6 @@ struct test { + { KV5M_DATA, 12, + "\xE0\x87\x39\xE3\x27\x9E\x29\x03\xEC\x8E\x38\x36" } + }, +- { +- { KV5M_DATA, 15, "fifteen sixteen" }, +- CKSUMTYPE_MD5_HMAC_ARCFOUR, ENCTYPE_ARCFOUR_HMAC, 5, +- { KV5M_DATA, 16, +- "\xF7\xD3\xA1\x55\xAF\x5E\x23\x8A\x0B\x7A\x87\x1A\x96\xBA\x2A\xB2" }, +- { KV5M_DATA, 16, +- "\x9F\x41\xDF\x30\x49\x07\xDE\x73\x54\x47\x00\x1F\xD2\xA1\x97\xB9" } +- }, +- { +- { KV5M_DATA, 34, "seventeen eighteen nineteen twenty" }, +- CKSUMTYPE_HMAC_MD5_ARCFOUR, ENCTYPE_ARCFOUR_HMAC, 6, +- { KV5M_DATA, 16, +- "\xF7\xD3\xA1\x55\xAF\x5E\x23\x8A\x0B\x7A\x87\x1A\x96\xBA\x2A\xB2" }, +- { KV5M_DATA, 16, +- "\xEB\x38\xCC\x97\xE2\x23\x0F\x59\xDA\x41\x17\xDC\x58\x59\xD7\xEC" } +- }, +- { +- { KV5M_DATA, 11, "abcdefghijk" }, +- CKSUMTYPE_CMAC_CAMELLIA128, ENCTYPE_CAMELLIA128_CTS_CMAC, 7, +- { KV5M_DATA, 16, +- "\x1D\xC4\x6A\x8D\x76\x3F\x4F\x93\x74\x2B\xCB\xA3\x38\x75\x76\xC3" }, +- { KV5M_DATA, 16, +- "\x11\x78\xE6\xC5\xC4\x7A\x8C\x1A\xE0\xC4\xB9\xC7\xD4\xEB\x7B\x6B" } +- }, +- { +- { KV5M_DATA, 26, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, +- CKSUMTYPE_CMAC_CAMELLIA128, ENCTYPE_CAMELLIA128_CTS_CMAC, 8, +- { KV5M_DATA, 16, +- "\x50\x27\xBC\x23\x1D\x0F\x3A\x9D\x23\x33\x3F\x1C\xA6\xFD\xBE\x7C" }, +- { KV5M_DATA, 16, +- "\xD1\xB3\x4F\x70\x04\xA7\x31\xF2\x3A\x0C\x00\xBF\x6C\x3F\x75\x3A" } +- }, +- { +- { KV5M_DATA, 9, "123456789" }, +- CKSUMTYPE_CMAC_CAMELLIA256, ENCTYPE_CAMELLIA256_CTS_CMAC, 9, +- { KV5M_DATA, 32, +- "\xB6\x1C\x86\xCC\x4E\x5D\x27\x57\x54\x5A\xD4\x23\x39\x9F\xB7\x03" +- "\x1E\xCA\xB9\x13\xCB\xB9\x00\xBD\x7A\x3C\x6D\xD8\xBF\x92\x01\x5B" }, +- { KV5M_DATA, 16, +- "\x87\xA1\x2C\xFD\x2B\x96\x21\x48\x10\xF0\x1C\x82\x6E\x77\x44\xB1" } +- }, +- { +- { KV5M_DATA, 30, "!@#$%^&*()!@#$%^&*()!@#$%^&*()" }, +- CKSUMTYPE_CMAC_CAMELLIA256, ENCTYPE_CAMELLIA256_CTS_CMAC, 10, +- { KV5M_DATA, 32, +- "\x32\x16\x4C\x5B\x43\x4D\x1D\x15\x38\xE4\xCF\xD9\xBE\x80\x40\xFE" +- "\x8C\x4A\xC7\xAC\xC4\xB9\x3D\x33\x14\xD2\x13\x36\x68\x14\x7A\x05" }, +- { KV5M_DATA, 16, +- "\x3F\xA0\xB4\x23\x55\xE5\x2B\x18\x91\x87\x29\x4A\xA2\x52\xAB\x64" } +- }, + { + { KV5M_DATA, 21, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" +diff --git a/src/lib/crypto/crypto_tests/t_cmac.c b/src/lib/crypto/crypto_tests/t_cmac.c +index 565c35da7..bf82581b7 100644 +--- a/src/lib/crypto/crypto_tests/t_cmac.c ++++ b/src/lib/crypto/crypto_tests/t_cmac.c +@@ -99,49 +99,6 @@ check_result(const char *name, const unsigned char *result, + int + main(int argc, char **argv) + { +- krb5_error_code ret; +- krb5_context context = NULL; +- krb5_keyblock keyblock; +- krb5_key key; +- const struct krb5_enc_provider *enc = &krb5int_enc_camellia128; +- krb5_crypto_iov iov; +- unsigned char resultbuf[16]; +- krb5_data result = make_data(resultbuf, 16); +- +- /* Create the example key. */ +- keyblock.magic = KV5M_KEYBLOCK; +- keyblock.enctype = ENCTYPE_CAMELLIA128_CTS_CMAC; +- keyblock.length = 16; +- keyblock.contents = keybytes; +- ret = krb5_k_create_key(context, &keyblock, &key); +- assert(!ret); +- +- /* Example 1. */ +- iov.flags = KRB5_CRYPTO_TYPE_DATA; +- iov.data = make_data(input, 0); +- ret = krb5int_cmac_checksum(enc, key, &iov, 1, &result); +- assert(!ret); +- check_result("example 1", resultbuf, cmac1); +- +- /* Example 2. */ +- iov.data.length = 16; +- ret = krb5int_cmac_checksum(enc, key, &iov, 1, &result); +- assert(!ret); +- check_result("example 2", resultbuf, cmac2); +- +- /* Example 3. */ +- iov.data.length = 40; +- ret = krb5int_cmac_checksum(enc, key, &iov, 1, &result); +- assert(!ret); +- check_result("example 3", resultbuf, cmac3); +- +- /* Example 4. */ +- iov.data.length = 64; +- ret = krb5int_cmac_checksum(enc, key, &iov, 1, &result); +- assert(!ret); +- check_result("example 4", resultbuf, cmac4); +- +- printf("All CMAC tests passed.\n"); +- krb5_k_free_key(context, key); ++ /* CMAC tests require camellia, which is not supported in wolfProvider */ + return 0; + } +diff --git a/src/lib/crypto/crypto_tests/t_decrypt.c b/src/lib/crypto/crypto_tests/t_decrypt.c +index a40a85500..164a0fce4 100644 +--- a/src/lib/crypto/crypto_tests/t_decrypt.c ++++ b/src/lib/crypto/crypto_tests/t_decrypt.c +@@ -39,162 +39,6 @@ struct test { + krb5_data keybits; + krb5_data ciphertext; + } test_cases[] = { +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 0, "", }, 0, +- { KV5M_DATA, 24, +- "\x7A\x25\xDF\x89\x92\x29\x6D\xCE\xDA\x0E\x13\x5B\xC4\x04\x6E\x23" +- "\x75\xB3\xC1\x4C\x98\xFB\xC1\x62" }, +- { KV5M_DATA, 28, +- "\x54\x8A\xF4\xD5\x04\xF7\xD7\x23\x30\x3F\x12\x17\x5F\xE8\x38\x6B" +- "\x7B\x53\x35\xA9\x67\xBA\xD6\x1F\x3B\xF0\xB1\x43" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 1, "1", }, 1, +- { KV5M_DATA, 24, +- "\xBC\x07\x83\x89\x15\x13\xD5\xCE\x57\xBC\x13\x8F\xD3\xC1\x1A\xE6" +- "\x40\x45\x23\x85\x32\x29\x62\xB6" }, +- { KV5M_DATA, 36, +- "\x9C\x3C\x1D\xBA\x47\x47\xD8\x5A\xF2\x91\x6E\x47\x45\xF2\xDC\xE3" +- "\x80\x46\x79\x6E\x51\x04\xBC\xCD\xFB\x66\x9A\x91\xD4\x4B\xC3\x56" +- "\x66\x09\x45\xC7" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 9, "9 bytesss", }, 2, +- { KV5M_DATA, 24, +- "\x2F\xD0\xF7\x25\xCE\x04\x10\x0D\x2F\xC8\xA1\x80\x98\x83\x1F\x85" +- "\x0B\x45\xD9\xEF\x85\x0B\xD9\x20" }, +- { KV5M_DATA, 44, +- "\xCF\x91\x44\xEB\xC8\x69\x79\x81\x07\x5A\x8B\xAD\x8D\x74\xE5\xD7" +- "\xD5\x91\xEB\x7D\x97\x70\xC7\xAD\xA2\x5E\xE8\xC5\xB3\xD6\x94\x44" +- "\xDF\xEC\x79\xA5\xB7\xA0\x14\x82\xD9\xAF\x74\xE6" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 13, "13 bytes byte", }, 3, +- { KV5M_DATA, 24, +- "\x0D\xD5\x20\x94\xE0\xF4\x1C\xEC\xCB\x5B\xE5\x10\xA7\x64\xB3\x51" +- "\x76\xE3\x98\x13\x32\xF1\xE5\x98" }, +- { KV5M_DATA, 44, +- "\x83\x9A\x17\x08\x1E\xCB\xAF\xBC\xDC\x91\xB8\x8C\x69\x55\xDD\x3C" +- "\x45\x14\x02\x3C\xF1\x77\xB7\x7B\xF0\xD0\x17\x7A\x16\xF7\x05\xE8" +- "\x49\xCB\x77\x81\xD7\x6A\x31\x6B\x19\x3F\x8D\x30" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, +- { KV5M_DATA, 24, +- "\xF1\x16\x86\xCB\xBC\x9E\x23\xEA\x54\xFE\xCD\x2A\x3D\xCD\xFB\x20" +- "\xB6\xFE\x98\xBF\x26\x45\xC4\xC4" }, +- { KV5M_DATA, 60, +- "\x89\x43\x3E\x83\xFD\x0E\xA3\x66\x6C\xFF\xCD\x18\xD8\xDE\xEB\xC5" +- "\x3B\x9A\x34\xED\xBE\xB1\x59\xD9\xF6\x67\xC6\xC2\xB9\xA9\x64\x40" +- "\x1D\x55\xE7\xE9\xC6\x8D\x64\x8D\x65\xC3\xAA\x84\xFF\xA3\x79\x0C" +- "\x14\xA8\x64\xDA\x80\x73\xA9\xA9\x5C\x4B\xA2\xBC" } +- }, +- +- { +- ENCTYPE_ARCFOUR_HMAC, +- { KV5M_DATA, 0, "", }, 0, +- { KV5M_DATA, 16, +- "\xF8\x1F\xEC\x39\x25\x5F\x57\x84\xE8\x50\xC4\x37\x7C\x88\xBD\x85" }, +- { KV5M_DATA, 24, +- "\x02\xC1\xEB\x15\x58\x61\x44\x12\x2E\xC7\x17\x76\x3D\xD3\x48\xBF" +- "\x00\x43\x4D\xDC\x65\x85\x95\x4C" } +- }, +- { +- ENCTYPE_ARCFOUR_HMAC, +- { KV5M_DATA, 1, "1", }, 1, +- { KV5M_DATA, 16, +- "\x67\xD1\x30\x0D\x28\x12\x23\x86\x7F\x96\x47\xFF\x48\x72\x12\x73" }, +- { KV5M_DATA, 25, +- "\x61\x56\xE0\xCC\x04\xE0\xA0\x87\x4F\x9F\xDA\x00\x8F\x49\x8A\x7A" +- "\xDB\xBC\x80\xB7\x0B\x14\xDD\xDB\xC0" } +- }, +- { +- ENCTYPE_ARCFOUR_HMAC, +- { KV5M_DATA, 9, "9 bytesss", }, 2, +- { KV5M_DATA, 16, +- "\x3E\x40\xAB\x60\x93\x69\x52\x81\xB3\xAC\x1A\x93\x04\x22\x4D\x98" }, +- { KV5M_DATA, 33, +- "\x0F\x9A\xD1\x21\xD9\x9D\x4A\x09\x44\x8E\x4F\x1F\x71\x8C\x4F\x5C" +- "\xBE\x60\x96\x26\x2C\x66\xF2\x9D\xF2\x32\xA8\x7C\x9F\x98\x75\x5D" +- "\x55" } +- }, +- { +- ENCTYPE_ARCFOUR_HMAC, +- { KV5M_DATA, 13, "13 bytes byte", }, 3, +- { KV5M_DATA, 16, +- "\x4B\xA2\xFB\xF0\x37\x9F\xAE\xD8\x7A\x25\x4D\x3B\x35\x3D\x5A\x7E" }, +- { KV5M_DATA, 37, +- "\x61\x2C\x57\x56\x8B\x17\xA7\x03\x52\xBA\xE8\xCF\x26\xFB\x94\x59" +- "\xA6\xF3\x35\x3C\xD3\x5F\xD4\x39\xDB\x31\x07\xCB\xEC\x76\x5D\x32" +- "\x6D\xFC\x04\xC1\xDD" } +- }, +- { +- ENCTYPE_ARCFOUR_HMAC, +- { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, +- { KV5M_DATA, 16, +- "\x68\xF2\x63\xDB\x3F\xCE\x15\xD0\x31\xC9\xEA\xB0\x2D\x67\x10\x7A" }, +- { KV5M_DATA, 54, +- "\x95\xF9\x04\x7C\x3A\xD7\x58\x91\xC2\xE9\xB0\x4B\x16\x56\x6D\xC8" +- "\xB6\xEB\x9C\xE4\x23\x1A\xFB\x25\x42\xEF\x87\xA7\xB5\xA0\xF2\x60" +- "\xA9\x9F\x04\x60\x50\x8D\xE0\xCE\xCC\x63\x2D\x07\xC3\x54\x12\x4E" +- "\x46\xC5\xD2\x23\x4E\xB8" } +- }, +- +- { +- ENCTYPE_ARCFOUR_HMAC_EXP, +- { KV5M_DATA, 0, "", }, 0, +- { KV5M_DATA, 16, +- "\xF7\xD3\xA1\x55\xAF\x5E\x23\x8A\x0B\x7A\x87\x1A\x96\xBA\x2A\xB2" }, +- { KV5M_DATA, 24, +- "\x28\x27\xF0\xE9\x0F\x62\xE7\x46\x0C\x4E\x2F\xB3\x9F\x96\x57\xBA" +- "\x8B\xFA\xA9\x91\xD7\xFD\xAD\xFF" } +- }, +- { +- ENCTYPE_ARCFOUR_HMAC_EXP, +- { KV5M_DATA, 1, "1", }, 1, +- { KV5M_DATA, 16, +- "\xDE\xEA\xA0\x60\x7D\xB7\x99\xE2\xFD\xD6\xDB\x29\x86\xBB\x8D\x65" }, +- { KV5M_DATA, 25, +- "\x3D\xDA\x39\x2E\x2E\x27\x5A\x4D\x75\x18\x3F\xA6\x32\x8A\x0A\x4E" +- "\x6B\x75\x2D\xF6\xCD\x2A\x25\xFA\x4E" } +- }, +- { +- ENCTYPE_ARCFOUR_HMAC_EXP, +- { KV5M_DATA, 9, "9 bytesss", }, 2, +- { KV5M_DATA, 16, +- "\x33\xAD\x7F\xC2\x67\x86\x15\x56\x9B\x2B\x09\x83\x6E\x0A\x3A\xB6" }, +- { KV5M_DATA, 33, +- "\x09\xD1\x36\xAC\x48\x5D\x92\x64\x4E\xC6\x70\x1D\x6A\x0D\x03\xE8" +- "\x98\x2D\x7A\x3C\xA7\xEF\xD0\xF8\xF4\xF8\x36\x60\xEF\x42\x77\xBB" +- "\x81" } +- }, +- { +- ENCTYPE_ARCFOUR_HMAC_EXP, +- { KV5M_DATA, 13, "13 bytes byte", }, 3, +- { KV5M_DATA, 16, +- "\x39\xF2\x5C\xD4\xF0\xD4\x1B\x2B\x2D\x9D\x30\x0F\xCB\x29\x81\xCB" }, +- { KV5M_DATA, 37, +- "\x91\x23\x88\xD7\xC0\x76\x12\x81\x9E\x3B\x64\x0F\xF5\xCE\xCD\xAF" +- "\x72\xE5\xA5\x9D\xF1\x0F\x10\x91\xA6\xBE\xC3\x9C\xAA\xD7\x48\xAF" +- "\x9B\xD2\xD8\xD5\x46" } +- }, +- { +- ENCTYPE_ARCFOUR_HMAC_EXP, +- { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, +- { KV5M_DATA, 16, +- "\x9F\x72\x55\x42\xD9\xF7\x2A\xA1\xF3\x86\xCB\xE7\x89\x69\x84\xFC" }, +- { KV5M_DATA, 54, +- "\x78\xB3\x5A\x08\xB0\x8B\xE2\x65\xAE\xB4\x14\x5F\x07\x65\x13\xB6" +- "\xB5\x6E\xFE\xD3\xF7\x52\x65\x74\xAF\x74\xF7\xD2\xF9\xBA\xE9\x6E" +- "\xAB\xB7\x6F\x2D\x87\x38\x6D\x2E\x93\xE3\xA7\x7B\x99\x91\x9F\x1D" +- "\x97\x64\x90\xE2\xBD\x45" } +- }, +- + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 0, "", }, 0, +@@ -244,7 +88,6 @@ struct test { + "\x15\x6E\xCB\x53\x2F\xC2\x03\xE3\x0F\xF6\x00\xB6\x3B\x35\x09\x39" + "\xFE\xCE\x51\x0F\x02\xD7\xFF\x1E\x7B\xAC" } + }, +- + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 0, "", }, 0, +@@ -299,114 +142,6 @@ struct test { + "\x29\x5C\x68\x88\x58\xF3\xB3\x4B\x9C\xBD\x6E\xEB\xAE\x81\xDA\xF6" + "\xB7\x34\xD4\xD4\x98\xB6\x71\x4F\x1C\x1D" } + }, +- +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- { KV5M_DATA, 0, "", }, 0, +- { KV5M_DATA, 16, +- "\x1D\xC4\x6A\x8D\x76\x3F\x4F\x93\x74\x2B\xCB\xA3\x38\x75\x76\xC3" }, +- { KV5M_DATA, 32, +- "\xC4\x66\xF1\x87\x10\x69\x92\x1E\xDB\x7C\x6F\xDE\x24\x4A\x52\xDB" +- "\x0B\xA1\x0E\xDC\x19\x7B\xDB\x80\x06\x65\x8C\xA3\xCC\xCE\x6E\xB8" } +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- { KV5M_DATA, 1, "1", }, 1, +- { KV5M_DATA, 16, +- "\x50\x27\xBC\x23\x1D\x0F\x3A\x9D\x23\x33\x3F\x1C\xA6\xFD\xBE\x7C" }, +- { KV5M_DATA, 33, +- "\x84\x2D\x21\xFD\x95\x03\x11\xC0\xDD\x46\x4A\x3F\x4B\xE8\xD6\xDA" +- "\x88\xA5\x6D\x55\x9C\x9B\x47\xD3\xF9\xA8\x50\x67\xAF\x66\x15\x59" +- "\xB8" } +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- { KV5M_DATA, 9, "9 bytesss", }, 2, +- { KV5M_DATA, 16, +- "\xA1\xBB\x61\xE8\x05\xF9\xBA\x6D\xDE\x8F\xDB\xDD\xC0\x5C\xDE\xA0" }, +- { KV5M_DATA, 41, +- "\x61\x9F\xF0\x72\xE3\x62\x86\xFF\x0A\x28\xDE\xB3\xA3\x52\xEC\x0D" +- "\x0E\xDF\x5C\x51\x60\xD6\x63\xC9\x01\x75\x8C\xCF\x9D\x1E\xD3\x3D" +- "\x71\xDB\x8F\x23\xAA\xBF\x83\x48\xA0" } +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- { KV5M_DATA, 13, "13 bytes byte", }, 3, +- { KV5M_DATA, 16, +- "\x2C\xA2\x7A\x5F\xAF\x55\x32\x24\x45\x06\x43\x4E\x1C\xEF\x66\x76" }, +- { KV5M_DATA, 45, +- "\xB8\xEC\xA3\x16\x7A\xE6\x31\x55\x12\xE5\x9F\x98\xA7\xC5\x00\x20" +- "\x5E\x5F\x63\xFF\x3B\xB3\x89\xAF\x1C\x41\xA2\x1D\x64\x0D\x86\x15" +- "\xC9\xED\x3F\xBE\xB0\x5A\xB6\xAC\xB6\x76\x89\xB5\xEA" } +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, +- { KV5M_DATA, 16, +- "\x78\x24\xF8\xC1\x6F\x83\xFF\x35\x4C\x6B\xF7\x51\x5B\x97\x3F\x43" }, +- { KV5M_DATA, 62, +- "\xA2\x6A\x39\x05\xA4\xFF\xD5\x81\x6B\x7B\x1E\x27\x38\x0D\x08\x09" +- "\x0C\x8E\xC1\xF3\x04\x49\x6E\x1A\xBD\xCD\x2B\xDC\xD1\xDF\xFC\x66" +- "\x09\x89\xE1\x17\xA7\x13\xDD\xBB\x57\xA4\x14\x6C\x15\x87\xCB\xA4" +- "\x35\x66\x65\x59\x1D\x22\x40\x28\x2F\x58\x42\xB1\x05\xA5" } +- }, +- +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- { KV5M_DATA, 0, "", }, 0, +- { KV5M_DATA, 32, +- "\xB6\x1C\x86\xCC\x4E\x5D\x27\x57\x54\x5A\xD4\x23\x39\x9F\xB7\x03" +- "\x1E\xCA\xB9\x13\xCB\xB9\x00\xBD\x7A\x3C\x6D\xD8\xBF\x92\x01\x5B" }, +- { KV5M_DATA, 32, +- "\x03\x88\x6D\x03\x31\x0B\x47\xA6\xD8\xF0\x6D\x7B\x94\xD1\xDD\x83" +- "\x7E\xCC\xE3\x15\xEF\x65\x2A\xFF\x62\x08\x59\xD9\x4A\x25\x92\x66" } +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- { KV5M_DATA, 1, "1", }, 1, +- { KV5M_DATA, 32, +- "\x1B\x97\xFE\x0A\x19\x0E\x20\x21\xEB\x30\x75\x3E\x1B\x6E\x1E\x77" +- "\xB0\x75\x4B\x1D\x68\x46\x10\x35\x58\x64\x10\x49\x63\x46\x38\x33" }, +- { KV5M_DATA, 33, +- "\x2C\x9C\x15\x70\x13\x3C\x99\xBF\x6A\x34\xBC\x1B\x02\x12\x00\x2F" +- "\xD1\x94\x33\x87\x49\xDB\x41\x35\x49\x7A\x34\x7C\xFC\xD9\xD1\x8A" +- "\x12" } +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- { KV5M_DATA, 9, "9 bytesss", }, 2, +- { KV5M_DATA, 32, +- "\x32\x16\x4C\x5B\x43\x4D\x1D\x15\x38\xE4\xCF\xD9\xBE\x80\x40\xFE" +- "\x8C\x4A\xC7\xAC\xC4\xB9\x3D\x33\x14\xD2\x13\x36\x68\x14\x7A\x05" }, +- { KV5M_DATA, 41, +- "\x9C\x6D\xE7\x5F\x81\x2D\xE7\xED\x0D\x28\xB2\x96\x35\x57\xA1\x15" +- "\x64\x09\x98\x27\x5B\x0A\xF5\x15\x27\x09\x91\x3F\xF5\x2A\x2A\x9C" +- "\x8E\x63\xB8\x72\xF9\x2E\x64\xC8\x39" } +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- { KV5M_DATA, 13, "13 bytes byte", }, 3, +- { KV5M_DATA, 32, +- "\xB0\x38\xB1\x32\xCD\x8E\x06\x61\x22\x67\xFA\xB7\x17\x00\x66\xD8" +- "\x8A\xEC\xCB\xA0\xB7\x44\xBF\xC6\x0D\xC8\x9B\xCA\x18\x2D\x07\x15" }, +- { KV5M_DATA, 45, +- "\xEE\xEC\x85\xA9\x81\x3C\xDC\x53\x67\x72\xAB\x9B\x42\xDE\xFC\x57" +- "\x06\xF7\x26\xE9\x75\xDD\xE0\x5A\x87\xEB\x54\x06\xEA\x32\x4C\xA1" +- "\x85\xC9\x98\x6B\x42\xAA\xBE\x79\x4B\x84\x82\x1B\xEE" } +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, +- { KV5M_DATA, 32, +- "\xCC\xFC\xD3\x49\xBF\x4C\x66\x77\xE8\x6E\x4B\x02\xB8\xEA\xB9\x24" +- "\xA5\x46\xAC\x73\x1C\xF9\xBF\x69\x89\xB9\x96\xE7\xD6\xBF\xBB\xA7" }, +- { KV5M_DATA, 62, +- "\x0E\x44\x68\x09\x85\x85\x5F\x2D\x1F\x18\x12\x52\x9C\xA8\x3B\xFD" +- "\x8E\x34\x9D\xE6\xFD\x9A\xDA\x0B\xAA\xA0\x48\xD6\x8E\x26\x5F\xEB" +- "\xF3\x4A\xD1\x25\x5A\x34\x49\x99\xAD\x37\x14\x68\x87\xA6\xC6\x84" +- "\x57\x31\xAC\x7F\x46\x37\x6A\x05\x04\xCD\x06\x57\x14\x74" } +- }, +- + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + { KV5M_DATA, 0, "", }, 2, +@@ -524,13 +259,8 @@ printhex(const char *head, void *data, size_t len) + + static krb5_enctype + enctypes[] = { +- ENCTYPE_DES3_CBC_SHA1, +- ENCTYPE_ARCFOUR_HMAC, +- ENCTYPE_ARCFOUR_HMAC_EXP, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- ENCTYPE_CAMELLIA256_CTS_CMAC, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + ENCTYPE_AES256_CTS_HMAC_SHA384_192 + }; +diff --git a/src/lib/crypto/crypto_tests/t_derive.c b/src/lib/crypto/crypto_tests/t_derive.c +index afbf7477f..550b314c9 100644 +--- a/src/lib/crypto/crypto_tests/t_derive.c ++++ b/src/lib/crypto/crypto_tests/t_derive.c +@@ -38,41 +38,6 @@ struct test { + enum deriv_alg alg; + krb5_data expected_key; + } test_cases[] = { +- /* Kc, Ke, Kei for a DES3 key */ +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 24, +- "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE" +- "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, +- { KV5M_DATA, 5, "\0\0\0\2\x99" }, +- DERIVE_RFC3961, +- { KV5M_DATA, 24, +- "\xF7\x8C\x49\x6D\x16\xE6\xC2\xDA\xE0\xE0\xB6\xC2\x40\x57\xA8\x4C" +- "\x04\x26\xAE\xEF\x26\xFD\x6D\xCE" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 24, +- "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE" +- "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, +- { KV5M_DATA, 5, "\0\0\0\2\xAA" }, +- DERIVE_RFC3961, +- { KV5M_DATA, 24, +- "\x5B\x57\x23\xD0\xB6\x34\xCB\x68\x4C\x3E\xBA\x52\x64\xE9\xA7\x0D" +- "\x52\xE6\x83\x23\x1A\xD3\xC4\xCE" } +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- { KV5M_DATA, 24, +- "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE" +- "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, +- { KV5M_DATA, 5, "\0\0\0\2\x55" }, +- DERIVE_RFC3961, +- { KV5M_DATA, 24, +- "\xA7\x7C\x94\x98\x0E\x9B\x73\x45\xA8\x15\x25\xC4\x23\xA7\x37\xCE" +- "\x67\xF4\xCD\x91\xB6\xB3\xDA\x45" } +- }, +- + /* Kc, Ke, Ki for an AES-128 key */ + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, +@@ -137,70 +102,6 @@ struct test { + "\xD7\xBB\xA9\x07\x76\xD8\x12\x6D\x91\xF3\x4F\x31\x01\xAE\xA8\xBA" } + }, + +- /* Kc, Ke, Ki for a Camellia-128 key */ +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- { KV5M_DATA, 16, +- "\x57\xD0\x29\x72\x98\xFF\xD9\xD3\x5D\xE5\xA4\x7F\xB4\xBD\xE2\x4B" }, +- { KV5M_DATA, 5, "\0\0\0\2\x99" }, +- DERIVE_SP800_108_CMAC, +- { KV5M_DATA, 16, +- "\xD1\x55\x77\x5A\x20\x9D\x05\xF0\x2B\x38\xD4\x2A\x38\x9E\x5A\x56" } +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- { KV5M_DATA, 16, +- "\x57\xD0\x29\x72\x98\xFF\xD9\xD3\x5D\xE5\xA4\x7F\xB4\xBD\xE2\x4B" }, +- { KV5M_DATA, 5, "\0\0\0\2\xAA" }, +- DERIVE_SP800_108_CMAC, +- { KV5M_DATA, 16, +- "\x64\xDF\x83\xF8\x5A\x53\x2F\x17\x57\x7D\x8C\x37\x03\x57\x96\xAB" } +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- { KV5M_DATA, 16, +- "\x57\xD0\x29\x72\x98\xFF\xD9\xD3\x5D\xE5\xA4\x7F\xB4\xBD\xE2\x4B" }, +- { KV5M_DATA, 5, "\0\0\0\2\x55" }, +- DERIVE_SP800_108_CMAC, +- { KV5M_DATA, 16, +- "\x3E\x4F\xBD\xF3\x0F\xB8\x25\x9C\x42\x5C\xB6\xC9\x6F\x1F\x46\x35" } +- }, +- +- /* Kc, Ke, Ki for a Camellia-256 key */ +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- { KV5M_DATA, 32, +- "\xB9\xD6\x82\x8B\x20\x56\xB7\xBE\x65\x6D\x88\xA1\x23\xB1\xFA\xC6" +- "\x82\x14\xAC\x2B\x72\x7E\xCF\x5F\x69\xAF\xE0\xC4\xDF\x2A\x6D\x2C" }, +- { KV5M_DATA, 5, "\0\0\0\2\x99" }, +- DERIVE_SP800_108_CMAC, +- { KV5M_DATA, 32, +- "\xE4\x67\xF9\xA9\x55\x2B\xC7\xD3\x15\x5A\x62\x20\xAF\x9C\x19\x22" +- "\x0E\xEE\xD4\xFF\x78\xB0\xD1\xE6\xA1\x54\x49\x91\x46\x1A\x9E\x50" } +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- { KV5M_DATA, 32, +- "\xB9\xD6\x82\x8B\x20\x56\xB7\xBE\x65\x6D\x88\xA1\x23\xB1\xFA\xC6" +- "\x82\x14\xAC\x2B\x72\x7E\xCF\x5F\x69\xAF\xE0\xC4\xDF\x2A\x6D\x2C" }, +- { KV5M_DATA, 5, "\0\0\0\2\xAA" }, +- DERIVE_SP800_108_CMAC, +- { KV5M_DATA, 32, +- "\x41\x2A\xEF\xC3\x62\xA7\x28\x5F\xC3\x96\x6C\x6A\x51\x81\xE7\x60" +- "\x5A\xE6\x75\x23\x5B\x6D\x54\x9F\xBF\xC9\xAB\x66\x30\xA4\xC6\x04" } +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- { KV5M_DATA, 32, +- "\xB9\xD6\x82\x8B\x20\x56\xB7\xBE\x65\x6D\x88\xA1\x23\xB1\xFA\xC6" +- "\x82\x14\xAC\x2B\x72\x7E\xCF\x5F\x69\xAF\xE0\xC4\xDF\x2A\x6D\x2C" }, +- { KV5M_DATA, 5, "\0\0\0\2\x55" }, +- DERIVE_SP800_108_CMAC, +- { KV5M_DATA, 32, +- "\xFA\x62\x4F\xA0\xE5\x23\x99\x3F\xA3\x88\xAE\xFD\xC6\x7E\x67\xEB" +- "\xCD\x8C\x08\xE8\xA0\x24\x6B\x1D\x73\xB0\xD1\xDD\x9F\xC5\x82\xB0" } +- }, +- + /* Kc, Ke, Ki for an aes128-sha2 key. */ + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, +@@ -286,11 +187,8 @@ static const struct krb5_enc_provider * + get_enc_provider(krb5_enctype enctype) + { + switch (enctype) { +- case ENCTYPE_DES3_CBC_SHA1: return &krb5int_enc_des3; + case ENCTYPE_AES128_CTS_HMAC_SHA1_96: return &krb5int_enc_aes128; + case ENCTYPE_AES256_CTS_HMAC_SHA1_96: return &krb5int_enc_aes256; +- case ENCTYPE_CAMELLIA128_CTS_CMAC: return &krb5int_enc_camellia128; +- case ENCTYPE_CAMELLIA256_CTS_CMAC: return &krb5int_enc_camellia256; + case ENCTYPE_AES128_CTS_HMAC_SHA256_128: return &krb5int_enc_aes128; + case ENCTYPE_AES256_CTS_HMAC_SHA384_192: return &krb5int_enc_aes256; + } +diff --git a/src/lib/crypto/crypto_tests/t_encrypt.c b/src/lib/crypto/crypto_tests/t_encrypt.c +index bd9b94691..bac685a43 100644 +--- a/src/lib/crypto/crypto_tests/t_encrypt.c ++++ b/src/lib/crypto/crypto_tests/t_encrypt.c +@@ -37,13 +37,8 @@ + + /* What enctypes should we test?*/ + krb5_enctype interesting_enctypes[] = { +- ENCTYPE_DES3_CBC_SHA1, +- ENCTYPE_ARCFOUR_HMAC, +- ENCTYPE_ARCFOUR_HMAC_EXP, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- ENCTYPE_CAMELLIA256_CTS_CMAC, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + 0 +@@ -264,23 +259,6 @@ main () + krb5_k_free_key (context, key); + } + +- /* Test the RC4 decrypt fallback from key usage 9 to 8. */ +- test ("Initializing an RC4 keyblock", +- krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &keyblock)); +- test ("Generating random RC4 key", +- krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, keyblock)); +- enc_out.ciphertext = out; +- krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len); +- enc_out.ciphertext.length = len; +- check.length = 2048; +- test ("Encrypting with RC4 key usage 8", +- krb5_c_encrypt (context, keyblock, 8, 0, &in, &enc_out)); +- display ("Enc output", &enc_out.ciphertext); +- test ("Decrypting with RC4 key usage 9", +- krb5_c_decrypt (context, keyblock, 9, 0, &enc_out, &check)); +- test ("Comparing", compare_results (&in, &check)); +- +- krb5_free_keyblock (context, keyblock); + free(out.data); + free(out2.data); + free(check.data); +diff --git a/src/lib/crypto/crypto_tests/t_fork.c b/src/lib/crypto/crypto_tests/t_fork.c +index 428fc8a6a..43c2483de 100644 +--- a/src/lib/crypto/crypto_tests/t_fork.c ++++ b/src/lib/crypto/crypto_tests/t_fork.c +@@ -57,10 +57,10 @@ prepare_enc_data(krb5_key key, size_t in_len, krb5_enc_data *enc_data) + int + main() + { +- krb5_keyblock kb_aes, kb_rc4; +- krb5_key key_aes, key_rc4; +- krb5_data state_rc4, plain = string2data("plain"), decrypted; +- krb5_enc_data out_aes, out_rc4; ++ krb5_keyblock kb_aes; ++ krb5_key key_aes; ++ krb5_data plain = string2data("plain"), decrypted; ++ krb5_enc_data out_aes; + pid_t pid, wpid; + int status; + +@@ -68,17 +68,11 @@ main() + * krb5.conf. */ + t(krb5_c_random_seed(ctx, &plain)); + +- /* Create AES and RC4 ciphertexts with random keys. Use cipher state for +- * RC4. */ ++ /* Create AES ciphertext with random key. */ + t(krb5_c_make_random_key(ctx, ENCTYPE_AES256_CTS_HMAC_SHA1_96, &kb_aes)); +- t(krb5_c_make_random_key(ctx, ENCTYPE_ARCFOUR_HMAC, &kb_rc4)); + t(krb5_k_create_key(ctx, &kb_aes, &key_aes)); +- t(krb5_k_create_key(ctx, &kb_rc4, &key_rc4)); + prepare_enc_data(key_aes, plain.length, &out_aes); +- prepare_enc_data(key_aes, plain.length, &out_rc4); +- t(krb5_c_init_state(ctx, &kb_rc4, 0, &state_rc4)); + t(krb5_k_encrypt(ctx, key_aes, 0, NULL, &plain, &out_aes)); +- t(krb5_k_encrypt(ctx, key_rc4, 0, &state_rc4, &plain, &out_rc4)); + + /* Fork; continue in both parent and child. */ + pid = fork(); +@@ -91,16 +85,9 @@ main() + t(krb5_c_decrypt(ctx, &kb_aes, 0, NULL, &out_aes, &decrypted)); + assert(data_eq(plain, decrypted)); + +- /* Encrypt another RC4 message. */ +- t(krb5_k_encrypt(ctx, key_rc4, 0, &state_rc4, &plain, &out_rc4)); +- t(krb5_c_free_state(ctx, &kb_rc4, &state_rc4)); +- + krb5_free_keyblock_contents(ctx, &kb_aes); +- krb5_free_keyblock_contents(ctx, &kb_rc4); + krb5_k_free_key(ctx, key_aes); +- krb5_k_free_key(ctx, key_rc4); + krb5_free_data_contents(ctx, &out_aes.ciphertext); +- krb5_free_data_contents(ctx, &out_rc4.ciphertext); + krb5_free_data_contents(ctx, &decrypted); + + /* If we're the parent, make sure the child succeeded. */ +diff --git a/src/lib/crypto/crypto_tests/t_short.c b/src/lib/crypto/crypto_tests/t_short.c +index d4c2b97df..d5a97b4f7 100644 +--- a/src/lib/crypto/crypto_tests/t_short.c ++++ b/src/lib/crypto/crypto_tests/t_short.c +@@ -34,13 +34,8 @@ + #include "k5-int.h" + + krb5_enctype interesting_enctypes[] = { +- ENCTYPE_DES3_CBC_SHA1, +- ENCTYPE_ARCFOUR_HMAC, +- ENCTYPE_ARCFOUR_HMAC_EXP, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- ENCTYPE_CAMELLIA256_CTS_CMAC, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + 0 +diff --git a/src/lib/crypto/crypto_tests/t_str2key.c b/src/lib/crypto/crypto_tests/t_str2key.c +index cdb1acc6d..e81d70f52 100644 +--- a/src/lib/crypto/crypto_tests/t_str2key.c ++++ b/src/lib/crypto/crypto_tests/t_str2key.c +@@ -35,143 +35,12 @@ struct test { + krb5_error_code expected_err; + krb5_boolean allow_weak; + } test_cases[] = { +- /* Test vectors from RFC 3961 appendix A.4. */ +- { +- ENCTYPE_DES3_CBC_SHA1, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C" +- "\x31\x3E\x3B\xFE\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, +- 0, +- FALSE +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- "potatoe", +- { KV5M_DATA, 19, "WHITEHOUSE.GOVdanny" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\xDF\xCD\x23\x3D\xD0\xA4\x32\x04\xEA\x6D\xC4\x37" +- "\xFB\x15\xE0\x61\xB0\x29\x79\xC1\xF7\x4F\x37\x7A" }, +- 0, +- FALSE +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- "penny", +- { KV5M_DATA, 19, "EXAMPLE.COMbuckaroo" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\x6D\x2F\xCD\xF2\xD6\xFB\xBC\x3D\xDC\xAD\xB5\xDA" +- "\x57\x10\xA2\x34\x89\xB0\xD3\xB6\x9D\x5D\x9D\x4A" }, +- 0, +- FALSE +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- "\xC3\x9F", +- { KV5M_DATA, 23, "ATHENA.MIT.EDUJuri\xC5\xA1\x69\xC4\x87" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\x16\xD5\xA4\x0E\x1C\xE3\xBA\xCB\x61\xB9\xDC\xE0" +- "\x04\x70\x32\x4C\x83\x19\x73\xA7\xB9\x52\xFE\xB0" }, +- 0, +- FALSE +- }, +- { +- ENCTYPE_DES3_CBC_SHA1, +- "\xF0\x9D\x84\x9E", +- { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, +- { KV5M_DATA, 0, NULL }, +- { KV5M_DATA, 24, "\x85\x76\x37\x26\x58\x5D\xBC\x1C\xCE\x6E\xC4\x3E" +- "\x1F\x75\x1F\x07\xF1\xC4\xCB\xB0\x98\xF4\x0B\x19" }, +- 0, +- FALSE +- }, ++ /* Modified for FIPS: Removed test vectors with: ++ * 1. Iteration counts < 1000 (FIPS minimum per NIST SP 800-132) ++ * 2. Password/HMAC key length < 14 bytes (FIPS minimum for HMAC keys) ++ * Only tests with >=1000 iterations and >=14 byte passwords remain. */ + +- /* Test vectors from RFC 3962 appendix B. */ +- { +- ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\0\1" }, +- { KV5M_DATA, 16, +- "\x42\x26\x3C\x6E\x89\xF4\xFC\x28\xB8\xDF\x68\xEE\x09\x79\x9F\x15" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\0\1" }, +- { KV5M_DATA, 32, +- "\xFE\x69\x7B\x52\xBC\x0D\x3C\xE1\x44\x32\xBA\x03\x6A\x92\xE6\x5B" +- "\xBB\x52\x28\x09\x90\xA2\xFA\x27\x88\x39\x98\xD7\x2A\xF3\x01\x61" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\0\2" }, +- { KV5M_DATA, 16, +- "\xC6\x51\xBF\x29\xE2\x30\x0A\xC2\x7F\xA4\x69\xD6\x93\xBD\xDA\x13" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\0\2" }, +- { KV5M_DATA, 32, +- "\xA2\xE1\x6D\x16\xB3\x60\x69\xC1\x35\xD5\xE9\xD2\xE2\x5F\x89\x61" +- "\x02\x68\x56\x18\xB9\x59\x14\xB4\x67\xC6\x76\x22\x22\x58\x24\xFF" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ +- { KV5M_DATA, 16, +- "\x4C\x01\xCD\x46\xD6\x32\xD0\x1E\x6D\xBE\x23\x0A\x01\xED\x64\x2A" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ +- { KV5M_DATA, 32, +- "\x55\xA6\xAC\x74\x0A\xD1\x7B\x48\x46\x94\x10\x51\xE1\xE8\xB0\xA7" +- "\x54\x8D\x93\xB0\xAB\x30\xA8\xBC\x3F\xF1\x62\x80\x38\x2B\x8C\x2A" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- "password", +- { KV5M_DATA, 8, "\x12\x34\x56\x78\x78\x56\x34\x12" }, +- { KV5M_DATA, 4, "\0\0\0\5" }, +- { KV5M_DATA, 16, +- "\xE9\xB2\x3D\x52\x27\x37\x47\xDD\x5C\x35\xCB\x55\xBE\x61\x9D\x8E" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- "password", +- { KV5M_DATA, 8, "\x12\x34\x56\x78\x78\x56\x34\x12" }, +- { KV5M_DATA, 4, "\0\0\0\5" }, +- { KV5M_DATA, 32, +- "\x97\xA4\xE7\x86\xBE\x20\xD8\x1A\x38\x2D\x5E\xBC\x96\xD5\x90\x9C" +- "\xAB\xCD\xAD\xC8\x7C\xA4\x8F\x57\x45\x04\x15\x9F\x16\xC3\x6E\x31" }, +- 0, +- TRUE +- }, ++ /* Test vectors from RFC 3962 appendix B - 1200 iterations, long passwords (FIPS-compliant) */ + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", +@@ -214,228 +83,6 @@ struct test { + 0, + TRUE + }, +- { +- ENCTYPE_AES128_CTS_HMAC_SHA1_96, +- "\xF0\x9D\x84\x9E", +- { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, +- { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ +- { KV5M_DATA, 16, +- "\xF1\x49\xC1\xF2\xE1\x54\xA7\x34\x52\xD4\x3E\x7F\xE6\x2A\x56\xE5" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- "\xF0\x9D\x84\x9E", +- { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, +- { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ +- { KV5M_DATA, 32, +- "\x4B\x6D\x98\x39\xF8\x44\x06\xDF\x1F\x09\xCC\x16\x6D\xB4\xB8\x3C" +- "\x57\x18\x48\xB7\x84\xA3\xD6\xBD\xC3\x46\x58\x9A\x3E\x39\x3F\x9E" }, +- 0, +- TRUE +- }, +- /* Check for KRB5_ERR_BAD_S2K_PARAMS return when weak iteration counts are +- * forbidden. */ +- { +- ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- "\xF0\x9D\x84\x9E", +- { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, +- { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ +- { KV5M_DATA, 32, +- "\x4B\x6D\x98\x39\xF8\x44\x06\xDF\x1F\x09\xCC\x16\x6D\xB4\xB8\x3C" +- "\x57\x18\x48\xB7\x84\xA3\xD6\xBD\xC3\x46\x58\x9A\x3E\x39\x3F\x9E" }, +- KRB5_ERR_BAD_S2K_PARAMS, +- FALSE +- }, +- +- /* The same inputs applied to Camellia enctypes. */ +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\0\1" }, +- { KV5M_DATA, 16, +- "\x57\xD0\x29\x72\x98\xFF\xD9\xD3\x5D\xE5\xA4\x7F\xB4\xBD\xE2\x4B" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\0\1" }, +- { KV5M_DATA, 32, +- "\xB9\xD6\x82\x8B\x20\x56\xB7\xBE\x65\x6D\x88\xA1\x23\xB1\xFA\xC6" +- "\x82\x14\xAC\x2B\x72\x7E\xCF\x5F\x69\xAF\xE0\xC4\xDF\x2A\x6D\x2C" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\0\2" }, +- { KV5M_DATA, 16, +- "\x73\xF1\xB5\x3A\xA0\xF3\x10\xF9\x3B\x1D\xE8\xCC\xAA\x0C\xB1\x52" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\0\2" }, +- { KV5M_DATA, 32, +- "\x83\xFC\x58\x66\xE5\xF8\xF4\xC6\xF3\x86\x63\xC6\x5C\x87\x54\x9F" +- "\x34\x2B\xC4\x7E\xD3\x94\xDC\x9D\x3C\xD4\xD1\x63\xAD\xE3\x75\xE3" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ +- { KV5M_DATA, 16, +- "\x8E\x57\x11\x45\x45\x28\x55\x57\x5F\xD9\x16\xE7\xB0\x44\x87\xAA" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- "password", +- { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ +- { KV5M_DATA, 32, +- "\x77\xF4\x21\xA6\xF2\x5E\x13\x83\x95\xE8\x37\xE5\xD8\x5D\x38\x5B" +- "\x4C\x1B\xFD\x77\x2E\x11\x2C\xD9\x20\x8C\xE7\x2A\x53\x0B\x15\xE6" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- "password", +- { KV5M_DATA, 8, "\x12\x34\x56\x78\x78\x56\x34\x12" }, +- { KV5M_DATA, 4, "\0\0\0\5" }, +- { KV5M_DATA, 16, +- "\x00\x49\x8F\xD9\x16\xBF\xC1\xC2\xB1\x03\x1C\x17\x08\x01\xB3\x81" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- "password", +- { KV5M_DATA, 8, "\x12\x34\x56\x78\x78\x56\x34\x12" }, +- { KV5M_DATA, 4, "\0\0\0\5" }, +- { KV5M_DATA, 32, +- "\x11\x08\x3A\x00\xBD\xFE\x6A\x41\xB2\xF1\x97\x16\xD6\x20\x2F\x0A" +- "\xFA\x94\x28\x9A\xFE\x8B\x27\xA0\x49\xBD\x28\xB1\xD7\x6C\x38\x9A" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", +- { KV5M_DATA, 29, "pass phrase equals block size" }, +- { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ +- { KV5M_DATA, 16, +- "\x8B\xF6\xC3\xEF\x70\x9B\x98\x1D\xBB\x58\x5D\x08\x68\x43\xBE\x05" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", +- { KV5M_DATA, 29, "pass phrase equals block size" }, +- { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ +- { KV5M_DATA, 32, +- "\x11\x9F\xE2\xA1\xCB\x0B\x1B\xE0\x10\xB9\x06\x7A\x73\xDB\x63\xED" +- "\x46\x65\xB4\xE5\x3A\x98\xD1\x78\x03\x5D\xCF\xE8\x43\xA6\xB9\xB0" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", +- { KV5M_DATA, 30, "pass phrase exceeds block size" }, +- { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ +- { KV5M_DATA, 16, +- "\x57\x52\xAC\x8D\x6A\xD1\xCC\xFE\x84\x30\xB3\x12\x87\x1C\x2F\x74" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", +- { KV5M_DATA, 30, "pass phrase exceeds block size" }, +- { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ +- { KV5M_DATA, 32, +- "\x61\x4D\x5D\xFC\x0B\xA6\xD3\x90\xB4\x12\xB8\x9A\xE4\xD5\xB0\x88" +- "\xB6\x12\xB3\x16\x51\x09\x94\x67\x9D\xDB\x43\x83\xC7\x12\x6D\xDF" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA128_CTS_CMAC, +- "\xf0\x9d\x84\x9e", +- { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, +- { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ +- { KV5M_DATA, 16, +- "\xCC\x75\xC7\xFD\x26\x0F\x1C\x16\x58\x01\x1F\xCC\x0D\x56\x06\x16" }, +- 0, +- TRUE +- }, +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- "\xf0\x9d\x84\x9e", +- { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, +- { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ +- { KV5M_DATA, 32, +- "\x16\x3B\x76\x8C\x6D\xB1\x48\xB4\xEE\xC7\x16\x3D\xF5\xAE\xD7\x0E" +- "\x20\x6B\x68\xCE\xC0\x78\xBC\x06\x9E\xD6\x8A\x7E\xD3\x6B\x1E\xCC" }, +- 0, +- TRUE +- }, +- /* Check for KRB5_ERR_BAD_S2K_PARAMS return when weak iteration counts are +- * forbidden. */ +- { +- ENCTYPE_CAMELLIA256_CTS_CMAC, +- "\xf0\x9d\x84\x9e", +- { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, +- { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ +- { KV5M_DATA, 32, +- "\x16\x3B\x76\x8C\x6D\xB1\x48\xB4\xEE\xC7\x16\x3D\xF5\xAE\xD7\x0E" +- "\x20\x6B\x68\xCE\xC0\x78\xBC\x06\x9E\xD6\x8A\x7E\xD3\x6B\x1E\xCC" }, +- KRB5_ERR_BAD_S2K_PARAMS, +- FALSE +- }, +- +- { +- ENCTYPE_AES128_CTS_HMAC_SHA256_128, +- "password", +- { KV5M_DATA, 37, +- "\x10\xDF\x9D\xD7\x83\xE5\xBC\x8A\xCE\xA1\x73\x0E\x74\x35\x5F\x61" +- "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\x00\x00\x80\x00" }, +- { KV5M_DATA, 16, +- "\x08\x9B\xCA\x48\xB1\x05\xEA\x6E\xA7\x7C\xA5\xD2\xF3\x9D\xC5\xE7" }, +- 0, +- FALSE +- }, +- { +- ENCTYPE_AES256_CTS_HMAC_SHA384_192, +- "password", +- { KV5M_DATA, 37, +- "\x10\xDF\x9D\xD7\x83\xE5\xBC\x8A\xCE\xA1\x73\x0E\x74\x35\x5F\x61" +- "ATHENA.MIT.EDUraeburn" }, +- { KV5M_DATA, 4, "\x00\x00\x80\x00" }, +- { KV5M_DATA, 32, +- "\x45\xBD\x80\x6D\xBF\x6A\x83\x3A\x9C\xFF\xC1\xC9\x45\x89\xA2\x22" +- "\x36\x7A\x79\xBC\x21\xC4\x13\x71\x89\x06\xE9\xF5\x78\xA7\x84\x67" }, +- 0, +- FALSE +- }, + }; + + static void +diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h +index 3629616d9..cb5db72b2 100644 +--- a/src/lib/crypto/krb/crypto_int.h ++++ b/src/lib/crypto/krb/crypto_int.h +@@ -48,9 +48,9 @@ + * the EVP_MAC interface which can be used for CMAC. (We could use the CMAC + * interface with OpenSSL 1.1 but currently do not.) + */ +-#define K5_BUILTIN_DES_KEY_PARITY +-#define K5_BUILTIN_MD4 +-#define K5_BUILTIN_RC4 ++#define K5_OPENSSL_DES_KEY_PARITY ++#define K5_OPENSSL_MD4 ++#define K5_OPENSSL_RC4 + #define K5_OPENSSL_KDF + #define K5_OPENSSL_CMAC + #else +diff --git a/src/lib/kadm5/t_kadm5.c b/src/lib/kadm5/t_kadm5.c +index 153147ffb..d4eff6e58 100644 +--- a/src/lib/kadm5/t_kadm5.c ++++ b/src/lib/kadm5/t_kadm5.c +@@ -39,8 +39,9 @@ static krb5_boolean rpc; + static krb5_context context; + + /* These must match the creation commands in t_kadm5.py. */ +-#define ADMIN_PASSWORD "admin" +-#define USER_PASSWORD "us3r" ++/* Modified for FIPS: passwords must be >= 14 bytes for PBKDF2 HMAC key requirement */ ++#define ADMIN_PASSWORD "admin-password-test" ++#define USER_PASSWORD "user-password-test" + + /* This list must match the supported_enctypes setting in t_kadm5.py. */ + static krb5_enctype +@@ -49,6 +50,9 @@ default_supported_enctypes[] = { + ENCTYPE_NULL + }; + ++/* Generic test password for FIPS compliance (>= 14 bytes) */ ++#define TEST_PASSWORD "test-password-fips" ++ + static void + check(krb5_error_code code) + { +@@ -168,7 +172,7 @@ create_simple_princ(krb5_principal princ, char *policy) + ent.policy = policy; + if (policy != NULL) + mask |= KADM5_POLICY; +- check(kadm5_create_principal(handle, &ent, mask, "pw")); ++ check(kadm5_create_principal(handle, &ent, mask, TEST_PASSWORD)); + free_handle(handle); + } + +@@ -288,7 +292,7 @@ test_chpass() + + /* Check kvno and enctypes after a password change. */ + handle = get_handle("admin"); +- check(kadm5_chpass_principal(handle, princ, "newpassword")); ++ check(kadm5_chpass_principal(handle, princ, "new-password-fips-test")); + check(kadm5_get_principal(handle, princ, &ent, KADM5_KEY_DATA)); + compare_key_data(&ent, default_supported_enctypes); + assert(ent.key_data[0].key_data_kvno == 2); +@@ -296,19 +300,19 @@ test_chpass() + free_handle(handle); + + /* Fails for protected principal. */ +- cpw_test_fail("admin", hist_princ, "pw", KADM5_PROTECT_PRINCIPAL); ++ cpw_test_fail("admin", hist_princ, TEST_PASSWORD, KADM5_PROTECT_PRINCIPAL); + + /* Fails over RPC if "change" ACL is not granted, or if we authenticated to + * kadmin/changepw and are changing another principal's password. */ + if (rpc) { +- cpw_test_succeed("admin/modify", princ, "pw2"); +- cpw_test_fail("admin/none", princ, "pw3", KADM5_AUTH_CHANGEPW); +- cpw_test_fail("$admin", princ, "pw3", KADM5_AUTH_CHANGEPW); ++ cpw_test_succeed("admin/modify", princ, "password-test-2-fips"); ++ cpw_test_fail("admin/none", princ, "password-test-3-fips", KADM5_AUTH_CHANGEPW); ++ cpw_test_fail("$admin", princ, "password-test-3-fips", KADM5_AUTH_CHANGEPW); + } + + /* Fails with null handle or principal name. */ +- cpw_test_fail(NULL, princ, "pw", KADM5_BAD_SERVER_HANDLE); +- cpw_test_fail("admin", NULL, "pw", EINVAL); ++ cpw_test_fail(NULL, princ, TEST_PASSWORD, KADM5_BAD_SERVER_HANDLE); ++ cpw_test_fail("admin", NULL, TEST_PASSWORD, EINVAL); + + delete_princ(princ); + krb5_free_principal(context, princ); +@@ -452,42 +456,45 @@ test_create_principal() + + /* Fails with undefined or prohibited mask bit. */ + cprinc_test_fail("admin", &ent, 0x100000, "", KADM5_BAD_MASK); +- cprinc_test_fail("admin", &ent, KADM5_LAST_PWD_CHANGE, "pw", ++ cprinc_test_fail("admin", &ent, KADM5_LAST_PWD_CHANGE, TEST_PASSWORD, + KADM5_BAD_MASK); +- cprinc_test_fail("admin", &ent, KADM5_MOD_TIME, "pw", KADM5_BAD_MASK); +- cprinc_test_fail("admin", &ent, KADM5_MOD_NAME, "pw", KADM5_BAD_MASK); +- cprinc_test_fail("admin", &ent, KADM5_MKVNO, "pw", KADM5_BAD_MASK); +- cprinc_test_fail("admin", &ent, KADM5_AUX_ATTRIBUTES, "pw", ++ cprinc_test_fail("admin", &ent, KADM5_MOD_TIME, TEST_PASSWORD, KADM5_BAD_MASK); ++ cprinc_test_fail("admin", &ent, KADM5_MOD_NAME, TEST_PASSWORD, KADM5_BAD_MASK); ++ cprinc_test_fail("admin", &ent, KADM5_MKVNO, TEST_PASSWORD, KADM5_BAD_MASK); ++ cprinc_test_fail("admin", &ent, KADM5_AUX_ATTRIBUTES, TEST_PASSWORD, + KADM5_BAD_MASK); + + /* Fails without KADM5_PRINCIPAL mask bit. */ + handle = get_handle("admin"); +- check_fail(kadm5_create_principal(handle, &ent, 0, "pw"), KADM5_BAD_MASK); ++ check_fail(kadm5_create_principal(handle, &ent, 0, TEST_PASSWORD), KADM5_BAD_MASK); + free_handle(handle); + + /* Fails with empty password or password prohibited by policy. */ + cprinc_test_fail("admin", &ent, 0, "", KADM5_PASS_Q_TOOSHORT); + ent.policy = "test-pol"; +- cprinc_test_fail("admin", &ent, KADM5_POLICY, "tP", KADM5_PASS_Q_TOOSHORT); ++ /* SKIP: FIPS requires passwords >= 14 bytes, but test-pol minlength is 8, ++ * so any FIPS-compliant password will pass the policy minlength check. ++ * Cannot test "password too short" with FIPS-compliant passwords. */ ++ /* cprinc_test_fail("admin", &ent, KADM5_POLICY, "testPassword-tP", KADM5_PASS_Q_TOOSHORT); */ + cprinc_test_fail("admin", &ent, KADM5_POLICY, "testpassword", + KADM5_PASS_Q_CLASS); + cprinc_test_fail("admin", &ent, KADM5_POLICY, "Abyssinia", + KADM5_PASS_Q_DICT); + +- cprinc_test_compare("admin", &ent, 0, "pw"); ++ cprinc_test_compare("admin", &ent, 0, TEST_PASSWORD); + ent.policy = "nonexistent-pol"; +- cprinc_test_compare("admin", &ent, KADM5_POLICY, "pw"); +- cprinc_test_compare("admin/rename", &ent, KADM5_POLICY, "pw"); ++ cprinc_test_compare("admin", &ent, KADM5_POLICY, TEST_PASSWORD); ++ cprinc_test_compare("admin/rename", &ent, KADM5_POLICY, TEST_PASSWORD); + + /* Test pw_expiration explicit specifications vs. policy pw_max_life. */ + ent.policy = "test-pol"; + cprinc_test_compare("admin", &ent, KADM5_POLICY, "NotinTheDictionary"); +- cprinc_test_compare("admin", &ent, KADM5_PRINC_EXPIRE_TIME, "pw"); +- cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, "pw"); ++ cprinc_test_compare("admin", &ent, KADM5_PRINC_EXPIRE_TIME, TEST_PASSWORD); ++ cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, TEST_PASSWORD); + cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION, + "NotinTheDictionary"); + ent.pw_expiration = 1234; +- cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, "pw"); ++ cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, TEST_PASSWORD); + cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION, + "NotinTheDictionary"); + ent.pw_expiration = 999999999; +@@ -495,25 +502,25 @@ test_create_principal() + "NotinTheDictionary"); + ent.policy = "dict-only-pol"; + cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION, +- "pw"); ++ TEST_PASSWORD); + + /* Fails over RPC if "add" ACL is not granted, or if we authenticated to + * kadmin/changepw. */ + if (rpc) { +- cprinc_test_fail("$admin", &ent, 0, "pw", KADM5_AUTH_ADD); +- cprinc_test_fail("admin/none", &ent, 0, "pw", KADM5_AUTH_ADD); +- cprinc_test_fail("admin/get", &ent, 0, "pw", KADM5_AUTH_ADD); +- cprinc_test_fail("admin/modify", &ent, 0, "pw", KADM5_AUTH_ADD); +- cprinc_test_fail("admin/delete", &ent, 0, "pw", KADM5_AUTH_ADD); ++ cprinc_test_fail("$admin", &ent, 0, TEST_PASSWORD, KADM5_AUTH_ADD); ++ cprinc_test_fail("admin/none", &ent, 0, TEST_PASSWORD, KADM5_AUTH_ADD); ++ cprinc_test_fail("admin/get", &ent, 0, TEST_PASSWORD, KADM5_AUTH_ADD); ++ cprinc_test_fail("admin/modify", &ent, 0, TEST_PASSWORD, KADM5_AUTH_ADD); ++ cprinc_test_fail("admin/delete", &ent, 0, TEST_PASSWORD, KADM5_AUTH_ADD); + } + + /* Fails with existing policy name. */ + ent.principal = user_princ; +- cprinc_test_fail("admin", &ent, 0, "pw", KADM5_DUP); ++ cprinc_test_fail("admin", &ent, 0, TEST_PASSWORD, KADM5_DUP); + + /* Fails with null handle or principal ent. */ +- cprinc_test_fail(NULL, &ent, 0, "pw", KADM5_BAD_SERVER_HANDLE); +- cprinc_test_fail("admin", NULL, 0, "pw", EINVAL); ++ cprinc_test_fail(NULL, &ent, 0, TEST_PASSWORD, KADM5_BAD_SERVER_HANDLE); ++ cprinc_test_fail("admin", NULL, 0, TEST_PASSWORD, EINVAL); + + krb5_free_principal(context, princ); + krb5_free_principal(context, user_princ); +@@ -766,49 +773,49 @@ test_init_destroy() + check_fail(kadm5_destroy(NULL), KADM5_BAD_SERVER_HANDLE); + + /* Fails with bad structure version mask. */ +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, NULL, + 0x65432101, api, NULL, &handle), + KADM5_BAD_STRUCT_VERSION); +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, NULL, + 1, api, NULL, &handle), KADM5_BAD_STRUCT_VERSION); + + /* Fails with too-old or too-new structure version. */ +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION_MASK, api, NULL, &handle), + KADM5_OLD_STRUCT_VERSION); +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION_MASK | 0xca, api, NULL, + &handle), KADM5_NEW_STRUCT_VERSION); + + /* Fails with bad API version mask. */ +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, 0x65432100, NULL, &handle), + KADM5_BAD_API_VERSION); +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, 4, NULL, &handle), + KADM5_BAD_API_VERSION); + + /* Fails with too-old or too-new API version.*/ +- ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, ++ ret = kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_MASK, NULL, + &handle); + assert(ret == (rpc ? KADM5_OLD_LIB_API_VERSION : + KADM5_OLD_SERVER_API_VERSION)); +- ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, ++ ret = kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_MASK | 0xca, NULL, + &handle); + assert(ret == (rpc ? KADM5_NEW_LIB_API_VERSION : + KADM5_NEW_SERVER_API_VERSION)); + + /* Fails with structure and API version reversed. */ +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, NULL, + api, KADM5_STRUCT_VERSION, NULL, &handle), + KADM5_BAD_STRUCT_VERSION); + + /* Hardcoded default max lifetime is used when no handle or krb5.conf + * setting is given. */ + handle = get_handle("admin"); +- check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, "pw")); ++ check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, TEST_PASSWORD)); + check(kadm5_get_principal(handle, princ, &gent, + KADM5_PRINCIPAL_NORMAL_MASK)); + assert(gent.max_life == KRB5_KDB_MAX_LIFE); +@@ -821,21 +828,21 @@ test_init_destroy() + check(kadm5_init_krb5_context(&ctx)); + params.realm = ""; + params.mask = KADM5_CONFIG_REALM; +- ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, ¶ms, ++ ret = kadm5_init(ctx, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, ¶ms, + KADM5_STRUCT_VERSION, api, NULL, &handle); + assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT)); + krb5_free_context(ctx); + + check(kadm5_init_krb5_context(&ctx)); + params.realm = "@"; +- ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, ¶ms, ++ ret = kadm5_init(ctx, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, ¶ms, + KADM5_STRUCT_VERSION, api, NULL, &handle); + assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT)); + krb5_free_context(ctx); + + check(kadm5_init_krb5_context(&ctx)); + params.realm = "BAD.REALM"; +- ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, ¶ms, ++ ret = kadm5_init(ctx, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, ¶ms, + KADM5_STRUCT_VERSION, api, NULL, &handle); + assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT)); + krb5_free_context(ctx); +@@ -843,13 +850,13 @@ test_init_destroy() + /* Succeeds with explicit client realm and configured realm. */ + check(kadm5_init_krb5_context(&ctx)); + params.realm = "KRBTEST.COM"; +- check(kadm5_init(ctx, "admin@KRBTEST.COM", "admin", KADM5_ADMIN_SERVICE, ++ check(kadm5_init(ctx, "admin@KRBTEST.COM", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + krb5_free_context(ctx); + + /* Succeeds with explicit client realm. */ +- check(kadm5_init(context, "admin@KRBTEST.COM", "admin", ++ check(kadm5_init(context, "admin@KRBTEST.COM", ADMIN_PASSWORD, + KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, api, + NULL, &handle)); + check(kadm5_destroy(handle)); +@@ -862,20 +869,20 @@ test_init_destroy() + params.admin_server = hostname; + params.kadmind_port = 61001; + params.mask = KADM5_CONFIG_ADMIN_SERVER | KADM5_CONFIG_KADMIND_PORT; +- check(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, ++ check(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + + /* Fails with wrong configured port. */ + params.kadmind_port = 4; +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, + &handle), KADM5_RPC_ERROR); + + /* Fails with non-resolving hostname. */ + params.admin_server = "does.not.exist"; + params.mask = KADM5_CONFIG_ADMIN_SERVER; +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, + &handle), KADM5_CANT_RESOLVE); + +@@ -886,69 +893,69 @@ test_init_destroy() + &handle), KRB5_FCC_NOFILE); + + /* Succeeds with cache containing kadmin/admin cred. */ +- kinit(cc, "admin", "admin", KADM5_ADMIN_SERVICE); ++ kinit(cc, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE); + check(kadm5_init_with_creds(context, "admin", cc, KADM5_ADMIN_SERVICE, + NULL, KADM5_STRUCT_VERSION, api, NULL, + &handle)); + check(kadm5_destroy(handle)); + + /* Succeeds with cache containing kadmin/changepw cred. */ +- kinit(cc, "admin", "admin", KADM5_CHANGEPW_SERVICE); ++ kinit(cc, "admin", ADMIN_PASSWORD, KADM5_CHANGEPW_SERVICE); + check(kadm5_init_with_creds(context, "admin", cc, + KADM5_CHANGEPW_SERVICE, NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + + /* Fails with cache containing only a TGT. */ +- kinit(cc, "admin", "admin", NULL); ++ kinit(cc, "admin", ADMIN_PASSWORD, NULL); + check_fail(kadm5_init_with_creds(context, "admin", cc, + KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, api, NULL, + &handle), KRB5_CC_NOTFOUND); + + /* Fails authenticating to non-kadmin princ. */ +- check_fail(kadm5_init(context, "admin", "admin", "user", NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, "user", NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle), + KADM5_RPC_ERROR); + + /* Fails authenticating to nonexistent princ. */ +- check_fail(kadm5_init(context, "admin", "admin", "noexist", NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, "noexist", NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle), + KADM5_SECURE_PRINC_MISSING); + + /* Fails authenticating to client princ (which is non-kadmin). */ +- check_fail(kadm5_init(context, "admin", "admin", "admin", NULL, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, "admin", NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle), + KADM5_RPC_ERROR); + + /* Fails with wrong password. */ +- check_fail(kadm5_init(context, "admin", "wrong", KADM5_ADMIN_SERVICE, ++ check_fail(kadm5_init(context, "admin", "wrong-password-test-fips", KADM5_ADMIN_SERVICE, + NULL, KADM5_STRUCT_VERSION, api, NULL, &handle), + KADM5_BAD_PASSWORD); + + /* Fails with null client name. */ +- check_fail(kadm5_init(context, NULL, "admin", KADM5_ADMIN_SERVICE, ++ check_fail(kadm5_init(context, NULL, ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, + NULL, KADM5_STRUCT_VERSION, api, NULL, &handle), + EINVAL); + + /* Fails with nonexistent client name. */ +- check_fail(kadm5_init(context, "noexist", "admin", KADM5_ADMIN_SERVICE, ++ check_fail(kadm5_init(context, "noexist", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, + NULL, KADM5_STRUCT_VERSION, api, NULL, &handle), + KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN); + + /* Fails with nonexistent client name with explicit realm. */ +- check_fail(kadm5_init(context, "noexist@KRBTEST.COM", "admin", ++ check_fail(kadm5_init(context, "noexist@KRBTEST.COM", ADMIN_PASSWORD, + KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, + api, NULL, &handle), + KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN); + + /* Fails with nonexistent client name with unknown realm. */ +- check_fail(kadm5_init(context, "noexist@BAD.REALM", "admin", ++ check_fail(kadm5_init(context, "noexist@BAD.REALM", ADMIN_PASSWORD, + KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, + api, NULL, &handle), KRB5_REALM_UNKNOWN); + + /* Fails with known name but unknown realm. */ +- check_fail(kadm5_init(context, "admin@BAD.REALM", "admin", ++ check_fail(kadm5_init(context, "admin@BAD.REALM", ADMIN_PASSWORD, + KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, + api, NULL, &handle), KRB5_REALM_UNKNOWN); + +@@ -957,7 +964,7 @@ test_init_destroy() + /* Fails with nonexistent stash file. */ + params.stash_file = "does/not/exist"; + params.mask = KADM5_CONFIG_STASH_FILE; +- check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, ++ check_fail(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, + &handle), KRB5_KDB_CANTREAD_STORED); + +@@ -968,9 +975,9 @@ test_init_destroy() + params.num_keysalts = 0; + params.mask = KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | + KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES; +- check(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, ++ check(kadm5_init(context, "admin", ADMIN_PASSWORD, KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, &handle)); +- check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, "pw")); ++ check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, TEST_PASSWORD)); + check(kadm5_get_principal(handle, princ, &gent, + KADM5_PRINCIPAL_NORMAL_MASK | + KADM5_KEY_DATA)); +@@ -983,17 +990,17 @@ test_init_destroy() + check(kadm5_destroy(handle)); + + /* Succeeds with incorrect password using local auth. */ +- check(kadm5_init(context, "admin", "wrong", KADM5_ADMIN_SERVICE, NULL, ++ check(kadm5_init(context, "admin", "wrong-password-test-fips", KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + + /* Succeeds with null service using local auth. */ +- check(kadm5_init(context, "admin", "admin", NULL, NULL, ++ check(kadm5_init(context, "admin", ADMIN_PASSWORD, NULL, NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + + /* Succeeds with nonexistent, non-kadmin service using local auth. */ +- check(kadm5_init(context, "admin", "admin", "foobar", NULL, ++ check(kadm5_init(context, "admin", ADMIN_PASSWORD, "foobar", NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + } +diff --git a/src/lib/kadm5/t_kadm5.py b/src/lib/kadm5/t_kadm5.py +index c218b67c4..fdb07777b 100644 +--- a/src/lib/kadm5/t_kadm5.py ++++ b/src/lib/kadm5/t_kadm5.py +@@ -30,14 +30,17 @@ realm.run([kadminl, 'addpol', '-maxlife', '10000s', '-minlength', '8', + 'test-pol']) + realm.run([kadminl, 'addpol', '-minlife', '10s', 'minlife-pol']) + realm.run([kadminl, 'addpol', 'dict-only-pol']) +-realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin']) +-realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/get']) +-realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/modify']) +-realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/delete']) +-realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/add']) +-realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/rename']) +-realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/none']) +-realm.run([kadminl, 'addprinc', '-pw', 'us3r', '-policy', 'minlife-pol', ++# Modified for FIPS: password must be >= 14 bytes for PBKDF2 HMAC key requirement ++adminpass = 'admin-password-test' ++userpass = 'user-password-test' ++realm.run([kadminl, 'addprinc', '-pw', adminpass, 'admin']) ++realm.run([kadminl, 'addprinc', '-pw', adminpass, 'admin/get']) ++realm.run([kadminl, 'addprinc', '-pw', adminpass, 'admin/modify']) ++realm.run([kadminl, 'addprinc', '-pw', adminpass, 'admin/delete']) ++realm.run([kadminl, 'addprinc', '-pw', adminpass, 'admin/add']) ++realm.run([kadminl, 'addprinc', '-pw', adminpass, 'admin/rename']) ++realm.run([kadminl, 'addprinc', '-pw', adminpass, 'admin/none']) ++realm.run([kadminl, 'addprinc', '-pw', userpass, '-policy', 'minlife-pol', + 'user']) + + realm.run(['./t_kadm5srv', 'srv']) +diff --git a/src/lib/krad/Makefile.in b/src/lib/krad/Makefile.in +index 8c3317fe4..c5b3230a4 100644 +--- a/src/lib/krad/Makefile.in ++++ b/src/lib/krad/Makefile.in +@@ -32,12 +32,13 @@ install-unix: install-libs + clean-unix:: clean-liblinks clean-libs clean-libobjs + + check-unix: t_attr t_attrset t_code t_packet t_remote t_client +- $(RUN_TEST) ./t_attr +- $(RUN_TEST) ./t_attrset +- $(RUN_TEST) ./t_code +- $(RUN_TEST) ./t_packet $(PYTHON) $(srcdir)/t_daemon.py +- $(RUN_TEST) ./t_remote $(PYTHON) $(srcdir)/t_daemon.py +- $(RUN_TEST) ./t_client $(PYTHON) $(srcdir)/t_daemon.py ++ #$(RUN_TEST) ./t_attr ++ #$(RUN_TEST) ./t_attrset ++ #$(RUN_TEST) ./t_code ++ #$(RUN_TEST) ./t_packet $(PYTHON) $(srcdir)/t_daemon.py ++ #$(RUN_TEST) ./t_remote $(PYTHON) $(srcdir)/t_daemon.py ++ #$(RUN_TEST) ./t_client $(PYTHON) $(srcdir)/t_daemon.py ++ @echo "SKIP: KRAD tests require MD5 (RADIUS protocol requirement, not available in FIPS mode)" + + TESTDEPS=t_test.o $(KRB5_BASE_DEPLIBS) + TESTLIBS=t_test.o $(KRB5_BASE_LIBS) +diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in +index e4b560fb8..4c25b9d42 100644 +--- a/src/lib/krb5/krb/Makefile.in ++++ b/src/lib/krb5/krb/Makefile.in +@@ -361,7 +361,7 @@ SRCS= $(srcdir)/addr_comp.c \ + $(srcdir)/t_parse_host_string.c \ + $(srcdir)/t_princ.c \ + $(srcdir)/t_etypes.c \ +- $(srcdir)/t_expire_warn.c \ ++ #$(srcdir)/t_expire_warn.c \ + $(srcdir)/t_authdata.c \ + $(srcdir)/t_cc_config.c \ + $(srcdir)/t_copy_context.c \ +diff --git a/src/lib/krb5/krb/t_expire_warn.py b/src/lib/krb5/krb/t_expire_warn.py +index e163cc7..2b56d8f 100755 +--- a/src/lib/krb5/krb/t_expire_warn.py ++++ b/src/lib/krb5/krb/t_expire_warn.py +@@ -26,41 +26,41 @@ from k5test import * + realm = K5Realm(create_user=False, create_host=False) + + # Create principals with various password expirations. +-realm.run([kadminl, 'addprinc', '-pw', 'pass', 'noexpire']) +-realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '30 minutes', ++realm.run([kadminl, 'addprinc', '-pw', 'password-test12', 'noexpire']) ++realm.run([kadminl, 'addprinc', '-pw', 'password-test12', '-pwexpire', '30 minutes', + 'minutes']) +-realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '12 hours', ++realm.run([kadminl, 'addprinc', '-pw', 'password-test12', '-pwexpire', '12 hours', + 'hours']) +-realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '3 days', 'days']) ++realm.run([kadminl, 'addprinc', '-pw', 'password-test12', '-pwexpire', '3 days', 'days']) + + # Check for expected prompter warnings when no expire callback is used. +-output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '0', '0']) ++output = realm.run(['./t_expire_warn', 'noexpire', 'password-test12', '0', '0']) + if output: + fail('Unexpected output for noexpire') +-realm.run(['./t_expire_warn', 'minutes', 'pass', '0', '0'], ++realm.run(['./t_expire_warn', 'minutes', 'password-test12', '0', '0'], + expected_msg=' less than one hour on ') +-realm.run(['./t_expire_warn', 'hours', 'pass', '0', '0'], ++realm.run(['./t_expire_warn', 'hours', 'password-test12', '0', '0'], + expected_msg=' hours on ') +-realm.run(['./t_expire_warn', 'days', 'pass', '0', '0'], ++realm.run(['./t_expire_warn', 'days', 'password-test12', '0', '0'], + expected_msg=' days on ') + # Try one case with the stepwise interface. +-realm.run(['./t_expire_warn', 'days', 'pass', '0', '1'], ++realm.run(['./t_expire_warn', 'days', 'password-test12', '0', '1'], + expected_msg=' days on ') + + # Check for expected expire callback behavior. These tests are + # carefully agnostic about whether the KDC supports last_req fields, + # and could be made more specific if last_req support is added. +-output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '1', '0']) ++output = realm.run(['./t_expire_warn', 'noexpire', 'password-test12', '1', '0']) + if 'password_expiration = 0\n' not in output or \ + 'account_expiration = 0\n' not in output or \ + 'is_last_req = ' not in output: + fail('Expected callback output not seen for noexpire') +-output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '0']) ++output = realm.run(['./t_expire_warn', 'days', 'password-test12', '1', '0']) + if 'password_expiration = ' not in output or \ + 'password_expiration = 0\n' in output: + fail('Expected non-zero password expiration not seen for days') + # Try one case with the stepwise interface. +-output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '1']) ++output = realm.run(['./t_expire_warn', 'days', 'password-test12', '1', '1']) + if 'password_expiration = ' not in output or \ + 'password_expiration = 0\n' in output: + fail('Expected non-zero password expiration not seen for days') +diff --git a/src/lib/krb5/krb/t_get_etype_info.py b/src/lib/krb5/krb/t_get_etype_info.py +index 3c9168591..0529b6729 100644 +--- a/src/lib/krb5/krb/t_get_etype_info.py ++++ b/src/lib/krb5/krb/t_get_etype_info.py +@@ -3,11 +3,13 @@ from k5test import * + conf = {'libdefaults': {'allow_weak_crypto': 'true'}} + realm = K5Realm(create_host=False, krb5_conf=conf) + +-realm.run([kadminl, 'ank', '-pw', 'pw', '+preauth', 'puser']) ++# Modified for FIPS: password must be >= 14 bytes for PBKDF2 HMAC key requirement ++testpass = 'password-test-fips' ++realm.run([kadminl, 'ank', '-pw', testpass, '+preauth', 'puser']) + realm.run([kadminl, 'ank', '-nokey', 'nokey']) + realm.run([kadminl, 'ank', '-nokey', '+preauth', 'pnokey']) +-realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', 'exp']) +-realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', '+preauth', ++realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', testpass, 'exp']) ++realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', testpass, '+preauth', + 'pexp']) + + # Extract the explicit salt values from the database. +diff --git a/src/lib/krb5/krb/t_in_ccache_patypes.py b/src/lib/krb5/krb/t_in_ccache_patypes.py +index b2812688c..fc6d47b2d 100755 +--- a/src/lib/krb5/krb/t_in_ccache_patypes.py ++++ b/src/lib/krb5/krb/t_in_ccache_patypes.py +@@ -26,56 +26,58 @@ from k5test import * + realm = K5Realm(create_user=False, create_host=False) + + # Create principals with various password expirations. +-realm.run([kadminl, 'addprinc', '-pw', 'pass', 'nopreauth']) +-realm.run([kadminl, 'addprinc', '-pw', 'pass', '+requires_preauth', 'preauth']) ++# Modified for FIPS: password must be >= 14 bytes for PBKDF2 HMAC key requirement ++testpass = 'password-test-fips' ++realm.run([kadminl, 'addprinc', '-pw', testpass, 'nopreauth']) ++realm.run([kadminl, 'addprinc', '-pw', testpass, '+requires_preauth', 'preauth']) + + # Check that we can get creds without preauth without an in_ccache. This is + # the default behavior for kinit. +-realm.run(['./t_in_ccache', 'nopreauth', 'pass']) ++realm.run(['./t_in_ccache', 'nopreauth', testpass]) + + # Check that we can get creds with preauth without an in_ccache. This is the + # default behavior for kinit. +-realm.run(['./t_in_ccache', 'preauth', 'pass']) ++realm.run(['./t_in_ccache', 'preauth', testpass]) + + # Check that we can get creds while supplying a now-populated input ccache that + # doesn't contain any relevant configuration. +-realm.run(['./t_in_ccache', 'nopreauth', 'pass']) +-realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', 'pass']) ++realm.run(['./t_in_ccache', 'nopreauth', testpass]) ++realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', testpass]) + + # Check that we can get creds while supplying a now-populated input ccache. +-realm.run(['./t_in_ccache', 'preauth', 'pass']) +-realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', 'pass']) ++realm.run(['./t_in_ccache', 'preauth', testpass]) ++realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', testpass]) + + # Check that we can't get creds while specifying patypes that aren't available + # in a FAST tunnel while using a FAST tunnel. Expect the client-end + # preauth-failed error. +-realm.run(['./t_in_ccache', 'nopreauth', 'pass']) ++realm.run(['./t_in_ccache', 'nopreauth', testpass]) + realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type', '2']) + realm.run(['./t_in_ccache', '-A', realm.ccache, '-I', realm.ccache, +- 'preauth', 'pass'], expected_code=210) ++ 'preauth', testpass], expected_code=210) + + # Check that we can't get creds while specifying patypes that are only + # available in a FAST tunnel while not using a FAST tunnel. Expect the + # client-end preauth-failed error. +-realm.run(['./t_in_ccache', 'nopreauth', 'pass']) ++realm.run(['./t_in_ccache', 'nopreauth', testpass]) + realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type', '138']) +-realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', 'pass'], ++realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', testpass], + expected_code=210) + + # Check that we can get creds using FAST, and that we end up using + # encrypted_challenge when we do. +-realm.run(['./t_in_ccache', 'preauth', 'pass']) ++realm.run(['./t_in_ccache', 'preauth', testpass]) + realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type', '138']) +-realm.run(['./t_in_ccache', '-A', realm.ccache, 'preauth', 'pass']) ++realm.run(['./t_in_ccache', '-A', realm.ccache, 'preauth', testpass]) + output = realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type']) + # We should have selected and used encrypted_challenge. + if output != '138': + fail('Unexpected pa_type value in out_ccache: "%s"' % output) + + # Check that we can get creds while specifying the right patypes. +-realm.run(['./t_in_ccache', 'nopreauth', 'pass']) ++realm.run(['./t_in_ccache', 'nopreauth', testpass]) + realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type', '2']) +-realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', 'pass']) ++realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', testpass]) + output = realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type']) + # We should have selected and used encrypted_timestamp. + if output != '2': +diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c +index 173bde7ba..ee93f07d7 100644 +--- a/src/lib/krb5/krb/t_pac.c ++++ b/src/lib/krb5/krb/t_pac.c +@@ -41,61 +41,8 @@ + * regression test suite, they where created by Andrew Bartlet. + */ + +-static const unsigned char saved_pac[] = { +- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, +- 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, +- 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, +- 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, +- 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, +- 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb, +- 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, +- 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59, +- 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00, +- 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, +- 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00, +- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00, +- 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, +- 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, +- 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, +- 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00, +- 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00, +- 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00, +- 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00, +- 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, +- 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc, +- 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +- 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00, +- 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00, +- 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a, +- 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe, +- 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00 +-}; +- +-static unsigned int type_1_length = 472; +- +-static const krb5_keyblock kdc_keyblock = { +- 0, ENCTYPE_ARCFOUR_HMAC, +- 16, U("\xB2\x86\x75\x71\x48\xAF\x7F\xD2\x52\xC5\x36\x03\xA1\x50\xB7\xE7") +-}; ++/* Saved PAC data removed - used RC4 keys which are not FIPS-approved */ + +-static const krb5_keyblock member_keyblock = { +- 0, ENCTYPE_ARCFOUR_HMAC, +- 16, U("\xD2\x17\xFA\xEA\xE5\xE6\xB5\xF9\x5C\xCC\x94\x07\x7A\xB8\xA5\xFC") +-}; +- +-static time_t authtime = 1120440609; + static const char *user = "w2003final$@WIN2K3.THINKER.LOCAL"; + + /* The S4U2Self PACs below were collected by debugging krb5-mit code on +@@ -506,14 +453,9 @@ check_pac(krb5_context context, int index, const unsigned char *pdata, + const krb5_keyblock *server_key, const krb5_keyblock *kdc_key) + { + krb5_error_code ret; +- const krb5_keyblock *kdc_sign_key; + krb5_data data; + krb5_pac pac; + +- /* If we don't have the KDC key (S4U cases), just use another key as we'd +- * skip the KDC signature when verifying. */ +- kdc_sign_key = (kdc_key == NULL) ? &kdc_keyblock : kdc_key; +- + ret = krb5_pac_parse(context, pdata, plen, &pac); + if (ret) + err(context, ret, "[pac: %d] krb5_pac_parse", index); +@@ -523,22 +465,25 @@ check_pac(krb5_context context, int index, const unsigned char *pdata, + if (ret) + err(context, ret, "[pac: %d] krb5_pac_verify_ext", index); + +- ret = krb5_pac_sign_ext(context, pac, auth_time, p, server_key, +- kdc_sign_key, with_realm, &data); +- if (ret) +- err(context, ret, "[pac: %d] krb5_pac_sign_ext", index); ++ /* Only do sign/re-parse/verify cycle if we have a kdc_key */ ++ if (kdc_key != NULL) { ++ ret = krb5_pac_sign_ext(context, pac, auth_time, p, server_key, ++ kdc_key, with_realm, &data); ++ if (ret) ++ err(context, ret, "[pac: %d] krb5_pac_sign_ext", index); + +- krb5_pac_free(context, pac); ++ krb5_pac_free(context, pac); + +- ret = krb5_pac_parse(context, data.data, data.length, &pac); +- krb5_free_data_contents(context, &data); +- if (ret) +- err(context, ret, "[pac: %d] krb5_pac_parse 2", index); ++ ret = krb5_pac_parse(context, data.data, data.length, &pac); ++ krb5_free_data_contents(context, &data); ++ if (ret) ++ err(context, ret, "[pac: %d] krb5_pac_parse 2", index); + +- ret = krb5_pac_verify_ext(context, pac, auth_time, p, server_key, kdc_key, +- with_realm); +- if (ret) +- err(context, ret, "[pac: %d] krb5_pac_verify_ext 2", index); ++ ret = krb5_pac_verify_ext(context, pac, auth_time, p, server_key, kdc_key, ++ with_realm); ++ if (ret) ++ err(context, ret, "[pac: %d] krb5_pac_verify_ext 2", index); ++ } + + /* make a copy and try to reproduce it */ + { +@@ -581,23 +526,26 @@ check_pac(krb5_context context, int index, const unsigned char *pdata, + } + free(list); + +- ret = krb5_pac_sign_ext(context, pac2, auth_time, p, server_key, +- kdc_sign_key, with_realm, &data); +- if (ret) +- err(context, ret, "[pac: %d] krb5_pac_sign_ext 4", index); ++ /* Only sign/re-parse/verify if we have a kdc_key */ ++ if (kdc_key != NULL) { ++ ret = krb5_pac_sign_ext(context, pac2, auth_time, p, server_key, ++ kdc_key, with_realm, &data); ++ if (ret) ++ err(context, ret, "[pac: %d] krb5_pac_sign_ext 4", index); + +- krb5_pac_free(context, pac2); ++ krb5_pac_free(context, pac2); + +- ret = krb5_pac_parse(context, data.data, data.length, &pac2); +- if (ret) +- err(context, ret, "[pac: %d] krb5_pac_parse 4", index); ++ ret = krb5_pac_parse(context, data.data, data.length, &pac2); ++ if (ret) ++ err(context, ret, "[pac: %d] krb5_pac_parse 4", index); + +- ret = krb5_pac_verify_ext(context, pac2, auth_time, p, server_key, +- kdc_key, with_realm); +- if (ret) +- err(context, ret, "[pac: %d] krb5_pac_verify_ext 4", index); ++ ret = krb5_pac_verify_ext(context, pac2, auth_time, p, server_key, ++ kdc_key, with_realm); ++ if (ret) ++ err(context, ret, "[pac: %d] krb5_pac_verify_ext 4", index); + +- krb5_free_data_contents(context, &data); ++ krb5_free_data_contents(context, &data); ++ } + + krb5_pac_free(context, pac2); + } +@@ -605,185 +553,7 @@ check_pac(krb5_context context, int index, const unsigned char *pdata, + krb5_pac_free(context, pac); + } + +-static const krb5_keyblock ticket_sig_krbtgt_key = { +- 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- 32, U("\x7a\x58\x98\xd2\xaf\xa6\xaf\xc0\x6a\xce\x06\x04\x4b\xc2\x70\x84" +- "\x9b\x8e\x0a\x6c\x4c\x07\xdc\x6f\xbb\x48\x43\xe1\xd2\xaa\x97\xf7") +-}; +- +-static const krb5_keyblock ticket_sig_server_key = { +- 0, ENCTYPE_ARCFOUR_HMAC, +- 16, U("\xed\x23\x11\x20\x7a\x21\x44\x20\xbf\xc0\x8d\x36\xf7\xf6\xb2\x3e") +-}; +- +-static const krb5_data ticket_data = { +- .length = 972, .data = +- "\x61\x82\x03\xC8\x30\x82\x03\xC4\xA0\x03\x02\x01\x05\xA1\x0A\x1B" +- "\x08\x43\x44\x4F\x4D\x2E\x43\x4F\x4D\xA2\x0F\x30\x0D\xA0\x03\x02" +- "\x01\x01\xA1\x06\x30\x04\x1B\x02\x73\x31\xA3\x82\x03\x9E\x30\x82" +- "\x03\x9A\xA0\x03\x02\x01\x17\xA1\x03\x02\x01\x03\xA2\x82\x03\x8C" +- "\x04\x82\x03\x88\x44\x31\x61\x20\x17\xC9\xFE\xBC\xAC\x46\xB5\x77" +- "\xE9\x68\x04\x4C\x9B\x31\x91\x0C\xC1\xD4\xDD\xEF\xC7\x34\x20\x08" +- "\x90\x91\xE8\x79\xE0\xB5\x03\x26\xA4\x65\xDE\xEC\x47\x03\x2A\x8F" +- "\x61\xE7\x4D\x38\x5A\x42\x95\x5A\xF9\x2F\x41\x2C\x2A\x6E\x60\xA1" +- "\xEB\x51\xB3\xBD\x4C\x00\x41\x2A\x44\x76\x08\x37\x1A\x51\xFD\x65" +- "\x67\x7E\xBF\x3D\x90\x86\xE3\x9A\x54\x6B\x67\xA8\x08\x7A\x73\xCC" +- "\xC3\xB7\x4B\xD5\x5C\x3A\x14\x6C\xC1\x5F\x54\x4B\x92\x55\xB4\xB7" +- "\x92\x23\x3F\x53\x89\x47\x8E\x1F\x8B\xB9\xDB\x3B\x93\xE8\x70\xE4" +- "\x24\xB8\x9D\xF0\x0E\x35\x28\xF8\x7A\x27\x5D\xF7\x25\x97\x9C\xF5" +- "\x9F\x9F\x64\x04\xF2\xA3\xAB\x11\x15\xB6\xDA\x18\xD6\x46\xD5\xE6" +- "\xB8\x08\xDE\x0A\x62\xFD\xF8\xAA\x52\x90\xD9\x67\x29\xB2\xCD\x06" +- "\xB6\xB0\x50\x2B\x3F\x0F\xA3\xA5\xBF\xAA\x6E\x40\x03\xD6\x5F\x02" +- "\xBC\xD8\x18\x47\x97\x09\xD7\xE4\x96\x3B\xCB\xEB\x92\x2C\x3C\x49" +- "\xFF\x1F\x71\xE0\x52\x94\x0F\x8B\x9F\xB8\x2A\xBB\x9C\xE2\xA3\xDD" +- "\x38\x89\xE2\xB1\x0B\x9E\x1F\x7A\xB3\xE3\xD2\xB0\x94\xDC\x87\xBE" +- "\x37\xA6\xD3\xB3\x29\x35\x9A\x72\xC3\x7A\xF1\xA9\xE6\xC5\xD1\x26" +- "\x83\x65\x44\x17\xBA\x55\xA8\x5E\x94\x26\xED\xE9\x8A\x93\x11\x5D" +- "\x7E\x20\x1B\x9C\x15\x9E\x13\x37\x03\x4D\xDD\x99\x51\xD8\x66\x29" +- "\x6A\xB9\xFB\x49\xFE\x52\x78\xDA\x86\x85\xA9\xA3\xB9\xEF\xEC\xAD" +- "\x35\xA6\x8D\xAC\x0F\x75\x22\xBB\x0B\x49\x1C\x13\x52\x40\xC9\x52" +- "\x69\x09\x54\xD1\x0F\x94\x3F\x22\x48\x67\xB0\x96\x28\xAA\xE6\x28" +- "\xD9\x0C\x08\xEF\x51\xED\x15\x5E\xA2\x53\x59\xA5\x03\xB4\x06\x20" +- "\x3D\xCC\xB4\xC5\xF8\x8C\x73\x67\xA3\x21\x3D\x19\xCD\xD4\x12\x28" +- "\xD2\x93\xDE\x0D\xF0\x71\x10\x50\xD6\x33\x35\x04\x11\x64\x43\x39" +- "\xC3\xDF\x96\xE3\x66\xE3\x85\xCA\xE7\x67\x14\x3A\xF0\x43\xAA\xBB" +- "\xD4\x1D\xB5\x24\xB5\x74\x90\x25\xA7\x87\x7E\xDB\xD3\x83\x8A\x3A" +- "\x69\xA8\x2D\xAF\xB7\xB8\xF3\xDC\x13\xAF\x45\x61\x3F\x59\x39\x7E" +- "\x69\xDE\x0C\x04\xF1\x10\x6B\xB4\x56\xFA\x21\x9F\x72\x2B\x60\x86" +- "\xE3\x23\x0E\xC4\x51\xF6\xBE\xD8\xE1\x5F\xEE\x73\x4C\x17\x4C\x2C" +- "\x1B\xFB\x9F\x1F\x7A\x3B\x07\x5B\x8E\xF1\x01\xAC\xD6\x30\x94\x8A" +- "\x5D\x22\x6F\x08\xCE\xED\x5E\xB6\xDB\x86\x8C\x87\xEB\x8D\x91\xFF" +- "\x0A\x86\x30\xBD\xC0\xF8\x25\xE7\xAE\x24\x35\xF2\xFC\xE5\xFD\x1B" +- "\xB0\x05\x4A\xA3\xE5\xEB\x2E\x05\xAD\x99\x67\x49\x87\xE6\xB3\x87" +- "\x82\xA4\x59\xA7\x6E\xDD\xF2\xB6\x66\xE8\xF7\x70\xF5\xBD\xC9\x0E" +- "\xFA\x9C\x79\x84\xD4\x9B\x05\x0E\xBB\xF5\xDB\xEF\xFC\xCC\x26\xF2" +- "\x93\xCF\xD2\x04\x3C\xA9\x2C\x65\x42\x97\x86\xD8\x38\x0A\x1E\xF6" +- "\xD6\xCA\x30\xB5\x1A\xEC\xFB\xBA\x3B\x84\x57\xB0\xFD\xFB\xE6\xBC" +- "\xF2\x76\xF6\x4C\xBB\xAB\xB1\x31\xA1\x27\x7C\xE6\xE6\x81\xB6\xCE" +- "\x84\x86\x40\xB6\x40\x33\xC4\xF8\xB4\x15\xCF\xAA\xA5\x51\x78\xB9" +- "\x8B\x50\x25\xB2\x88\x86\x96\x72\x8C\x71\x4D\xB5\x3A\x94\x86\x77" +- "\x0E\x95\x9B\x16\x93\xEF\x3A\x11\x79\xBA\x83\xF7\x74\xD3\x8D\xBA" +- "\x15\xE1\x2C\x04\x57\xA8\x92\x1E\x9D\x00\x8E\x20\xFD\x30\x70\xE7" +- "\xF5\x65\x2F\x19\x0C\x94\xBA\x03\x71\x12\x96\xCD\xC8\xB4\x96\xDB" +- "\xCE\x19\xC2\xDF\x3C\xC2\xF6\x3D\x53\xED\x98\xA5\x41\x72\x2A\x22" +- "\x7B\xF3\x2B\x17\x6C\xE1\x39\x7D\xAE\x9B\x11\xF9\xC1\xA6\x9E\x9F" +- "\x89\x3C\x12\xAA\x94\x74\xA7\x4F\x70\xE8\xB9\xDE\x04\xF0\x9D\x39" +- "\x24\x2D\x92\xE8\x46\x2D\x2E\xF0\x40\x66\x1A\xD9\x27\xF9\x98\xF1" +- "\x81\x1D\x70\x62\x63\x30\x6D\xCD\x84\x04\x5F\xFA\x83\xD3\xEC\x8D" +- "\x86\xFB\x40\x61\xC1\x8A\x45\xFF\x7B\xD9\xD4\x18\x61\x7F\x51\xE3" +- "\xFC\x1E\x18\xF0\xAF\xC6\x18\x2C\xE1\x6D\x5D\xF9\x62\xFC\x20\xA3" +- "\xB2\x8A\x5F\xE5\xBB\x29\x0F\x99\x63\x07\x88\x38\x3A\x3B\x73\x2A" +- "\x6D\xDA\x3D\xA8\x0D\x8F\x56\x41\x89\x82\xE5\xB8\x61\x00\x64\x7D" +- "\x17\x0C\xCE\x03\x55\x8F\xF4\x5B\x0D\x50\xF2\xEB\x05\x67\xBE\xDB" +- "\x7B\x75\xC5\xEA\xA1\xAB\x1D\xB0\x3C\x6D\x42\x08\x0B\x9A\x45\x20" +- "\xA8\x8F\xE5\x67\x47\x30\xDE\x93\x5F\x43\x05\xEB\xA8\x2D\x80\xF5" +- "\x1A\xB8\x4A\x4E\x42\x2D\x0B\x7A\xDC\x46\x20\x2D\x13\x17\xDD\x4B" +- "\x94\x96\xAA\x1F\x06\x0C\x1F\x62\x07\x9C\x40\xA1" +-}; +- +-static void +-test_pac_ticket_signature(krb5_context context) +-{ +- krb5_error_code ret; +- krb5_ticket *ticket; +- krb5_principal sprinc; +- krb5_authdata **authdata1, **authdata2; +- krb5_pac pac, pac2, pac3; +- uint32_t *list; +- size_t len, i; +- krb5_data data; +- +- ret = krb5_decode_ticket(&ticket_data, &ticket); +- if (ret) +- err(context, ret, "while decoding ticket"); +- +- ret = krb5_decrypt_tkt_part(context, &ticket_sig_server_key, ticket); +- if (ret) +- err(context, ret, "while decrypting ticket"); +- +- ret = krb5_parse_name(context, "s1@CDOM.COM", &sprinc); +- if (ret) +- err(context, ret, "krb5_parse_name"); +- +- ret = krb5_kdc_verify_ticket(context, ticket->enc_part2, sprinc, +- &ticket_sig_server_key, +- &ticket_sig_krbtgt_key, &pac); +- if (ret) +- err(context, ret, "while verifying ticket"); +- +- /* In this test, the server is also the client. */ +- ret = krb5_pac_verify(context, pac, ticket->enc_part2->times.authtime, +- ticket->server, NULL, NULL); +- if (ret) +- err(context, ret, "while verifying PAC client info"); +- +- /* We know there is only a PAC in this test's ticket. */ +- authdata1 = ticket->enc_part2->authorization_data; +- ticket->enc_part2->authorization_data = NULL; +- +- ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac, sprinc, +- sprinc, &ticket_sig_server_key, +- &ticket_sig_krbtgt_key, FALSE); +- if (ret) +- err(context, ret, "while signing ticket"); +- +- authdata2 = ticket->enc_part2->authorization_data; +- assert(authdata2 != NULL); +- assert(authdata2[1] == NULL); +- +- assert(authdata1[0]->length == authdata2[0]->length); +- assert(memcmp(authdata1[0]->contents, authdata2[0]->contents, +- authdata1[0]->length) == 0); +- +- /* Test adding signatures to a new PAC. */ +- ret = krb5_pac_init(context, &pac2); +- if (ret) +- err(context, ret, "krb5_pac_init"); +- +- ret = krb5_pac_get_types(context, pac, &len, &list); +- if (ret) +- err(context, ret, "krb5_pac_get_types"); +- +- for (i = 0; i < len; i++) { +- /* Skip server_cksum, privsvr_cksum, and ticket_cksum. */ +- if (list[i] == 6 || list[i] == 7 || list[i] == 16) +- continue; +- +- ret = krb5_pac_get_buffer(context, pac, list[i], &data); +- if (ret) +- err(context, ret, "krb5_pac_get_buffer"); +- +- ret = krb5_pac_add_buffer(context, pac2, list[i], &data); +- if (ret) +- err(context, ret, "krb5_pac_add_buffer"); +- +- krb5_free_data_contents(context, &data); +- } +- free(list); +- +- krb5_free_authdata(context, authdata1); +- krb5_free_authdata(context, ticket->enc_part2->authorization_data); +- ticket->enc_part2->authorization_data = NULL; +- +- ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac2, sprinc, NULL, +- &ticket_sig_server_key, &ticket_sig_krbtgt_key, +- FALSE); +- if (ret) +- err(context, ret, "while signing ticket"); +- +- /* We can't compare the data since the order of the buffers may differ. */ +- ret = krb5_kdc_verify_ticket(context, ticket->enc_part2, sprinc, +- &ticket_sig_server_key, +- &ticket_sig_krbtgt_key, &pac3); +- if (ret) +- err(context, ret, "while verifying ticket"); +- +- krb5_pac_free(context, pac); +- krb5_pac_free(context, pac2); +- krb5_pac_free(context, pac3); +- krb5_free_principal(context, sprinc); +- krb5_free_ticket(context, ticket); +-} ++/* Ticket signature test data and function removed - used RC4 which is not FIPS-approved */ + + int + main(int argc, char **argv) +@@ -791,14 +561,13 @@ main(int argc, char **argv) + krb5_error_code ret; + krb5_context context; + krb5_pac pac; +- krb5_data data; + krb5_principal p; + + ret = krb5_init_context(&context); + if (ret) + err(NULL, 0, "krb5_init_contex"); + +- test_pac_ticket_signature(context); ++ /* test_pac_ticket_signature() removed - used RC4 */ + + ret = krb5_set_default_realm(context, "WIN2K3.THINKER.LOCAL"); + if (ret) +@@ -808,9 +577,7 @@ main(int argc, char **argv) + if (ret) + err(context, ret, "krb5_parse_name"); + +- /* Check a pre-saved PAC. */ +- check_pac(context, -1, saved_pac, sizeof(saved_pac), authtime, p, +- type_1_length, 0, &member_keyblock, &kdc_keyblock); ++ /* Pre-saved PAC check removed - used RC4 keys */ + + /* Check S4U2Self PACs. */ + { +@@ -856,263 +623,9 @@ main(int argc, char **argv) + krb5_pac_free(context, pac); + + /* +- * Test add remove buffer ++ * Test add remove buffer - removed (used RC4 keys) + */ + +- ret = krb5_pac_init(context, &pac); +- if (ret) +- err(context, ret, "krb5_pac_init"); +- +- { +- const krb5_data cdata = { 0, 2, "\x00\x01" } ; +- +- ret = krb5_pac_add_buffer(context, pac, 1, &cdata); +- if (ret) +- err(context, ret, "krb5_pac_add_buffer"); +- } +- { +- ret = krb5_pac_get_buffer(context, pac, 1, &data); +- if (ret) +- err(context, ret, "krb5_pac_get_buffer"); +- if (data.length != 2 || memcmp(data.data, "\x00\x01", 2) != 0) +- err(context, 0, "krb5_pac_get_buffer data not the same"); +- krb5_free_data_contents(context, &data); +- } +- +- { +- const krb5_data cdata = { 0, 2, "\x02\x00" } ; +- +- ret = krb5_pac_add_buffer(context, pac, 2, &cdata); +- if (ret) +- err(context, ret, "krb5_pac_add_buffer"); +- } +- { +- ret = krb5_pac_get_buffer(context, pac, 1, &data); +- if (ret) +- err(context, ret, "krb5_pac_get_buffer"); +- if (data.length != 2 || memcmp(data.data, "\x00\x01", 2) != 0) +- err(context, 0, "krb5_pac_get_buffer data not the same"); +- krb5_free_data_contents(context, &data); +- /* */ +- ret = krb5_pac_get_buffer(context, pac, 2, &data); +- if (ret) +- err(context, ret, "krb5_pac_get_buffer"); +- if (data.length != 2 || memcmp(data.data, "\x02\x00", 2) != 0) +- err(context, 0, "krb5_pac_get_buffer data not the same"); +- krb5_free_data_contents(context, &data); +- } +- +- ret = krb5_pac_sign(context, pac, authtime, p, +- &member_keyblock, &kdc_keyblock, &data); +- if (ret) +- err(context, ret, "krb5_pac_sign"); +- +- krb5_pac_free(context, pac); +- +- ret = krb5_pac_parse(context, data.data, data.length, &pac); +- krb5_free_data_contents(context, &data); +- if (ret) +- err(context, ret, "krb5_pac_parse 3"); +- +- ret = krb5_pac_verify(context, pac, authtime, p, +- &member_keyblock, &kdc_keyblock); +- if (ret) +- err(context, ret, "krb5_pac_verify 3"); +- +- { +- uint32_t *list; +- size_t len; +- +- /* our two user buffer plus the three "system" buffers */ +- ret = krb5_pac_get_types(context, pac, &len, &list); +- if (ret) +- err(context, ret, "krb5_pac_get_types"); +- if (len != 5) +- err(context, 0, "list wrong length"); +- free(list); +- } +- +- { +- krb5_principal ep, np; +- +- ret = krb5_parse_name_flags(context, user, +- KRB5_PRINCIPAL_PARSE_ENTERPRISE, &ep); +- if (ret) +- err(context, ret, "krb5_parse_name_flags"); +- +- ret = krb5_copy_principal(context, ep, &np); +- if (ret) +- err(context, ret, "krb5_copy_principal"); +- np->type = KRB5_NT_MS_PRINCIPAL; +- +- /* Try to verify as enterprise. */ +- ret = krb5_pac_verify(context, pac, authtime, ep, &member_keyblock, +- &kdc_keyblock); +- if (!ret) +- err(context, ret, "krb5_pac_verify should have failed"); +- +- ret = krb5_pac_sign(context, pac, authtime, ep, &member_keyblock, +- &kdc_keyblock, &data); +- if (!ret) +- err(context, ret, "krb5_pac_sign should have failed"); +- +- /* Try to verify with realm. */ +- ret = krb5_pac_verify_ext(context, pac, authtime, p, &member_keyblock, +- &kdc_keyblock, TRUE); +- if (!ret) +- err(context, ret, "krb5_pac_verify_ext with realm should fail"); +- +- /* Currently we can't re-sign the PAC with realm (although that could +- * be useful), only sign a new one. */ +- ret = krb5_pac_sign_ext(context, pac, authtime, p, &member_keyblock, +- &kdc_keyblock, TRUE, &data); +- if (!ret) +- err(context, ret, "krb5_pac_sign_ext with realm should fail"); +- +- krb5_pac_free(context, pac); +- +- /* Test enterprise. */ +- ret = krb5_pac_init(context, &pac); +- if (ret) +- err(context, ret, "krb5_pac_init"); +- +- ret = krb5_pac_sign(context, pac, authtime, ep, &member_keyblock, +- &kdc_keyblock, &data); +- if (ret) +- err(context, ret, "krb5_pac_sign enterprise failed"); +- +- krb5_pac_free(context, pac); +- +- ret = krb5_pac_parse(context, data.data, data.length, &pac); +- krb5_free_data_contents(context, &data); +- if (ret) +- err(context, ret, "krb5_pac_parse failed"); +- +- ret = krb5_pac_verify(context, pac, authtime, ep, &member_keyblock, +- &kdc_keyblock); +- if (ret) +- err(context, ret, "krb5_pac_verify enterprise failed"); +- +- /* Also verify enterprise as KRB5_NT_MS_PRINCIPAL. */ +- ret = krb5_pac_verify(context, pac, authtime, np, &member_keyblock, +- &kdc_keyblock); +- if (ret) +- err(context, ret, "krb5_pac_verify enterprise as nt-ms failed"); +- +- ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, +- &kdc_keyblock); +- if (!ret) +- err(context, ret, "krb5_pac_verify should have failed"); +- +- krb5_pac_free(context, pac); +- +- /* Test nt-ms-principal. */ +- ret = krb5_pac_init(context, &pac); +- if (ret) +- err(context, ret, "krb5_pac_init"); +- +- ret = krb5_pac_sign(context, pac, authtime, np, &member_keyblock, +- &kdc_keyblock, &data); +- if (ret) +- err(context, ret, "krb5_pac_sign enterprise failed"); +- +- krb5_pac_free(context, pac); +- +- ret = krb5_pac_parse(context, data.data, data.length, &pac); +- krb5_free_data_contents(context, &data); +- if (ret) +- err(context, ret, "krb5_pac_parse failed"); +- +- ret = krb5_pac_verify(context, pac, authtime, np, &member_keyblock, +- &kdc_keyblock); +- if (ret) +- err(context, ret, "krb5_pac_verify enterprise failed"); +- +- /* Also verify as enterprise principal. */ +- ret = krb5_pac_verify(context, pac, authtime, ep, &member_keyblock, +- &kdc_keyblock); +- if (ret) +- err(context, ret, "krb5_pac_verify nt-ms as enterprise failed"); +- +- ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, +- &kdc_keyblock); +- if (!ret) +- err(context, ret, "krb5_pac_verify should have failed"); +- +- krb5_pac_free(context, pac); +- +- /* Test with realm. */ +- ret = krb5_pac_init(context, &pac); +- if (ret) +- err(context, ret, "krb5_pac_init"); +- +- ret = krb5_pac_sign_ext(context, pac, authtime, p, &member_keyblock, +- &kdc_keyblock, TRUE, &data); +- if (ret) +- err(context, ret, "krb5_pac_sign_ext with realm failed"); +- +- krb5_pac_free(context, pac); +- +- ret = krb5_pac_parse(context, data.data, data.length, &pac); +- krb5_free_data_contents(context, &data); +- if (ret) +- err(context, ret, "krb5_pac_parse failed"); +- +- ret = krb5_pac_verify_ext(context, pac, authtime, p, &member_keyblock, +- &kdc_keyblock, TRUE); +- if (ret) +- err(context, ret, "krb5_pac_verify_ext with realm failed"); +- +- ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, +- &kdc_keyblock); +- if (!ret) +- err(context, ret, "krb5_pac_verify should have failed"); +- +- krb5_pac_free(context, pac); +- +- /* Test enterprise with realm. */ +- ret = krb5_pac_init(context, &pac); +- if (ret) +- err(context, ret, "krb5_pac_init"); +- +- ret = krb5_pac_sign_ext(context, pac, authtime, ep, &member_keyblock, +- &kdc_keyblock, TRUE, &data); +- if (ret) +- err(context, ret, "krb5_pac_sign_ext ent with realm failed"); +- +- krb5_pac_free(context, pac); +- +- ret = krb5_pac_parse(context, data.data, data.length, &pac); +- krb5_free_data_contents(context, &data); +- if (ret) +- err(context, ret, "krb5_pac_parse failed"); +- +- ret = krb5_pac_verify_ext(context, pac, authtime, ep, &member_keyblock, +- &kdc_keyblock, TRUE); +- if (ret) +- err(context, ret, "krb5_pac_verify_ext ent with realm failed"); +- +- ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, +- &kdc_keyblock); +- if (!ret) +- err(context, ret, "krb5_pac_verify should have failed"); +- +- ret = krb5_pac_verify(context, pac, authtime, ep, &member_keyblock, +- &kdc_keyblock); +- if (!ret) +- err(context, ret, "krb5_pac_verify should have failed"); +- +- ret = krb5_pac_verify_ext(context, pac, authtime, p, &member_keyblock, +- &kdc_keyblock, TRUE); +- if (!ret) +- err(context, ret, "krb5_pac_verify_ext should have failed"); +- +- krb5_free_principal(context, ep); +- krb5_free_principal(context, np); +- } +- +- krb5_pac_free(context, pac); +- + krb5_free_principal(context, p); + krb5_free_context(context); + +diff --git a/src/lib/rpc/unit-test/Makefile.in b/src/lib/rpc/unit-test/Makefile.in +index 309ae2b21..be6f90958 100644 +--- a/src/lib/rpc/unit-test/Makefile.in ++++ b/src/lib/rpc/unit-test/Makefile.in +@@ -31,7 +31,7 @@ client.o server.o: rpc_test.h + # + + check-pytests: +- $(RUNPYTEST) $(srcdir)/t_rpc.py $(PYTESTFLAGS) ++ @echo "SKIP: t_rpc.py test requires MD5 (not available in FIPS mode)" + + clean: + $(RM) server client +diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +index d500455de..67784e17b 100644 +--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c ++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +@@ -2735,57 +2735,7 @@ algid_to_md(const krb5_data *alg_id) + return NULL; + } + +-#if OPENSSL_VERSION_NUMBER >= 0x30000000L +- +-#define sskdf openssl_sskdf +-static krb5_error_code +-openssl_sskdf(krb5_context context, const EVP_MD *md, krb5_data *key, +- krb5_data *info, size_t len, krb5_data *out) +-{ +- krb5_error_code ret; +- EVP_KDF *kdf = NULL; +- EVP_KDF_CTX *kctx = NULL; +- OSSL_PARAM params[4], *p = params; +- +- ret = alloc_data(out, len); +- if (ret) +- goto cleanup; +- +- kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL); +- if (kdf == NULL) { +- ret = oerr(context, KRB5_CRYPTO_INTERNAL, _("Failed to fetch SSKDF")); +- goto cleanup; +- } +- +- kctx = EVP_KDF_CTX_new(kdf); +- if (!kctx) { +- ret = oerr(context, KRB5_CRYPTO_INTERNAL, +- _("Failed to instantiate SSKDF")); +- goto cleanup; +- } +- +- *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, +- (char *)EVP_MD_get0_name(md), 0); +- *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, +- key->data, key->length); +- *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, +- info->data, info->length); +- *p = OSSL_PARAM_construct_end(); +- if (EVP_KDF_derive(kctx, (uint8_t *)out->data, len, params) <= 0) { +- ret = oerr(context, KRB5_CRYPTO_INTERNAL, +- _("Failed to derive key using SSKDF")); +- goto cleanup; +- } +- +- ret = 0; +- +-cleanup: +- EVP_KDF_free(kdf); +- EVP_KDF_CTX_free(kctx); +- return ret; +-} +- +-#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */ ++/* Always use inline implementation of SSKDF */ + + #define sskdf builtin_sskdf + static krb5_error_code +@@ -2851,8 +2801,6 @@ cleanup: + return ret; + } + +-#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ +- + /* id-pkinit-kdf family, as specified by RFC 8636. */ + krb5_error_code + pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret, +diff --git a/src/plugins/preauth/pkinit/pkinit_kdf_test.c b/src/plugins/preauth/pkinit/pkinit_kdf_test.c +index 7f38e8491..2c265933e 100644 +--- a/src/plugins/preauth/pkinit/pkinit_kdf_test.c ++++ b/src/plugins/preauth/pkinit/pkinit_kdf_test.c +@@ -72,156 +72,6 @@ krb5_octet key3_hex[] = + int + main(int argc, char **argv) + { +- /* arguments for calls to pkinit_alg_agility_kdf() */ +- krb5_context context = 0; +- krb5_data secret; +- krb5_algorithm_identifier alg_id; +- krb5_data as_req; +- krb5_data pk_as_rep; +- krb5_keyblock key_block; +- +- /* other local variables */ +- int retval = 0; +- krb5_enctype enctype = 0; +- krb5_principal u_principal = NULL; +- krb5_principal v_principal = NULL; +- +- /* initialize variables that get malloc'ed, so cleanup is safe */ +- krb5_init_context (&context); +- memset(&alg_id, 0, sizeof(alg_id)); +- memset(&as_req, 0, sizeof(as_req)); +- memset(&pk_as_rep, 0, sizeof(pk_as_rep)); +- memset(&key_block, 0, sizeof(key_block)); +- +- /* set up a 256-byte, ALL-ZEROS secret */ +- if (NULL == (secret.data = malloc(secret_len))) { +- printf("ERROR in pkinit_kdf_test: Memory allocation failed."); +- retval = ENOMEM; +- goto cleanup; +- } +- secret.length = secret_len; +- memset(secret.data, 0, secret_len); +- +- /* set-up the partyUInfo and partyVInfo principals */ +- if ((0 != (retval = krb5_parse_name(context, party_u_name, +- &u_principal))) || +- (0 != (retval = krb5_parse_name(context, party_v_name, +- &v_principal)))) { +- printf("ERROR in pkinit_kdf_test: Error parsing names, retval = %d", +- retval); +- goto cleanup; +- } +- +- /* The test vectors in RFC 8636 implicitly use NT-PRINCIPAL names. */ +- u_principal->type = KRB5_NT_PRINCIPAL; +- v_principal->type = KRB5_NT_PRINCIPAL; +- +- /* set-up the as_req and and pk_as_rep data */ +- memset(twenty_as, 0xaa, sizeof(twenty_as)); +- memset(eighteen_bs, 0xbb, sizeof(eighteen_bs)); +- as_req.length = sizeof(twenty_as); +- as_req.data = twenty_as; +- +- pk_as_rep.length = sizeof(eighteen_bs); +- pk_as_rep.data = eighteen_bs; +- +- /* TEST 1: SHA-1/AES */ +- /* set up algorithm id */ +- alg_id.algorithm = sha1_id; +- +- enctype = enctype_aes; +- +- /* call pkinit_alg_agility_kdf() with test vector values*/ +- if (0 != (retval = pkinit_alg_agility_kdf(context, &secret, +- &alg_id.algorithm, +- u_principal, v_principal, +- enctype, &as_req, &pk_as_rep, +- &key_block))) { +- printf("ERROR in pkinit_kdf_test: kdf call failed, retval = %d\n", +- retval); +- goto cleanup; +- } +- +- /* compare key to expected key value */ +- +- if ((key_block.length == sizeof(key1_hex)) && +- (0 == memcmp(key_block.contents, key1_hex, key_block.length))) { +- printf("SUCCESS: TEST 1 (SHA-1/AES), Correct key value generated.\n"); +- retval = 0; +- /* free the keyblock contents, so we can use it for the next test */ +- krb5_free_keyblock_contents(context, &key_block); +- } else { +- printf("FAILURE: TEST 1 (SHA-1/AES), Incorrect key value generated!\n"); +- retval = 1; +- goto cleanup; +- } +- +- /* TEST 2: SHA-256/AES */ +- /* set up algorithm id */ +- alg_id.algorithm = sha256_id; +- +- enctype = enctype_aes; +- +- /* call pkinit_alg_agility_kdf() with test vector values*/ +- if (0 != (retval = pkinit_alg_agility_kdf(context, &secret, +- &alg_id.algorithm, +- u_principal, v_principal, +- enctype, &as_req, &pk_as_rep, +- &key_block))) { +- printf("ERROR in pkinit_kdf_test: kdf call failed, retval = %d\n", +- retval); +- goto cleanup; +- } +- +- /* compare key to expected key value */ +- +- if ((key_block.length == sizeof(key2_hex)) && +- (0 == memcmp(key_block.contents, key2_hex, key_block.length))) { +- printf("SUCCESS: TEST 2 (SHA-256/AES), Correct key value generated.\n"); +- retval = 0; +- /* free the keyblock contents, so we can use it for the next test */ +- krb5_free_keyblock_contents(context, &key_block); +- } else { +- printf("FAILURE: TEST 2 (SHA-256/AES), Incorrect key value generated!\n"); +- retval = 1; +- goto cleanup; +- } +- +- /* TEST 3: SHA-512/DES3 */ +- /* set up algorithm id */ +- alg_id.algorithm = sha512_id; +- +- enctype = enctype_des3; +- +- /* call pkinit_alg_agility_kdf() with test vector values*/ +- if (0 != (retval = pkinit_alg_agility_kdf(context, &secret, +- &alg_id.algorithm, +- u_principal, v_principal, +- enctype, &as_req, &pk_as_rep, +- &key_block))) { +- printf("ERROR in pkinit_kdf_test: kdf call failed, retval = %d\n", +- retval); +- goto cleanup; +- } +- +- /* compare key to expected key value */ +- +- if ((key_block.length == sizeof(key3_hex)) && +- (0 == memcmp(key_block.contents, key3_hex, key_block.length))) { +- printf("SUCCESS: TEST 3 (SHA-512/DES3), Correct key value generated.\n"); +- retval = 0; +- } else { +- printf("FAILURE: TEST 2 (SHA-512/DES3), Incorrect key value generated!\n"); +- retval = 1; +- goto cleanup; +- } +- +-cleanup: +- /* release all allocated resources, whether good or bad return */ +- free(secret.data); +- krb5_free_principal(context, u_principal); +- krb5_free_principal(context, v_principal); +- krb5_free_keyblock_contents(context, &key_block); +- krb5_free_context(context); +- return retval ? 1 : 0; ++ /* pkinit is disabled for wolfProvider at this time */ ++ return 0; + } +diff --git a/src/plugins/preauth/spake/t_vectors.c b/src/plugins/preauth/spake/t_vectors.c +index 2279202d3..aed1c5620 100644 +--- a/src/plugins/preauth/spake/t_vectors.c ++++ b/src/plugins/preauth/spake/t_vectors.c +@@ -56,56 +56,6 @@ struct test { + const char *K2; + const char *K3; + } tests[] = { +- { ENCTYPE_DES3_CBC_SHA1, SPAKE_GROUP_EDWARDS25519, +- /* initial key, w, x, y, T, S, K */ +- "850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E", +- "686D84730CB8679AE95416C6567C6A63F2C9CEF124F7A3371AE81E11CAD42A37", +- "201012D07BFD48DDFA33C4AAC4FB1E229FB0D043CFE65EBFB14399091C71A723", +- "500B294797B8B042ACA1BEDC0F5931A4F52C537B3608B2D05CC8A2372F439F25", +- "18F511E750C97B592ACD30DB7D9E5FCA660389102E6BF610C1BFBED4616C8362", +- "5D10705E0D1E43D5DBF30240CCFBDE4A0230C70D4C79147AB0B317EDAD2F8AE7", +- "25BDE0D875F0FEB5755F45BA5E857889D916ECF7476F116AA31DC3E037EC4292", +- /* support, challenge, thash, body */ +- "A0093007A0053003020101", +- "A1363034A003020101A122042018F511E750C97B592ACD30DB7D9E5FCA660389" +- "102E6BF610C1BFBED4616C8362A20930073005A003020101", +- "EAAA08807D0616026FF51C849EFBF35BA0CE3C5300E7D486DA46351B13D4605B", +- "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" +- "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" +- "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" +- "303130313030303030305AA703020100A8053003020110", +- /* K'[0], K'[1], K'[2], K'[3] */ +- "BAF12FAE7CD958CBF1A29BFBC71F89CE49E03E295D89DAFD", +- "64F73DD9C41908206BCEC1F719026B574F9D13463D7A2520", +- "0454520B086B152C455829E6BAEFF78A61DFE9E3D04A895D", +- "4A92260B25E3EF94C125D5C24C3E5BCED5B37976E67F25C4", +- }, +- +- { ENCTYPE_ARCFOUR_HMAC, SPAKE_GROUP_EDWARDS25519, +- /* initial key, w, x, y, T, S, K */ +- "8846F7EAEE8FB117AD06BDD830B7586C", +- "7C86659D29CF2B2EA93BFE79C3CEFB8850E82215B3EA6FCD896561D48048F49C", +- "C8A62E7B626F44CAD807B2D695450697E020D230A738C5CD5691CC781DCE8754", +- "18FE7C1512708C7FD06DB270361F04593775BC634CEAF45347E5C11C38AAE017", +- "7DB465F1C08C64983A19F560BCE966FE5306C4B447F70A5BCA14612A92DA1D63", +- "38F8D4568090148EBC9FD17C241B4CC2769505A7CA6F3F7104417B72B5B5CF54", +- "03E75EDD2CD7E7677642DD68736E91700953AC55DC650E3C2A1B3B4ACDB800F8", +- /* support, challenge, thash, body */ +- "A0093007A0053003020101", +- "A1363034A003020101A12204207DB465F1C08C64983A19F560BCE966FE5306C4" +- "B447F70A5BCA14612A92DA1D63A20930073005A003020101", +- "F4B208458017DE6EF7F6A307D47D87DB6C2AF1D291B726860F68BC08BFEF440A", +- "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" +- "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" +- "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" +- "303130313030303030305AA703020100A8053003020117", +- /* K'[0], K'[1], K'[2], K'[3] */ +- "770B720C82384CBB693E85411EEDECBA", +- "621DEEC88E2865837C4D3462BB50A1D5", +- "1CC8F6333B9FA3B42662FD9914FBD5BB", +- "EDB4032B7FC3806D5211A534DCBC390C", +- }, +- + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, SPAKE_GROUP_EDWARDS25519, + /* initial key, w, x, y, T, S, K */ + "FCA822951813FB252154C883F5EE1CF4", +diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in +index e7cf64e08..cd382ff00 100644 +--- a/src/tests/Makefile.in ++++ b/src/tests/Makefile.in +@@ -17,7 +17,7 @@ EXTRADEPSRCS= adata.c conccache.c etinfo.c forward.c gcred.c hist.c hooks.c \ + + TEST_DB = ./testdb + TEST_REALM = FOO.TEST.REALM +-TEST_MKEY = footes ++TEST_MKEY = footes-fips-password + TEST_NUM = 65 + TEST_DEPTH = 5 + TEST_PREFIX = "foo bar" +@@ -136,15 +136,15 @@ check-pytests: responder s2p s4u2proxy unlockiter s4u2self + $(RUNPYTEST) $(srcdir)/t_dump.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_iprop.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kprop.py $(PYTESTFLAGS) +- $(RUNPYTEST) $(srcdir)/t_policy.py $(PYTESTFLAGS) ++ #$(RUNPYTEST) $(srcdir)/t_policy.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_changepw.py $(PYTESTFLAGS) +- $(RUNPYTEST) $(srcdir)/t_pkinit.py $(PYTESTFLAGS) ++ #$(RUNPYTEST) $(srcdir)/t_pkinit.py $(PYTESTFLAGS) TODO check this + $(RUNPYTEST) $(srcdir)/t_otp.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_spake.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_localauth.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadm5_hook.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadm5_auth.py $(PYTESTFLAGS) +- $(RUNPYTEST) $(srcdir)/t_pwqual.py $(PYTESTFLAGS) ++ #$(RUNPYTEST) $(srcdir)/t_pwqual.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_hostrealm.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kdb_locking.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_keyrollover.py $(PYTESTFLAGS) +diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in +index 33047c35d..b1619362e 100644 +--- a/src/tests/gssapi/Makefile.in ++++ b/src/tests/gssapi/Makefile.in +@@ -39,7 +39,7 @@ all: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect t_ciflags \ + t_s4u t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs t_store_cred + + check-unix: t_oid reload +- $(RUN_TEST) ./t_invalid ++ #$(RUN_TEST) ./t_invalid + $(RUN_TEST) ./t_oid + $(RUN_TEST) ./t_prf + $(RUN_TEST) ./t_imp_name +@@ -53,7 +53,7 @@ check-pytests: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect \ + $(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_store_cred.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_credstore.py $(PYTESTFLAGS) +- $(RUNPYTEST) $(srcdir)/t_bindings.py $(PYTESTFLAGS) ++ #$(RUNPYTEST) $(srcdir)/t_bindings.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_enctypes.py $(PYTESTFLAGS) +diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py +index 7494d7fcd..6702fd246 100755 +--- a/src/tests/gssapi/t_enctypes.py ++++ b/src/tests/gssapi/t_enctypes.py +@@ -8,17 +8,14 @@ from k5test import * + # encryption without the RFC3961 framing. + aes256 = 'aes256-cts-hmac-sha1-96' + aes128 = 'aes128-cts-hmac-sha1-96' +-des3 = 'des3-cbc-sha1' +-d_des3 = 'DEPRECATED:des3-cbc-sha1' +-des3raw = 'des3-cbc-raw' +-d_des3raw = 'DEPRECATED:des3-cbc-raw' + rc4 = 'arcfour-hmac' + d_rc4 = 'DEPRECATED:arcfour-hmac' + + # These tests make assumptions about the default enctype lists, so set + # them explicitly rather than relying on the library defaults. +-supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal' +-conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4'}, ++# Modified for FIPS: removed rc4-hmac (not FIPS-approved) ++supp='aes256-cts:normal aes128-cts:normal' ++conf = {'libdefaults': {'permitted_enctypes': 'aes'}, + 'realms': {'$realm': {'supported_enctypes': supp}}} + realm = K5Realm(krb5_conf=conf) + shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save')) +@@ -87,60 +84,14 @@ test('both aes128', 'aes128-cts', 'aes128-cts', + test_err('acc aes128', None, 'aes128-cts', + 'Encryption type aes256-cts-hmac-sha1-96 not permitted') + +-# If the initiator constrains the permitted session enctypes to des3, +-# no acceptor subkey will be generated because we can't upgrade to a +-# CFX enctype. +-test('init des3', 'des3', None, +- tktenc=aes256, tktsession=d_des3, +- proto='rfc1964', isubkey=des3raw, asubkey=None) +- +-# Force the ticket session key to be rc4, so we can test some subkey +-# upgrade cases. The ticket encryption key remains aes256. +-realm.run([kadminl, 'setstr', realm.host_princ, 'session_enctypes', 'rc4']) +- +-# With no arguments, the initiator should send an upgrade list of +-# [aes256 aes128 des3] and the acceptor should upgrade to an aes256 +-# subkey. +-test('upgrade noargs', None, None, +- tktenc=aes256, tktsession=d_rc4, +- proto='cfx', isubkey=rc4, asubkey=aes256) +- +-# If the initiator won't permit rc4 as a session key, it won't be able +-# to get a ticket. +-test_err('upgrade init aes', 'aes', None, 'no support for encryption type') +- +-# If the initiator permits rc4 but prefers aes128, it will send an +-# upgrade list of [aes128] and the acceptor will upgrade to aes128. +-test('upgrade init aes128+rc4', 'aes128-cts rc4', None, +- tktenc=aes256, tktsession=d_rc4, +- proto='cfx', isubkey=rc4, asubkey=aes128) +- +-# If the initiator permits rc4 but prefers des3, it will send an +-# upgrade list of [des3], but the acceptor won't generate a subkey +-# because des3 isn't a CFX enctype. +-test('upgrade init des3+rc4', 'des3 rc4', None, +- tktenc=aes256, tktsession=d_rc4, +- proto='rfc1964', isubkey=rc4, asubkey=None) +- +-# If the acceptor permits only aes128, subkey negotiation will fail +-# because the ticket session key and initiator subkey are +-# non-permitted. (This is unfortunate if the acceptor's restriction +-# is only for the sake of the kernel, since we could upgrade to an +-# aes128 subkey, but it's the current semantics.) +-test_err('upgrade acc aes128', None, 'aes128-cts', +- 'Encryption type arcfour-hmac not permitted') +- +-# If the acceptor permits rc4 but prefers aes128, it will negotiate an +-# upgrade to aes128. +-test('upgrade acc aes128 rc4', None, 'aes128-cts rc4', +- tktenc=aes256, tktsession=d_rc4, +- proto='cfx', isubkey=rc4, asubkey=aes128) +- +-# In this test, the initiator and acceptor each prefer an AES enctype +-# to rc4, but they can't agree on which one, so no subkey is +-# generated. +-test('upgrade mismatch', 'aes128-cts rc4', 'aes256-cts rc4', +- tktenc=aes256, tktsession=d_rc4, +- proto='rfc1964', isubkey=rc4, asubkey=None) ++# Removed: All RC4/DES3 subkey upgrade tests (lines 86-133) ++# These tests require RC4 and DES3 which are not FIPS-approved: ++# - upgrade noargs: RC4 session key upgrade to AES256 ++# - upgrade init aes: RC4 permission test ++# - upgrade init aes128+rc4: RC4 to AES128 upgrade ++# - upgrade init des3+rc4: DES3 + RC4 test ++# - upgrade acc aes128: RC4 not permitted test ++# - upgrade acc aes128 rc4: RC4 to AES128 upgrade ++# - upgrade mismatch: RC4 mismatch test + + success('gss_krb5_set_allowable_enctypes tests') +diff --git a/src/tests/gssapi/t_prf.c b/src/tests/gssapi/t_prf.c +index f71774cdc..3f2ef2d71 100644 +--- a/src/tests/gssapi/t_prf.c ++++ b/src/tests/gssapi/t_prf.c +@@ -41,20 +41,6 @@ static struct { + const char *key2; + const char *out2; + } tests[] = { +- { ENCTYPE_DES3_CBC_SHA1, +- "70378A19CD64134580C27C0115D6B34A1CF2FEECEF9886A2", +- "9F8D127C520BB826BFF3E0FE5EF352389C17E0C073D9" +- "AC4A333D644D21BA3EF24F4A886D143F85AC9F6377FB", +- "3452A167DF1094BA1089E0A20E9E51ABEF1525922558B69E", +- "6BF24FABC858F8DD9752E4FCD331BB831F238B5BE190" +- "4EEA42E38F7A60C588F075C5C96A67E7F8B7BD0AECF4" }, +- { ENCTYPE_ARCFOUR_HMAC, +- "3BB3AE288C12B3B9D06B208A4151B3B6", +- "9AEA11A3BCF3C53F1F91F5A0BA2132E2501ADF5F3C28" +- "3C8A983AB88757CE865A22132D6100EAD63E9E291AFA", +- "6DB7B33A01BD2B72F7655CB7B3D5FA0B", +- "CDA9A544869FC84873B692663A82AFDA101C8611498B" +- "A46138B01E927C9B95EEC953B562807434037837DDDF" }, + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "6C742096EB896230312B73972FA28B5D", + "94208D982FC1BB7778128BDD77904420B45C9DA699F3" +@@ -69,20 +55,6 @@ static struct { + "F5B68B7823D8944F33F41541B4E4D38C9B2934F8D16334A796645B066152B4BE", + "112F2B2D878590653CCC7DE278E9F0AA46FA5A380B62" + "59F774CB7C134FCD37F61A50FD0D9F89BF8FE1A6B593" }, +- { ENCTYPE_CAMELLIA128_CTS_CMAC, +- "866E0466A178279A32AC0BDA92B72AEB", +- "97FBB354BF341C3A160DCC86A7A910FDA824601DF677" +- "68797BACEEBF5D250AE929DEC9760772084267F50A54", +- "D4893FD37DA1A211E12DD1E03E0F03B7", +- "1DEE2FF126CA563A2A2326B9DD3F0095013257414C83" +- "FAD4398901013D55F367C82681186B7B2FE62F746BA4" }, +- { ENCTYPE_CAMELLIA256_CTS_CMAC, +- "203071B1AE77BD3D6FCE70174AF95C225B1CED46B35CF52B6479EFEB47E6B063", +- "9B30020634C10FDA28420CEE7B96B70A90A771CED43A" +- "D8346554163E5949CBAE2FB8EF36AFB6B32CE75116A0", +- "A171AD582C1AFBBAD52ABD622EE6B6A14D19BF95C6914B2BA40FFD99A88EC660", +- "A47CBB6E104DCC77E4DB48A7A474B977F2FB6A7A1AB6" +- "52317D50508AE72B7BE2E4E4BA24164E029CBACF786B" }, + { ENCTYPE_AES128_CTS_HMAC_SHA256_128, + "089BCA48B105EA6EA77CA5D2F39DC5E7", + "ED1736209B7C59C9F6A3AE8CCC8A7C97ADFDD11688AD" +diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py +index 97e2474bf..4aba94ffc 100644 +--- a/src/tests/t_authdata.py ++++ b/src/tests/t_authdata.py +@@ -6,68 +6,6 @@ greet_path = os.path.join(buildtop, 'plugins', 'authdata', 'greet_server', + conf = {'plugins': {'kdcauthdata': {'module': 'greet:' + greet_path}}} + realm = K5Realm(krb5_conf=conf) + +-# With no requested authdata, we expect to see PAC (128) in an +-# if-relevant container and the greet authdata in a kdc-issued +-# container. +-mark('baseline authdata') +-out = realm.run(['./adata', realm.host_princ]) +-if '?128: [6, 7, 10, 16]' not in out or '^-42: Hello' not in out: +- fail('expected authdata not seen for basic request') +- +-# Requested authdata is copied into the ticket, with KDC-only types +-# filtered out. (128 is win2k-pac, which should be filtered.) +-mark('request authdata') +-out = realm.run(['./adata', realm.host_princ, '-5', 'test1', '?-6', 'test2', +- '128', 'fakepac', '?128', 'ifrelfakepac', +- '^-8', 'fakekdcissued', '?^-8', 'ifrelfakekdcissued']) +-if ' -5: test1' not in out or '?-6: test2' not in out: +- fail('expected authdata not seen for request with authdata') +-if 'fake' in out: +- fail('KDC-only authdata not filtered for request with authdata') +- +-mark('AD-MANDATORY-FOR-KDC') +-realm.run(['./adata', realm.host_princ, '!-1', 'mandatoryforkdc'], +- expected_code=1, expected_msg='KDC policy rejects request') +- +-# The no_auth_data_required server flag should suppress the PAC, but +-# not module or request authdata. +-mark('no_auth_data_required server flag') +-realm.run([kadminl, 'ank', '-randkey', '+no_auth_data_required', 'noauth']) +-realm.extract_keytab('noauth', realm.keytab) +-out = realm.run(['./adata', 'noauth', '-2', 'test']) +-if '^-42: Hello' not in out or ' -2: test' not in out: +- fail('expected authdata not seen for no_auth_data_required request') +-if '128: ' in out: +- fail('PAC authdata seen for no_auth_data_required request') +- +-# Cross-realm TGT requests should not suppress PAC or request +-# authdata. +-mark('cross-realm') +-realm.addprinc('krbtgt/XREALM') +-realm.extract_keytab('krbtgt/XREALM', realm.keytab) +-out = realm.run(['./adata', 'krbtgt/XREALM', '-3', 'test']) +-if '128:' not in out or '^-42: Hello' not in out or ' -3: test' not in out: +- fail('expected authdata not seen for cross-realm TGT request') +- +-realm.stop() +- +-if not pkinit_enabled: +- skipped('anonymous ticket authdata tests', 'PKINIT not built') +-else: +- # Set up a realm with PKINIT support and get anonymous tickets. +- realm = K5Realm(krb5_conf=conf, get_creds=False, pkinit=True) +- realm.addprinc('WELLKNOWN/ANONYMOUS') +- realm.kinit('@%s' % realm.realm, flags=['-n']) +- +- # PAC and module authdata should be suppressed for anonymous +- # tickets, but not request authdata. +- mark('anonymous') +- out = realm.run(['./adata', realm.host_princ, '-4', 'test']) +- if ' -4: test' not in out: +- fail('expected authdata not seen for anonymous request') +- if '128: ' in out or '-42: ' in out: +- fail('PAC or greet authdata seen for anonymous request') +- + realm.stop() + + # Test authentication indicators. Load the test preauth module so we +@@ -164,7 +102,7 @@ realm.run([kvno, 'restricted']) + # preferred krbtgt enctype changes. + mark('#8139 regression test') + realm.kinit(realm.user_princ, password('user'), ['-f']) +-realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'des3-cbc-sha1', ++realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes128-cts', + realm.krbtgt_princ]) + realm.run(['./forward']) + realm.run([kvno, realm.host_princ]) +@@ -180,168 +118,4 @@ realm.run([kvno, realm.host_princ]) + realm.stop() + realm2.stop() + +-# Load the test KDB module to allow successful S4U2Proxy +-# auth-indicator requests and to detect whether replaced_reply_key is +-# set. +-testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'}, +- 'krbtgt/FOREIGN': {'keys': 'aes128-cts'}, +- 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, +- 'user2': {'keys': 'aes128-cts', 'flags': '+preauth'}, +- 'rservice': {'keys': 'aes128-cts', +- 'strings': 'require_auth:strong'}, +- 'service/1': {'keys': 'aes128-cts', +- 'flags': '+ok_to_auth_as_delegate'}, +- 'service/2': {'keys': 'aes128-cts'}, +- 'noauthdata': {'keys': 'aes128-cts', +- 'flags': '+no_auth_data_required'}} +-kdcconf = {'realms': {'$realm': {'database_module': 'test'}}, +- 'dbmodules': {'test': {'db_library': 'test', +- 'princs': testprincs, +- 'delegation': {'service/1': 'service/2'}}}} +-realm = K5Realm(krb5_conf=krb5conf, kdc_conf=kdcconf, create_kdb=False, +- pkinit=True) +-usercache = 'FILE:' + os.path.join(realm.testdir, 'usercache') +-realm.extract_keytab(realm.krbtgt_princ, realm.keytab) +-realm.extract_keytab('krbtgt/FOREIGN', realm.keytab) +-realm.extract_keytab(realm.user_princ, realm.keytab) +-realm.extract_keytab('ruser', realm.keytab) +-realm.extract_keytab('service/1', realm.keytab) +-realm.extract_keytab('service/2', realm.keytab) +-realm.extract_keytab('noauthdata', realm.keytab) +-realm.start_kdc() +- +-if not pkinit_enabled: +- skipped('replaced_reply_key test', 'PKINIT not built') +-else: +- # Check that replaced_reply_key is set in issue_pac() when PKINIT +- # is used. The test KDB module will indicate this by including a +- # fake PAC_CREDENTIAL_INFO(2) buffer in the PAC. +- mark('PKINIT (replaced_reply_key set)') +- realm.pkinit(realm.user_princ) +- realm.run(['./adata', realm.krbtgt_princ], +- expected_msg='?128: [1, 2, 6, 7, 10]') +- +-# S4U2Self (should have no indicators since client did not authenticate) +-mark('S4U2Self (no auth indicators expected)') +-realm.kinit('service/1', None, ['-k', '-f', '-X', 'indicators=inds1']) +-realm.run([kvno, '-U', 'user', 'service/1']) +-out = realm.run(['./adata', '-p', realm.user_princ, 'service/1']) +-if '97:' in out: +- fail('auth-indicator present in S4U2Self response') +- +-# Get another S4U2Self ticket with requested authdata. +-realm.run(['./s4u2self', 'user', 'service/1', '-', '-2', 'self_ad']) +-realm.run(['./adata', '-p', realm.user_princ, 'service/1', '-2', 'self_ad'], +- expected_msg=' -2: self_ad') +- +-# S4U2Proxy (indicators should come from evidence ticket, not TGT) +-mark('S4U2Proxy (auth indicators from evidence ticket expected)') +-realm.kinit(realm.user_princ, None, ['-k', '-f', '-X', 'indicators=indcl', +- '-S', 'service/1', '-c', usercache]) +-realm.run(['./s4u2proxy', usercache, 'service/2']) +-out = realm.run(['./adata', '-p', realm.user_princ, 'service/2']) +-if '+97: [indcl]' not in out or '[inds1]' in out: +- fail('correct auth-indicator not seen for S4U2Proxy req') +-# Make sure a PAC with an S4U_DELEGATION_INFO(11) buffer is included. +-if '?128: [1, 6, 7, 10, 11, 16]' not in out: +- fail('PAC with delegation info not seen for S4U2Proxy req') +- +-# Get another S4U2Proxy ticket including request-authdata. +-realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad']) +-realm.run(['./adata', '-p', realm.user_princ, 'service/2', '-2', 'proxy_ad'], +- expected_msg=' -2: proxy_ad') +- +-# Get an S4U2Proxy ticket using an evidence ticket obtained by S4U2Self, +-# with request authdata in both steps. +-realm.run(['./s4u2self', 'user2', 'service/1', usercache, '-2', 'self_ad']) +-realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad']) +-out = realm.run(['./adata', '-p', 'user2', 'service/2', '-2', 'proxy_ad']) +-if ' -2: self_ad' not in out or ' -2: proxy_ad' not in out: +- fail('expected authdata not seen in S4U2Proxy ticket') +- +-# Test alteration of auth indicators by KDB module (AS and TGS). +-realm.kinit(realm.user_princ, None, ['-k', '-X', 'indicators=dummy dbincr1']) +-realm.run(['./adata', realm.krbtgt_princ], expected_msg='+97: [dbincr2]') +-realm.run(['./adata', 'service/1'], expected_msg='+97: [dbincr3]') +-realm.kinit(realm.user_princ, None, +- ['-k', '-X', 'indicators=strong', '-S', 'rservice']) +-# Test enforcement of altered indicators during AS request. +-realm.kinit(realm.user_princ, None, +- ['-k', '-X', 'indicators=strong dbincr1', '-S', 'rservice'], +- expected_code=1) +- +-# Test that the PAC is suppressed in an AS request by a negative PAC +-# request. +-mark('AS-REQ PAC client supression') +-realm.kinit(realm.user_princ, None, ['-k', '--no-request-pac']) +-out = realm.run(['./adata', realm.krbtgt_princ]) +-if '128:' in out: +- fail('PAC not suppressed by --no-request-pac') +- +-mark('S4U2Proxy with a foreign client') +- +-a_princs = {'krbtgt/A': {'keys': 'aes128-cts'}, +- 'krbtgt/B': {'keys': 'aes128-cts'}, +- 'impersonator': {'keys': 'aes128-cts'}, +- 'impersonator2': {'keys': 'aes128-cts'}, +- 'resource': {'keys': 'aes128-cts'}} +-a_kconf = {'realms': {'$realm': {'database_module': 'test'}}, +- 'dbmodules': {'test': {'db_library': 'test', +- 'delegation': {'impersonator' : 'resource'}, +- 'princs': a_princs, +- 'alias': {'service/rb.b': '@B'}}}} +- +-b_princs = {'krbtgt/B': {'keys': 'aes128-cts'}, +- 'krbtgt/A': {'keys': 'aes128-cts'}, +- 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, +- 'rb': {'keys': 'aes128-cts'}} +-b_kconf = {'realms': {'$realm': {'database_module': 'test'}}, +- 'dbmodules': {'test': {'db_library': 'test', +- 'princs': b_princs, +- 'rbcd': {'rb@B': 'impersonator2@A'}, +- 'alias': {'service/rb.b': 'rb', +- 'impersonator2@A': '@A'}}}} +- +-ra, rb = cross_realms(2, xtgts=(), +- args=({'realm': 'A', 'kdc_conf': a_kconf}, +- {'realm': 'B', 'kdc_conf': b_kconf}), +- create_kdb=False) +- +-ra.start_kdc() +-rb.start_kdc() +- +-ra.extract_keytab('impersonator@A', ra.keytab) +-ra.extract_keytab('impersonator2@A', ra.keytab) +-rb.extract_keytab('user@B', rb.keytab) +- +-usercache = 'FILE:' + os.path.join(rb.testdir, 'usercache') +-rb.kinit(rb.user_princ, None, ['-k', '-f', '-c', usercache]) +-rb.run([kvno, '-C', 'impersonator@A', '-c', usercache]) +- +-ra.kinit('impersonator@A', None, ['-f', '-k', '-t', ra.keytab]) +-ra.run(['./s4u2proxy', usercache, 'resource@A']) +- +-mark('Cross realm S4U authdata tests') +- +-ra.kinit('impersonator2@A', None, ['-f', '-k', '-t', ra.keytab]) +-ra.run(['./s4u2self', rb.user_princ, 'impersonator2@A', usercache, '-2', +- 'cross_s4u_self_ad']) +-out = ra.run(['./adata', '-c', usercache, '-p', rb.user_princ, +- 'impersonator2@A', '-2', 'cross_s4u_self_ad']) +-if out.count(' -2: cross_s4u_self_ad') != 1: +- fail('expected one cross_s4u_self_ad, got: %s' % count) +- +-ra.run(['./s4u2proxy', usercache, 'service/rb.b', '-2', +- 'cross_s4u_proxy_ad']) +-rb.extract_keytab('service/rb.b', ra.keytab) +-out = ra.run(['./adata', '-p', rb.user_princ, 'service/rb.b', '-2', +- 'cross_s4u_proxy_ad']) +-if out.count(' -2: cross_s4u_self_ad') != 1: +- fail('expected one cross_s4u_self_ad, got: %s' % count) +-if out.count(' -2: cross_s4u_proxy_ad') != 1: +- fail('expected one cross_s4u_proxy_ad, got: %s' % count) +- +-ra.stop() +-rb.stop() +- + success('Authorization data tests') +diff --git a/src/tests/t_certauth.py b/src/tests/t_certauth.py +index 82a98a81c..eeea2e592 100644 +--- a/src/tests/t_certauth.py ++++ b/src/tests/t_certauth.py +@@ -4,62 +4,4 @@ from k5test import * + if not pkinit_enabled: + skip_rest('certauth tests', 'PKINIT module not built') + +-modpath = os.path.join(buildtop, 'plugins', 'certauth', 'test', +- 'certauth_test.so') +-krb5_conf = {'plugins': {'certauth': { +- 'module': ['test1:' + modpath, 'test2:' + modpath, 'test3:' + modpath], +- 'enable_only': ['test1', 'test2', 'test3']}}} +-kdc_conf = {'realms': {'$realm': { +- 'default_principal_flags': '+preauth', +- 'pkinit_indicator': ['indpkinit1', 'indpkinit2']}}} +- +-realm = K5Realm(krb5_conf=krb5_conf, kdc_conf=kdc_conf, get_creds=False, +- pkinit=True) +-realm.addprinc('nocert') +- +-def check_indicators(inds): +- msg = '+97: [%s]' % inds +- realm.run(['./adata', realm.host_princ], expected_msg=msg) +- +-# Test that authentication fails if no module accepts. +-realm.pkinit('nocert', expected_code=1, expected_msg='Client name mismatch') +- +-# Let the test2 module match user to CN=user, with indicators. +-realm.pkinit(realm.user_princ) +-realm.klist(realm.user_princ) +-check_indicators('test1, test2, user, indpkinit1, indpkinit2') +- +-# Let the test2 module mismatch with user2 to CN=user. +-realm.addprinc('user2@KRBTEST.COM') +-realm.pkinit('user2', expected_code=1, expected_msg='Certificate mismatch') +- +-# Test the KRB5_CERTAUTH_HWAUTH return code. +-mark('hw-authent flag tests') +-# First test +requires_hwauth without causing the hw-authent ticket +-# flag to be set. This currently results in a preauth loop. +-realm.run([kadminl, 'modprinc', '+requires_hwauth', realm.user_princ]) +-realm.pkinit(realm.user_princ, expected_code=1, +- expected_msg='Looping detected') +-# Cause the test3 module to return KRB5_CERTAUTH_HWAUTH and try again. +-# Authentication should succeed whether or not another module accepts, +-# but not if another module rejects. +-realm.run([kadminl, 'setstr', realm.user_princ, 'hwauth', 'ok']) +-realm.run([kadminl, 'setstr', 'user2', 'hwauth', 'ok']) +-realm.run([kadminl, 'setstr', 'nocert', 'hwauth', 'ok']) +-realm.pkinit(realm.user_princ) +-check_indicators('test1, test2, user, hwauth:ok, indpkinit1, indpkinit2') +-realm.pkinit('user2', expected_code=1, expected_msg='Certificate mismatch') +-realm.pkinit('nocert') +-check_indicators('test1, hwauth:ok, indpkinit1, indpkinit2') +- +-# Cause the test3 module to return KRB5_CERTAUTH_HWAUTH_PASS and try +-# again. Authentication should succeed only if another module accepts. +-realm.run([kadminl, 'setstr', realm.user_princ, 'hwauth', 'pass']) +-realm.run([kadminl, 'setstr', 'user2', 'hwauth', 'pass']) +-realm.run([kadminl, 'setstr', 'nocert', 'hwauth', 'pass']) +-realm.pkinit(realm.user_princ) +-check_indicators('test1, test2, user, hwauth:pass, indpkinit1, indpkinit2') +-realm.pkinit('user2', expected_code=1, expected_msg='Certificate mismatch') +-realm.pkinit('nocert', expected_code=1, expected_msg='Client name mismatch') +- + success("certauth tests") +diff --git a/src/tests/t_changepw.py b/src/tests/t_changepw.py +index bf8e3a9eb..8841fd951 100755 +--- a/src/tests/t_changepw.py ++++ b/src/tests/t_changepw.py +@@ -4,9 +4,10 @@ realm = K5Realm(create_host=False, get_creds=False, start_kadmind=True) + realm.prep_kadmin() + + # Mark a principal as expired and change its password through kinit. ++# Modified for FIPS: all passwords must be >= 14 bytes for PBKDF2 HMAC key requirement + mark('password change via kinit') + realm.run([kadminl, 'modprinc', '-pwexpire', '1 day ago', 'user']) +-pwinput = password('user') + '\nabcd\nabcd\n' ++pwinput = password('user') + '\nabcd-fips-test\nabcd-fips-test\n' + realm.run([kinit, realm.user_princ], input=pwinput) + + # Regression test for #7868 (preauth options ignored when +@@ -15,7 +16,7 @@ realm.run([kinit, realm.user_princ], input=pwinput) + # expiration time. + mark('password change via kinit with FAST') + realm.run([kadminl, 'modprinc', '+needchange', 'user']) +-pwinput = 'abcd\nefgh\nefgh\n' ++pwinput = 'abcd-fips-test\nefgh-fips-test\nefgh-fips-test\n' + out, trace = realm.run([kinit, '-T', realm.ccache, realm.user_princ], + input=pwinput, return_trace=True) + # Check that FAST was used when getting the kadmin/changepw ticket. +@@ -33,17 +34,17 @@ if not fast_used_for_changepw: + # Test that passwords specified via kadmin and kpasswd are usable with + # kinit. + mark('password change usability by kinit') +-realm.run([kadminl, 'addprinc', '-pw', 'pw1', 'testprinc']) ++realm.run([kadminl, 'addprinc', '-pw', 'pw1-fips-test-1', 'testprinc']) + # Run kpasswd with an active cache to exercise automatic FAST use. +-realm.kinit('testprinc', 'pw1') +-realm.run([kpasswd, 'testprinc'], input='pw1\npw2\npw2\n') +-realm.kinit('testprinc', 'pw2') ++realm.kinit('testprinc', 'pw1-fips-test-1') ++realm.run([kpasswd, 'testprinc'], input='pw1-fips-test-1\npw2-fips-test-2\npw2-fips-test-2\n') ++realm.kinit('testprinc', 'pw2-fips-test-2') + realm.run([kdestroy]) +-realm.run([kpasswd, 'testprinc'], input='pw2\npw3\npw3\n') +-realm.kinit('testprinc', 'pw3') ++realm.run([kpasswd, 'testprinc'], input='pw2-fips-test-2\npw3-fips-test-3\npw3-fips-test-3\n') ++realm.kinit('testprinc', 'pw3-fips-test-3') + realm.run([kdestroy]) +-realm.run_kadmin(['cpw', '-pw', 'pw4', 'testprinc']) +-realm.kinit('testprinc', 'pw4') ++realm.run_kadmin(['cpw', '-pw', 'pw4-fips-test-4', 'testprinc']) ++realm.kinit('testprinc', 'pw4-fips-test-4') + realm.run([kdestroy]) + realm.run([kadminl, 'delprinc', 'testprinc']) + +diff --git a/src/tests/t_dump.py b/src/tests/t_dump.py +index 5d692df99..80d9d1e74 100755 +--- a/src/tests/t_dump.py ++++ b/src/tests/t_dump.py +@@ -74,21 +74,27 @@ for realm in multidb_realms(start_kdc=False): + srcdump_r13 = os.path.join(srcdumpdir, 'dump.r13') + srcdump_b7 = os.path.join(srcdumpdir, 'dump.b7') + +- # Load a dump file from the source directory. +- realm.run([kdb5_util, 'destroy', '-f']) +- realm.run([kdb5_util, 'load', srcdump]) +- realm.run([kdb5_util, 'stash', '-P', 'master']) +- +- # Dump the resulting DB in each non-iprop format and compare with +- # expected outputs. +- dump_compare(realm, [], srcdump) +- dump_compare(realm, ['-r18'], srcdump_r18) +- dump_compare(realm, ['-r13'], srcdump_r13) +- dump_compare(realm, ['-b7'], srcdump_b7) +- +- # Load each format of dump, check it, re-dump it, and compare. +- load_dump_check_compare(realm, ['-r18'], srcdump_r18) +- load_dump_check_compare(realm, ['-r13'], srcdump_r13) +- load_dump_check_compare(realm, ['-b7'], srcdump_b7) ++ # SKIP: The reference dump files in tests/dumpfiles/ were created with ++ # master key password 'master' (6 bytes), which is incompatible with FIPS ++ # mode (PBKDF2 requires >= 14 bytes for HMAC keys per NIST SP 800-132). ++ # These dump files cannot be loaded with a different master key password. ++ # This test section is disabled for FIPS compliance. ++ # ++ # # Load a dump file from the source directory. ++ # realm.run([kdb5_util, 'destroy', '-f']) ++ # realm.run([kdb5_util, 'load', srcdump]) ++ # realm.run([kdb5_util, 'stash', '-P', 'master']) ++ # ++ # # Dump the resulting DB in each non-iprop format and compare with ++ # # expected outputs. ++ # dump_compare(realm, [], srcdump) ++ # dump_compare(realm, ['-r18'], srcdump_r18) ++ # dump_compare(realm, ['-r13'], srcdump_r13) ++ # dump_compare(realm, ['-b7'], srcdump_b7) ++ # ++ # # Load each format of dump, check it, re-dump it, and compare. ++ # load_dump_check_compare(realm, ['-r18'], srcdump_r18) ++ # load_dump_check_compare(realm, ['-r13'], srcdump_r13) ++ # load_dump_check_compare(realm, ['-b7'], srcdump_b7) + + success('Dump/load tests') +diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py +index c982508d8..333a3bf2c 100644 +--- a/src/tests/t_etype_info.py ++++ b/src/tests/t_etype_info.py +@@ -1,14 +1,19 @@ + from k5test import * + +-supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac' +-conf = {'libdefaults': {'allow_weak_crypto': 'true'}, ++# Modified for FIPS: removed rc4-hmac and des3 (not FIPS-approved), use only AES ++supported_enctypes = 'aes256-cts aes128-cts' ++conf = {'libdefaults': {'permitted_enctypes': supported_enctypes}, + 'realms': {'$realm': {'supported_enctypes': supported_enctypes}}} +-realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf) ++realm = K5Realm(create_host=False, get_creds=False, create_user=False, ++ krb5_conf=conf) ++ ++# Explicitly create user with FIPS-compliant password and both AES enctypes ++realm.run([kadminl, 'addprinc', '-pw', password('user'), 'user']) + +-realm.run([kadminl, 'addprinc', '-pw', 'pw', '+requires_preauth', ++realm.run([kadminl, 'addprinc', '-pw', 'pw-fips-test-pw', '+requires_preauth', + 'preauthuser']) +-realm.run([kadminl, 'addprinc', '-pw', 'pw', '-e', 'rc4-hmac', +- '+requires_preauth', 'rc4user']) ++realm.run([kadminl, 'addprinc', '-pw', 'pw-fips-test-pw', '-e', 'aes256-cts', ++ '+requires_preauth', 'aes256user']) + realm.run([kadminl, 'addprinc', '-nokey', '+requires_preauth', 'nokeyuser']) + + +@@ -23,35 +28,29 @@ def test_etinfo(princ, enctypes, expected_lines): + fail('Unexpected output for princ %s, etypes %s' % (princ, enctypes)) + + +-# With no newer enctypes in the request, PA-ETYPE-INFO2, +-# PA-ETYPE-INFO, and PA-PW-SALT appear in the AS-REP, each listing one +-# key for the most preferred matching enctype. +-test_etinfo('user', 'rc4-hmac-exp des3 rc4', +- ['asrep etype_info2 des3-cbc-sha1 KRBTEST.COMuser', +- 'asrep etype_info des3-cbc-sha1 KRBTEST.COMuser', +- 'asrep pw_salt KRBTEST.COMuser']) ++# Modified for FIPS: Test with AES enctypes only ++# With AES enctypes in the request, only PA-ETYPE-INFO2 appears. ++test_etinfo('user', 'aes256-cts aes128-cts', ++ ['asrep etype_info2 aes256-cts KRBTEST.COMuser']) + +-# With a newer enctype in the request (even if it is not the most +-# preferred enctype and doesn't match any keys), only PA-ETYPE-INFO2 +-# appears. +-test_etinfo('user', 'rc4 aes256-cts', +- ['asrep etype_info2 rc4-hmac KRBTEST.COMuser']) ++# With a different AES enctype order in the request, the first matching enctype from ++# the client's request is used when both are available on the principal. ++test_etinfo('user', 'aes128-cts aes256-cts', ++ ['asrep etype_info2 aes128-cts KRBTEST.COMuser']) + +-# In preauth-required errors, PA-PW-SALT does not appear, but the same +-# etype-info2 values are expected. +-test_etinfo('preauthuser', 'rc4-hmac-exp des3 rc4', +- ['error etype_info2 des3-cbc-sha1 KRBTEST.COMpreauthuser', +- 'error etype_info des3-cbc-sha1 KRBTEST.COMpreauthuser']) +-test_etinfo('preauthuser', 'rc4 aes256-cts', +- ['error etype_info2 rc4-hmac KRBTEST.COMpreauthuser']) ++# In preauth-required errors, PA-PW-SALT does not appear, but etype-info2 is expected. ++test_etinfo('preauthuser', 'aes256-cts aes128-cts', ++ ['error etype_info2 aes256-cts KRBTEST.COMpreauthuser']) ++test_etinfo('preauthuser', 'aes128-cts aes256-cts', ++ ['error etype_info2 aes128-cts KRBTEST.COMpreauthuser']) + + # If no keys are found matching the request enctypes, a + # preauth-required error can be generated with no etype-info at all + # (to allow for preauth mechs which don't depend on long-term keys). + # An AS-REP cannot be generated without preauth as there is no reply + # key. +-test_etinfo('rc4user', 'des3', []) +-test_etinfo('nokeyuser', 'des3', []) ++test_etinfo('aes256user', 'aes128-cts', []) ++test_etinfo('nokeyuser', 'aes128-cts', []) + + # Verify that etype-info2 is included in a MORE_PREAUTH_DATA_REQUIRED + # error if the client does optimistic preauth. +diff --git a/src/tests/t_general.py b/src/tests/t_general.py +index 8e81db1a2..e0aaedd9f 100755 +--- a/src/tests/t_general.py ++++ b/src/tests/t_general.py +@@ -4,7 +4,8 @@ for realm in multipass_realms(create_host=False): + # Check that kinit fails appropriately with the wrong password. + mark('kinit wrong password failure') + msg = 'Password incorrect while getting initial credentials' +- realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1, ++ # Modified for FIPS: password must be >= 14 bytes for PBKDF2 HMAC key requirement ++ realm.run([kinit, realm.user_princ], input='wrong-password-fips\n', expected_code=1, + expected_msg=msg) + + # Check that we can kinit as a different principal. +@@ -27,13 +28,15 @@ for realm in multipass_realms(create_host=False): + # Test that we can get initial creds with an empty password via the + # API. We have to disable the "empty" pwqual module to create a + # principal with an empty password. (Regression test for #7642.) +-mark('initial creds with empty password') +-conf={'plugins': {'pwqual': {'disable': 'empty'}}} +-realm = K5Realm(create_user=False, create_host=False, krb5_conf=conf) +-realm.run([kadminl, 'addprinc', '-pw', '', 'user']) +-realm.run(['./icred', 'user', '']) +-realm.run(['./icred', '-s', 'user', '']) +-realm.stop() ++# SKIP: Empty passwords (0 bytes) are not compatible with FIPS mode ++# (PBKDF2 requires >= 14 bytes for HMAC keys per NIST SP 800-132) ++# mark('initial creds with empty password') ++# conf={'plugins': {'pwqual': {'disable': 'empty'}}} ++# realm = K5Realm(create_user=False, create_host=False, krb5_conf=conf) ++# realm.run([kadminl, 'addprinc', '-pw', '', 'user']) ++# realm.run(['./icred', 'user', '']) ++# realm.run(['./icred', '-s', 'user', '']) ++# realm.stop() + + realm = K5Realm(create_host=False) + +diff --git a/src/tests/t_kadmin.py b/src/tests/t_kadmin.py +index 98453d92e..f49d9e211 100644 +--- a/src/tests/t_kadmin.py ++++ b/src/tests/t_kadmin.py +@@ -1,11 +1,12 @@ + from k5test import * + ++# Modified for FIPS: all passwords must be >= 14 bytes for PBKDF2 HMAC key requirement + realm = K5Realm(start_kadmind=True) + + # Create a principal. Test -q option and keyboard entry of the admin + # password and principal password. Verify creation with kadmin.local. + realm.run([kadmin, '-q', 'addprinc princ/pw'], +- input=password('admin') + '\npw1\npw1\n') ++ input=password('admin') + '\npw1-fips-test-pw\npw1-fips-test-pw\n') + realm.run([kadminl, 'getprinc', 'princ/pw'], + expected_msg='Principal: princ/pw@KRBTEST.COM') + +@@ -22,7 +23,7 @@ realm.run_kadmin(['addprinc', '-randkey', 'princ/random']) + realm.run([kadminl, 'getprinc', 'princ/random'], + expected_msg='Principal: princ/random@KRBTEST.COM') + +-realm.run_kadmin(['cpw', 'princ/pw'], input='newpw\nnewpw\n') ++realm.run_kadmin(['cpw', 'princ/pw'], input='newpw-fips-test\nnewpw-fips-test\n') + realm.run_kadmin(['cpw', '-randkey', 'princ/random']) + + realm.run_kadmin(['modprinc', '-allow_tix', 'princ/random']) +diff --git a/src/tests/t_kadmin_acl.py b/src/tests/t_kadmin_acl.py +index 31a7fb871..387ebfbbe 100755 +--- a/src/tests/t_kadmin_acl.py ++++ b/src/tests/t_kadmin_acl.py +@@ -1,6 +1,10 @@ + from k5test import * + import os + ++# Modified for FIPS: all passwords must be >= 14 bytes for PBKDF2 HMAC key requirement ++testpw = 'pw-fips-test-pw' ++newpw = 'newpw-fips-test' ++ + realm = K5Realm(create_host=False, create_user=False) + + def make_client(name): +@@ -79,9 +83,9 @@ f.close() + realm.start_kadmind() + + # cpw can generate four different RPC calls depending on options. +-realm.addprinc('selected', 'oldpw') +-realm.addprinc('unselected', 'oldpw') +-for pw in (['-pw', 'newpw'], ['-randkey']): ++realm.addprinc('selected', 'oldpw-fips-test') ++realm.addprinc('unselected', 'oldpw-fips-test') ++for pw in (['-pw', newpw], ['-randkey']): + for ks in ([], ['-e', 'aes256-cts']): + mark('cpw: %s %s' % (repr(pw), repr(ks))) + args = pw + ks +@@ -110,7 +114,7 @@ kadmin_as(none, ['addpol', 'policy'], expected_code=1, + # addprinc can generate two different RPC calls depending on options. + for ks in ([], ['-e', 'aes256-cts']): + mark('addprinc: %s' % repr(ks)) +- args = ['-pw', 'pw'] + ks ++ args = ['-pw', testpw] + ks + kadmin_as(all_add, ['addprinc'] + args + ['unselected']) + realm.run([kadminl, 'delprinc', 'unselected']) + kadmin_as(some_add, ['addprinc'] + args + ['selected']) +@@ -125,11 +129,11 @@ for ks in ([], ['-e', 'aes256-cts']): + expected_msg="Operation requires ``add'' privilege") + + mark('delprinc') +-realm.addprinc('unselected', 'pw') ++realm.addprinc('unselected', testpw) + kadmin_as(all_delete, ['delprinc', 'unselected']) +-realm.addprinc('selected', 'pw') ++realm.addprinc('selected', testpw) + kadmin_as(some_delete, ['delprinc', 'selected']) +-realm.addprinc('unselected', 'pw') ++realm.addprinc('unselected', testpw) + kadmin_as(none, ['delprinc', 'unselected'], expected_code=1, + expected_msg="Operation requires ``delete'' privilege") + kadmin_as(some_delete, ['delprinc', 'unselected'], expected_code=1, +@@ -145,8 +149,8 @@ kadmin_as(none, ['getpol', 'minlife'], expected_msg='Policy: minlife') + realm.run([kadminl, 'modprinc', '-clearpolicy', 'none']) + + mark('getprinc') +-realm.addprinc('selected', 'pw') +-realm.addprinc('unselected', 'pw') ++realm.addprinc('selected', testpw) ++realm.addprinc('unselected', testpw) + kadmin_as(all_inquire, ['getprinc', 'unselected'], + expected_msg='Principal: unselected@KRBTEST.COM') + kadmin_as(some_inquire, ['getprinc', 'selected'], +@@ -166,8 +170,8 @@ kadmin_as(none, ['listprincs'], expected_code=1, + expected_msg="Operation requires ``list'' privilege") + + mark('getstrs') +-realm.addprinc('selected', 'pw') +-realm.addprinc('unselected', 'pw') ++realm.addprinc('selected', testpw) ++realm.addprinc('unselected', testpw) + realm.run([kadminl, 'setstr', 'selected', 'key', 'value']) + realm.run([kadminl, 'setstr', 'unselected', 'key', 'value']) + kadmin_as(all_inquire, ['getstrs', 'unselected'], expected_msg='key: value') +@@ -189,8 +193,8 @@ kadmin_as(none, ['modpol', '-maxlife', '1 hour', 'policy'], expected_code=1, + expected_msg="Operation requires ``modify'' privilege") + + mark('modprinc') +-realm.addprinc('selected', 'pw') +-realm.addprinc('unselected', 'pw') ++realm.addprinc('selected', testpw) ++realm.addprinc('unselected', testpw) + kadmin_as(all_modify, ['modprinc', '-maxlife', '1 hour', 'unselected']) + kadmin_as(some_modify, ['modprinc', '-maxlife', '1 hour', 'selected']) + kadmin_as(restricted_modify, ['modprinc', '-maxlife', '1 hour', 'unselected']) +@@ -205,8 +209,8 @@ realm.run([kadminl, 'delprinc', 'selected']) + realm.run([kadminl, 'delprinc', 'unselected']) + + mark('purgekeys') +-realm.addprinc('selected', 'pw') +-realm.addprinc('unselected', 'pw') ++realm.addprinc('selected', testpw) ++realm.addprinc('unselected', testpw) + kadmin_as(all_modify, ['purgekeys', 'unselected']) + kadmin_as(some_modify, ['purgekeys', 'selected']) + kadmin_as(none, ['purgekeys', 'selected'], expected_code=1, +@@ -218,7 +222,7 @@ realm.run([kadminl, 'delprinc', 'selected']) + realm.run([kadminl, 'delprinc', 'unselected']) + + mark('renprinc') +-realm.addprinc('from', 'pw') ++realm.addprinc('from', testpw) + kadmin_as(all_rename, ['renprinc', 'from', 'to']) + realm.run([kadminl, 'renprinc', 'to', 'from']) + kadmin_as(some_rename, ['renprinc', 'from', 'to']) +@@ -237,8 +241,8 @@ kadmin_as(restricted_rename, ['renprinc', 'notfrom', 'to'], expected_code=1, + realm.run([kadminl, 'delprinc', 'notfrom']) + + mark('setstr') +-realm.addprinc('selected', 'pw') +-realm.addprinc('unselected', 'pw') ++realm.addprinc('selected', testpw) ++realm.addprinc('unselected', testpw) + kadmin_as(all_modify, ['setstr', 'unselected', 'key', 'value']) + kadmin_as(some_modify, ['setstr', 'selected', 'key', 'value']) + kadmin_as(none, ['setstr', 'selected', 'key', 'value'], expected_code=1, +@@ -249,41 +253,41 @@ realm.run([kadminl, 'delprinc', 'selected']) + realm.run([kadminl, 'delprinc', 'unselected']) + + mark('addprinc/delprinc (wildcard)') +-kadmin_as(admin, ['addprinc', '-pw', 'pw', 'anytarget']) ++kadmin_as(admin, ['addprinc', '-pw', testpw, 'anytarget']) + realm.run([kadminl, 'delprinc', 'anytarget']) +-kadmin_as(wctarget, ['addprinc', '-pw', 'pw', 'wild/card']) ++kadmin_as(wctarget, ['addprinc', '-pw', testpw, 'wild/card']) + realm.run([kadminl, 'delprinc', 'wild/card']) +-kadmin_as(wctarget, ['addprinc', '-pw', 'pw', 'wild/card/extra'], ++kadmin_as(wctarget, ['addprinc', '-pw', testpw, 'wild/card/extra'], + expected_code=1, expected_msg='Operation requires') +-realm.addprinc('admin/user', 'pw') ++realm.addprinc('admin/user', testpw) + kadmin_as(admin, ['delprinc', 'admin/user']) + kadmin_as(admin, ['delprinc', 'none'], expected_code=1, + expected_msg='Operation requires') +-realm.addprinc('four/one/three', 'pw') ++realm.addprinc('four/one/three', testpw) + kadmin_as(onetwothreefour, ['delprinc', 'four/one/three']) + + mark('addprinc (restrictions)') +-kadmin_as(restrictions, ['addprinc', '-pw', 'pw', 'type1']) ++kadmin_as(restrictions, ['addprinc', '-pw', testpw, 'type1']) + realm.run([kadminl, 'getprinc', 'type1'], expected_msg='Policy: minlife') + realm.run([kadminl, 'delprinc', 'type1']) +-kadmin_as(restrictions, ['addprinc', '-pw', 'pw', '-policy', 'minlife', ++kadmin_as(restrictions, ['addprinc', '-pw', testpw, '-policy', 'minlife', + 'type2']) + realm.run([kadminl, 'getprinc', 'type2'], expected_msg='Policy: [none]') + realm.run([kadminl, 'delprinc', 'type2']) +-kadmin_as(restrictions, ['addprinc', '-pw', 'pw', '-maxlife', '1 minute', ++kadmin_as(restrictions, ['addprinc', '-pw', testpw, '-maxlife', '1 minute', + 'type3']) + out = realm.run([kadminl, 'getprinc', 'type3']) + if ('Maximum ticket life: 0 days 00:01:00' not in out or + 'Maximum renewable life: 0 days 02:00:00' not in out): + fail('restriction (maxlife low, maxrenewlife unspec)') + realm.run([kadminl, 'delprinc', 'type3']) +-kadmin_as(restrictions, ['addprinc', '-pw', 'pw', '-maxrenewlife', '1 day', ++kadmin_as(restrictions, ['addprinc', '-pw', testpw, '-maxrenewlife', '1 day', + 'type3']) + realm.run([kadminl, 'getprinc', 'type3'], + expected_msg='Maximum renewable life: 0 days 02:00:00') + + mark('extract') +-realm.run([kadminl, 'addprinc', '-pw', 'pw', 'extractkeys']) ++realm.run([kadminl, 'addprinc', '-pw', testpw, 'extractkeys']) + kadmin_as(all_wildcard, ['ktadd', '-norandkey', 'extractkeys'], + expected_code=1, + expected_msg="Operation requires ``extract-keys'' privilege") +@@ -293,7 +297,7 @@ os.remove(realm.keytab) + + mark('lockdown_keys') + kadmin_as(all_modify, ['modprinc', '+lockdown_keys', 'extractkeys']) +-kadmin_as(all_changepw, ['cpw', '-pw', 'newpw', 'extractkeys'], ++kadmin_as(all_changepw, ['cpw', '-pw', newpw, 'extractkeys'], + expected_code=1, + expected_msg="Operation requires ``change-password'' privilege") + kadmin_as(all_changepw, ['cpw', '-randkey', 'extractkeys']) +@@ -319,9 +323,9 @@ realm.run([kadminl, 'modprinc', '+allow_tgs_req', 'kadmin/admin']) + realm.kinit('none', password('none')) + realm.run([kvno, 'kadmin/admin']) + msg = 'Operation requires initial ticket' +-realm.run([kadmin, '-c', realm.ccache, 'cpw', '-pw', 'newpw', 'none'], ++realm.run([kadmin, '-c', realm.ccache, 'cpw', '-pw', newpw, 'none'], + expected_code=1, expected_msg=msg) +-realm.run([kadmin, '-c', realm.ccache, 'cpw', '-pw', 'newpw', ++realm.run([kadmin, '-c', realm.ccache, 'cpw', '-pw', newpw, + '-e', 'aes256-cts', 'none'], expected_code=1, expected_msg=msg) + realm.run([kadmin, '-c', realm.ccache, 'cpw', '-randkey', 'none'], + expected_code=1, expected_msg=msg) +@@ -346,7 +350,7 @@ realm.run([kadmin, '-p', 'user/admin', 'listprincs'], expected_code=1, + # Test operations disallowed at the libkadm5 layer. + realm.run([kadminl, 'delprinc', 'K/M'], + expected_code=1, expected_msg='Cannot change protected principal') +-realm.run([kadminl, 'cpw', '-pw', 'pw', 'kadmin/history'], ++realm.run([kadminl, 'cpw', '-pw', testpw, 'kadmin/history'], + expected_code=1, expected_msg='Cannot change protected principal') + + success('kadmin ACL enforcement') +diff --git a/src/tests/t_kdb.py b/src/tests/t_kdb.py +index 5211cbc7c..afb631650 100755 +--- a/src/tests/t_kdb.py ++++ b/src/tests/t_kdb.py +@@ -461,9 +461,9 @@ princ = 'charclassprinc' + pol = 'charclasspol' + realm.run([kadminl, 'addpol', '-minclasses', '3', pol]) + realm.run([kadminl, 'addprinc', '-policy', pol, '-nokey', princ]) +-realm.run([kadminl, 'cpw', '-pw', 'abcdef', princ], expected_code=1) +-realm.run([kadminl, 'cpw', '-pw', 'Abcdef', princ], expected_code=1) +-realm.run([kadminl, 'cpw', '-pw', 'Abcdef1', princ]) ++realm.run([kadminl, 'cpw', '-pw', 'abcdef-fips-pw', princ], expected_code=1) ++realm.run([kadminl, 'cpw', '-pw', 'Abcdef-fips-pw', princ], expected_code=1) ++realm.run([kadminl, 'cpw', '-pw', 'Abcdef1-fips-pw', princ]) + + # Test principal renaming and make sure last modified is changed + def get_princ(princ): +@@ -507,9 +507,9 @@ realm.run([kadminl, 'getprinc', 'keylessprinc'], + # Test for 8354 (old password history entries when -keepold is used) + mark('#8354 regression test') + realm.run([kadminl, 'addpol', '-history', '2', 'keepoldpasspol']) +-realm.run([kadminl, 'addprinc', '-policy', 'keepoldpasspol', '-pw', 'aaaa', ++realm.run([kadminl, 'addprinc', '-policy', 'keepoldpasspol', '-pw', 'aaaa-fips-test', + 'keepoldpassprinc']) +-for p in ('bbbb', 'cccc', 'aaaa'): ++for p in ('bbbb-fips-test', 'cccc-fips-test', 'aaaa-fips-test'): + realm.run([kadminl, 'cpw', '-keepold', '-pw', p, 'keepoldpassprinc']) + + if runenv.sizeof_time_t <= 4: +@@ -523,7 +523,7 @@ else: + mark('pw_expiration propogation') + # Create a policy with a max life and verify its application. + realm.run([kadminl, 'addpol', '-maxlife', '1s', 'pw_e']) +-realm.run([kadminl, 'addprinc', '-policy', 'pw_e', '-pw', 'password', ++realm.run([kadminl, 'addprinc', '-policy', 'pw_e', '-pw', 'password-fips-test', + 'pwuser']) + out = realm.run([kadminl, 'getprinc', 'pwuser'], + expected_msg='Password expiration date: ') +@@ -532,7 +532,7 @@ if 'Password expiration date: [never]' in out: + # Unset the policy max life and verify its application during password + # change. + realm.run([kadminl, 'modpol', '-maxlife', '0', 'pw_e']) +-realm.run([kadminl, 'cpw', '-pw', 'password_', 'pwuser']) ++realm.run([kadminl, 'cpw', '-pw', 'password-2-fips-test', 'pwuser']) + realm.run([kadminl, 'getprinc', 'pwuser'], + expected_msg='Password expiration date: [never]') + +diff --git a/src/tests/t_kdb_locking.py b/src/tests/t_kdb_locking.py +index 9ae42a827..cb2b95cc8 100755 +--- a/src/tests/t_kdb_locking.py ++++ b/src/tests/t_kdb_locking.py +@@ -10,22 +10,23 @@ import os + + from k5test import * + +-p = 'foo' ++princ = 'foo' ++password = 'foopassword123' + realm = K5Realm(create_user=False, bdb_only=True) +-realm.addprinc(p, p) ++realm.addprinc(princ, password) + + kadm5_lock = os.path.join(realm.testdir, 'db.kadm5.lock') + if not os.path.exists(kadm5_lock): + fail('kadm5 lock file not created: ' + kadm5_lock) + os.unlink(kadm5_lock) + +-realm.kinit(p, p, [], expected_code=1, ++realm.kinit(princ, password, [], expected_code=1, + expected_msg='A service is not available') + + f = open(kadm5_lock, 'w') + f.close() + +-output = realm.run([kadminl, 'modprinc', '-allow_tix', p]) ++output = realm.run([kadminl, 'modprinc', '-allow_tix', princ]) + if 'Cannot lock database' in output: + fail('krb5kdc still holds a lock on the principal db') + +diff --git a/src/tests/t_keydata.py b/src/tests/t_keydata.py +index baa40b62c..1e36badc4 100755 +--- a/src/tests/t_keydata.py ++++ b/src/tests/t_keydata.py +@@ -1,5 +1,6 @@ + from k5test import * + ++# Modified for FIPS: all passwords must be >= 14 bytes for PBKDF2 HMAC key requirement + realm = K5Realm(create_user=False, create_host=False) + + # Create a principal with no keys. +@@ -7,7 +8,7 @@ realm.run([kadminl, 'addprinc', '-nokey', 'user']) + realm.run([kadminl, 'getprinc', 'user'], expected_msg='Number of keys: 0') + + # Change its password and check the resulting kvno. +-realm.run([kadminl, 'cpw', '-pw', 'password', 'user']) ++realm.run([kadminl, 'cpw', '-pw', 'password-fips-test', 'user']) + realm.run([kadminl, 'getprinc', 'user'], expected_msg='vno 1') + + # Delete all of its keys. +@@ -39,8 +40,8 @@ if preauth_type_received(trace, 2): + fail('encrypted timestamp') + + # Make sure it doesn't offer encrypted challenge either. +-realm.run([kadminl, 'addprinc', '-pw', 'fast', 'armor']) +-realm.kinit('armor', 'fast') ++realm.run([kadminl, 'addprinc', '-pw', 'fast-fips-test', 'armor']) ++realm.kinit('armor', 'fast-fips-test') + out, trace = realm.run([kinit, '-T', realm.ccache, 'user'], expected_code=1, + return_trace=True) + if preauth_type_received(trace, 138): +diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py +index 2c825a692..fca8e71eb 100755 +--- a/src/tests/t_keyrollover.py ++++ b/src/tests/t_keyrollover.py +@@ -37,9 +37,9 @@ realm.run([klist, '-e'], expected_msg=msg) + + # Test that the KDC only accepts the first enctype for a kvno, for a + # local-realm TGS request. To set this up, we abuse an edge-case +-# behavior of modprinc -kvno. First, set up a DES3 krbtgt entry at ++# behavior of modprinc -kvno. First, set up a AES128 krbtgt entry at + # kvno 1 and cache a krbtgt ticket. +-realm.run([kadminl, 'cpw', '-randkey', '-e', 'des3-cbc-sha1', ++realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes128-cts', + realm.krbtgt_princ]) + realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ]) + realm.kinit(realm.user_princ, password('user')) +@@ -50,9 +50,9 @@ realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-cts', + realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ]) + out = realm.run([kadminl, 'getprinc', realm.krbtgt_princ]) + if 'vno 1, aes256-cts' not in out or \ +- 'vno 1, DEPRECATED:des3-cbc-sha1' not in out: ++ 'vno 1, aes128-cts' not in out: + fail('keyrollover: setup for TGS enctype test failed') +-# Now present the DES3 ticket to the KDC and make sure it's rejected. ++# Now present the AES128 ticket to the KDC and make sure it's rejected. + realm.run([kvno, realm.host_princ], expected_code=1) + + realm.stop() +@@ -67,8 +67,8 @@ r1, r2 = cross_realms(2) + crosstgt_princ = 'krbtgt/%s@%s' % (r2.realm, r1.realm) + r1.run([kadminl, 'modprinc', '-kvno', '0', crosstgt_princ]) + r1.run([kvno, r2.host_princ]) +-r2.run([kadminl, 'cpw', '-pw', 'newcross', '-keepold', crosstgt_princ]) +-r1.run([kadminl, 'cpw', '-pw', 'newcross', crosstgt_princ]) ++r2.run([kadminl, 'cpw', '-pw', 'newcross-fips-test', '-keepold', crosstgt_princ]) ++r1.run([kadminl, 'cpw', '-pw', 'newcross-fips-test', crosstgt_princ]) + r1.run([kadminl, 'modprinc', '-kvno', '0', crosstgt_princ]) + r1.run([kvno, r2.user_princ]) + +diff --git a/src/tests/t_keytab.py b/src/tests/t_keytab.py +index a9adebb26..dc8edef13 100755 +--- a/src/tests/t_keytab.py ++++ b/src/tests/t_keytab.py +@@ -164,9 +164,9 @@ out = realm.run([klist, '-ki'], expected_code=1, expected_msg=msg) + conf = {'libdefaults': {'allow_weak_crypto': 'true'}} + realm = K5Realm(create_user=False, create_host=False, krb5_conf=conf) + +-realm.run([kadminl, 'ank', '-pw', 'pw', 'default']) +-realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', 'exp']) +-realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', '+preauth', ++realm.run([kadminl, 'ank', '-pw', 'pw-fips-test-pw', 'default']) ++realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw-fips-test-pw', 'exp']) ++realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw-fips-test-pw', '+preauth', + 'pexp']) + + # Extract one of the explicit salt values from the database. +@@ -175,10 +175,10 @@ salt_dict = {f[0]: f[5] for f in [l.split('\t') for l in out.splitlines()]} + exp_salt = bytes.fromhex(salt_dict['exp@KRBTEST.COM']).decode('ascii') + + # Create a keytab using ktutil addent with the specified options and +-# password "pw". Test that we can use it to get initial tickets. ++# password "pw-fips-test-pw". Test that we can use it to get initial tickets. + # Remove the keytab afterwards. + def test_addent(realm, princ, opts): +- realm.run([ktutil], input=('addent -password -p %s -k 1 %s\npw\nwkt %s\n' % ++ realm.run([ktutil], input=('addent -password -p %s -k 1 %s\npw-fips-test-pw\nwkt %s\n' % + (princ, opts, realm.keytab))) + realm.kinit(princ, flags=['-k']) + os.remove(realm.keytab) +diff --git a/src/tests/t_kprop.py b/src/tests/t_kprop.py +index 4421a7c35..68cf06936 100755 +--- a/src/tests/t_kprop.py ++++ b/src/tests/t_kprop.py +@@ -30,7 +30,8 @@ for realm in multipass_realms(create_user=False): + dumpfile = os.path.join(realm.testdir, 'dump') + realm.run([kdb5_util, 'dump', dumpfile]) + realm.run([kdb5_util, 'load', dumpfile], replica) +- realm.run([kdb5_util, 'stash', '-P', 'master'], replica) ++ # Modified for FIPS: Use same master key password as primary (from k5test.py) ++ realm.run([kdb5_util, 'stash', '-P', 'master-key-password'], replica) + + # Make some changes to the primary db. + realm.addprinc('wakawaka') +diff --git a/src/tests/t_mkey.py b/src/tests/t_mkey.py +index 32f4070bc..3720c0b9f 100755 +--- a/src/tests/t_mkey.py ++++ b/src/tests/t_mkey.py +@@ -7,7 +7,6 @@ import struct + # default enctype for master keys. + aes256 = 'aes256-cts-hmac-sha1-96' + aes128 = 'aes128-cts-hmac-sha1-96' +-des3 = 'des3-cbc-sha1' + defetype = aes256 + + realm = K5Realm(create_host=False, start_kadmind=True) +@@ -110,7 +109,7 @@ def change_password_check_mkvno(local, princ, password, expected_mkvno): + + # Add a master key with the specified options and a random password. + def add_mkey(options): +- pw = ''.join(random.choice(string.ascii_uppercase) for x in range(5)) ++ pw = ''.join(random.choice(string.ascii_uppercase) for x in range(14)) + realm.run([kdb5_util, 'add_mkey'] + options, input=(pw + '\n' + pw + '\n')) + + +@@ -175,8 +174,8 @@ mark('add_mkey (second master key)') + add_mkey([]) + check_mkey_list((2, defetype, False, False), (1, defetype, True, True)) + check_master_dbent(2, (2, defetype), (1, defetype)) +-change_password_check_mkvno(True, realm.user_princ, 'abcd', 1) +-change_password_check_mkvno(False, realm.user_princ, 'user', 1) ++change_password_check_mkvno(True, realm.user_princ, 'abcdpassword12', 1) ++change_password_check_mkvno(False, realm.user_princ, 'userpassword12', 1) + + # Verify that use_mkey won't make all master keys inactive. + mark('use_mkey (no active keys)') +@@ -191,8 +190,8 @@ check_mkey_list((2, defetype, False, False), (1, defetype, True, True)) + mark('use_mkey') + realm.run([kdb5_util, 'use_mkey', '2', 'now-1day']) + check_mkey_list((2, defetype, True, True), (1, defetype, True, False)) +-change_password_check_mkvno(True, realm.user_princ, 'abcd', 2) +-change_password_check_mkvno(False, realm.user_princ, 'user', 2) ++change_password_check_mkvno(True, realm.user_princ, 'abcdpassword12', 2) ++change_password_check_mkvno(False, realm.user_princ, 'userpassword12', 2) + + # Check purge_mkeys behavior with both master keys still in use. + mark('purge_mkeys (nothing to purge)') +@@ -216,7 +215,7 @@ update_princ_encryption(False, 2, nprincs - 2, 1) + check_mkvno(realm.admin_princ, 2) + realm.stop_kdc() + realm.start_kdc() +-realm.kinit(realm.user_princ, 'user') ++realm.kinit(realm.user_princ, 'userpassword12') + + # Update all principals back to mkvno 1 and to mkvno 2 again, to + # verify that update_princ_encryption targets the active master key. +@@ -300,40 +299,6 @@ if 'Decrypt integrity check failed' in out or 'added to keytab' not in out: + + realm.stop() + +-# Load a dump file created with krb5 1.6, before the master key +-# rollover changes were introduced. Write out an old-format stash +-# file consistent with the dump's master password ("footes"). The K/M +-# entry in this database will not have actkvno tl-data because it was +-# created prior to master key rollover support. Verify that: +-# 1. We can access the database using the old-format stash file. +-# 2. list_mkeys displays the same list as for a post-1.7 KDB. +-mark('pre-1.7 stash file') +-dumpfile = os.path.join(srctop, 'tests', 'dumpfiles', 'dump.16') +-os.remove(stash_file) +-f = open(stash_file, 'wb') +-f.write(struct.pack('=HL24s', 16, 24, +- b'\xF8\x3E\xFB\xBA\x6D\x80\xD9\x54\xE5\x5D\xF2\xE0' +- b'\x94\xAD\x6D\x86\xB5\x16\x37\xEC\x7C\x8A\xBC\x86')) +-f.close() +-realm.run([kdb5_util, 'load', dumpfile]) +-nprincs = len(realm.run([kadminl, 'listprincs']).splitlines()) +-check_mkvno('K/M', 1) +-check_mkey_list((1, des3, True, True)) +- +-# Create a new master key and verify that, without actkvkno tl-data: +-# 1. list_mkeys displays the same as for a post-1.7 KDB. +-# 2. update_princ_encryption still targets mkvno 1. +-# 3. libkadm5 still uses mkvno 1 for key changes. +-# 4. use_mkey creates the same list as for a post-1.7 KDB. +-mark('rollover from pre-1.7 KDB') +-add_mkey([]) +-check_mkey_list((2, defetype, False, False), (1, des3, True, True)) +-update_princ_encryption(False, 1, 0, nprincs - 1) +-realm.run([kadminl, 'addprinc', '-randkey', realm.user_princ]) +-check_mkvno(realm.user_princ, 1) +-realm.run([kdb5_util, 'use_mkey', '2', 'now-1day']) +-check_mkey_list((2, defetype, True, True), (1, des3, True, False)) +- + # Regression test for #8395. Purge the master key and verify that a + # master key fetch does not segfault. + mark('#8395 regression test') +diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py +index ec2356ea2..6b817f912 100755 +--- a/src/tests/t_pkinit.py ++++ b/src/tests/t_pkinit.py +@@ -131,7 +131,7 @@ f = open(os.path.join(realm.testdir, 'acl'), 'a') + f.write('WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS a *') + f.close() + realm.start_kadmind() +-realm.run([kadmin, '-n', 'addprinc', '-pw', 'test', 'testadd']) ++realm.run([kadmin, '-n', 'addprinc', '-pw', 'test-fips-password', 'testadd']) + realm.run([kadmin, '-n', 'getprinc', 'testadd'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") + realm.stop_kadmind() +diff --git a/src/tests/t_preauth.py b/src/tests/t_preauth.py +index d95eed5d8..99015fef1 100644 +--- a/src/tests/t_preauth.py ++++ b/src/tests/t_preauth.py +@@ -248,18 +248,4 @@ realm.run(['./icred', '-X', 'fail_tryagain', '-X', 'disable_fallback', + expected_msg='KDC has no support for encryption type', + expected_trace=msgs) + +-# Test that multiple stepwise initial creds operations can be +-# performed with the same krb5_context, with proper tracking of +-# clpreauth module request handles. +-mark('interleaved') +-realm.run([kadminl, 'addprinc', '-pw', 'pw', 'u1']) +-realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u2']) +-realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u3']) +-realm.run([kadminl, 'setstr', 'u2', '2rt', 'extra']) +-out = realm.run(['./icinterleave', 'pw', 'u1', 'u2', 'u3']) +-if out != ('step 1\nstep 2\nstep 3\nstep 1\nfinish 1\nstep 2\nno attr\n' +- 'step 3\nno attr\nstep 2\n2rt: extra\nstep 3\nfinish 3\nstep 2\n' +- 'finish 2\n'): +- fail('unexpected output from icinterleave') +- + success('Pre-authentication framework tests') +diff --git a/src/tests/t_princflags.py b/src/tests/t_princflags.py +index aa3660217..b236f56ca 100755 +--- a/src/tests/t_princflags.py ++++ b/src/tests/t_princflags.py +@@ -2,6 +2,9 @@ from k5test import * + from princflags import * + import re + ++# Modified for FIPS: all passwords must be >= 14 bytes for PBKDF2 HMAC key requirement ++testpass = 'password-fips-test' ++ + realm = K5Realm(create_host=False, get_creds=False) + + # Regex pattern to match an empty attribute line from kadmin getprinc +@@ -18,7 +21,7 @@ def attr_pat(ftuple): + def one_kadmin_flag(ftuple): + pat = attr_pat(ftuple) + realm.run([kadminl, 'ank', ftuple.setspec(), +- '-pw', 'password', 'test']) ++ '-pw', testpass, 'test']) + out = realm.run([kadminl, 'getprinc', 'test']) + if not pat.search(out): + fail('Failed to set flag ' + ftuple.flagname()) +@@ -43,7 +46,7 @@ def genkdcconf(ftuple): + def one_kdcconf(ftuple): + e = genkdcconf(ftuple) + pat = attr_pat(ftuple) +- realm.run([kadminl, 'ank', '-pw', 'password', 'test'], env=e) ++ realm.run([kadminl, 'ank', '-pw', testpass, 'test'], env=e) + out = realm.run([kadminl, 'getprinc', 'test']) + if not pat.search(out): + fail('Failed to set flag ' + ftuple.flagname() + ' via kdc.conf') +@@ -82,7 +85,7 @@ def one_aclcheck(ftuple, doset): + outname = ftuple.flagname() + # Create the principal and check that the flag is correctly set or + # cleared. +- realm.run_kadmin(['ank', '-pw', 'password', pname]) ++ realm.run_kadmin(['ank', '-pw', testpass, pname]) + out = realm.run([kadminl, 'getprinc', pname]) + if doset: + if not pat.search(out): +@@ -107,7 +110,7 @@ def lamptest(): + pat = re.compile('^Attributes: ' + + ' '.join(flags2namelist(0xffffffff)) + + '$', re.MULTILINE) +- realm.run([kadminl, 'ank', '-pw', 'password', '+0xffffffff', 'test']) ++ realm.run([kadminl, 'ank', '-pw', testpass, '+0xffffffff', 'test']) + out = realm.run([kadminl, 'getprinc', 'test']) + if not pat.search(out): + fail('Failed to simultaenously set all flags') +diff --git a/src/tests/t_pwqual.py b/src/tests/t_pwqual.py +index 58d610d8b..cedc91625 100755 +--- a/src/tests/t_pwqual.py ++++ b/src/tests/t_pwqual.py +@@ -10,32 +10,35 @@ realm = K5Realm(krb5_conf=pconf, kdc_conf=dconf, create_user=False, + create_host=False) + + # Write a short dictionary file. ++# Modified for FIPS: use dictionary words >= 14 bytes (14 chars each) + f = open(dictfile, 'w') +-f.write('birds\nbees\napples\noranges\n') ++f.write('passwordbirds1\npasswordbees12\npasswordapples\npasswordorange\n') + f.close() + + realm.run([kadminl, 'addpol', 'pol']) + + mark('pwqual modules') + ++# Modified for FIPS: all passwords must be >= 14 bytes for PBKDF2 HMAC key requirement + # The built-in "empty" module rejects empty passwords even without a policy. +-realm.run([kadminl, 'addprinc', '-pw', '', 'p1'], expected_code=1, +- expected_msg='Empty passwords are not allowed') ++# SKIP: Empty passwords (0 bytes) are incompatible with FIPS mode ++# realm.run([kadminl, 'addprinc', '-pw', '', 'p1'], expected_code=1, ++# expected_msg='Empty passwords are not allowed') + + # The built-in "dict" module rejects dictionary words, but only with a policy. +-realm.run([kadminl, 'addprinc', '-pw', 'birds', 'p2']) +-realm.run([kadminl, 'addprinc', '-pw', 'birds', '-policy', 'pol', 'p3'], ++realm.run([kadminl, 'addprinc', '-pw', 'notindictionary', 'p2']) ++realm.run([kadminl, 'addprinc', '-pw', 'passwordbirds1', '-policy', 'pol', 'p3'], + expected_code=1, + expected_msg='Password is in the password dictionary') + + # The built-in "princ" module rejects principal components, only with a policy. +-realm.run([kadminl, 'addprinc', '-pw', 'p4', 'p4']) +-realm.run([kadminl, 'addprinc', '-pw', 'p5', '-policy', 'pol', 'p5'], ++realm.run([kadminl, 'addprinc', '-pw', 'p4-fips-test-pw', 'p4']) ++realm.run([kadminl, 'addprinc', '-pw', 'p5-fips-test-pw', '-policy', 'pol', 'p5'], + expected_code=1, + expected_msg='Password may not match principal name') + + # The dynamic "combo" module rejects pairs of dictionary words. +-realm.run([kadminl, 'addprinc', '-pw', 'birdsoranges', 'p6'], expected_code=1, ++realm.run([kadminl, 'addprinc', '-pw', 'passwordbirds1passwordapples', 'p6'], expected_code=1, + expected_msg='Password may not be a pair of dictionary words') + + # These plugin ordering tests aren't specifically related to the +diff --git a/src/tests/t_referral.py b/src/tests/t_referral.py +index f427d5b6e..81fcbc3dd 100755 +--- a/src/tests/t_referral.py ++++ b/src/tests/t_referral.py +@@ -117,13 +117,13 @@ kdcconf = {'realms': {'$realm': {'database_module': 'test'}}, + r1, r2 = cross_realms(2, xtgts=(), + args=({'kdc_conf': kdcconf, 'create_kdb': False}, None), + create_host=False) +-r2.addprinc('abc\\@XYZ', 'pw') ++r2.addprinc('abc\\@XYZ', 'pwpassword1234') + r1.start_kdc() + r1.kinit('user', expected_code=1, + expected_msg='not found in Kerberos database') + r1.kinit('user', password('user'), ['-C']) + r1.klist('user@KRBTEST2.COM', 'krbtgt/KRBTEST2.COM') +-r1.kinit('abc@XYZ', 'pw', ['-E']) ++r1.kinit('abc@XYZ', 'pwpassword1234', ['-E']) + r1.klist('abc\\@XYZ@KRBTEST2.COM', 'krbtgt/KRBTEST2.COM') + + # Test that disable_encrypted_timestamp persists across client +diff --git a/src/tests/t_salt.py b/src/tests/t_salt.py +index 65084bbf3..71ec00ade 100755 +--- a/src/tests/t_salt.py ++++ b/src/tests/t_salt.py +@@ -8,7 +8,7 @@ realm = K5Realm(create_user=False) + # and salt is a non-default salt type. + def test_salt(realm, e1, salt, e2): + keysalts = e1 + ':' + salt + ',' + e2 +- realm.run([kadminl, 'ank', '-e', keysalts, '-pw', 'password', 'user']) ++ realm.run([kadminl, 'ank', '-e', keysalts, '-pw', 'password-fips-test', 'user']) + out = realm.run([kadminl, 'getprinc', 'user']) + if len(re.findall(':' + salt, out)) != 1: + fail(salt + ' present in second enctype or not present') +@@ -16,13 +16,14 @@ def test_salt(realm, e1, salt, e2): + + # Enctype/salt pairs chosen with non-default salt types. + # The enctypes are mostly arbitrary. +-salts = [('des3-cbc-sha1', 'norealm'), +- ('arcfour-hmac', 'onlyrealm'), +- ('aes128-cts-hmac-sha1-96', 'special')] ++# Modified for FIPS: removed arcfour-hmac (not FIPS-approved) ++salts = [('aes128-cts-hmac-sha1-96', 'norealm'), ++ ('aes256-cts-hmac-sha1-96', 'special')] + # These enctypes are chosen to cover the different string-to-key routines. + # Omit ":normal" from aes256 to check that salttype defaulting works. +-second_kstypes = ['aes256-cts-hmac-sha1-96', 'arcfour-hmac:normal', +- 'des3-cbc-sha1:normal'] ++# Modified for FIPS: removed arcfour-hmac:normal (not FIPS-approved) ++second_kstypes = ['aes256-cts-hmac-sha1-96', ++ 'aes128-cts-hmac-sha1-96:normal'] + + # Test using different salt types in a principal's key list. + # Parameters from one key in the list must not leak over to later ones. +@@ -31,7 +32,7 @@ for e1, string in salts: + test_salt(realm, e1, string, e2) + + def test_dup(realm, ks): +- realm.run([kadminl, 'ank', '-e', ks, '-pw', 'password', 'ks_princ']) ++ realm.run([kadminl, 'ank', '-e', ks, '-pw', 'password-fips-test', 'ks_princ']) + out = realm.run([kadminl, 'getprinc', 'ks_princ']) + lines = out.split('\n') + keys = [l for l in lines if 'Key: ' in l] +@@ -44,8 +45,8 @@ def test_dup(realm, ks): + # All in-tree callers request duplicate suppression from + # krb5_string_to_keysalts(); we should check that it works, respects + # aliases, and doesn't result in an infinite loop. +-dup_kstypes = ['arcfour-hmac-md5:normal,rc4-hmac:normal', +- 'aes256-cts-hmac-sha1-96:normal,aes128-cts,aes256-cts', ++# Modified for FIPS: removed arcfour-hmac-md5,rc4-hmac test (not FIPS-approved) ++dup_kstypes = ['aes256-cts-hmac-sha1-96:normal,aes128-cts,aes256-cts', + 'aes256-cts-hmac-sha1-96:normal,aes256-cts:special,' + + 'aes256-cts-hmac-sha1-96:normal'] + +diff --git a/src/tests/t_spake.py b/src/tests/t_spake.py +index f0afefb60..fcbe7496c 100644 +--- a/src/tests/t_spake.py ++++ b/src/tests/t_spake.py +@@ -1,5 +1,6 @@ + from k5test import * + ++# Modified for FIPS: all passwords must be >= 14 bytes for PBKDF2 HMAC key requirement + # The name and number of each supported SPAKE group. + builtin_groups = ((1, 'edwards25519'),) + openssl_groups = ((2, 'P-256'), (3, 'P-384'), (4, 'P-521')) +@@ -13,7 +14,7 @@ for gnum, gname in groups: + conf = {'libdefaults': {'spake_preauth_groups': gname}} + for realm in multipass_realms(create_user=False, create_host=False, + krb5_conf=conf): +- realm.run([kadminl, 'addprinc', '+preauth', '-pw', 'pw', 'user']) ++ realm.run([kadminl, 'addprinc', '+preauth', '-pw', 'pw-fips-test-pw', 'user']) + + # Test a basic SPAKE preauth scenario with no optimizations. + msgs = ('Sending unauthenticated request', +@@ -28,7 +29,7 @@ for gnum, gname in groups: + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + 'AS key determined by preauth:', + 'Decrypted AS reply') +- realm.kinit('user', 'pw', expected_trace=msgs) ++ realm.kinit('user', 'pw-fips-test-pw', expected_trace=msgs) + + # Test an unsuccessful authentication. + msgs = ('/Additional pre-authentication required', +@@ -40,12 +41,12 @@ for gnum, gname in groups: + 'SPAKE challenge received with group ' + str(gnum), + 'Sending SPAKE response', + '/Preauthentication failed') +- realm.kinit('user', 'wrongpw', expected_code=1, expected_trace=msgs) ++ realm.kinit('user', 'wrongpw-fips-test-wrong-pw', expected_code=1, expected_trace=msgs) + + conf = {'libdefaults': {'spake_preauth_groups': 'edwards25519'}} + kdcconf = {'realms': {'$realm': {'spake_preauth_indicator': 'indspake'}}} + realm = K5Realm(create_user=False, krb5_conf=conf, kdc_conf=kdcconf) +-realm.run([kadminl, 'addprinc', '+preauth', '-pw', 'pw', 'user']) ++realm.run([kadminl, 'addprinc', '+preauth', '-pw', 'pw-fips-test-pw', 'user']) + + # Test with FAST. + mark('FAST') +@@ -65,7 +66,7 @@ msgs = ('Using FAST due to armor ccache negotiation', + 'AS key determined by preauth:', + 'FAST reply key:') + realm.kinit(realm.host_princ, flags=['-k']) +-realm.kinit('user', 'pw', flags=['-T', realm.ccache], expected_trace=msgs) ++realm.kinit('user', 'pw-fips-test-pw', flags=['-T', realm.ccache], expected_trace=msgs) + + # Test optimistic client preauth (151 is PA-SPAKE). + mark('client optimistic') +@@ -80,7 +81,7 @@ msgs = ('Attempting optimistic preauth', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + 'AS key determined by preauth:', + 'Decrypted AS reply') +-realm.run(['./icred', '-o', '151', 'user', 'pw'], expected_trace=msgs) ++realm.run(['./icred', '-o', '151', 'user', 'pw-fips-test-pw'], expected_trace=msgs) + + # Test KDC optimistic challenge (accepted by client). + mark('KDC optimistic') +@@ -96,7 +97,7 @@ msgs = ('Sending unauthenticated request', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + 'AS key determined by preauth:', + 'Decrypted AS reply') +-realm.kinit('user', 'pw', expected_trace=msgs) ++realm.kinit('user', 'pw-fips-test-pw', expected_trace=msgs) + + if runenv.have_spake_openssl != 'yes': + skip_rest('SPAKE fallback tests', 'SPAKE not built using OpenSSL') +@@ -116,7 +117,7 @@ msgs = ('Attempting optimistic preauth', + 'for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)', + 'AS key determined by preauth:', + 'Decrypted AS reply') +-realm.run(['./icred', '-o', '151', 'user', 'pw'], env=p256env, ++realm.run(['./icred', '-o', '151', 'user', 'pw-fips-test-pw'], env=p256env, + expected_trace=msgs) + + # Test KDC optimistic challenge (rejected by client). +@@ -139,7 +140,7 @@ msgs = ('Sending unauthenticated request', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + 'AS key determined by preauth:', + 'Decrypted AS reply') +-realm.kinit('user', 'pw', expected_trace=msgs) ++realm.kinit('user', 'pw-fips-test-pw', expected_trace=msgs) + + # Check that the auth indicator for SPAKE is properly included by the KDC. + mark('auth indicator') +diff --git a/src/util/k5test.py b/src/util/k5test.py +index 619f1995f..970b638c3 100644 +--- a/src/util/k5test.py ++++ b/src/util/k5test.py +@@ -26,7 +26,7 @@ To run test scripts during "make check" (if Python 2.5 or later is + available), add rules like the following to Makefile.in: + + check-pytests:: +- $(RUNPYTEST) $(srcdir)/t_testname.py $(PYTESTFLAGS) ++ $(RUNPYTEST) $(srcdir)/t_testname.py $(PYTESTFLAGS) + + A sample test script: + +@@ -471,7 +471,12 @@ def which(progname): + + def password(name): + """Choose a weakly random password from name, consistent across calls.""" +- return name + str(os.getpid()) ++ # Modified for FIPS: Ensure password >= 14 bytes for PBKDF2 HMAC key requirement ++ # Pad with '-password' suffix to meet minimum length ++ base = name + str(os.getpid()) ++ if len(base) < 14: ++ base = base + '-password' ++ return base + + + def canonicalize_hostname(name, rdns=True): +@@ -1071,7 +1076,8 @@ class K5Realm(object): + + def create_kdb(self): + global kdb5_util +- self.run([kdb5_util, 'create', '-s', '-P', 'master']) ++ # Modified for FIPS: master key password must be >= 14 bytes for HMAC ++ self.run([kdb5_util, 'create', '-s', '-P', 'master-key-password']) + + def start_kdc(self, args=[], env=None): + global krb5kdc +@@ -1344,19 +1350,7 @@ _passes = [ + # No special settings; exercises AES256. + ('default', None, None, None), + +- # Exercise the DES3 enctype. +- ('des3', None, +- {'libdefaults': {'permitted_enctypes': 'des3'}}, +- {'realms': {'$realm': { +- 'supported_enctypes': 'des3-cbc-sha1:normal', +- 'master_key_type': 'des3-cbc-sha1'}}}), +- +- # Exercise the arcfour enctype. +- ('arcfour', None, +- {'libdefaults': {'permitted_enctypes': 'rc4'}}, +- {'realms': {'$realm': { +- 'supported_enctypes': 'arcfour-hmac:normal', +- 'master_key_type': 'arcfour-hmac'}}}), ++ # Removed: arcfour pass - uses RC4 which is not FIPS-approved + + # Exercise the AES128 enctype. + ('aes128', None, +@@ -1365,13 +1359,6 @@ _passes = [ + 'supported_enctypes': 'aes128-cts:normal', + 'master_key_type': 'aes128-cts'}}}), + +- # Exercise the camellia256-cts enctype. +- ('camellia256', None, +- {'libdefaults': {'permitted_enctypes': 'camellia256-cts'}}, +- {'realms': {'$realm': { +- 'supported_enctypes': 'camellia256-cts:normal', +- 'master_key_type': 'camellia256-cts'}}}), +- + # Exercise the aes128-sha2 enctype. + ('aes128-sha2', None, + {'libdefaults': {'permitted_enctypes': 'aes128-sha2'}}, +@@ -1386,10 +1373,7 @@ _passes = [ + 'supported_enctypes': 'aes256-sha2:normal', + 'master_key_type': 'aes256-sha2'}}}), + +- # Test a setup with modern principal keys but an old TGT key. +- ('aes256.destgt', 'arcfour-hmac:normal', +- {'libdefaults': {'allow_weak_crypto': 'true'}}, +- None) ++ # Removed: aes256.destgt pass - uses arcfour-hmac for TGT which is not FIPS-approved + ] + + _success = False diff --git a/wolfProvider/libfido2/README.md b/wolfProvider/libfido2/README.md index c72d510e..9b9dc15d 100644 --- a/wolfProvider/libfido2/README.md +++ b/wolfProvider/libfido2/README.md @@ -1,3 +1,3 @@ -`wolfProvider/libfido2/libfido2-FIPS-1.15.0-wolfprov.patch` adds testing support +`wolfProvider/libfido2/libfido2-1.15.0-wolfprov-fips.patch` adds testing support for libfido2 with FIPS wolfprovider. To use this patch make sure to set the flag `HAVE_FIPS` to `ON` when configuring libfido2. This will disable EdDSA tests. diff --git a/wolfProvider/libfido2/libfido2-FIPS-1.15.0-wolfprov.patch b/wolfProvider/libfido2/libfido2-1.15.0-wolfprov-fips.patch similarity index 100% rename from wolfProvider/libfido2/libfido2-FIPS-1.15.0-wolfprov.patch rename to wolfProvider/libfido2/libfido2-1.15.0-wolfprov-fips.patch diff --git a/wolfProvider/libmemcached/libmemcached-FIPS-wolfprov.patch b/wolfProvider/libmemcached/libmemcached-wolfprov-fips.patch similarity index 100% rename from wolfProvider/libmemcached/libmemcached-FIPS-wolfprov.patch rename to wolfProvider/libmemcached/libmemcached-wolfprov-fips.patch diff --git a/wolfProvider/liboauth2/README.md b/wolfProvider/liboauth2/README.md index af1014b1..fcab649b 100644 --- a/wolfProvider/liboauth2/README.md +++ b/wolfProvider/liboauth2/README.md @@ -1,4 +1,4 @@ -`liboauth2-FIPS-v1.4.5.4-wolfprov.patch` adds testing support for liboauth2 +`liboauth2-v1.4.5.4-wolfprov-fips.patch` adds testing support for liboauth2 `v1.4.5.4` with FIPS wolfprovider. To use this patch make sure to configure liboauth2 with `--enable-wolfprov-fips`. This will disable problematic tests in Docker/valgrind. diff --git a/wolfProvider/liboauth2/liboauth2-FIPS-v1.4.5.4-wolfprov.patch b/wolfProvider/liboauth2/liboauth2-v1.4.5.4-wolfprov-fips.patch similarity index 100% rename from wolfProvider/liboauth2/liboauth2-FIPS-v1.4.5.4-wolfprov.patch rename to wolfProvider/liboauth2/liboauth2-v1.4.5.4-wolfprov-fips.patch diff --git a/wolfProvider/libssh2/libssh2-libssh2-1.10.0-debian-wolfprov.patch b/wolfProvider/libssh2/libssh2-libssh2-1.10.0-debian-wolfprov.patch index dacdec19..1f0c2d53 100644 --- a/wolfProvider/libssh2/libssh2-libssh2-1.10.0-debian-wolfprov.patch +++ b/wolfProvider/libssh2/libssh2-libssh2-1.10.0-debian-wolfprov.patch @@ -24,6 +24,19 @@ index dc9e108..03b90a1 100644 or public/private key. .SH SEE ALSO .BR libssh2_session_init_ex(3) +diff --git a/tests/mansyntax.sh b/tests/mansyntax.sh +index dd4aa77..c589431 100755 +--- a/tests/mansyntax.sh ++++ b/tests/mansyntax.sh +@@ -26,7 +26,7 @@ ln -sf "$mandir" "$dstdir/man3" + + for manpage in $mandir/libssh2_*.*; do + echo "$manpage" +- warnings=$(LANG=en_US.UTF-8 MANWIDTH=80 man -M "$dstdir" --warnings \ ++ warnings=$(LANG=C.UTF-8 MANWIDTH=80 man -M "$dstdir" --warnings \ + -E UTF-8 -l "$manpage" 2>&1 >/dev/null) + if [ -n "$warnings" ]; then + echo "$warnings" diff --git a/tests/ssh2.c b/tests/ssh2.c index f903e07..3105c15 100644 --- a/tests/ssh2.c diff --git a/wolfProvider/libssh2/libssh2-libssh2-1.10.0-debian-wolfssl-5.8.4-wolfprov.patch b/wolfProvider/libssh2/libssh2-libssh2-1.10.0-debian-wolfssl-5.8.4-wolfprov.patch new file mode 100644 index 00000000..1f0c2d53 --- /dev/null +++ b/wolfProvider/libssh2/libssh2-libssh2-1.10.0-debian-wolfssl-5.8.4-wolfprov.patch @@ -0,0 +1,174 @@ +diff --git a/docs/libssh2_userauth_keyboard_interactive_ex.3 b/docs/libssh2_userauth_keyboard_interactive_ex.3 +index ada012a..222b2ba 100644 +--- a/docs/libssh2_userauth_keyboard_interactive_ex.3 ++++ b/docs/libssh2_userauth_keyboard_interactive_ex.3 +@@ -52,7 +52,7 @@ number, it isn't really a failure per se. + + \fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket. + +-\fLIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password ++\fILIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password + or public/private key. + .SH SEE ALSO + .BR libssh2_session_init_ex(3) +diff --git a/docs/libssh2_userauth_password_ex.3 b/docs/libssh2_userauth_password_ex.3 +index dc9e108..03b90a1 100644 +--- a/docs/libssh2_userauth_password_ex.3 ++++ b/docs/libssh2_userauth_password_ex.3 +@@ -51,7 +51,7 @@ Some of the errors this function may return include: + + \fILIBSSH2_ERROR_PASSWORD_EXPIRED\fP - + +-\fLIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password ++\fILIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - failed, invalid username/password + or public/private key. + .SH SEE ALSO + .BR libssh2_session_init_ex(3) +diff --git a/tests/mansyntax.sh b/tests/mansyntax.sh +index dd4aa77..c589431 100755 +--- a/tests/mansyntax.sh ++++ b/tests/mansyntax.sh +@@ -26,7 +26,7 @@ ln -sf "$mandir" "$dstdir/man3" + + for manpage in $mandir/libssh2_*.*; do + echo "$manpage" +- warnings=$(LANG=en_US.UTF-8 MANWIDTH=80 man -M "$dstdir" --warnings \ ++ warnings=$(LANG=C.UTF-8 MANWIDTH=80 man -M "$dstdir" --warnings \ + -E UTF-8 -l "$manpage" 2>&1 >/dev/null) + if [ -n "$warnings" ]; then + echo "$warnings" +diff --git a/tests/ssh2.c b/tests/ssh2.c +index f903e07..3105c15 100644 +--- a/tests/ssh2.c ++++ b/tests/ssh2.c +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #include + + int main(int argc, char *argv[]) +@@ -41,10 +43,16 @@ int main(int argc, char *argv[]) + LIBSSH2_CHANNEL *channel; + const char *pubkeyfile = "etc/user.pub"; + const char *privkeyfile = "etc/user"; +- const char *username = "username"; ++ const char *username = NULL; + const char *password = "password"; + int ec = 1; + ++ /* Initialize libssh2 library */ ++ if (libssh2_init(0) != 0) { ++ fprintf(stderr, "Failed to initialize libssh2\n"); ++ return 1; ++ } ++ + #ifdef WIN32 + WSADATA wsadata; + int err; +@@ -59,8 +67,17 @@ int main(int argc, char *argv[]) + (void)argc; + (void)argv; + +- if(getenv("USER")) +- username = getenv("USER"); ++ /* Detect Docker by /.dockerenv or IN_DOCKER env var */ ++ if (getenv("IN_DOCKER") || access("/.dockerenv", F_OK) == 0) { ++ username = "user"; ++ } else { ++ struct passwd *pw = getpwuid(getuid()); ++ if (pw) { ++ username = pw->pw_name; ++ } else { ++ username = "user"; ++ } ++ } + + if(getenv ("PRIVKEY")) + privkeyfile = getenv("PRIVKEY"); +@@ -182,5 +199,6 @@ int main(int argc, char *argv[]) + close(sock); + #endif + ++ libssh2_exit(); + return ec; + } +diff --git a/tests/ssh2.sh b/tests/ssh2.sh +index 07795bb..657fb4b 100755 +--- a/tests/ssh2.sh ++++ b/tests/ssh2.sh +@@ -1,10 +1,12 @@ +-#!/bin/sh ++#!/bin/bash + + # Written by Simon Josefsson. + + # Start sshd, invoke parameters, saving exit code, kill sshd, and + # return exit code. + ++WOLFPROV_DIR=$(cd "$(dirname "$0")/../.." && pwd) ++ + srcdir=${srcdir:-$PWD} + SSHD=${SSHD:-/usr/sbin/sshd} + +@@ -20,14 +22,39 @@ if test -n "$DEBUG"; then + libssh2_sshd_params="-d -d" + fi + ++# Create privilege separation directory if it doesn't exist ++mkdir -p /run/sshd 2>/dev/null || sudo mkdir -p /run/sshd 2>/dev/null || true ++ ++# Create a 'user' account if it doesn't exist (for SSH authentication) ++if ! id "user" &>/dev/null; then ++ # Create user account without home directory and shell ++ useradd -r -s /bin/false user 2>/dev/null || true ++ # Unlock the account for SSH authentication ++ passwd -u user 2>/dev/null || true ++ # Alternative: set empty password to unlock ++ passwd -d user 2>/dev/null || true ++fi ++ ++# Set the wrapper script to load the system ossl for sshd ++chmod +x "$WOLFPROV_DIR/libssh2/tests/sshd-wrapper.sh" ++export SSHD="$WOLFPROV_DIR/libssh2/tests/sshd-wrapper.sh" ++ ++# Start sshd with FIPS approved algos + chmod go-rwx "$srcdir"/etc/host* + $SSHD -f /dev/null -h "$srcdir"/etc/host \ ++ -o 'KexAlgorithms diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512' \ ++ -o 'HostKeyAlgorithms +ssh-rsa' \ ++ -o 'PubkeyAcceptedAlgorithms +ssh-rsa' \ + -o 'Port 4711' \ + -o 'Protocol 2' \ + -o "AuthorizedKeysFile $srcdir/etc/user.pub" \ + -o 'UsePrivilegeSeparation no' \ + -o 'StrictModes no' \ +- -D \ ++ -o 'PubkeyAuthentication yes' \ ++ -o 'PasswordAuthentication no' \ ++ -o 'ChallengeResponseAuthentication no' \ ++ -o 'UsePAM no' \ ++ -D -e -d \ + $libssh2_sshd_params & + sshdpid=$! + +diff --git a/tests/sshd-wrapper.sh b/tests/sshd-wrapper.sh +new file mode 100755 +index 0000000..5652e18 +--- /dev/null ++++ b/tests/sshd-wrapper.sh +@@ -0,0 +1,12 @@ ++#!/bin/sh ++# Sets a clean env for sshd(openssh) so we can use system ossl ++exec env -i \ ++ PATH=/usr/sbin:/usr/bin:/bin \ ++ LC_ALL=C LANG=C \ ++ LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu \ ++ OPENSSL_CONF= \ ++ OPENSSL_MODULES= \ ++ PKG_CONFIG_PATH= \ ++ LDFLAGS= \ ++ CPPFLAGS= \ ++ /usr/sbin/sshd "$@" diff --git a/wolfProvider/net-snmp/net-snmp-FIPS-v5.9.3-wolfprov.patch b/wolfProvider/net-snmp/net-snmp-v5.9.3-wolfprov-fips.patch similarity index 100% rename from wolfProvider/net-snmp/net-snmp-FIPS-v5.9.3-wolfprov.patch rename to wolfProvider/net-snmp/net-snmp-v5.9.3-wolfprov-fips.patch diff --git a/wolfProvider/openpace/openpace-FIPS-1.1.3-wolfprov.patch b/wolfProvider/openpace/openpace-1.1.3-wolfprov-fips.patch similarity index 100% rename from wolfProvider/openpace/openpace-FIPS-1.1.3-wolfprov.patch rename to wolfProvider/openpace/openpace-1.1.3-wolfprov-fips.patch diff --git a/wolfProvider/opensc/README.md b/wolfProvider/opensc/README.md index dc9fa382..10a29cea 100644 --- a/wolfProvider/opensc/README.md +++ b/wolfProvider/opensc/README.md @@ -1,2 +1,2 @@ -`wolfProvider/opensc/opensc-0.25.1-wolfprovider.patch` adds wolfProvider support +`wolfProvider/opensc/opensc-0.25.1-wolfprov.patch` adds wolfProvider support for opensc version `0.25.1`. This patch disables SM4 and some tests with PKCS11SPY. diff --git a/wolfProvider/opensc/opensc-0.25.1-wolfprovider.patch b/wolfProvider/opensc/opensc-0.25.1-wolfprov.patch similarity index 100% rename from wolfProvider/opensc/opensc-0.25.1-wolfprovider.patch rename to wolfProvider/opensc/opensc-0.25.1-wolfprov.patch diff --git a/wolfProvider/openssh/openssh-V_9_6_P1-FIPS-wolfprov.patch b/wolfProvider/openssh/openssh-V_9_6_P1-wolfprov-fips.patch similarity index 100% rename from wolfProvider/openssh/openssh-V_9_6_P1-FIPS-wolfprov.patch rename to wolfProvider/openssh/openssh-V_9_6_P1-wolfprov-fips.patch diff --git a/wolfProvider/ppp/README.md b/wolfProvider/ppp/README.md index 69e01c1a..42d2fa8b 100644 --- a/wolfProvider/ppp/README.md +++ b/wolfProvider/ppp/README.md @@ -1,3 +1,3 @@ -`wolfProvider/ppp/ppp-FIPS-v2.5.2-wolfprov.patch` adds testing support for ppp +`wolfProvider/ppp/ppp-v2.5.2-wolfprov-fips.patch` adds testing support for ppp with FIPS wolfprovider. To use this patch make sure to configure ppp with `--enable-wolfprov-fips` flag. This will disable MD5 tests. diff --git a/wolfProvider/ppp/ppp-FIPS-v2.5.2-wolfprov.patch b/wolfProvider/ppp/ppp-v2.5.2-wolfprov-fips.patch similarity index 100% rename from wolfProvider/ppp/ppp-FIPS-v2.5.2-wolfprov.patch rename to wolfProvider/ppp/ppp-v2.5.2-wolfprov-fips.patch diff --git a/wolfProvider/python3-ntp/README.md b/wolfProvider/python3-ntp/README.md index b141b175..3974ec17 100644 --- a/wolfProvider/python3-ntp/README.md +++ b/wolfProvider/python3-ntp/README.md @@ -1,6 +1,6 @@ All patches disable tests that call openssl low level CMAC API that is not supported with the openssl provider model. -`python3-ntp-FIPS-NTPsec_1_2_2-wolfprov.patch` also disables a test that uses +`python3-ntp-NTPsec_1_2_2-wolfprov-fips.patch` also disables a test that uses non FIPS algorithms. Conicidentally `python3-ntp-master-wolfprov.patch` already disables this test for FIPS testing on master because it also contains the CMAC issue in that test. diff --git a/wolfProvider/python3-ntp/python3-ntp-FIPS-NTPsec_1_2_2-wolfprov.patch b/wolfProvider/python3-ntp/python3-ntp-NTPsec_1_2_2-wolfprov-fips.patch similarity index 100% rename from wolfProvider/python3-ntp/python3-ntp-FIPS-NTPsec_1_2_2-wolfprov.patch rename to wolfProvider/python3-ntp/python3-ntp-NTPsec_1_2_2-wolfprov-fips.patch diff --git a/wolfProvider/stunnel/stunnel-WPFF-5.67-wolfprov.patch b/wolfProvider/stunnel/stunnel-WPFF-5.67-wolfprov.patch index f7b67334..5423f333 100644 --- a/wolfProvider/stunnel/stunnel-WPFF-5.67-wolfprov.patch +++ b/wolfProvider/stunnel/stunnel-WPFF-5.67-wolfprov.patch @@ -1,5 +1,18 @@ +diff --git a/src/options.c b/src/options.c +index e1149a4..c8d6632 100644 +--- a/src/options.c ++++ b/src/options.c +@@ -38,7 +38,7 @@ + #include "prototypes.h" + + #if OPENSSL_VERSION_NUMBER >= 0x10101000L +-#define DEFAULT_CURVES "X25519:P-256:X448:P-521:P-384" ++#define DEFAULT_CURVES "P-256:P-384:P-521" + #else /* OpenSSL version < 1.1.1 */ + #define DEFAULT_CURVES "prime256v1" + #endif /* OpenSSL version >= 1.1.1 */ diff --git a/tests/certs/maketestcert.sh b/tests/certs/maketestcert.sh -index 3c4f8b5..23af9af 100755 +index 3c4f8b5..4f9a557 100755 --- a/tests/certs/maketestcert.sh +++ b/tests/certs/maketestcert.sh @@ -9,6 +9,13 @@ cd "${result_path}" @@ -16,6 +29,15 @@ index 3c4f8b5..23af9af 100755 # create new psk secrets gen_psk () { tr -c -d 'A-Za-z0-9' > "maketestcert.log" | head -c 50 > tmp/psk.txt +@@ -90,7 +97,7 @@ cat tmp/server_cert.pem >> tmp/PeerCerts.pem 2>> "maketestcert.log" + cat demoCA/server.key >> tmp/server_cert.pem 2>> "maketestcert.log" + + # create a PKCS#12 file with a server certificate +-$OPENSSL pkcs12 -export -certpbe pbeWithSHA1And3-KeyTripleDES-CBC -in tmp/server_cert.pem -out tmp/server_cert.p12 -passout pass: 1>&2 2>> "maketestcert.log" ++$OPENSSL pkcs12 -export -certpbe AES-256-CBC -keypbe AES-256-CBC -macalg sha256 -in tmp/server_cert.pem -out tmp/server_cert.p12 -passout pass:fipspasswordhere 1>&2 2>> "maketestcert.log" + + # copy new files + if [ -s tmp/stunnel.pem ] && [ -s tmp/CACert.pem ] && [ -s tmp/CACertCRL.pem ] && \ @@ -113,3 +120,9 @@ rm -rf "tmp/" # restore settings @@ -26,150 +48,3303 @@ index 3c4f8b5..23af9af 100755 + echo "WOLFPROV_FORCE_FAIL is set to 1 - Setting back to 1 to continue with tests" + export WOLFPROV_FORCE_FAIL=1 +fi +diff --git a/tests/plugins/p01_client_cert.py b/tests/plugins/p01_client_cert.py +index 2df2dab..4d17dcd 100644 +--- a/tests/plugins/p01_client_cert.py ++++ b/tests/plugins/p01_client_cert.py +@@ -19,53 +19,6 @@ class StunnelTest(StunnelAcceptConnect): + self.params.services = ['client'] + + +-class CertTest(StunnelTest): +- """ Checking if the cert option ensures a client certificate. +- The success is expected because the client presents a certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '011. Test \"cert\" option' +- self.params.context = 'cert_required' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[0]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- + class FailureCertTest(StunnelTest): + """ Checking if the cert option ensures a client certificate. + The failure is expected because the client does not present any certificate. +@@ -109,6 +62,7 @@ class FailureCertTest(StunnelTest): + [{service}] + client = yes + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{ports[0]} + ;client does not present any certificate + ;cert = {cfg.certdir}/client_cert.pem +@@ -132,8 +86,5 @@ class StunnelClientTest(Plugin): + + async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: + """Run tests""" +- stunnel = CertTest(cfg, logger) +- await stunnel.test_stunnel(cfg) +- + stunnel = FailureCertTest(cfg, logger) + await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p02_require_cert.py b/tests/plugins/p02_require_cert.py +index f174b6d..613fa6b 100644 +--- a/tests/plugins/p02_require_cert.py ++++ b/tests/plugins/p02_require_cert.py +@@ -56,55 +56,7 @@ class RequireCertTest(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureRequireCertTest(StunnelTest): +- """Checking if the requireCert option requires a client certificate. +- The failure is expected because the client does not present any certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '022. Failure test \"requireCert\" option' +- self.events.count = 1 +- self.events.success = [ +- "peer did not return a certificate" +- ] +- self.events.failure = [ +- #"peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- #"Connection reset by peer", +- #"Connection lost", +- #"Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- requireCert = yes +- +- [{service}] +- accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + """ +@@ -129,5 +81,3 @@ class StunnelServerTest(Plugin): + stunnel = RequireCertTest(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = FailureRequireCertTest(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p03_verify_peer.py b/tests/plugins/p03_verify_peer.py +index cedff93..aa723fe 100644 +--- a/tests/plugins/p03_verify_peer.py ++++ b/tests/plugins/p03_verify_peer.py +@@ -56,59 +56,7 @@ class VerifyPeer(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureVerifyPeer(StunnelTest): +- """Checking if the verifyPeer option verifies the peer certificate. +- The valid peer certificate is stored in the file specified with CAfile. +- The failure is expected because the client presents an incorrect certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '032. Failure test \"verifyPeer\" option' +- self.params.context = 'load_wrong_cert' +- self.events.count = 1 +- self.events.success = [ +- "certificate verify failed", +- "unknown CA" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- #"certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- #"Connection reset by peer", +- #"Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + verifyPeer = yes +@@ -135,5 +83,3 @@ class StunnelServerTest(Plugin): + stunnel = VerifyPeer(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = FailureVerifyPeer(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p04_verify_chain.py b/tests/plugins/p04_verify_chain.py +index d6fb408..f3929c4 100644 +--- a/tests/plugins/p04_verify_chain.py ++++ b/tests/plugins/p04_verify_chain.py +@@ -56,59 +56,7 @@ class VerifyChain(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyChain = yes +- CAfile = {cfg.certdir}/CACert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureVerifyChain(StunnelTest): +- """Checking if the verifyChain option verifies the peer certificate starting from the root CA. +- The self-signed root CA certificate is stored in the file specified with CAfile. +- The failure is expected because python client presents an incorrect certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '042. Failure test \"verifyChain\" option' +- self.params.context = 'load_wrong_cert' +- self.events.count = 1 +- self.events.success = [ +- "certificate verify failed", +- "unknown CA" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- #"certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- #"Connection reset by peer", +- #"Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + verifyChain = yes +@@ -135,5 +83,3 @@ class StunnelServerTest(Plugin): + stunnel = VerifyChain(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = FailureVerifyChain(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p05_verify_crl.py b/tests/plugins/p05_verify_crl.py +index b5a9eae..c363134 100644 +--- a/tests/plugins/p05_verify_crl.py ++++ b/tests/plugins/p05_verify_crl.py +@@ -58,62 +58,7 @@ class VerifyCRL(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyChain = yes +- CAfile = {cfg.certdir}/CACert.pem +- CRLfile = {cfg.certdir}/CACertCRL.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureVerifyCRL(StunnelTest): +- """Checking if the CRL is verified. +- The verifyChain option verifies the peer certificate starting from the root CA. +- The self-signed root CA certificate is stored in the file specified with CAfile. +- Certificate Revocation Lists file is stored in the file specified with CRLfile. +- The failure is expected because the python client presents the revoked certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '052. CRL file with revoked certificate' +- self.params.context = 'load_revoked_cert' +- self.events.count = 1 +- self.events.success = [ +- "certificate verify failed", +- "certificate revoked" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- #"certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- #"Connection reset by peer", +- #"Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + verifyChain = yes +@@ -141,5 +86,3 @@ class StunnelServerTest(Plugin): + stunnel = VerifyCRL(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = FailureVerifyCRL(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p06_psk_secrets.py b/tests/plugins/p06_psk_secrets.py +index 21871cc..00ea9f7 100644 +--- a/tests/plugins/p06_psk_secrets.py ++++ b/tests/plugins/p06_psk_secrets.py +@@ -56,6 +56,7 @@ class PSKSecrets(StunnelTest): + [{service}] + client = yes + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{ports[1]} + PSKsecrets = {cfg.certdir}/psk1.txt + """ +@@ -77,6 +78,7 @@ class PSKSecrets(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + PSKsecrets = {cfg.certdir}/secrets.txt + """ +@@ -128,6 +130,7 @@ class FailurePSKSecrets(StunnelTest): + [{service}] + client = yes + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{ports[1]} + PSKsecrets = {cfg.certdir}/psk2.txt + """ +@@ -149,6 +152,7 @@ class FailurePSKSecrets(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + PSKsecrets = {cfg.certdir}/secrets.txt + """ +diff --git a/tests/plugins/p07_p12cert.py b/tests/plugins/p07_p12cert.py +deleted file mode 100644 +index 662aefc..0000000 +--- a/tests/plugins/p07_p12cert.py ++++ /dev/null +@@ -1,81 +0,0 @@ +-"""stunnel server tests""" +- +-import logging +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.ssl_client = True +- self.params.services = ['server'] +- +- +-class Certp12Test(StunnelTest): +- """Checking if the file containing certificates used by stunnel to authenticate +- itself against the remote client may be in the P12 format. +- The success is expected because the server presents the valid certificate in the P12 format. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '071. Test PKCS#12 certificate' +- self.params.context = 'load_verify_locations"' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.p12 +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelServerTest(Plugin): +- """Stunnel server tests: +- HTTPS client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Existing PKCS#12 certificate' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = Certp12Test(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p08_ipv6.py b/tests/plugins/p08_ipv6.py +deleted file mode 100644 +index 2483a54..0000000 +--- a/tests/plugins/p08_ipv6.py ++++ /dev/null +@@ -1,98 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- +- +-class IPv6Test(StunnelTest): +- """ Checking if IPv6 is supported. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '081. Test IPv6 support' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = ::1:{ports[1]} +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = ::1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'IPv6 support' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = IPv6Test(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p09_bind.py b/tests/plugins/p09_bind.py +index bf44b74..0bcf035 100644 +--- a/tests/plugins/p09_bind.py ++++ b/tests/plugins/p09_bind.py +@@ -55,8 +55,11 @@ class BindingTest(StunnelTest): + + [{service}] + accept = 127.0.0.1:{port} ++ sslVersionMax = TLSv1.2 + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + accept = 127.0.0.1:{port} ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + """ +diff --git a/tests/plugins/p10_fips.py b/tests/plugins/p10_fips.py +deleted file mode 100644 +index 5d2bc56..0000000 +--- a/tests/plugins/p10_fips.py ++++ /dev/null +@@ -1,108 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- +- +-class FIPSTest(StunnelTest): +- """ Checking FIPS mode. +- The success is expected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '101. Test FIPS mode' +- self.events.skip = [ +- "FIPS provider not available", +- "fips mode not supported", +- r"FIPS PROVIDER.*could not load the shared library" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'FIPS mode' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = FIPSTest(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p11_fips_cipher.py b/tests/plugins/p11_fips_cipher.py +deleted file mode 100644 +index 0280a1d..0000000 +--- a/tests/plugins/p11_fips_cipher.py ++++ /dev/null +@@ -1,216 +0,0 @@ +-"""stunnel server tests""" +- +-import logging +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ExpectedConfigurationFailure +-) +- +- +-class StunnelTest(ExpectedConfigurationFailure): +- """Base class for stunnel server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.ssl_client = True +- self.params.services = ['server'] +- +- +-class FailureCipherFIPS(StunnelTest): +- """Checking FIPS mode. +- The cipher "CAMELLIA256-SHA" (TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256) +- is unavailable if FIPS is enabled. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '111. Failure FIPS mode with unavailable cipher' +- self.events.skip = [ +- "FIPS provider not available", +- "fips mode not supported", +- r"FIPS PROVIDER.*could not load the shared library" +- ] +- self.events.count = 1 +- self.events.success = [ +- "no cipher match" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- #"Something went wrong: stunnel 'server' failed", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- ciphers = CAMELLIA256-SHA +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureCiphersuitesFIPS(StunnelTest): +- """Checking FIPS mode. +- The ciphersuite "TLS_CHACHA20_POLY1305_SHA256" is unavailable if FIPS is enabled. +- This option requires OpenSSL 1.1.1 or later. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '112. Failure FIPS mode with unavailable ciphersuite' +- self.events.skip = [ +- "FIPS provider not available", +- "fips mode not supported", +- r"FIPS PROVIDER.*could not load the shared library", +- "Specified option name is not valid here" +- ] +- self.events.count = 1 +- self.events.success = [ +- "disabled for FIPS", +- "no ciphers available" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- ciphersuites = TLS_CHACHA20_POLY1305_SHA256 +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +- +- +-class FailureEllipticCurveFIPS(StunnelTest): +- """ Checking FIPS mode. +- The elliptic curve "sect163r1" is unavailable if FIPS is enabled. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '113. Failure FIPS mode with unavailable elliptic curve' +- self.events.skip = [ +- "FIPS provider not available", +- "fips mode not supported", +- r"FIPS PROVIDER.*could not load the shared library" +- ] +- self.events.count = 1 +- self.events.success = [ +- "no suitable key share", +- "Invalid groups list in 'curves'" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- curves = sect163r1 +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelServerTest(Plugin): +- """Stunnel server tests: +- HTTPS client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'FIPS mode cipher' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = FailureCipherFIPS(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = FailureCiphersuitesFIPS(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = FailureEllipticCurveFIPS(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p12_sni.py b/tests/plugins/p12_sni.py +deleted file mode 100644 +index 95c5a63..0000000 +--- a/tests/plugins/p12_sni.py ++++ /dev/null +@@ -1,196 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server_virtual', 'client'] +- +- +-class SNITest(StunnelTest): +- """Use the service as a secondary service (a name-based virtual server) +- for Server Name Indication TLS extension. +- SERVICE_NAME (server_virtual) specifies the primary service that +- accepts client connections with the accept option. +- SERVER_NAME_PATTERN (*.mydomain.com) specifies the host name to be redirected. +- The success is expected because the client presents the sni pattern (sni.mydomain.com) +- corresponding with SERVER_NAME_PATTERN (*.mydomain.com). +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '121. Test \"sni\" option' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- sni = sni.mydomain.com +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- cert = {cfg.certdir}/server_cert.pem +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- +- [sni] +- connect = 127.0.0.1:{port} +- sni = server_virtual:*.mydomain.com +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureSNITest(StunnelTest): +- """Use the service as a secondary service (a name-based virtual server) +- for Server Name Indication TLS extension. +- SERVICE_NAME (server_virtual) specifies the primary service that +- accepts client connections with the accept option. +- SERVER_NAME_PATTERN sni.mydomain.com) specifies the host name to be redirected. +- The success is expected because the client doesn't present any sni pattern. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '122. Failure test \"sni\" option' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- ;the client doesn't present any sni pattern +- ;sni = sni.mydomain.com +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- +- [sni] +- sni = server_virtual:*.mydomain.com +- cert = {cfg.certdir}/server_cert.pem +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Server Name Indication' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = SNITest(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = FailureSNITest(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p13_resume.py b/tests/plugins/p13_resume.py +deleted file mode 100644 +index 7645525..0000000 +--- a/tests/plugins/p13_resume.py ++++ /dev/null +@@ -1,351 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- self.params.conn_num = 3 +- +- +-class ResumePSK(StunnelTest): +- """Checking if the PSK authentication works properly when the session is resumed. +- We expect exactly 2 "TLS accepted: previous session reused" to be logged +- by the [server] service because the client presents the valid PSK. +- PSK identities and corresponding keys are stored in files specified with PSKsecrets. +- This resumption of the session does not work for the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '131. Resume session with PSK authentication' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- PSKsecrets = {cfg.certdir}/psk1.txt +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- PSKsecrets = {cfg.certdir}/secrets.txt +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class ResumeCacheTLSv12(StunnelTest): +- """Checking the cache session resumption. +- We expect exactly 2 "TLS accepted: previous session reused" to be +- logged by the [server] service. +- "options = NO_TICKET" turns off ticket support in TLSv1.2 and older. +- In TLSv1.3, "options = NO_TICKET" switches from using stateful tickets to +- stateless tickets (traditional cache with session id sent in tickets). +- https://github.com/openssl/openssl/issues/10280 +- Session cache resumption does not work with the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '132. Cache session resumption with TLSv1.2' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sslVersion = TLSv1.2 +- options = NO_TICKET +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class SessionResume(StunnelTest): +- """Enable the 'sessionResume' service-level option to allow session resumption. +- This resumption of the session does not work for the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '133. Test enabled \"sessionResume\" option' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sessionResume = yes +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class NoSessionResume(StunnelTest): +- """Disable the 'sessionResume' service-level option to disallow session resumption. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '134. Test disabled \"sessionResume\" option' +- self.events.count = 3 +- self.events.success = [ +- "TLS accepted: new session negotiated" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sessionResume = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Resume session' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = ResumePSK(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = ResumeCacheTLSv12(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = SessionResume(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = NoSessionResume(cfg, logger) +- await stunnel.test_stunnel(cfg) diff --git a/tests/plugins/p14_resume_ticket.py b/tests/plugins/p14_resume_ticket.py -index 22db91e..b2ad7ce 100644 +deleted file mode 100644 +index 22db91e..0000000 --- a/tests/plugins/p14_resume_ticket.py -+++ b/tests/plugins/p14_resume_ticket.py -@@ -33,6 +33,13 @@ class ResumeTicketTLSv12(StunnelTest): - def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): - super().__init__(cfg, logger, path) - self.params.description = '141. Stateless session ticket resumption with TLSv1.2' -+ -+ # Skip this test when force fail is enabled -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.events.skip = ["Skipping session resumption test in force fail mode"] -+ self.events.count = 0 # Set count to 0 to force skip -+ return -+ - self.events.count = 2 - self.events.success = [ - "TLS accepted: previous session reused" -@@ -53,6 +60,12 @@ class ResumeTicketTLSv12(StunnelTest): - ] - self.path = path - -+ async def test_stunnel(self, cfg: Config) -> None: -+ """Override test_stunnel to skip when force fail is enabled""" -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.logger.info("Skipping session resumption test in force fail mode") -+ return -+ await super().test_stunnel(cfg) - - async def prepare_client_cfgfile( - self, cfg: Config, ports: list, service: str -@@ -117,6 +130,13 @@ class ResumeTicketTLSv13(StunnelTest): - def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): - super().__init__(cfg, logger, path) - self.params.description = '142. Stateless session ticket resumption with TLSv1.3' -+ -+ # Skip this test when force fail is enabled -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.events.skip = ["Skipping session resumption test in force fail mode"] -+ self.events.count = 0 # Set count to 0 to force skip -+ return -+ - self.events.count = 2 - self.events.skip = [ - "Incorrect version of TLS protocol", -@@ -141,6 +161,12 @@ class ResumeTicketTLSv13(StunnelTest): - ] - self.path = path - -+ async def test_stunnel(self, cfg: Config) -> None: -+ """Override test_stunnel to skip when force fail is enabled""" -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.logger.info("Skipping session resumption test in force fail mode") -+ return -+ await super().test_stunnel(cfg) - - async def prepare_client_cfgfile( - self, cfg: Config, ports: list, service: str ++++ /dev/null +@@ -1,213 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ClientConnectExec +-) +- +- +-class StunnelTest(ClientConnectExec): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.services = ['server', 'client'] +- self.params.conn_num = 3 +- self.events.count = 2 +- +- +-class ResumeTicketTLSv12(StunnelTest): +- """Checking the stateless session ticket resumption (RFC 4507bis) with TLSv1.2. +- We expect exactly 2 "TLS accepted: previous session reused" to be logged by the +- [server] service, because [client] connected 3 times (1 new session, 2 reused sessions). +- The following options are used to disable session cache: +- - The "sessionCacheSize = 1" option sets the internal session cache size. +- - "options = -NO_TICKET" (it is the default with OpenSSL 1.1.1 or later) +- Stateless session ticket resumption also works with the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '141. Stateless session ticket resumption with TLSv1.2' +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sslVersion = TLSv1.2 +- sessionCacheSize = 1 +- options = -NO_TICKET +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class ResumeTicketTLSv13(StunnelTest): +- """Checking the stateless session ticket resumption (RFC 4507bis) with TLS 1.3. +- We expect exactly 2 "TLS accepted: previous session reused" to be logged by the +- [server] service, because [client] connected 3 times (1 new session, 2 reused sessions). +- The following options are used to disable session cache: +- - The "sessionCacheSize = 1" option sets the internal session cache size. +- - "options = -NO_TICKET" (it is the default with OpenSSL 1.1.1 or later). +- Stateless session ticket resumption also works with the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '142. Stateless session ticket resumption with TLSv1.3' +- self.events.count = 2 +- self.events.skip = [ +- "Incorrect version of TLS protocol", +- "Invalid protocol version" +- ] +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sslVersion = TLSv1.3 +- sessionCacheSize = 1 +- options = -NO_TICKET +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Resume session' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- path = os.path.join(cfg.tempd, 'unix.sock') +- stunnel = ResumeTicketTLSv12(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +- +- stunnel = ResumeTicketTLSv13(cfg, logger, path) +- await stunnel.test_stunnel(cfg) diff --git a/tests/plugins/p15_resume_secret.py b/tests/plugins/p15_resume_secret.py -index 85bd69b..723f4d9 100644 +deleted file mode 100644 +index 85bd69b..0000000 --- a/tests/plugins/p15_resume_secret.py -+++ b/tests/plugins/p15_resume_secret.py -@@ -31,6 +31,13 @@ class ResumeTicketSecret(StunnelTest): - def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): - super().__init__(cfg, logger, path) - self.params.description = '151. Session resumption with secret keys' -+ -+ # Skip this test when force fail is enabled -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.events.skip = ["Skipping session resumption test in force fail mode"] -+ self.events.count = 0 # Set count to 0 to force skip -+ return -+ - self.events.count = 3 - self.events.success = [ - "TLS accepted: previous session reused" -@@ -51,6 +58,12 @@ class ResumeTicketSecret(StunnelTest): - ] - self.path = path - -+ async def test_stunnel(self, cfg: Config) -> None: -+ """Override test_stunnel to skip when force fail is enabled""" -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.logger.info("Skipping session resumption test in force fail mode") -+ return -+ await super().test_stunnel(cfg) - - async def prepare_client_cfgfile( - self, cfg: Config, ports: list, service: str ++++ /dev/null +@@ -1,145 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ServerReopen +-) +- +- +-class StunnelTest(ServerReopen): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.services = ['server', 'client'] +- self.params.conn_num = 4 +- self.events.count = 1 +- +- +-class ResumeTicketSecret(StunnelTest): +- """Checking if the reloaded server resume the session with secret keys for +- the session ticket processing. +- We expect exactly 2 "TLS accepted: previous session reused" to be logged by the +- [server] service, because the server holds keys for the session ticket processing. +- The ticket session resumption also works for the FORK model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '151. Session resumption with secret keys' +- self.events.count = 3 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- options = -NO_TICKET +- ticketKeySecret = 6c:42:72:46:57:23:3a:3d:4b:54:2d:7b:55:4b:6e:8f:32:5c:21:6a:2e:6e:47:31:57:20:2f:75:26:7b:4d:25 +- ticketMacSecret = 3f:3c:77:53:32:48:79:76:75:7a:50:33:70:65:47:27:32:79:73:7e:73:2c:21:6c:3a:6f:30:28:4c:5c:27:1f +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +- async def prepare_additional_server_cfgfile( +- self, cfg: Config, ports: list, lport: int +- ) -> pathlib.Path: +- """Create a configuration file for new stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_new_server.pid +- foreground = yes +- debug = debug +- syslog = no +- +- ticketKeySecret = 6c:42:72:46:57:23:3a:3d:4b:54:2d:7b:55:4b:6e:8f:32:5c:21:6a:2e:6e:47:31:57:20:2f:75:26:7b:4d:25 +- ticketMacSecret = 3f:3c:77:53:32:48:79:76:75:7a:50:33:70:65:47:27:32:79:73:7e:73:2c:21:6c:3a:6f:30:28:4c:5c:27:1f +- +- [server] +- accept = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{lport} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Resume session' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- path = os.path.join(cfg.tempd, 'unix.sock') +- stunnel = ResumeTicketSecret(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p16_redirect.py b/tests/plugins/p16_redirect.py +index dd29a19..6d7b852 100644 +--- a/tests/plugins/p16_redirect.py ++++ b/tests/plugins/p16_redirect.py +@@ -17,111 +17,6 @@ class StunnelTest(StunnelAcceptConnect): + self.params.services = ['server'] + + +-class RedirectWrongPeerCert(StunnelTest): +- """Redirect stunnel server test. +- The client presents the *wrong* certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '161. Redirect connection (wrong peer certificate)' +- self.params.context = 'load_wrong_cert' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RedirectNoPeerCert(StunnelTest): +- """Redirect stunnel server test. +- The client does not present any certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '162. Redirect connection (no peer certificate)' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- + class NoRedirectCorrectPeerCert(StunnelTest): + """No redirect stunnel server test. + The client presents the *correct* certificate and the connection is not redirected. +@@ -159,6 +54,7 @@ class NoRedirectCorrectPeerCert(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + redirect = 127.0.0.1:0 + cert = {cfg.certdir}/server_cert.pem +@@ -170,110 +66,6 @@ class NoRedirectCorrectPeerCert(StunnelTest): + return cfgfile + + +-class RedirectWrongChainCert(StunnelTest): +- """Redirect stunnel server test. +- The client does not present any certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '164. Redirect connection (wrong chain)' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyChain = yes +- CAfile = {cfg.certdir}/CACert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RedirectNoChainCert(StunnelTest): +- """No redirect stunnel server test. +- The client does not present any certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '165. Redirect connection (no chain)' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyChain = yes +- CAfile = {cfg.certdir}/CACert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- + class NoRedirectCorrectChainCert(StunnelTest): + """No redirect stunnel server test. + The client presents the *correct* certificate and the connection is not redirected. +@@ -311,6 +103,7 @@ class NoRedirectCorrectChainCert(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + redirect = 127.0.0.1:0 + cert = {cfg.certdir}/server_cert.pem +@@ -335,20 +128,8 @@ class RedirectStunnelTest(Plugin): + + async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: + """Run tests""" +- stunnel = RedirectWrongPeerCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = RedirectNoPeerCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- + stunnel = NoRedirectCorrectPeerCert(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = RedirectWrongChainCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = RedirectNoChainCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- + stunnel = NoRedirectCorrectChainCert(cfg, logger) + await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p17_redirect_proxy.py b/tests/plugins/p17_redirect_proxy.py +index 437d91d..fe9606e 100644 +--- a/tests/plugins/p17_redirect_proxy.py ++++ b/tests/plugins/p17_redirect_proxy.py +@@ -17,115 +17,6 @@ class StunnelTest(StunnelAcceptConnect): + self.params.services = ['server'] + + +-class RedirectProxyWrongPeerCert(StunnelTest): +- """Redirect stunnel server test. +- The client presents the *wrong* certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '171. Redirect proxy connection (wrong peer certificate)' +- self.params.context = 'load_wrong_cert' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- protocol = proxy +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RedirectProxyNoPeerCert(StunnelTest): +- """Redirect stunnel server test. +- The client does not present any certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '172. Redirect proxy connection (no peer certificate)' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- protocol = proxy +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- + class NoRedirectProxyCorrectPeerCert(StunnelTest): + """No redirect stunnel server test. + The client presents the *correct* certificate and the connection is not redirected. +@@ -165,6 +56,7 @@ class NoRedirectProxyCorrectPeerCert(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + redirect = 127.0.0.1:0 + cert = {cfg.certdir}/server_cert.pem +@@ -190,11 +82,5 @@ class RedirectStunnelTest(Plugin): + async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: + """Run tests""" + +- stunnel = RedirectProxyWrongPeerCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = RedirectProxyNoPeerCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- + stunnel = NoRedirectProxyCorrectPeerCert(cfg, logger) + await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p18_redirect_resume.py b/tests/plugins/p18_redirect_resume.py +deleted file mode 100644 +index a0030c0..0000000 +--- a/tests/plugins/p18_redirect_resume.py ++++ /dev/null +@@ -1,273 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- self.params.conn_num = 3 +- self.events.count = 2 +- self.events.skip = [ +- "FORK" +- ] +- +- +-class ResumeRedirectWrongCert(StunnelTest): +- """Checking if redirect TLS client connections works properly when the session is resumed. +- Redirect TLS client connections on certificate-based authentication failures. +- Exactly 2 "TLS accepted: previous session reused" logs for [server] services are expected, +- because the client presents the wrong certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '181. Session resumption and redirect (wrong certificate)' +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- ;cert = {cfg.certdir}/client_cert.pem +- ;wrong certificate +- cert = {cfg.certdir}/stunnel.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class ResumeRedirectNoCert(StunnelTest): +- """Checking if redirect TLS client connections works properly when the session is resumed. +- Redirect TLS client connections on certificate-based authentication failures. +- Exactly 2 "TLS accepted: previous session reused" logs for [server] services are expected, +- because the client does not present the any certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '182. Session resumption and redirect (no certificate)' +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- ;no certificate +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class ResumeNoRedirectCorrectCert(StunnelTest): +- """Checking if redirect TLS client connections works properly when the session is resumed. +- Do not redirect TLS client connections on certificate-based authentication success. +- Just 2 "TLS accepted: previous session reused" log for [server] service +- is expected, because the client presents the *correct* certificate. +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '183. Session resumption and no redirect (valid certificate)' +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- ;correct certificate +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- redirect = 127.0.0.1:0 +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RedirectStunnelTest(Plugin): +- """Stunnel redirect-client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server or "Wrong_connection!" +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Resume redirected connection' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = ResumeRedirectWrongCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = ResumeRedirectNoCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = ResumeNoRedirectCorrectCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p19_reload.py b/tests/plugins/p19_reload.py +deleted file mode 100644 +index 413ae20..0000000 +--- a/tests/plugins/p19_reload.py ++++ /dev/null +@@ -1,96 +0,0 @@ +-"""stunnel client tests""" +- +-import logging +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.ssl_server = True +- self.params.services = ['client'] +- +- +-class ReloadTest(StunnelTest): +- """ Checking if the stunnel works correctly after reloading the configuration. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '191. Reload configuration' +- self.params.context = 'cert_required' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- ;client doesn't present any certificate +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[0]} +- """ +- reload_contents = f""" +- ;client presents a certificate +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[0]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- reload_cfgfile = cfg.tempd / "reload_stunnel_client.conf" +- reload_cfgfile.write_text(reload_contents, encoding="UTF-8") +- return cfgfile, reload_cfgfile +- +- +- +-class StunnelClientTest(Plugin): +- """Stunnel client tests +- HTTP client --> stunnel client --> HTTPS server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Reload configuration' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = ReloadTest(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p20_failover.py b/tests/plugins/p20_failover.py +deleted file mode 100644 +index 95f5a6a..0000000 +--- a/tests/plugins/p20_failover.py ++++ /dev/null +@@ -1,191 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = [ +- 'server1', +- 'server2', +- 'server3', +- 'client' +- ] +- self.params.conn_num = 3 +- +- +-class FailoverRoundRobin(StunnelTest): +- """Checking if the failover strategy for multiple "connect" targets. +- The round robin (rr) strategy ensures fair load distribution. +- Exactly one connection with each service is expected, +- so "TLS accepted: previous session reused" message shows an error. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '201. Failover round robin (rr) strategy' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- failover = rr +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{ports[2]} +- connect = 127.0.0.1:{ports[3]} +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailoverPriority(StunnelTest): +- """Checking if the failover strategy for multiple "connect" targets. +- The priority (prio) strategy uses the order specified in the config file. +- All connections to the [server1] service are expected. +- "TLS accepted: previous session reused" is not achievable with +- the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '202. Failover priority (prio) strategy' +- self.events.count = 2 +- self.events.success = [ +- r"\[server1\].*TLS accepted" +- ] +- self.events.failure = [ +- r"\[server2\].*TLS accepted", +- r"\[server3\].*TLS accepted", +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- failover = prio +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{ports[2]} +- connect = 127.0.0.1:{ports[3]} +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Failover strategy' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = FailoverRoundRobin(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = FailoverPriority(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p21_include.py b/tests/plugins/p21_include.py +deleted file mode 100644 +index 93321d8..0000000 +--- a/tests/plugins/p21_include.py ++++ /dev/null +@@ -1,115 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- +- +-class IncludedConfiguration(StunnelTest): +- """Checking if stunnel works with the configuration placed in a few files. +- All configuration file parts are located in the directory specified with include. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '211. Included configuration files' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- +- with open(f"{cfg.tempd}/conf.d/00-global.conf", "w") as conf: +- conf.write(f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- """ +- ) +- with open(f"{cfg.tempd}/conf.d/01-service.conf", "w") as conf: +- conf.write(f""" +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- """) +- +- contents = f""" +- include = {cfg.tempd}/conf.d +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- os.mkdir(f"{cfg.tempd}/conf.d") +- with open(f"{cfg.tempd}/conf.d/00-global.conf", "w") as conf: +- conf.write(f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- """) +- with open(f"{cfg.tempd}/conf.d/01-service.conf", "w") as conf: +- conf.write(f""" +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """) +- contents = f""" +- include = {cfg.tempd}/conf.d +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Included configuration' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = IncludedConfiguration(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p23_exec_conn.py b/tests/plugins/p23_exec_conn.py +deleted file mode 100644 +index 5dea668..0000000 +--- a/tests/plugins/p23_exec_conn.py ++++ /dev/null +@@ -1,84 +0,0 @@ +-"""stunnel client tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ClientConnectExec +-) +- +- +-class StunnelTest(ClientConnectExec): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.ssl_server = True +- self.params.services = ['client'] +- +- +-class ExecConnect(StunnelTest): +- """Simple execute a local inetd-type program in the client service. +- The execArgs option contains arguments for exec including the program name. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '231. Test exec+connect service' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[0]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client tests +- HTTP client --> stunnel client --> HTTPS server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Execute a local inetd-type program' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- path = os.path.join(cfg.tempd, 'unix.sock') +- stunnel = ExecConnect(cfg, logger, path) +- await stunnel.test_stunnel(cfg) diff --git a/tests/plugins/p24_delay.py b/tests/plugins/p24_delay.py -index a66e833..39d9aeb 100644 +deleted file mode 100644 +index a66e833..0000000 --- a/tests/plugins/p24_delay.py -+++ b/tests/plugins/p24_delay.py -@@ -39,6 +39,13 @@ class RetryDelay(StunnelTest): - self.events.skip = [ - "FORK" - ] -+ -+ # Skip this test when force fail is enabled -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.events.skip = ["Skipping session resumption test in force fail mode"] -+ self.events.count = 0 # Set count to 0 to force skip -+ return -+ - self.events.count = 2 - self.events.success = [ - r"\[server1\].*TLS accepted: previous session reused" -@@ -59,6 +66,12 @@ class RetryDelay(StunnelTest): - ] - self.path = path - -+ async def test_stunnel(self, cfg: Config) -> None: -+ """Override test_stunnel to skip when force fail is enabled""" -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.logger.info("Skipping session resumption test in force fail mode") -+ return -+ await super().test_stunnel(cfg) - - async def prepare_client_cfgfile( - self, cfg: Config, ports: list, service: str -@@ -121,6 +134,13 @@ class RetryNoDelay(StunnelTest): - self.events.skip = [ - "FORK" - ] -+ -+ # Skip this test when force fail is enabled -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.events.skip = ["Skipping session resumption test in force fail mode"] -+ self.events.count = 0 # Set count to 0 to force skip -+ return -+ - self.events.count = 2 - self.events.success = [ - "TLS accepted: new session negotiated" -@@ -141,6 +161,12 @@ class RetryNoDelay(StunnelTest): - ] - self.path = path - -+ async def test_stunnel(self, cfg: Config) -> None: -+ """Override test_stunnel to skip when force fail is enabled""" -+ if os.environ.get('WOLFPROV_FORCE_FAIL') == '1': -+ self.logger.info("Skipping session resumption test in force fail mode") -+ return -+ await super().test_stunnel(cfg) - - async def prepare_client_cfgfile( - self, cfg: Config, ports: list, service: str ++++ /dev/null +@@ -1,211 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ClientConnectExec +-) +- +- +-class StunnelTest(ClientConnectExec): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.services = [ +- 'server1', +- 'server2', +- 'server3', +- 'client' +- ] +- self.params.conn_num = 3 +- +- +-class RetryDelay(StunnelTest): +- """Checking if the delay option works properly when the session is resumed. +- This option delays DNS lookup for the connect option. +- Delayed resolver inflicts failover = prio. +- We expect exactly 2 "TLS accepted: previous session reused" to be +- logged by the [server] service. +- The resumption of the session does not work for the FORK model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '241. Resume session with delay option' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- r"\[server1\].*TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- delay = yes +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{ports[2]} +- connect = 127.0.0.1:{ports[3]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RetryNoDelay(StunnelTest): +- """Checking if disable delay option works properly when the session is resumed. +- This option delays DNS lookup for the connect option. +- We expect exactly 3 "TLS accepted: new session negotiated" to be +- logged by all services, because failover = rr. +- The resumption of the session does not work for the FORK model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '242. Resume session with disable delay option' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: new session negotiated" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- delay = no +- failover = rr +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{ports[2]} +- connect = 127.0.0.1:{ports[3]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Delay option vs resumed session' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- path = os.path.join(cfg.tempd, 'unix.sock') +- stunnel = RetryDelay(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +- +- stunnel = RetryNoDelay(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p25_wrong_client.py b/tests/plugins/p25_wrong_client.py +index 688c9a6..339d7cf 100644 +--- a/tests/plugins/p25_wrong_client.py ++++ b/tests/plugins/p25_wrong_client.py +@@ -60,6 +60,7 @@ class WrongClientTest(StunnelTest): + [{service}] + client = yes + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + ;*** error *** + ;connect = 127.0.0.1:{ports[0]} + cert = {cfg.certdir}/client_cert.pem +diff --git a/tests/plugins/p26_wrong_server.py b/tests/plugins/p26_wrong_server.py +index d79ee33..030b3b0 100644 +--- a/tests/plugins/p26_wrong_server.py ++++ b/tests/plugins/p26_wrong_server.py +@@ -58,6 +58,7 @@ class WrongServerTest(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + ;*** error *** + ;connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.p12 diff --git a/wolfProvider/stunnel/stunnel-WPFF-5.67-wolfssl-5.8.4-wolfprov.patch b/wolfProvider/stunnel/stunnel-WPFF-5.67-wolfssl-5.8.4-wolfprov.patch new file mode 100644 index 00000000..5423f333 --- /dev/null +++ b/wolfProvider/stunnel/stunnel-WPFF-5.67-wolfssl-5.8.4-wolfprov.patch @@ -0,0 +1,3350 @@ +diff --git a/src/options.c b/src/options.c +index e1149a4..c8d6632 100644 +--- a/src/options.c ++++ b/src/options.c +@@ -38,7 +38,7 @@ + #include "prototypes.h" + + #if OPENSSL_VERSION_NUMBER >= 0x10101000L +-#define DEFAULT_CURVES "X25519:P-256:X448:P-521:P-384" ++#define DEFAULT_CURVES "P-256:P-384:P-521" + #else /* OpenSSL version < 1.1.1 */ + #define DEFAULT_CURVES "prime256v1" + #endif /* OpenSSL version >= 1.1.1 */ +diff --git a/tests/certs/maketestcert.sh b/tests/certs/maketestcert.sh +index 3c4f8b5..4f9a557 100755 +--- a/tests/certs/maketestcert.sh ++++ b/tests/certs/maketestcert.sh +@@ -9,6 +9,13 @@ cd "${result_path}" + + mkdir "tmp/" + ++# Unset WOLFPROV_FORCE_FAIL to generate certs ++if [ "${WOLFPROV_FORCE_FAIL}" = "1" ]; then ++ echo "WOLFPROV_FORCE_FAIL is set to 1 - Unsetting to generate certs" ++ export WOLFPROV_FORCE_FAIL= ++ FORCE_FAIL_UNSET=1 ++fi ++ + # create new psk secrets + gen_psk () { + tr -c -d 'A-Za-z0-9' > "maketestcert.log" | head -c 50 > tmp/psk.txt +@@ -90,7 +97,7 @@ cat tmp/server_cert.pem >> tmp/PeerCerts.pem 2>> "maketestcert.log" + cat demoCA/server.key >> tmp/server_cert.pem 2>> "maketestcert.log" + + # create a PKCS#12 file with a server certificate +-$OPENSSL pkcs12 -export -certpbe pbeWithSHA1And3-KeyTripleDES-CBC -in tmp/server_cert.pem -out tmp/server_cert.p12 -passout pass: 1>&2 2>> "maketestcert.log" ++$OPENSSL pkcs12 -export -certpbe AES-256-CBC -keypbe AES-256-CBC -macalg sha256 -in tmp/server_cert.pem -out tmp/server_cert.p12 -passout pass:fipspasswordhere 1>&2 2>> "maketestcert.log" + + # copy new files + if [ -s tmp/stunnel.pem ] && [ -s tmp/CACert.pem ] && [ -s tmp/CACertCRL.pem ] && \ +@@ -113,3 +120,9 @@ rm -rf "tmp/" + + # restore settings + LD_LIBRARY_PATH=$TEMP_LD_LIBRARY_PATH ++ ++# Set WOLFPROV_FORCE_FAIL back to 1 to continue with tests ++if [ "${FORCE_FAIL_UNSET}" = "1" ]; then ++ echo "WOLFPROV_FORCE_FAIL is set to 1 - Setting back to 1 to continue with tests" ++ export WOLFPROV_FORCE_FAIL=1 ++fi +diff --git a/tests/plugins/p01_client_cert.py b/tests/plugins/p01_client_cert.py +index 2df2dab..4d17dcd 100644 +--- a/tests/plugins/p01_client_cert.py ++++ b/tests/plugins/p01_client_cert.py +@@ -19,53 +19,6 @@ class StunnelTest(StunnelAcceptConnect): + self.params.services = ['client'] + + +-class CertTest(StunnelTest): +- """ Checking if the cert option ensures a client certificate. +- The success is expected because the client presents a certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '011. Test \"cert\" option' +- self.params.context = 'cert_required' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[0]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- + class FailureCertTest(StunnelTest): + """ Checking if the cert option ensures a client certificate. + The failure is expected because the client does not present any certificate. +@@ -109,6 +62,7 @@ class FailureCertTest(StunnelTest): + [{service}] + client = yes + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{ports[0]} + ;client does not present any certificate + ;cert = {cfg.certdir}/client_cert.pem +@@ -132,8 +86,5 @@ class StunnelClientTest(Plugin): + + async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: + """Run tests""" +- stunnel = CertTest(cfg, logger) +- await stunnel.test_stunnel(cfg) +- + stunnel = FailureCertTest(cfg, logger) + await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p02_require_cert.py b/tests/plugins/p02_require_cert.py +index f174b6d..613fa6b 100644 +--- a/tests/plugins/p02_require_cert.py ++++ b/tests/plugins/p02_require_cert.py +@@ -56,55 +56,7 @@ class RequireCertTest(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureRequireCertTest(StunnelTest): +- """Checking if the requireCert option requires a client certificate. +- The failure is expected because the client does not present any certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '022. Failure test \"requireCert\" option' +- self.events.count = 1 +- self.events.success = [ +- "peer did not return a certificate" +- ] +- self.events.failure = [ +- #"peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- #"Connection reset by peer", +- #"Connection lost", +- #"Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- requireCert = yes +- +- [{service}] +- accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + """ +@@ -129,5 +81,3 @@ class StunnelServerTest(Plugin): + stunnel = RequireCertTest(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = FailureRequireCertTest(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p03_verify_peer.py b/tests/plugins/p03_verify_peer.py +index cedff93..aa723fe 100644 +--- a/tests/plugins/p03_verify_peer.py ++++ b/tests/plugins/p03_verify_peer.py +@@ -56,59 +56,7 @@ class VerifyPeer(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureVerifyPeer(StunnelTest): +- """Checking if the verifyPeer option verifies the peer certificate. +- The valid peer certificate is stored in the file specified with CAfile. +- The failure is expected because the client presents an incorrect certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '032. Failure test \"verifyPeer\" option' +- self.params.context = 'load_wrong_cert' +- self.events.count = 1 +- self.events.success = [ +- "certificate verify failed", +- "unknown CA" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- #"certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- #"Connection reset by peer", +- #"Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + verifyPeer = yes +@@ -135,5 +83,3 @@ class StunnelServerTest(Plugin): + stunnel = VerifyPeer(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = FailureVerifyPeer(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p04_verify_chain.py b/tests/plugins/p04_verify_chain.py +index d6fb408..f3929c4 100644 +--- a/tests/plugins/p04_verify_chain.py ++++ b/tests/plugins/p04_verify_chain.py +@@ -56,59 +56,7 @@ class VerifyChain(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyChain = yes +- CAfile = {cfg.certdir}/CACert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureVerifyChain(StunnelTest): +- """Checking if the verifyChain option verifies the peer certificate starting from the root CA. +- The self-signed root CA certificate is stored in the file specified with CAfile. +- The failure is expected because python client presents an incorrect certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '042. Failure test \"verifyChain\" option' +- self.params.context = 'load_wrong_cert' +- self.events.count = 1 +- self.events.success = [ +- "certificate verify failed", +- "unknown CA" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- #"certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- #"Connection reset by peer", +- #"Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + verifyChain = yes +@@ -135,5 +83,3 @@ class StunnelServerTest(Plugin): + stunnel = VerifyChain(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = FailureVerifyChain(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p05_verify_crl.py b/tests/plugins/p05_verify_crl.py +index b5a9eae..c363134 100644 +--- a/tests/plugins/p05_verify_crl.py ++++ b/tests/plugins/p05_verify_crl.py +@@ -58,62 +58,7 @@ class VerifyCRL(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyChain = yes +- CAfile = {cfg.certdir}/CACert.pem +- CRLfile = {cfg.certdir}/CACertCRL.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureVerifyCRL(StunnelTest): +- """Checking if the CRL is verified. +- The verifyChain option verifies the peer certificate starting from the root CA. +- The self-signed root CA certificate is stored in the file specified with CAfile. +- Certificate Revocation Lists file is stored in the file specified with CRLfile. +- The failure is expected because the python client presents the revoked certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '052. CRL file with revoked certificate' +- self.params.context = 'load_revoked_cert' +- self.events.count = 1 +- self.events.success = [ +- "certificate verify failed", +- "certificate revoked" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- #"certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- #"Connection reset by peer", +- #"Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + verifyChain = yes +@@ -141,5 +86,3 @@ class StunnelServerTest(Plugin): + stunnel = VerifyCRL(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = FailureVerifyCRL(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p06_psk_secrets.py b/tests/plugins/p06_psk_secrets.py +index 21871cc..00ea9f7 100644 +--- a/tests/plugins/p06_psk_secrets.py ++++ b/tests/plugins/p06_psk_secrets.py +@@ -56,6 +56,7 @@ class PSKSecrets(StunnelTest): + [{service}] + client = yes + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{ports[1]} + PSKsecrets = {cfg.certdir}/psk1.txt + """ +@@ -77,6 +78,7 @@ class PSKSecrets(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + PSKsecrets = {cfg.certdir}/secrets.txt + """ +@@ -128,6 +130,7 @@ class FailurePSKSecrets(StunnelTest): + [{service}] + client = yes + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{ports[1]} + PSKsecrets = {cfg.certdir}/psk2.txt + """ +@@ -149,6 +152,7 @@ class FailurePSKSecrets(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + PSKsecrets = {cfg.certdir}/secrets.txt + """ +diff --git a/tests/plugins/p07_p12cert.py b/tests/plugins/p07_p12cert.py +deleted file mode 100644 +index 662aefc..0000000 +--- a/tests/plugins/p07_p12cert.py ++++ /dev/null +@@ -1,81 +0,0 @@ +-"""stunnel server tests""" +- +-import logging +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.ssl_client = True +- self.params.services = ['server'] +- +- +-class Certp12Test(StunnelTest): +- """Checking if the file containing certificates used by stunnel to authenticate +- itself against the remote client may be in the P12 format. +- The success is expected because the server presents the valid certificate in the P12 format. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '071. Test PKCS#12 certificate' +- self.params.context = 'load_verify_locations"' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.p12 +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelServerTest(Plugin): +- """Stunnel server tests: +- HTTPS client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Existing PKCS#12 certificate' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = Certp12Test(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p08_ipv6.py b/tests/plugins/p08_ipv6.py +deleted file mode 100644 +index 2483a54..0000000 +--- a/tests/plugins/p08_ipv6.py ++++ /dev/null +@@ -1,98 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- +- +-class IPv6Test(StunnelTest): +- """ Checking if IPv6 is supported. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '081. Test IPv6 support' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = ::1:{ports[1]} +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = ::1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'IPv6 support' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = IPv6Test(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p09_bind.py b/tests/plugins/p09_bind.py +index bf44b74..0bcf035 100644 +--- a/tests/plugins/p09_bind.py ++++ b/tests/plugins/p09_bind.py +@@ -55,8 +55,11 @@ class BindingTest(StunnelTest): + + [{service}] + accept = 127.0.0.1:{port} ++ sslVersionMax = TLSv1.2 + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + accept = 127.0.0.1:{port} ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.pem + """ +diff --git a/tests/plugins/p10_fips.py b/tests/plugins/p10_fips.py +deleted file mode 100644 +index 5d2bc56..0000000 +--- a/tests/plugins/p10_fips.py ++++ /dev/null +@@ -1,108 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- +- +-class FIPSTest(StunnelTest): +- """ Checking FIPS mode. +- The success is expected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '101. Test FIPS mode' +- self.events.skip = [ +- "FIPS provider not available", +- "fips mode not supported", +- r"FIPS PROVIDER.*could not load the shared library" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'FIPS mode' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = FIPSTest(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p11_fips_cipher.py b/tests/plugins/p11_fips_cipher.py +deleted file mode 100644 +index 0280a1d..0000000 +--- a/tests/plugins/p11_fips_cipher.py ++++ /dev/null +@@ -1,216 +0,0 @@ +-"""stunnel server tests""" +- +-import logging +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ExpectedConfigurationFailure +-) +- +- +-class StunnelTest(ExpectedConfigurationFailure): +- """Base class for stunnel server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.ssl_client = True +- self.params.services = ['server'] +- +- +-class FailureCipherFIPS(StunnelTest): +- """Checking FIPS mode. +- The cipher "CAMELLIA256-SHA" (TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256) +- is unavailable if FIPS is enabled. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '111. Failure FIPS mode with unavailable cipher' +- self.events.skip = [ +- "FIPS provider not available", +- "fips mode not supported", +- r"FIPS PROVIDER.*could not load the shared library" +- ] +- self.events.count = 1 +- self.events.success = [ +- "no cipher match" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- #"Something went wrong: stunnel 'server' failed", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- ciphers = CAMELLIA256-SHA +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureCiphersuitesFIPS(StunnelTest): +- """Checking FIPS mode. +- The ciphersuite "TLS_CHACHA20_POLY1305_SHA256" is unavailable if FIPS is enabled. +- This option requires OpenSSL 1.1.1 or later. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '112. Failure FIPS mode with unavailable ciphersuite' +- self.events.skip = [ +- "FIPS provider not available", +- "fips mode not supported", +- r"FIPS PROVIDER.*could not load the shared library", +- "Specified option name is not valid here" +- ] +- self.events.count = 1 +- self.events.success = [ +- "disabled for FIPS", +- "no ciphers available" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- ciphersuites = TLS_CHACHA20_POLY1305_SHA256 +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +- +- +-class FailureEllipticCurveFIPS(StunnelTest): +- """ Checking FIPS mode. +- The elliptic curve "sect163r1" is unavailable if FIPS is enabled. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '113. Failure FIPS mode with unavailable elliptic curve' +- self.events.skip = [ +- "FIPS provider not available", +- "fips mode not supported", +- r"FIPS PROVIDER.*could not load the shared library" +- ] +- self.events.count = 1 +- self.events.success = [ +- "no suitable key share", +- "Invalid groups list in 'curves'" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- fips = yes +- curves = sect163r1 +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelServerTest(Plugin): +- """Stunnel server tests: +- HTTPS client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'FIPS mode cipher' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = FailureCipherFIPS(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = FailureCiphersuitesFIPS(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = FailureEllipticCurveFIPS(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p12_sni.py b/tests/plugins/p12_sni.py +deleted file mode 100644 +index 95c5a63..0000000 +--- a/tests/plugins/p12_sni.py ++++ /dev/null +@@ -1,196 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server_virtual', 'client'] +- +- +-class SNITest(StunnelTest): +- """Use the service as a secondary service (a name-based virtual server) +- for Server Name Indication TLS extension. +- SERVICE_NAME (server_virtual) specifies the primary service that +- accepts client connections with the accept option. +- SERVER_NAME_PATTERN (*.mydomain.com) specifies the host name to be redirected. +- The success is expected because the client presents the sni pattern (sni.mydomain.com) +- corresponding with SERVER_NAME_PATTERN (*.mydomain.com). +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '121. Test \"sni\" option' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- sni = sni.mydomain.com +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- cert = {cfg.certdir}/server_cert.pem +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- +- [sni] +- connect = 127.0.0.1:{port} +- sni = server_virtual:*.mydomain.com +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailureSNITest(StunnelTest): +- """Use the service as a secondary service (a name-based virtual server) +- for Server Name Indication TLS extension. +- SERVICE_NAME (server_virtual) specifies the primary service that +- accepts client connections with the accept option. +- SERVER_NAME_PATTERN sni.mydomain.com) specifies the host name to be redirected. +- The success is expected because the client doesn't present any sni pattern. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '122. Failure test \"sni\" option' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- ;the client doesn't present any sni pattern +- ;sni = sni.mydomain.com +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- +- [sni] +- sni = server_virtual:*.mydomain.com +- cert = {cfg.certdir}/server_cert.pem +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Server Name Indication' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = SNITest(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = FailureSNITest(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p13_resume.py b/tests/plugins/p13_resume.py +deleted file mode 100644 +index 7645525..0000000 +--- a/tests/plugins/p13_resume.py ++++ /dev/null +@@ -1,351 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- self.params.conn_num = 3 +- +- +-class ResumePSK(StunnelTest): +- """Checking if the PSK authentication works properly when the session is resumed. +- We expect exactly 2 "TLS accepted: previous session reused" to be logged +- by the [server] service because the client presents the valid PSK. +- PSK identities and corresponding keys are stored in files specified with PSKsecrets. +- This resumption of the session does not work for the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '131. Resume session with PSK authentication' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- PSKsecrets = {cfg.certdir}/psk1.txt +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- PSKsecrets = {cfg.certdir}/secrets.txt +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class ResumeCacheTLSv12(StunnelTest): +- """Checking the cache session resumption. +- We expect exactly 2 "TLS accepted: previous session reused" to be +- logged by the [server] service. +- "options = NO_TICKET" turns off ticket support in TLSv1.2 and older. +- In TLSv1.3, "options = NO_TICKET" switches from using stateful tickets to +- stateless tickets (traditional cache with session id sent in tickets). +- https://github.com/openssl/openssl/issues/10280 +- Session cache resumption does not work with the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '132. Cache session resumption with TLSv1.2' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sslVersion = TLSv1.2 +- options = NO_TICKET +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class SessionResume(StunnelTest): +- """Enable the 'sessionResume' service-level option to allow session resumption. +- This resumption of the session does not work for the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '133. Test enabled \"sessionResume\" option' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sessionResume = yes +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class NoSessionResume(StunnelTest): +- """Disable the 'sessionResume' service-level option to disallow session resumption. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '134. Test disabled \"sessionResume\" option' +- self.events.count = 3 +- self.events.success = [ +- "TLS accepted: new session negotiated" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sessionResume = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Resume session' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = ResumePSK(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = ResumeCacheTLSv12(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = SessionResume(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = NoSessionResume(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p14_resume_ticket.py b/tests/plugins/p14_resume_ticket.py +deleted file mode 100644 +index 22db91e..0000000 +--- a/tests/plugins/p14_resume_ticket.py ++++ /dev/null +@@ -1,213 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ClientConnectExec +-) +- +- +-class StunnelTest(ClientConnectExec): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.services = ['server', 'client'] +- self.params.conn_num = 3 +- self.events.count = 2 +- +- +-class ResumeTicketTLSv12(StunnelTest): +- """Checking the stateless session ticket resumption (RFC 4507bis) with TLSv1.2. +- We expect exactly 2 "TLS accepted: previous session reused" to be logged by the +- [server] service, because [client] connected 3 times (1 new session, 2 reused sessions). +- The following options are used to disable session cache: +- - The "sessionCacheSize = 1" option sets the internal session cache size. +- - "options = -NO_TICKET" (it is the default with OpenSSL 1.1.1 or later) +- Stateless session ticket resumption also works with the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '141. Stateless session ticket resumption with TLSv1.2' +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sslVersion = TLSv1.2 +- sessionCacheSize = 1 +- options = -NO_TICKET +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class ResumeTicketTLSv13(StunnelTest): +- """Checking the stateless session ticket resumption (RFC 4507bis) with TLS 1.3. +- We expect exactly 2 "TLS accepted: previous session reused" to be logged by the +- [server] service, because [client] connected 3 times (1 new session, 2 reused sessions). +- The following options are used to disable session cache: +- - The "sessionCacheSize = 1" option sets the internal session cache size. +- - "options = -NO_TICKET" (it is the default with OpenSSL 1.1.1 or later). +- Stateless session ticket resumption also works with the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '142. Stateless session ticket resumption with TLSv1.3' +- self.events.count = 2 +- self.events.skip = [ +- "Incorrect version of TLS protocol", +- "Invalid protocol version" +- ] +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- sslVersion = TLSv1.3 +- sessionCacheSize = 1 +- options = -NO_TICKET +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Resume session' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- path = os.path.join(cfg.tempd, 'unix.sock') +- stunnel = ResumeTicketTLSv12(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +- +- stunnel = ResumeTicketTLSv13(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p15_resume_secret.py b/tests/plugins/p15_resume_secret.py +deleted file mode 100644 +index 85bd69b..0000000 +--- a/tests/plugins/p15_resume_secret.py ++++ /dev/null +@@ -1,145 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ServerReopen +-) +- +- +-class StunnelTest(ServerReopen): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.services = ['server', 'client'] +- self.params.conn_num = 4 +- self.events.count = 1 +- +- +-class ResumeTicketSecret(StunnelTest): +- """Checking if the reloaded server resume the session with secret keys for +- the session ticket processing. +- We expect exactly 2 "TLS accepted: previous session reused" to be logged by the +- [server] service, because the server holds keys for the session ticket processing. +- The ticket session resumption also works for the FORK model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '151. Session resumption with secret keys' +- self.events.count = 3 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- options = -NO_TICKET +- ticketKeySecret = 6c:42:72:46:57:23:3a:3d:4b:54:2d:7b:55:4b:6e:8f:32:5c:21:6a:2e:6e:47:31:57:20:2f:75:26:7b:4d:25 +- ticketMacSecret = 3f:3c:77:53:32:48:79:76:75:7a:50:33:70:65:47:27:32:79:73:7e:73:2c:21:6c:3a:6f:30:28:4c:5c:27:1f +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +- async def prepare_additional_server_cfgfile( +- self, cfg: Config, ports: list, lport: int +- ) -> pathlib.Path: +- """Create a configuration file for new stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_new_server.pid +- foreground = yes +- debug = debug +- syslog = no +- +- ticketKeySecret = 6c:42:72:46:57:23:3a:3d:4b:54:2d:7b:55:4b:6e:8f:32:5c:21:6a:2e:6e:47:31:57:20:2f:75:26:7b:4d:25 +- ticketMacSecret = 3f:3c:77:53:32:48:79:76:75:7a:50:33:70:65:47:27:32:79:73:7e:73:2c:21:6c:3a:6f:30:28:4c:5c:27:1f +- +- [server] +- accept = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{lport} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Resume session' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- path = os.path.join(cfg.tempd, 'unix.sock') +- stunnel = ResumeTicketSecret(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p16_redirect.py b/tests/plugins/p16_redirect.py +index dd29a19..6d7b852 100644 +--- a/tests/plugins/p16_redirect.py ++++ b/tests/plugins/p16_redirect.py +@@ -17,111 +17,6 @@ class StunnelTest(StunnelAcceptConnect): + self.params.services = ['server'] + + +-class RedirectWrongPeerCert(StunnelTest): +- """Redirect stunnel server test. +- The client presents the *wrong* certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '161. Redirect connection (wrong peer certificate)' +- self.params.context = 'load_wrong_cert' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RedirectNoPeerCert(StunnelTest): +- """Redirect stunnel server test. +- The client does not present any certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '162. Redirect connection (no peer certificate)' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- + class NoRedirectCorrectPeerCert(StunnelTest): + """No redirect stunnel server test. + The client presents the *correct* certificate and the connection is not redirected. +@@ -159,6 +54,7 @@ class NoRedirectCorrectPeerCert(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + redirect = 127.0.0.1:0 + cert = {cfg.certdir}/server_cert.pem +@@ -170,110 +66,6 @@ class NoRedirectCorrectPeerCert(StunnelTest): + return cfgfile + + +-class RedirectWrongChainCert(StunnelTest): +- """Redirect stunnel server test. +- The client does not present any certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '164. Redirect connection (wrong chain)' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyChain = yes +- CAfile = {cfg.certdir}/CACert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RedirectNoChainCert(StunnelTest): +- """No redirect stunnel server test. +- The client does not present any certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '165. Redirect connection (no chain)' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyChain = yes +- CAfile = {cfg.certdir}/CACert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- + class NoRedirectCorrectChainCert(StunnelTest): + """No redirect stunnel server test. + The client presents the *correct* certificate and the connection is not redirected. +@@ -311,6 +103,7 @@ class NoRedirectCorrectChainCert(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + redirect = 127.0.0.1:0 + cert = {cfg.certdir}/server_cert.pem +@@ -335,20 +128,8 @@ class RedirectStunnelTest(Plugin): + + async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: + """Run tests""" +- stunnel = RedirectWrongPeerCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = RedirectNoPeerCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- + stunnel = NoRedirectCorrectPeerCert(cfg, logger) + await stunnel.test_stunnel(cfg) + +- stunnel = RedirectWrongChainCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = RedirectNoChainCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- + stunnel = NoRedirectCorrectChainCert(cfg, logger) + await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p17_redirect_proxy.py b/tests/plugins/p17_redirect_proxy.py +index 437d91d..fe9606e 100644 +--- a/tests/plugins/p17_redirect_proxy.py ++++ b/tests/plugins/p17_redirect_proxy.py +@@ -17,115 +17,6 @@ class StunnelTest(StunnelAcceptConnect): + self.params.services = ['server'] + + +-class RedirectProxyWrongPeerCert(StunnelTest): +- """Redirect stunnel server test. +- The client presents the *wrong* certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '171. Redirect proxy connection (wrong peer certificate)' +- self.params.context = 'load_wrong_cert' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- protocol = proxy +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RedirectProxyNoPeerCert(StunnelTest): +- """Redirect stunnel server test. +- The client does not present any certificate so the connection is redirected. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '172. Redirect proxy connection (no peer certificate)' +- self.events.count = 1 +- self.events.success = [ +- "Redirecting connection" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- protocol = proxy +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- + class NoRedirectProxyCorrectPeerCert(StunnelTest): + """No redirect stunnel server test. + The client presents the *correct* certificate and the connection is not redirected. +@@ -165,6 +56,7 @@ class NoRedirectProxyCorrectPeerCert(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + connect = 127.0.0.1:{port} + redirect = 127.0.0.1:0 + cert = {cfg.certdir}/server_cert.pem +@@ -190,11 +82,5 @@ class RedirectStunnelTest(Plugin): + async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: + """Run tests""" + +- stunnel = RedirectProxyWrongPeerCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = RedirectProxyNoPeerCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- + stunnel = NoRedirectProxyCorrectPeerCert(cfg, logger) + await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p18_redirect_resume.py b/tests/plugins/p18_redirect_resume.py +deleted file mode 100644 +index a0030c0..0000000 +--- a/tests/plugins/p18_redirect_resume.py ++++ /dev/null +@@ -1,273 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- self.params.conn_num = 3 +- self.events.count = 2 +- self.events.skip = [ +- "FORK" +- ] +- +- +-class ResumeRedirectWrongCert(StunnelTest): +- """Checking if redirect TLS client connections works properly when the session is resumed. +- Redirect TLS client connections on certificate-based authentication failures. +- Exactly 2 "TLS accepted: previous session reused" logs for [server] services are expected, +- because the client presents the wrong certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '181. Session resumption and redirect (wrong certificate)' +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- ;cert = {cfg.certdir}/client_cert.pem +- ;wrong certificate +- cert = {cfg.certdir}/stunnel.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class ResumeRedirectNoCert(StunnelTest): +- """Checking if redirect TLS client connections works properly when the session is resumed. +- Redirect TLS client connections on certificate-based authentication failures. +- Exactly 2 "TLS accepted: previous session reused" logs for [server] services are expected, +- because the client does not present the any certificate. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '182. Session resumption and redirect (no certificate)' +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- #"Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- ;no certificate +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/error.py +- redirect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class ResumeNoRedirectCorrectCert(StunnelTest): +- """Checking if redirect TLS client connections works properly when the session is resumed. +- Do not redirect TLS client connections on certificate-based authentication success. +- Just 2 "TLS accepted: previous session reused" log for [server] service +- is expected, because the client presents the *correct* certificate. +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '183. Session resumption and no redirect (valid certificate)' +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- ;correct certificate +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- redirect = 127.0.0.1:0 +- cert = {cfg.certdir}/server_cert.pem +- verifyPeer = yes +- CAfile = {cfg.certdir}/PeerCerts.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RedirectStunnelTest(Plugin): +- """Stunnel redirect-client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server or "Wrong_connection!" +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Resume redirected connection' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = ResumeRedirectWrongCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = ResumeRedirectNoCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = ResumeNoRedirectCorrectCert(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p19_reload.py b/tests/plugins/p19_reload.py +deleted file mode 100644 +index 413ae20..0000000 +--- a/tests/plugins/p19_reload.py ++++ /dev/null +@@ -1,96 +0,0 @@ +-"""stunnel client tests""" +- +-import logging +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.ssl_server = True +- self.params.services = ['client'] +- +- +-class ReloadTest(StunnelTest): +- """ Checking if the stunnel works correctly after reloading the configuration. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '191. Reload configuration' +- self.params.context = 'cert_required' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- ;client doesn't present any certificate +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[0]} +- """ +- reload_contents = f""" +- ;client presents a certificate +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[0]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- reload_cfgfile = cfg.tempd / "reload_stunnel_client.conf" +- reload_cfgfile.write_text(reload_contents, encoding="UTF-8") +- return cfgfile, reload_cfgfile +- +- +- +-class StunnelClientTest(Plugin): +- """Stunnel client tests +- HTTP client --> stunnel client --> HTTPS server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Reload configuration' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = ReloadTest(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p20_failover.py b/tests/plugins/p20_failover.py +deleted file mode 100644 +index 95f5a6a..0000000 +--- a/tests/plugins/p20_failover.py ++++ /dev/null +@@ -1,191 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = [ +- 'server1', +- 'server2', +- 'server3', +- 'client' +- ] +- self.params.conn_num = 3 +- +- +-class FailoverRoundRobin(StunnelTest): +- """Checking if the failover strategy for multiple "connect" targets. +- The round robin (rr) strategy ensures fair load distribution. +- Exactly one connection with each service is expected, +- so "TLS accepted: previous session reused" message shows an error. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '201. Failover round robin (rr) strategy' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- failover = rr +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{ports[2]} +- connect = 127.0.0.1:{ports[3]} +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class FailoverPriority(StunnelTest): +- """Checking if the failover strategy for multiple "connect" targets. +- The priority (prio) strategy uses the order specified in the config file. +- All connections to the [server1] service are expected. +- "TLS accepted: previous session reused" is not achievable with +- the FORK threading model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '202. Failover priority (prio) strategy' +- self.events.count = 2 +- self.events.success = [ +- r"\[server1\].*TLS accepted" +- ] +- self.events.failure = [ +- r"\[server2\].*TLS accepted", +- r"\[server3\].*TLS accepted", +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- failover = prio +- +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{ports[2]} +- connect = 127.0.0.1:{ports[3]} +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Failover strategy' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = FailoverRoundRobin(cfg, logger) +- await stunnel.test_stunnel(cfg) +- +- stunnel = FailoverPriority(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p21_include.py b/tests/plugins/p21_include.py +deleted file mode 100644 +index 93321d8..0000000 +--- a/tests/plugins/p21_include.py ++++ /dev/null +@@ -1,115 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- StunnelAcceptConnect +-) +- +- +-class StunnelTest(StunnelAcceptConnect): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.services = ['server', 'client'] +- +- +-class IncludedConfiguration(StunnelTest): +- """Checking if stunnel works with the configuration placed in a few files. +- All configuration file parts are located in the directory specified with include. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger): +- super().__init__(cfg, logger) +- self.params.description = '211. Included configuration files' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> (pathlib.Path, pathlib.Path): +- """Create a configuration file for a stunnel client.""" +- +- with open(f"{cfg.tempd}/conf.d/00-global.conf", "w") as conf: +- conf.write(f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- """ +- ) +- with open(f"{cfg.tempd}/conf.d/01-service.conf", "w") as conf: +- conf.write(f""" +- [{service}] +- client = yes +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{ports[1]} +- """) +- +- contents = f""" +- include = {cfg.tempd}/conf.d +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- os.mkdir(f"{cfg.tempd}/conf.d") +- with open(f"{cfg.tempd}/conf.d/00-global.conf", "w") as conf: +- conf.write(f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- """) +- with open(f"{cfg.tempd}/conf.d/01-service.conf", "w") as conf: +- conf.write(f""" +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """) +- contents = f""" +- include = {cfg.tempd}/conf.d +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Included configuration' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- stunnel = IncludedConfiguration(cfg, logger) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p23_exec_conn.py b/tests/plugins/p23_exec_conn.py +deleted file mode 100644 +index 5dea668..0000000 +--- a/tests/plugins/p23_exec_conn.py ++++ /dev/null +@@ -1,84 +0,0 @@ +-"""stunnel client tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ClientConnectExec +-) +- +- +-class StunnelTest(ClientConnectExec): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.ssl_server = True +- self.params.services = ['client'] +- +- +-class ExecConnect(StunnelTest): +- """Simple execute a local inetd-type program in the client service. +- The execArgs option contains arguments for exec including the program name. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '231. Test exec+connect service' +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- "TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[0]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client tests +- HTTP client --> stunnel client --> HTTPS server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Execute a local inetd-type program' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- path = os.path.join(cfg.tempd, 'unix.sock') +- stunnel = ExecConnect(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p24_delay.py b/tests/plugins/p24_delay.py +deleted file mode 100644 +index a66e833..0000000 +--- a/tests/plugins/p24_delay.py ++++ /dev/null +@@ -1,211 +0,0 @@ +-"""stunnel client-server tests""" +- +-import logging +-import os +-import pathlib +-from plugin_collection import Plugin +-from maketest import ( +- Config, +- ClientConnectExec +-) +- +- +-class StunnelTest(ClientConnectExec): +- """Base class for stunnel client-server tests.""" +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.services = [ +- 'server1', +- 'server2', +- 'server3', +- 'client' +- ] +- self.params.conn_num = 3 +- +- +-class RetryDelay(StunnelTest): +- """Checking if the delay option works properly when the session is resumed. +- This option delays DNS lookup for the connect option. +- Delayed resolver inflicts failover = prio. +- We expect exactly 2 "TLS accepted: previous session reused" to be +- logged by the [server] service. +- The resumption of the session does not work for the FORK model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '241. Resume session with delay option' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- r"\[server1\].*TLS accepted: previous session reused" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- delay = yes +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{ports[2]} +- connect = 127.0.0.1:{ports[3]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class RetryNoDelay(StunnelTest): +- """Checking if disable delay option works properly when the session is resumed. +- This option delays DNS lookup for the connect option. +- We expect exactly 3 "TLS accepted: new session negotiated" to be +- logged by all services, because failover = rr. +- The resumption of the session does not work for the FORK model. +- """ +- +- def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path): +- super().__init__(cfg, logger, path) +- self.params.description = '242. Resume session with disable delay option' +- self.events.skip = [ +- "FORK" +- ] +- self.events.count = 2 +- self.events.success = [ +- "TLS accepted: new session negotiated" +- ] +- self.events.failure = [ +- "peer did not return a certificate", +- "bad certificate", +- "certificate verify failed", +- "unsupported protocol", +- #"TLS accepted: previous session reused", +- "Redirecting connection", +- "Connection reset by peer", +- "Connection lost", +- "Client received unexpected message", +- "Server received unexpected message", +- "Something went wrong", +- "INTERNAL ERROR" +- ] +- self.path = path +- +- +- async def prepare_client_cfgfile( +- self, cfg: Config, ports: list, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel client.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- delay = no +- failover = rr +- retry = yes +- +- [{service}] +- client = yes +- exec = {cfg.pythondir} +- execArgs = python3 {cfg.scriptdir}/reader.py {self.path} +- connect = 127.0.0.1:{ports[1]} +- connect = 127.0.0.1:{ports[2]} +- connect = 127.0.0.1:{ports[3]} +- cert = {cfg.certdir}/client_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_client.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile, os.devnull +- +- +- async def prepare_server_cfgfile( +- self, cfg: Config, port: int, service: str +- ) -> pathlib.Path: +- """Create a configuration file for a stunnel server.""" +- contents = f""" +- pid = {cfg.tempd}/stunnel_{service}.pid +- foreground = yes +- debug = debug +- syslog = no +- +- [{service}] +- accept = 127.0.0.1:0 +- connect = 127.0.0.1:{port} +- cert = {cfg.certdir}/server_cert.pem +- """ +- cfgfile = cfg.tempd / "stunnel_server.conf" +- cfgfile.write_text(contents, encoding="UTF-8") +- return cfgfile +- +- +-class StunnelClientServerTest(Plugin): +- """Stunnel client-server tests +- HTTP client --> stunnel client --> stunnel server --> HTTP server +- """ +- # pylint: disable=too-few-public-methods +- +- def __init__(self): +- super().__init__() +- self.description = 'Delay option vs resumed session' +- +- +- async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None: +- """Run tests""" +- path = os.path.join(cfg.tempd, 'unix.sock') +- stunnel = RetryDelay(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +- +- stunnel = RetryNoDelay(cfg, logger, path) +- await stunnel.test_stunnel(cfg) +diff --git a/tests/plugins/p25_wrong_client.py b/tests/plugins/p25_wrong_client.py +index 688c9a6..339d7cf 100644 +--- a/tests/plugins/p25_wrong_client.py ++++ b/tests/plugins/p25_wrong_client.py +@@ -60,6 +60,7 @@ class WrongClientTest(StunnelTest): + [{service}] + client = yes + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + ;*** error *** + ;connect = 127.0.0.1:{ports[0]} + cert = {cfg.certdir}/client_cert.pem +diff --git a/tests/plugins/p26_wrong_server.py b/tests/plugins/p26_wrong_server.py +index d79ee33..030b3b0 100644 +--- a/tests/plugins/p26_wrong_server.py ++++ b/tests/plugins/p26_wrong_server.py +@@ -58,6 +58,7 @@ class WrongServerTest(StunnelTest): + + [{service}] + accept = 127.0.0.1:0 ++ sslVersionMax = TLSv1.2 + ;*** error *** + ;connect = 127.0.0.1:{port} + cert = {cfg.certdir}/server_cert.p12 diff --git a/wolfProvider/tcpdump/README.md b/wolfProvider/tcpdump/README.md index 99931b1a..19b67ecf 100644 --- a/wolfProvider/tcpdump/README.md +++ b/wolfProvider/tcpdump/README.md @@ -1,4 +1,4 @@ -`wolfProvider/tcpdump/tcpdump-FIPS-tcpdump-4.99.3-wolfprov.patch` adds support +`wolfProvider/tcpdump/tcpdump-tcpdump-4.99.3-wolfprov-fips.patch` adds support for testing tcpdump `v4.99.3` with FIPS wolfprovider. To use this patch make sure to configure tcpdump with `--enable-wolfprov-fips`. This will disable problematic tests using DES3-CBC. diff --git a/wolfProvider/tcpdump/tcpdump-FIPS-tcpdump-4.99.3-wolfprov.patch b/wolfProvider/tcpdump/tcpdump-tcpdump-4.99.3-wolfprov-fips.patch similarity index 100% rename from wolfProvider/tcpdump/tcpdump-FIPS-tcpdump-4.99.3-wolfprov.patch rename to wolfProvider/tcpdump/tcpdump-tcpdump-4.99.3-wolfprov-fips.patch diff --git a/wolfProvider/xmlsec/xmlsec-FIPS-master-wolfprov.patch b/wolfProvider/xmlsec/xmlsec-master-wolfprov-fips.patch similarity index 100% rename from wolfProvider/xmlsec/xmlsec-FIPS-master-wolfprov.patch rename to wolfProvider/xmlsec/xmlsec-master-wolfprov-fips.patch diff --git a/wolfProvider/xmlsec/xmlsec-FIPS-xmlsec-1_2_37-wolfprov.patch b/wolfProvider/xmlsec/xmlsec-xmlsec-1_2_37-wolfprov-fips.patch similarity index 100% rename from wolfProvider/xmlsec/xmlsec-FIPS-xmlsec-1_2_37-wolfprov.patch rename to wolfProvider/xmlsec/xmlsec-xmlsec-1_2_37-wolfprov-fips.patch