diff options
Diffstat (limited to 'src/tests')
70 files changed, 2105 insertions, 1110 deletions
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index b55469146626..67d3e8200e3f 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -6,12 +6,12 @@ SUBDIRS = resolve asn.1 create hammer verify gssapi dejagnu shlib \ RUN_DB_TEST = $(RUN_SETUP) KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf \ LC_ALL=C $(VALGRIND) -OBJS= adata.o etinfo.o forward.o gcred.o hist.o hooks.o hrealm.o icred.o \ - kdbtest.o localauth.o plugorder.o rdreq.o responder.o s2p.o \ - s4u2proxy.o unlockiter.o +OBJS= adata.o etinfo.o forward.o gcred.o hist.o hooks.o hrealm.o \ + icinterleave.o icred.o kdbtest.o localauth.o plugorder.o rdreq.o \ + responder.o s2p.o s4u2proxy.o unlockiter.o EXTRADEPSRCS= adata.c etinfo.c forward.c gcred.c hist.c hooks.c hrealm.c \ - icred.c kdbtest.c localauth.c plugorder.c rdreq.o responder.c s2p.c \ - s4u2proxy.c unlockiter.c + icinterleave.c icred.c kdbtest.c localauth.c plugorder.c rdreq.o \ + responder.c s2p.c s4u2proxy.c unlockiter.c TEST_DB = ./testdb TEST_REALM = FOO.TEST.REALM @@ -44,6 +44,9 @@ hooks: hooks.o $(KRB5_BASE_DEPLIBS) hrealm: hrealm.o $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o $@ hrealm.o $(KRB5_BASE_LIBS) +icinterleave: icinterleave.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ icinterleave.o $(KRB5_BASE_LIBS) + icred: icred.o $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o $@ icred.o $(KRB5_BASE_LIBS) @@ -115,8 +118,9 @@ kdb_check: kdc.conf krb5.conf $(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) destroy -f $(RM) $(TEST_DB)* stash_file -check-pytests: adata etinfo forward gcred hist hooks hrealm icred kdbtest -check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter +check-pytests: adata etinfo forward gcred hist hooks hrealm icinterleave icred +check-pytests: kdbtest localauth plugorder rdreq responder s2p s4u2proxy +check-pytests: unlockiter $(RUNPYTEST) $(srcdir)/t_general.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_hooks.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_dump.py $(PYTESTFLAGS) @@ -128,6 +132,7 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter $(RUNPYTEST) $(srcdir)/t_otp.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_hostrealm.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_kdb_locking.py $(PYTESTFLAGS) @@ -167,10 +172,14 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter $(RUNPYTEST) $(srcdir)/t_preauth.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_princflags.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_tabdump.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_certauth.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_y2038.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kdcpolicy.py $(PYTESTFLAGS) clean: - $(RM) adata etinfo forward gcred hist hooks hrealm icred kdbtest - $(RM) localauth plugorder rdreq responder s2p s4u2proxy unlockiter + $(RM) adata etinfo forward gcred hist hooks hrealm icinterleave icred + $(RM) kdbtest localauth plugorder rdreq responder s2p s4u2proxy + $(RM) unlockiter $(RM) krb5.conf kdc.conf $(RM) -rf kdc_realm/sandbox ldap $(RM) au.log diff --git a/src/tests/create/kdb5_mkdums.c b/src/tests/create/kdb5_mkdums.c index 622f549f9f2e..7c0666601c48 100644 --- a/src/tests/create/kdb5_mkdums.c +++ b/src/tests/create/kdb5_mkdums.c @@ -247,7 +247,7 @@ add_princ(context, str_newprinc) { /* Add mod princ to db entry */ - krb5_int32 now; + krb5_timestamp now; retval = krb5_timeofday(context, &now); if (retval) { diff --git a/src/tests/dejagnu/pkinit-certs/ca.pem b/src/tests/dejagnu/pkinit-certs/ca.pem index 55fe02c92773..f7421ba02491 100644 --- a/src/tests/dejagnu/pkinit-certs/ca.pem +++ b/src/tests/dejagnu/pkinit-certs/ca.pem @@ -1,29 +1,29 @@ -----BEGIN CERTIFICATE----- -MIIE5TCCA82gAwIBAgIJANsFDWp1HgAaMA0GCSqGSIb3DQEBBQUAMIGnMQswCQYD -VQQGEwJVUzEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czESMBAGA1UEBxMJQ2FtYnJp -ZGdlMQwwCgYDVQQKEwNNSVQxKTAnBgNVBAsTIEluc2VjdXJlIFBraW5pdCBLZXJi -ZXJvcyB0ZXN0IENBMTMwMQYDVQQDFCpwa2luaXQgdGVzdCBzdWl0ZSBDQTsgZG8g -bm90IHVzZSBvdGhlcndpc2UwHhcNMTAwMTA2MTQ1MTI3WhcNMjMwOTE1MTQ1MTI3 -WjCBpzELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxEjAQBgNV -BAcTCUNhbWJyaWRnZTEMMAoGA1UEChMDTUlUMSkwJwYDVQQLEyBJbnNlY3VyZSBQ -a2luaXQgS2VyYmVyb3MgdGVzdCBDQTEzMDEGA1UEAxQqcGtpbml0IHRlc3Qgc3Vp -dGUgQ0E7IGRvIG5vdCB1c2Ugb3RoZXJ3aXNlMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAnYLMe58ny00MgskJP7tZ3PIQRpQkXGLJZKI0HfntCRbIuvmn -ZejPSKdNMyejzRIyjdw1FDJUAnpXYcic3TD5817G5H63UrllAGuy+lhQWNzE6c6K -ueerevR3pMaqHXonaflVasUu5e2AAWVnFbz4x04uLlQejqPwm5sR1xTeLUnVfSY7 -5NbXGIE488iDV0wW8nqGoVWn/TsRd+7KuQUIkJpt8+V6Jk6hPIcPqe6h7mXNGsgc -5dBSqBwVcjU9DbeT4xxxEmgQdLt7qdNwV1ZPLQnTQpogNrT5uf3oSbOTsyM02GOW -riIRmsqq81sfMrpviTRRDwoqTUEhoCSor0UmcwIDAQABo4IBEDCCAQwwHQYDVR0O -BBYEFFn82RUKgTvkFn0cgwyCQpNeWCxYMIHcBgNVHSMEgdQwgdGAFFn82RUKgTvk -Fn0cgwyCQpNeWCxYoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECBMNTWFz -c2FjaHVzZXR0czESMBAGA1UEBxMJQ2FtYnJpZGdlMQwwCgYDVQQKEwNNSVQxKTAn -BgNVBAsTIEluc2VjdXJlIFBraW5pdCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQD -FCpwa2luaXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCCQDb -BQ1qdR4AGjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBVL2Q6Xubs -gm881cAy6esku17/BSTZur7hCLHTGof1ZKNcCXALjmwNYNC3tl6owqpX8CSdBdsD -Bw/Vs9p3mqnaVEoZc8uW8zS6LoAQbcqiYdQHdEXMh3ec8uvAfmdlQsIsm5Ux8q8L -NM6bKnUOqOFOHme+RC4FGOLb8JqnnuQdwyIZaUyQP6hXbw4zyDphfgo1ZlZn20xh -I555kPfAZKEi/d3WY0oN4k+sfCs9tWRNjmqZfKkH1OqRpjCFGG0b0vY77MFRMuPz -YtN2iD3plgla7KkUMljp9th/Z8Ok79uA1TNLYKzoBjlAX0vToxfa8rrSNo1dHFKT -e5Tj7+29DE4I +MIIE5TCCA82gAwIBAgIBATANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTE3MDgyNTE4MzIxMFoXDTI4MDgwNzE4MzIxMFowgacxCzAJ +BgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYDVQQHDAlDYW1i +cmlkZ2UxDDAKBgNVBAoMA01JVDEpMCcGA1UECwwgSW5zZWN1cmUgUEtJTklUIEtl +cmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMMKnBraW5pdCB0ZXN0IHN1aXRlIENBOyBk +byBub3QgdXNlIG90aGVyd2lzZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL8HFT/+Uia/TcSFIJJd7Z7ZFvMOYLhEkCyqRhW1ggDp0xrIAoh/fyxq4qId +S8f7Aurf39kzyS9NtDD2snKwfoLaZpunIXNLCujrlrqdhKsZdtl8aYLmjIhTLu4r +rN5WZIRQULbkLiuqc6ZFOjOZxkR0NkC/CyfQTJO5a2TaMrweLswmY0k5KlAoevps +h+LPXsLC66sqgYuWDD8c1Z9GlI8dW2abRPt+WUKskEgHqYJrCkjvPIZgS7UDAzpU +OCXopDDr/qQ9dnAYzt98r/pCx621/2R4JttZbdsXQDbQaHhV69iJqACqZB0lLyKO +Ka4Y2U5zy3++t6pd3oGlWCr96D0CAwEAAaOCARgwggEUMB0GA1UdDgQWBBSvEuBX +VNKtIomCkLcxpsKp9Ag9qzCB1AYDVR0jBIHMMIHJgBSvEuBXVNKtIomCkLcxpsKp +9Ag9q6GBraSBqjCBpzELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0 +dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoGA1UECgwDTUlUMSkwJwYDVQQLDCBJ +bnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVzdCBDQTEzMDEGA1UEAwwqcGtpbml0 +IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ugb3RoZXJ3aXNlggEBMAsGA1UdDwQE +AwIB/jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQArUoCjqxsY +/m3nx/5BQSkBAL4T5RgWIX+L4y4GXloYYlafpw+SxRq0QffFm5fpCJBnMd21MbPl +k/YA+oq0/76cKyQmJ6h/Wl4KHCKKMmvGuhCEXzmrevk/EJ8lJXNdPfbBueAuLeyU +7X9tO8i9fJ59AZ9YWD9d//puOF+8xeHPxJIxHcR2jHpUOJPtm4yVu1LreHiJJTu4 +Xotp9yMpJu/uJM3aBKVS5N/5JreraLj9N6N8nZ/7nEw9Dj1zzGHcHCcqtcxz1oOH +Zbg5Jo8HhVhIHxKdKLvwEk60P+lkGFIE+IUmhWfcbbprTGs7VhxREwxaWyCapCOk +qlhbJdEcjHr2 -----END CERTIFICATE----- diff --git a/src/tests/dejagnu/pkinit-certs/generic.p12 b/src/tests/dejagnu/pkinit-certs/generic.p12 Binary files differnew file mode 100644 index 000000000000..238baa56bc7b --- /dev/null +++ b/src/tests/dejagnu/pkinit-certs/generic.p12 diff --git a/src/tests/dejagnu/pkinit-certs/generic.pem b/src/tests/dejagnu/pkinit-certs/generic.pem new file mode 100644 index 000000000000..706c2f341c87 --- /dev/null +++ b/src/tests/dejagnu/pkinit-certs/generic.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDZjCCAk4CAQcwDQYJKoZIhvcNAQELBQAwgacxCzAJBgNVBAYTAlVTMRYwFAYD +VQQIDA1NYXNzYWNodXNldHRzMRIwEAYDVQQHDAlDYW1icmlkZ2UxDDAKBgNVBAoM +A01JVDEpMCcGA1UECwwgSW5zZWN1cmUgUEtJTklUIEtlcmJlcm9zIHRlc3QgQ0Ex +MzAxBgNVBAMMKnBraW5pdCB0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVy +d2lzZTAeFw0xNzA4MjUxODMyMTFaFw0yODA4MDcxODMyMTFaMEoxCzAJBgNVBAYT +AlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRQwEgYDVQQKDAtLUkJURVNULkNP +TTENMAsGA1UEAwwEdXNlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AL8HFT/+Uia/TcSFIJJd7Z7ZFvMOYLhEkCyqRhW1ggDp0xrIAoh/fyxq4qIdS8f7 +Aurf39kzyS9NtDD2snKwfoLaZpunIXNLCujrlrqdhKsZdtl8aYLmjIhTLu4rrN5W +ZIRQULbkLiuqc6ZFOjOZxkR0NkC/CyfQTJO5a2TaMrweLswmY0k5KlAoevpsh+LP +XsLC66sqgYuWDD8c1Z9GlI8dW2abRPt+WUKskEgHqYJrCkjvPIZgS7UDAzpUOCXo +pDDr/qQ9dnAYzt98r/pCx621/2R4JttZbdsXQDbQaHhV69iJqACqZB0lLyKOKa4Y +2U5zy3++t6pd3oGlWCr96D0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAniIG+xJ +6rXbrH2kt40GE58fFzrIlzhG4VzncNnpFitvPEMzN0kMa5LBX5/zSYiMawQBQ7C0 +FpCjz+n82VVW8iabCNoqUUNwOP7ZYmsoraHT9klSak/mLfAXOyOG3DUV9jntivnl +HUIiDO7Pf6GnVVROio9psQEVOX1+W1uq9Vs79+F5GI/s0QR9dG0qXvdJ0h5UdVee +8LVXQOi3cQKyBOwECwt0HA0pJwwcD6w9e8Y2NYTeOTamWGQVEV3NlcvtdSVuDJ8y +lTke2YbEKyHdcsQ1vrDHtdyfEmJcgO5c9EL5ptYJB7Yv1QiwWJOhLdT13IBYvOtO +ebOF6zAD73Bpkw== +-----END CERTIFICATE----- diff --git a/src/tests/dejagnu/pkinit-certs/kdc.pem b/src/tests/dejagnu/pkinit-certs/kdc.pem index 5575ab579a33..4eb811debabf 100644 --- a/src/tests/dejagnu/pkinit-certs/kdc.pem +++ b/src/tests/dejagnu/pkinit-certs/kdc.pem @@ -1,25 +1,29 @@ -----BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBpzELMAkGA1UEBhMCVVMx -FjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcTCUNhbWJyaWRnZTEMMAoG -A1UEChMDTUlUMSkwJwYDVQQLEyBJbnNlY3VyZSBQa2luaXQgS2VyYmVyb3MgdGVz -dCBDQTEzMDEGA1UEAxQqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug -b3RoZXJ3aXNlMB4XDTEwMDEwNjE0NTgwOFoXDTIzMDkxNTE0NTgwOFowSjELMAkG -A1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxFTATBgNVBAoTDEtSQlRF -U1QuQ09NIDEMMAoGA1UECxMDS0RDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAnYLMe58ny00MgskJP7tZ3PIQRpQkXGLJZKI0HfntCRbIuvmnZejPSKdN -MyejzRIyjdw1FDJUAnpXYcic3TD5817G5H63UrllAGuy+lhQWNzE6c6KueerevR3 -pMaqHXonaflVasUu5e2AAWVnFbz4x04uLlQejqPwm5sR1xTeLUnVfSY75NbXGIE4 -88iDV0wW8nqGoVWn/TsRd+7KuQUIkJpt8+V6Jk6hPIcPqe6h7mXNGsgc5dBSqBwV -cjU9DbeT4xxxEmgQdLt7qdNwV1ZPLQnTQpogNrT5uf3oSbOTsyM02GOWriIRmsqq -81sfMrpviTRRDwoqTUEhoCSor0UmcwIDAQABo4HEMIHBMAkGA1UdEwQCMAAwCwYD -VR0PBAQDAgPoMBIGA1UdJQQLMAkGBysGAQUCAwUwHQYDVR0OBBYEFFn82RUKgTvk -Fn0cgwyCQpNeWCxYMB8GA1UdIwQYMBaAFFn82RUKgTvkFn0cgwyCQpNeWCxYMAkG -A1UdEgQCMAAwSAYDVR0RBEEwP6A9BgYrBgEFAgKgMzAxoA0bC0tSQlRFU1QuQ09N -oSAwHqADAgEBoRcwFRsGa3JidGd0GwtLUkJURVNULkNPTTANBgkqhkiG9w0BAQUF -AAOCAQEAP0byILHLWPyGlv/1HN34DfIpLdVkgGar2yceMtZ2v/7UjeA5PlZc8DFM -20bTq/vIN0eWDTPLI57e+MzQTMxs2UHsic4su0m5DG0cvQTsBXRK51CW/qUF+4n0 -qSEORULiDF6LNoo8akoLukNBhzBh+aqYt4aB46hhsmDmNZTDP1CXsNGHQI9/L52l -oqpUGx8tBpKIFos95PSajXrQn2u66rSMMi4aawitM2igurHPDMbC+XvEYMtXpOS5 -3PEzXEYiSV3TWLTzIE9ytswHeZyHCbp7XHx0LVZFxzqtIe4qmwJJOGhlbH21Izr4 -feF5h5e2ZrOVREY4cKkJmJhEwsqBVA== +MIIE4TCCA8mgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTE3MDgyNTE4MzIxMFoXDTI4MDgwNzE4MzIxMFowSTELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQwwCgYDVQQDDANLREMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC/BxU//lImv03EhSCSXe2e2RbzDmC4RJAsqkYVtYIA6dMayAKIf38sauKi +HUvH+wLq39/ZM8kvTbQw9rJysH6C2mabpyFzSwro65a6nYSrGXbZfGmC5oyIUy7u +K6zeVmSEUFC25C4rqnOmRTozmcZEdDZAvwsn0EyTuWtk2jK8Hi7MJmNJOSpQKHr6 +bIfiz17CwuurKoGLlgw/HNWfRpSPHVtmm0T7fllCrJBIB6mCawpI7zyGYEu1AwM6 +VDgl6KQw6/6kPXZwGM7ffK/6Qsettf9keCbbWW3bF0A20Gh4VevYiagAqmQdJS8i +jimuGNlOc8t/vreqXd6BpVgq/eg9AgMBAAGjggFzMIIBbzAdBgNVHQ4EFgQUrxLg +V1TSrSKJgpC3MabCqfQIPaswgdQGA1UdIwSBzDCByYAUrxLgV1TSrSKJgpC3MabC +qfQIPauhga2kgaowgacxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNl +dHRzMRIwEAYDVQQHDAlDYW1icmlkZ2UxDDAKBgNVBAoMA01JVDEpMCcGA1UECwwg +SW5zZWN1cmUgUEtJTklUIEtlcmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMMKnBraW5p +dCB0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZYIBATALBgNVHQ8E +BAMCA+gwDAYDVR0TAQH/BAIwADBIBgNVHREEQTA/oD0GBisGAQUCAqAzMDGgDRsL +S1JCVEVTVC5DT02hIDAeoAMCAQGhFzAVGwZrcmJ0Z3QbC0tSQlRFU1QuQ09NMBIG +A1UdJQQLMAkGBysGAQUCAwUwDQYJKoZIhvcNAQELBQADggEBAFMX7ZTpNPdzFwkE +hrab7fSDeoG+mN0yorY8e5Evx6sE7pXOtHgHIjQY2Ys0lk2mhbsIKptL/R6jTxWR +rbmU6jFNFeJgn5ba3NWdhlUiZ8WKe2knp6uc9ZDIK007XaKA4rRoHlJ3vHXoF+ga +JFOYwRzCtAlmsOCQ0UetoC3Ju6Y6NhCXIE8f81dsh6RMADoQT0n/fcLY/JtbbLXK +ANTIWHm0oSX9wvOU/yZkYGuwcPd91cc6Mea8f3J8D/OiatMZXc3719extmeR6Cv6 +aba31kv9wtbxVuxkR7HhjlJhzhqfzfIp3tNREaIxPb/qKGWBOjwxGRqSUkdEqMvD +GjaSlyc= -----END CERTIFICATE----- diff --git a/src/tests/dejagnu/pkinit-certs/make-certs.sh b/src/tests/dejagnu/pkinit-certs/make-certs.sh index b82ef6f83f6e..63f0c6f75b8b 100755 --- a/src/tests/dejagnu/pkinit-certs/make-certs.sh +++ b/src/tests/dejagnu/pkinit-certs/make-certs.sh @@ -4,7 +4,9 @@ NAMETYPE=1 KEYSIZE=2048 DAYS=4000 REALM=KRBTEST.COM +LOWREALM=krbtest.com KRB5_PRINCIPAL_SAN=1.3.6.1.5.2.2 +KRB5_UPN_SAN=1.3.6.1.4.1.311.20.2.3 PKINIT_KDC_EKU=1.3.6.1.5.2.3.5 PKINIT_CLIENT_EKU=1.3.6.1.5.2.3.4 TLS_SERVER_EKU=1.3.6.1.5.5.7.3.1 @@ -85,6 +87,30 @@ keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement basicConstraints = critical,CA:FALSE subjectAltName = otherName:$KRB5_PRINCIPAL_SAN;SEQUENCE:krb5princ_client extendedKeyUsage = $CLIENT_EKU_LIST + +[exts_upn_client] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user@$LOWREALM +extendedKeyUsage = $CLIENT_EKU_LIST + +[exts_upn2_client] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user +extendedKeyUsage = $CLIENT_EKU_LIST + +[exts_upn3_client] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user@$REALM +extendedKeyUsage = $CLIENT_EKU_LIST EOF # Generate a private key. @@ -96,15 +122,14 @@ SUBJECT=ca openssl req -config openssl.cnf -new -x509 -extensions exts_ca \ -set_serial 1 -days $DAYS -key privkey.pem -out ca.pem # Generate a KDC certificate. -SUBJECT=kdc openssl req -config openssl.cnf -new -subj /CN=kdc \ - -key privkey.pem -out kdc.csr +SUBJECT=kdc openssl req -config openssl.cnf -new -key privkey.pem -out kdc.csr SUBJECT=kdc openssl x509 -extfile openssl.cnf -extensions exts_kdc \ -set_serial 2 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \ -out kdc.pem -in kdc.csr # Generate a client certificate and PKCS#12 bundles. -SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \ - -key privkey.pem -out user.csr +SUBJECT=user openssl req -config openssl.cnf -new -key privkey.pem \ + -out user.csr SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_client \ -set_serial 3 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \ -out user.pem -in user.csr @@ -113,5 +138,39 @@ openssl pkcs12 -export -in user.pem -inkey privkey.pem -out user.p12 \ openssl pkcs12 -export -in user.pem -inkey privkey.pem -out user-enc.p12 \ -passout pass:encrypted +# Generate a client certificate and PKCS#12 bundles with a UPN SAN. +SUBJECT=user openssl req -config openssl.cnf -new -key privkey.pem \ + -out user-upn.csr +SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn_client \ + -set_serial 4 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \ + -out user-upn.pem -in user-upn.csr +openssl pkcs12 -export -in user-upn.pem -inkey privkey.pem -out user-upn.p12 \ + -passout pass: + +SUBJECT=user openssl req -config openssl.cnf -new -key privkey.pem \ + -out user-upn2.csr +SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn2_client \ + -set_serial 5 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \ + -out user-upn2.pem -in user-upn2.csr +openssl pkcs12 -export -in user-upn2.pem -inkey privkey.pem \ + -out user-upn2.p12 -passout pass: + +SUBJECT=user openssl req -config openssl.cnf -new -key privkey.pem \ + -out user-upn3.csr +SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn3_client \ + -set_serial 6 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \ + -out user-upn3.pem -in user-upn3.csr +openssl pkcs12 -export -in user-upn3.pem -inkey privkey.pem \ + -out user-upn3.p12 -passout pass: + +# Generate a client certificate and PKCS#12 bundle with no PKINIT extensions. +SUBJECT=user openssl req -config openssl.cnf -new -key privkey.pem \ + -out generic.csr +SUBJECT=user openssl x509 -set_serial 7 -days $DAYS -req -CA ca.pem \ + -CAkey privkey.pem -out generic.pem -in generic.csr +openssl pkcs12 -export -in generic.pem -inkey privkey.pem -out generic.p12 \ + -passout pass: + # Clean up. -rm -f openssl.cnf kdc.csr user.csr +rm -f openssl.cnf kdc.csr user.csr user-upn.csr user-upn2.csr user-upn3.csr +rm -f generic.csr diff --git a/src/tests/dejagnu/pkinit-certs/privkey-enc.pem b/src/tests/dejagnu/pkinit-certs/privkey-enc.pem index 9f7816f17951..ee35e5cdcf66 100644 --- a/src/tests/dejagnu/pkinit-certs/privkey-enc.pem +++ b/src/tests/dejagnu/pkinit-certs/privkey-enc.pem @@ -1,30 +1,30 @@ -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,91CA660D6286E453 +DEK-Info: DES-EDE3-CBC,7DF54DB740F92845 -DpJ5bo/AN37NcxTNv0Z4d5YomWqyryqYhuA43FlzWWKubld4Gp+owAv5BUd4VLx7 -Efq23ODfuiuh5zna/ZXnY+9m8RHS5AxDd2Kr1s/fVsn+m2Lw9qS69DLjxTjEuDLU -AwmVADqQUbvocZEt0Byn9oY4ku2lGOY/ax7tZ1WegLInnoCqT2xGC6TLw7Gwr3mX -z6xFB2Yv4PbvVU8y4V+ka0p5manxptYkrbAkC+vrC4LPUACdbonmpeXUxAfVV9hL -EMzY74IqY2QS1xFMhbLh2HunfjjC3HZ1wXMf1/LtLl1nnodiOk5o+MTLEHO+npaO -rJn2z3V/eQsr93M8/K5ONQcPAKZGOCmNpNQUj1UHnUHEubhpI+nqRYe3vqem5GaH -8gn+uc1/N6c/Bs037iSLWvkgk8mvHgH/26JobZ8qg9yYgVUl3AIVkkGwLGhE5+Kn -593/p4E5Mb6ttv3ZJ4f3Mz/1b84guhTENY67zxnQEGnpEjfRKoEN1vmHi6mIuWld -rrUCJ/x1Yvy2tN9eyuTNsGCcfvPeY22RrKgl7Wi0EIvBlLPKBQxqXOA7Mi9Acapd -+n5pW2Ka2FABSifZ36owa7SJEJ0GLMtdHmZPirolgIjOZVOMbSj2UuR/kXVZjZUM -LcRcVI1z8NgKF3RKs653HqkphcyRQMMQrL/A38t+v0zFA2P3HPoNWcD+BfKg0H37 -bHPjXdlvAD5yiFXKb1XN99utW5G/qCq5CdzAirm7drxR0bs4ZIV4SwTulvWLW644 -RYes8x7WKg3WUxtair++c1eTwTPhMLz/SxERYXxSUqpxJiRgYTQhwwbE22P6FCWT -H9pso5IMi6AJp35CGaYHi78NPLWVmrxgkkv2uBoDFd/iIQTac60aG/F86aozQD7V -DmHINEcsN3lVUmHinoNTcIfc5EZVEbLQIBhy3XI0UDxWuLnchVlU3ad1OKqknbbi -Ik3lmeLz07JFbpCcMk+xDlQsZYbxcRzyRh0NsWvHXuG77Hbcrnk3ndxT8wADsfOn -foXf1/R/gf7PDmte3nFlpEcJCHyeY1haIqgk4WsnUUKP56O75cGF1ylkaBrDPlLw -WaN2Li537ALo6TyB0jspdCzPqIRt8Gr4muoX0tqFjSfKaWmRb3Y7i6jbVrh8d6KV -xqLse0Vkaip4Lgf/VUWOTvlfHz9nLD0xR6OUPeQ3jxGdhLxmcYec1oRj1aVMlp6f -PyC6TN+NlPEtv6KWWB9OMc420DGOWllvS5+zsm7Ff7/5TkXlWmlhfhrkyQVy8NOe -/3ygPbpSfCFjJMwdbEX+ic/Qjk04f3CluP3FYiIG/Pd6ny6rclrhPHg08X6+sciU -Rj7QtoFpVsDvde2QO0depdoysAG1j1a+sas2lYNPG8hdzbPe20xIJCmF0fWfdxOy -BxxtKzpq46S8xKLfxAMvKrZNuZy5xhs3JMUjpxTIam7ZiQXd752LdzGx2s4CII6d -mkeQ/d32TDACAxyEK8es4Mcm3IoCAq/NjIU/ICwGDeOmfDUpsV2TMrg+aKMKcwUE -UK4bMXercw7Cs0C3o6mdCTFrTtsihHNTrbb7yyN83XK76niSc+LREbuJ8T0vp1Yh +3I3F5dJkYmjX49YRQub+AzWPOJock699vQZV3oxcAabcZWtLVbQ75QBXXBPEtm3j +LAqb3gRxfETHNHsSIEwGtN3rYre1UdKs3Bu9ROQNTvlbCwRdss3JA1kGhJu2o5bu +hf5sjpfR+ivf2prJ4whfhb4+efCHE0Ll669V33D2kbPKX0VCokkRmxsIoVtHd2qu +d1HM/EkjxrOy/GHZ+93mkSeWC4hz56VL5ApGOV4wHuphdvKy121mU0mjtQRKF2El +N7DtM9/AIAkLPx5wxrTJXuELd+BBDPbRMwmvgqCX1m8sJLJT2fBzVKRKWexowp7T +d3j9hT+kMiWCTgd4vJ+i/KPkK460Cy9PzFrzCtWut4jh6rZ+F9Tdp1g4Np0ygWAg +q9tV4RC7ylW0DeseRTXTLuohngfu0h7mXuhutr1Xmq+SoRuhBllZyexV4jJMc1kZ +2nv9RJ+h7mCAQbLSVvWCZpngfK2IcZhi4hfNiiQ/wqc6rE3eaBIR9E60kaCeBpWB +rxZm4VHOrwJw0GsaCRLQez1F65Ulk4TA+7TYJWnW/MGrvBptuBamwxk28Ts6eOee +RVwb/AdY4QBVJKKT+/e3Lfy409evmdTAA2N+tbYzALC1cH4ex4sO0BifaLmKo3t1 +fC2FLna4P9F17bbjcS1lSWVJKodofUEt4H03X7LaMhwe+sLRuKBIoTH2nLPHLIYg +B8NO1yFiJPFL0a8fi9kG8JJlCPkASQC5vcYg6BE40b7h7T4qw0HmkuH3i6TX6bsG +nQlryJ2BfQM+IT3MTEh/T1iHPZcTwFLPF9HMnZ/ydL/nM2kElF6YfMClFvuDGULQ +zmsvG4D/ndSisapJQeoevAwtCHybh8/3cy8CoAjBE9C1JlHOvP2+64rzvFVUAKfa +z5aZQQJKcdXcKcM8u8PgEyCN5x5tBqWQjSHR904k25KRkePAh8SoiSDuNQPwtzbB +RHesvkaSXuUaN7q1+oJzeQvzO8i79ud0Diu5y2KePrlB4HBSWCuWmvz9U+WvGBiw +KpEUAp/YpkqB1as4IUBDNjV1Y77cyUZ+/8EkPgAvB9wltCCAyQ5xi1h70cDJdabj +swabRD5JV1JLalFMDrOeOPZh1heaTNHXV8f7m8rMVeYVzVTM1JoQLlvKxcc3LVfN +9RLn/vTN7Ox//+385UiozC/PAo/Cep6Z1Wz+cwsd62HH0LVimVt2mrmHRKY983cw +U6cZyhvcTB5UOdJdhwbHfnxQipWRu//XRYY/yVdB6W2J4Gzh//adJfKOmHd8+cB+ +y8Q1yZP3diTGkhyY9pkXS7Gv2Q9mcXlMJtoyb7rqBIL/osVTKdsZn7Cj6ZYB6ftF ++hKQKNs/bKXYs3PF09UOInfUf57pENSr1AQBQceAisAsr8znRYsFlpqZ5L8G6um7 +XBneZ1RBj41wheB8g3kL6hj2UrXrE2rxDAw175a3BaxP/Wc2JgGcBWyJTVcZ35Ab +f24UNlrfcJdgEFETEiy12WY2VaqJCSY3J6YSimHDbffX+ku8QgU1shZf9z8K1l1A +OJQzbjlxPZT/k4cfw/Xi0rHdgWGcmL7tKLkTcrG/AixdEoI9KCSlQGSksI8CfFmj -----END RSA PRIVATE KEY----- diff --git a/src/tests/dejagnu/pkinit-certs/privkey.pem b/src/tests/dejagnu/pkinit-certs/privkey.pem index 1825dec4e34d..548e5a8d524a 100644 --- a/src/tests/dejagnu/pkinit-certs/privkey.pem +++ b/src/tests/dejagnu/pkinit-certs/privkey.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEAnYLMe58ny00MgskJP7tZ3PIQRpQkXGLJZKI0HfntCRbIuvmn -ZejPSKdNMyejzRIyjdw1FDJUAnpXYcic3TD5817G5H63UrllAGuy+lhQWNzE6c6K -ueerevR3pMaqHXonaflVasUu5e2AAWVnFbz4x04uLlQejqPwm5sR1xTeLUnVfSY7 -5NbXGIE488iDV0wW8nqGoVWn/TsRd+7KuQUIkJpt8+V6Jk6hPIcPqe6h7mXNGsgc -5dBSqBwVcjU9DbeT4xxxEmgQdLt7qdNwV1ZPLQnTQpogNrT5uf3oSbOTsyM02GOW -riIRmsqq81sfMrpviTRRDwoqTUEhoCSor0UmcwIDAQABAoIBAQCSMh5Tu9S2yUwM -dEZmZiGxhuf+anAZZAOjqT4QeLI/Fmu3yBNM7rq+p7JrAabyp6pOq46EsXXyWtWS -SB742wWUk2quGMNVQAj0TAJyhNgGstr+XJu8k8BBPnlycobhF0lP/oH+uQifl0KR -iSoWLjEG5JTOoXs/UAD6nQMBDDhv9TweEwSyIY9jq1J5Q3wVXm/Nr/FJ/8O53guJ -/TQeo6dtdx6x2+oxKkeWinfxmy2nSoEZd0eb3WUNPZswijO7QgSJolOo83VNqFcn -lj8hYT41zUM4chple8kGnuSV4ql4a1w/52dSTLKJbgukIqvxeDtKNost344eQqkS -Lwcc+NO5AoGBAM0bR8TmFlbP4RJAEOOilXTYgP6Ttd1r1mRXGi3DRPyv4EWGT7WW -MmBHsqU6Mqz+fcoD/AIy1BBdenhaYrrwyCSvitJpoHPjqzOJDX33wUcrnYeincQ3 -PVzpF41O45vTmm692DSJ8t/uR8DhGpCzf/kxuA9ixvdKgMPgBHYeb5zlAoGBAMSY -KZvgwbtlRR25CGaUgOCHtW76puaPcyxEeCbJEKkJO1vZDAf8vi1zXOM4e/gorKHm -349ZrBQfFCrvtZG//KvI12MpjBs0Z/ijSCwS4EkYJaSH+Hm+1ygLdArwWEFkNncL -qQ+Wme1OUoDiAAxRiBKUxUF/pAQqn7X+0MGa2th3AoGBAJ8kRaFu7XJaRUZF01Ts -d4571kqxDXFKFMUyGCvd0Q9G33rSZdJ9QYUW3HP7HgrAQ5WVVdnW2lgAT+BGMUjf -PkvIsKvmLQr+YX3RH1jX/W1dWBM/h64RNll6uj14Mn5bxv2Z68GIL5y0Y5QylMwl -mmwdubSmbb6+Xf6dOJj1sKBJAoGBAJwP0tAMHp6daL2Mmk+cSaZz9KJx1bYnYB1f -CSZ47IHTc0yZQ0S/7VR1ROKXf0njOA+aEBRi8ghTF5ZyDefyySixWdI9NByQgIzP -Sca7AVLlGVTAH4694VzHosngO59FZzsfhYh7XBwW1cW8Ip+kxWlCskgphFFOaNR3 -wM5AGMRHAoGAJELs9VYPRJd7h4dPUa2RqfVPlYkcMwvoLYykY0wE5mjoNaJkQbUr -W5aKhidh4h48fImt2rpB6OYSofYC4yu3VDEr/Kl2nSb8UPE5qEd1pvmdkHSxMNkh -M2diIqot6s2v20lE/6UCqLXonlquRK1MAlyfPw9yZHP9meCvlBsYZXc= +MIIEpAIBAAKCAQEAvwcVP/5SJr9NxIUgkl3tntkW8w5guESQLKpGFbWCAOnTGsgC +iH9/LGrioh1Lx/sC6t/f2TPJL020MPaycrB+gtpmm6chc0sK6OuWup2Eqxl22Xxp +guaMiFMu7ius3lZkhFBQtuQuK6pzpkU6M5nGRHQ2QL8LJ9BMk7lrZNoyvB4uzCZj +STkqUCh6+myH4s9ewsLrqyqBi5YMPxzVn0aUjx1bZptE+35ZQqyQSAepgmsKSO88 +hmBLtQMDOlQ4JeikMOv+pD12cBjO33yv+kLHrbX/ZHgm21lt2xdANtBoeFXr2Imo +AKpkHSUvIo4prhjZTnPLf763ql3egaVYKv3oPQIDAQABAoIBAEe7ACa8d9qm4SvX +FYkAjjakq/JuxrDKxhyPf6utMXjoVGXtDs50matzI1DekVMxlUHe+O5VfMkvc2cj +a5SXY5n9KqRuGKhzWFBoDnxao7Of5zn5dqE5szGJksjKS6pdZHcutXBHtHKfGbgo +rJctuf6AaNLdKfI0TFz4NjRznrN2NyFQGhXzPpq34Qm3Rg91hVlU3A8FYjE7ez6b +vlJBsbKqnvzxEQMWTk0z0bWC79zE1ElH3Hpwfwb2cG7H4EXf0j6N5k2zODg7C45I +xWtlES+OpZqdDH6mKFBQojU375j6rb2plZGkTA+qxX9GvG7GsF5aOM6Wkge7SUeT +NUY2lB0CgYEA83u0TtxCMye1p+ykZwQdcEKR+l4aSjNsM2V2s8Zy4eZseR7f5fgZ +71ggIpzK9pjT55OiYJOwsEkZAPB0gBgiEcqJgow52w3Hg8sUU5LBEahUpx3Qm64W +64WNIOL9oVXYQu1S/yJ3iWPMQcH1xIlDtPPC1LH+yHyEOnGe4szIeccCgYEAyNkN +K2JEbbfK7Wsh3/MOtx5KCkzJzFClTSQZ55IxRUf+myauljKt+kI99jYV6eoicAJv +SMHQeYurLtSkhuyptAHUqo5xgH0HZ7cE7LV1nfam2p588Yg21nIId9XLDPK4AvCx +Phz1oznaiGMu4jB7esozuW4FKxB1kRmUikM8bdsCgYEA23jMRLFhsr6+jclPP9SD +vKck8mtUg0Hq7EEvSEk/UMTlTiA4bhC/P/FNtiVjBfkoOXvoR+mYwK6DLUeRm80l +GKhaXySLGhtHllK91b9Y7NOwypqjaVD5M/9EATraqEy7DUjjITsuSNd+TF/LawbX +0wpOum5fXNRwVEYKlCFHLA0CgYApr3LeSDzvkK/batrTAj1RoEW5sYpIj4xfYFjI +CT2UpYagaPzfS5F0WX9GtJ8Dt4aCPN8f+KnuMCDNTXEAV+o45BBhfcLs6gY5bnDl +OBw7NtAWm8JO1viatXwwcvz7qPysD4yZ2aTZxc4ndH5sj6dxKrpliAIml/nuraJ4 +t8+49QKBgQCxJ7ZDlM9J0quVivSui5aoZ7iLEiu6GSZ5yF1HSNXY69OnqQK3UxMl +aERCn/cKqtquJQK3v1IE6k6uAaoM7PXDVKqKSH0Z1Jpqciqjg+J/i7Vym6oCdjer +6zt6P7Q13f9X9uUlZBnNrT9jk5WjR9pSpxAc0vU78VKa0lZMZ3bROg== -----END RSA PRIVATE KEY----- diff --git a/src/tests/dejagnu/pkinit-certs/user-enc.p12 b/src/tests/dejagnu/pkinit-certs/user-enc.p12 Binary files differindex 107480c6d256..b2648ceaa04b 100644 --- a/src/tests/dejagnu/pkinit-certs/user-enc.p12 +++ b/src/tests/dejagnu/pkinit-certs/user-enc.p12 diff --git a/src/tests/dejagnu/pkinit-certs/user-upn.p12 b/src/tests/dejagnu/pkinit-certs/user-upn.p12 Binary files differnew file mode 100644 index 000000000000..6daa5b378b83 --- /dev/null +++ b/src/tests/dejagnu/pkinit-certs/user-upn.p12 diff --git a/src/tests/dejagnu/pkinit-certs/user-upn.pem b/src/tests/dejagnu/pkinit-certs/user-upn.pem new file mode 100644 index 000000000000..21960ea6e2f1 --- /dev/null +++ b/src/tests/dejagnu/pkinit-certs/user-upn.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTE3MDgyNTE4MzIxMVoXDTI4MDgwNzE4MzIxMVowSjELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvwcVP/5SJr9NxIUgkl3tntkW8w5guESQLKpGFbWCAOnTGsgCiH9/LGri +oh1Lx/sC6t/f2TPJL020MPaycrB+gtpmm6chc0sK6OuWup2Eqxl22XxpguaMiFMu +7ius3lZkhFBQtuQuK6pzpkU6M5nGRHQ2QL8LJ9BMk7lrZNoyvB4uzCZjSTkqUCh6 ++myH4s9ewsLrqyqBi5YMPxzVn0aUjx1bZptE+35ZQqyQSAepgmsKSO88hmBLtQMD +OlQ4JeikMOv+pD12cBjO33yv+kLHrbX/ZHgm21lt2xdANtBoeFXr2ImoAKpkHSUv +Io4prhjZTnPLf763ql3egaVYKv3oPQIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFK8S +4FdU0q0iiYKQtzGmwqn0CD2rMIHUBgNVHSMEgcwwgcmAFK8S4FdU0q0iiYKQtzGm +wqn0CD2roYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz +ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM +IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu +aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P +BAQDAgPoMAwGA1UdEwEB/wQCMAAwKwYDVR0RBCQwIqAgBgorBgEEAYI3FAIDoBIM +EHVzZXJAa3JidGVzdC5jb20wEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0B +AQsFAAOCAQEAceeR7lFXkEEjcMGK/mvNOT5zXcq27ipYuV5HBgGGNLqiawc7NTxF +ocyZf9HujNOMvBNblTml2GJQ9wmyQesVTGgJFTGORS2sFizICq19jISxrv44cdeF +X/KQxNmnviClkL9jfA/6oKU0uSpvUAUet3MmDuo8O7ebVXVEmQdvLrhP9ycHGq8u +qG+5qjN4dpf/ejtCCMGGZdUdPxPosoXJzf17hpyt8/YQohKG2igLSy1O68tuHTXb +L4yiB52JQdnJfOU1a+vUSk425zMI00MU1aLcDxcjI64kxYBpWflDqn9Ky0N6vA1i +OoBZgRFeQSELxUp7SUsK4xO2gPM2w0zzvQ== +-----END CERTIFICATE----- diff --git a/src/tests/dejagnu/pkinit-certs/user-upn2.p12 b/src/tests/dejagnu/pkinit-certs/user-upn2.p12 Binary files differnew file mode 100644 index 000000000000..8f4c6b2d05d1 --- /dev/null +++ b/src/tests/dejagnu/pkinit-certs/user-upn2.p12 diff --git a/src/tests/dejagnu/pkinit-certs/user-upn2.pem b/src/tests/dejagnu/pkinit-certs/user-upn2.pem new file mode 100644 index 000000000000..37e123adec83 --- /dev/null +++ b/src/tests/dejagnu/pkinit-certs/user-upn2.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTE3MDgyNTE4MzIxMVoXDTI4MDgwNzE4MzIxMVowSjELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvwcVP/5SJr9NxIUgkl3tntkW8w5guESQLKpGFbWCAOnTGsgCiH9/LGri +oh1Lx/sC6t/f2TPJL020MPaycrB+gtpmm6chc0sK6OuWup2Eqxl22XxpguaMiFMu +7ius3lZkhFBQtuQuK6pzpkU6M5nGRHQ2QL8LJ9BMk7lrZNoyvB4uzCZjSTkqUCh6 ++myH4s9ewsLrqyqBi5YMPxzVn0aUjx1bZptE+35ZQqyQSAepgmsKSO88hmBLtQMD +OlQ4JeikMOv+pD12cBjO33yv+kLHrbX/ZHgm21lt2xdANtBoeFXr2ImoAKpkHSUv +Io4prhjZTnPLf763ql3egaVYKv3oPQIDAQABo4IBSjCCAUYwHQYDVR0OBBYEFK8S +4FdU0q0iiYKQtzGmwqn0CD2rMIHUBgNVHSMEgcwwgcmAFK8S4FdU0q0iiYKQtzGm +wqn0CD2roYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz +ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM +IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu +aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P +BAQDAgPoMAwGA1UdEwEB/wQCMAAwHwYDVR0RBBgwFqAUBgorBgEEAYI3FAIDoAYM +BHVzZXIwEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0BAQsFAAOCAQEAkYoU +bTCe61BRrB1yw8mIpnXlRrVLV91M8YEr07Jzk4qGfRLXbWf9BnMpxzbU4YVzEifh +w6+gYSWGjgq4kDmp6tcY3IDGvzXkglKMAZv2mpFnBa6ZooEQ96tgg9O9G5Lg8Sv0 +kSkoySJq03xapucEZbhPrtGNHKwB/EDo3T0Iaby+Go9bqkObNfuIFXRXC6HqPBS4 +khss6cJ+daEE3Yg21QZ1BUlncwYbkCzt+xp3YaHlY41gdaMdF0tn6iRJjANAM2Kg +6J45M4GKKT3yo5hJAWIS4lSCZX92g/uiT7BcBhE+vDzi3JuEc1QKajgnza1BMZMG +EEIPWkC+Lfg8scWS5g== +-----END CERTIFICATE----- diff --git a/src/tests/dejagnu/pkinit-certs/user-upn3.p12 b/src/tests/dejagnu/pkinit-certs/user-upn3.p12 Binary files differnew file mode 100644 index 000000000000..da888f519d91 --- /dev/null +++ b/src/tests/dejagnu/pkinit-certs/user-upn3.p12 diff --git a/src/tests/dejagnu/pkinit-certs/user-upn3.pem b/src/tests/dejagnu/pkinit-certs/user-upn3.pem new file mode 100644 index 000000000000..754114f5da3e --- /dev/null +++ b/src/tests/dejagnu/pkinit-certs/user-upn3.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBBjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTE3MDgyNTE4MzIxMVoXDTI4MDgwNzE4MzIxMVowSjELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvwcVP/5SJr9NxIUgkl3tntkW8w5guESQLKpGFbWCAOnTGsgCiH9/LGri +oh1Lx/sC6t/f2TPJL020MPaycrB+gtpmm6chc0sK6OuWup2Eqxl22XxpguaMiFMu +7ius3lZkhFBQtuQuK6pzpkU6M5nGRHQ2QL8LJ9BMk7lrZNoyvB4uzCZjSTkqUCh6 ++myH4s9ewsLrqyqBi5YMPxzVn0aUjx1bZptE+35ZQqyQSAepgmsKSO88hmBLtQMD +OlQ4JeikMOv+pD12cBjO33yv+kLHrbX/ZHgm21lt2xdANtBoeFXr2ImoAKpkHSUv +Io4prhjZTnPLf763ql3egaVYKv3oPQIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFK8S +4FdU0q0iiYKQtzGmwqn0CD2rMIHUBgNVHSMEgcwwgcmAFK8S4FdU0q0iiYKQtzGm +wqn0CD2roYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz +ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM +IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu +aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P +BAQDAgPoMAwGA1UdEwEB/wQCMAAwKwYDVR0RBCQwIqAgBgorBgEEAYI3FAIDoBIM +EHVzZXJAS1JCVEVTVC5DT00wEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0B +AQsFAAOCAQEAurL26+vQNYFbJNAFJ3yHOt1nwAVO4/OlCtgqzOAq0nBs35HY10Qe +y8eRcxrLmm4O/Wy+Rwre2v3pIP0AclvIytDzEm6K3Pgj4yJfUUM3VhnSOlXQP6UG +D9Z9pVxNiDeykj5/SzxwOQAmJbPcMx9aRwP9wOLMwUxi5sKHQlL9YUTC1hffhuYY +Yccc2dHWd5IyaKaLp9yBVXQryNdVTBYrGA2ZqcwETmcXqU/wCo/Rmf10Ra1sj88X +VfTb4Sr0j9RaSKeXRZgbEu6kz9i2WK70dcDke08xRv4xVfrlbXrfIS+Va9WYKxrf +Xb0XCkKp32Q0EHqapeJrCcuQtnDMGvncTQ== +-----END CERTIFICATE----- diff --git a/src/tests/dejagnu/pkinit-certs/user.p12 b/src/tests/dejagnu/pkinit-certs/user.p12 Binary files differindex a7c2baddf67f..e9c044c5b1d0 100644 --- a/src/tests/dejagnu/pkinit-certs/user.p12 +++ b/src/tests/dejagnu/pkinit-certs/user.p12 diff --git a/src/tests/dejagnu/pkinit-certs/user.pem b/src/tests/dejagnu/pkinit-certs/user.pem index e6beefcde771..5b2853bc83d1 100644 --- a/src/tests/dejagnu/pkinit-certs/user.pem +++ b/src/tests/dejagnu/pkinit-certs/user.pem @@ -1,32 +1,28 @@ -----BEGIN CERTIFICATE----- -MIIFkjCCBHqgAwIBAgIIYo5oQQ6iySowDQYJKoZIhvcNAQEFBQAwgacxCzAJBgNV -BAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNodXNldHRzMRIwEAYDVQQHEwlDYW1icmlk -Z2UxDDAKBgNVBAoTA01JVDEpMCcGA1UECxMgSW5zZWN1cmUgUGtpbml0IEtlcmJl -cm9zIHRlc3QgQ0ExMzAxBgNVBAMUKnBraW5pdCB0ZXN0IHN1aXRlIENBOyBkbyBu -b3QgdXNlIG90aGVyd2lzZTAeFw0xMzAxMTcxODU5MDVaFw0yMzEyMzExODU5MDVa -MIGhMQswCQYDVQQGEwJVUzEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czESMBAGA1UE -BxMJQ2FtYnJpZGdlMQwwCgYDVQQKEwNNSVQxKTAnBgNVBAsTIEluc2VjdXJlIFBr -aW5pdCBLZXJiZXJvcyB0ZXN0IENBMS0wKwYDVQQDFCRwa2luaXQgdGVzdCBzdWl0 -ZSBjbGllbnQ7IGRvIG5vdCB1c2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQCdgsx7nyfLTQyCyQk/u1nc8hBGlCRcYslkojQd+e0JFsi6+adl6M9Ip00z -J6PNEjKN3DUUMlQCeldhyJzdMPnzXsbkfrdSuWUAa7L6WFBY3MTpzoq556t69Hek -xqodeidp+VVqxS7l7YABZWcVvPjHTi4uVB6Oo/CbmxHXFN4tSdV9Jjvk1tcYgTjz -yINXTBbyeoahVaf9OxF37sq5BQiQmm3z5XomTqE8hw+p7qHuZc0ayBzl0FKoHBVy -NT0Nt5PjHHESaBB0u3up03BXVk8tCdNCmiA2tPm5/ehJs5OzIzTYY5auIhGayqrz -Wx8yum+JNFEPCipNQSGgJKivRSZzAgMBAAGjggHEMIIBwDAdBgNVHQ4EFgQUWfzZ -FQqBO+QWfRyDDIJCk15YLFgwgdwGA1UdIwSB1DCB0YAUWfzZFQqBO+QWfRyDDIJC -k15YLFihga2kgaowgacxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNodXNl -dHRzMRIwEAYDVQQHEwlDYW1icmlkZ2UxDDAKBgNVBAoTA01JVDEpMCcGA1UECxMg -SW5zZWN1cmUgUGtpbml0IEtlcmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMUKnBraW5p -dCB0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZYIJANsFDWp1HgAa -MA4GA1UdDwEB/wQEAwIE8DB9BgNVHREEdjB0oC4GBisGAQUCAqAkMCKgDRsLS1JC -VEVTVC5DT02hETAPoAMCAQGhCDAGGwR1c2VyoCAGCisGAQQBgjcUAgOgEgwQdXNl -ckBrcmJ0ZXN0LmNvbaAgBgorBgEEAYI3FAIDoBIMEHVzZXJAS1JCVEVTVC5DT00w -JgYDVR0lBB8wHQYHKwYBBQIDBAYIKwYBBQUHAwQGCCsGAQUFBwMCMAkGA1UdEwQC -MAAwDQYJKoZIhvcNAQEFBQADggEBAJZ+5CMbEj9anyH/b/jxUT8yGgYB3KGj7qL+ -RdU2zjgsQUMSdnlqQzpuEcY3z1wK94dYQVsPaYBv+zHl0rXFMfKlm97nVdCJi0ep -vplNAaUlhkma3D8rkPN5LmIdHslpJD6pwbV+o69aCEsrwm38flmEnBX0OUynULod -icDvxOxhmYG2kXmUmF7wZXI+XWX8b/TloDNLAnYfjKytMa3SQdp6wtj76BCk+ZZQ -GAF3D0BS36lkNQ/8buHFhVv/tC/rFvql8DRbFzk6W02Ymq2OhcP0uz67rFZ2KjZ5 -Z0WP1REC8Cv7yoqOKPk8S+1FK+8RdKHjT1n/n+Mws72F72bxQWQ= +MIIE0zCCA7ugAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTE3MDgyNTE4MzIxMVoXDTI4MDgwNzE4MzIxMVowSjELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvwcVP/5SJr9NxIUgkl3tntkW8w5guESQLKpGFbWCAOnTGsgCiH9/LGri +oh1Lx/sC6t/f2TPJL020MPaycrB+gtpmm6chc0sK6OuWup2Eqxl22XxpguaMiFMu +7ius3lZkhFBQtuQuK6pzpkU6M5nGRHQ2QL8LJ9BMk7lrZNoyvB4uzCZjSTkqUCh6 ++myH4s9ewsLrqyqBi5YMPxzVn0aUjx1bZptE+35ZQqyQSAepgmsKSO88hmBLtQMD +OlQ4JeikMOv+pD12cBjO33yv+kLHrbX/ZHgm21lt2xdANtBoeFXr2ImoAKpkHSUv +Io4prhjZTnPLf763ql3egaVYKv3oPQIDAQABo4IBZDCCAWAwHQYDVR0OBBYEFK8S +4FdU0q0iiYKQtzGmwqn0CD2rMIHUBgNVHSMEgcwwgcmAFK8S4FdU0q0iiYKQtzGm +wqn0CD2roYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz +ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM +IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu +aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P +BAQDAgPoMAwGA1UdEwEB/wQCMAAwOQYDVR0RBDIwMKAuBgYrBgEFAgKgJDAioA0b +C0tSQlRFU1QuQ09NoREwD6ADAgEBoQgwBhsEdXNlcjASBgNVHSUECzAJBgcrBgEF +AgMEMA0GCSqGSIb3DQEBCwUAA4IBAQClwfj6ACfmDie1YoKzr3zSWZJKZimv7wG1 +iZMNPE6bw22ZmE+P+Vq6WrY5M5e4u7ZdvFmkVq3rUA0HoU6bk3YLGapgsEAG6W1R +LVzxwoYDf4poOMqjCL34eLFdlVeRDADiulROE8bJGrPLJIiqeii0c7Kzxxuh5nxl +QHDgNV0fHQQJlejgJssOqgGErsCXCq7k6kkqB8MnKVMErRjsYuY3YI2tpjxBq9nA +A9dXgIU1zEUVzfpxzBjL9+2pMctbL1y4/ePpTP1+PlfI81TwrQNvMGYjxKNZM1ab +lZt37n8GQUZQyZ2TacR4JyY+w20ivE/JPN0L3Ncmem6bO1CULpwO -----END CERTIFICATE----- diff --git a/src/tests/deps b/src/tests/deps index 751805061c14..a7f1515bd795 100644 --- a/src/tests/deps +++ b/src/tests/deps @@ -80,8 +80,20 @@ $(OUTPRE)hrealm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ $(top_srcdir)/include/socket-utils.h hrealm.c -$(OUTPRE)icred.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \ - $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h icred.c +$(OUTPRE)icinterleave.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h icinterleave.c +$(OUTPRE)icred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + icred.c $(OUTPRE)kdbtest.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in index 6c146429793d..604f926dec45 100644 --- a/src/tests/gssapi/Makefile.in +++ b/src/tests/gssapi/Makefile.in @@ -15,15 +15,16 @@ SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \ $(srcdir)/t_gssexts.c $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c \ $(srcdir)/t_invalid.c $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \ $(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.c \ - $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c $(srcdir)/t_pcontok.c \ - $(srcdir)/t_prf.c $(srcdir)/t_s4u.c $(srcdir)/t_s4u2proxy_krb5.c \ - $(srcdir)/t_saslname.c $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c + $(srcdir)/t_lifetime.c $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c \ + $(srcdir)/t_pcontok.c $(srcdir)/t_prf.c $(srcdir)/t_s4u.c \ + $(srcdir)/t_s4u2proxy_krb5.c $(srcdir)/t_saslname.c \ + $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c OBJS= ccinit.o ccrefresh.o common.o t_accname.o t_ccselect.o t_ciflags.o \ t_credstore.o t_enctypes.o t_err.o t_export_cred.o t_export_name.o \ t_gssexts.o t_imp_cred.o t_imp_name.o t_invalid.o t_inq_cred.o \ - t_inq_ctx.o t_inq_mechs_name.o t_iov.o t_namingexts.o t_oid.o \ - t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \ + t_inq_ctx.o t_inq_mechs_name.o t_iov.o t_lifetime.o t_namingexts.o \ + t_oid.o t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \ t_spnego.o t_srcattrs.o COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) @@ -31,9 +32,9 @@ COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS) all: ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore t_enctypes \ t_err t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name \ - t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_namingexts \ - t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname t_spnego \ - t_srcattrs + t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime \ + t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname \ + t_spnego t_srcattrs check-unix: t_oid $(RUN_TEST) ./t_invalid @@ -42,8 +43,8 @@ check-unix: t_oid check-pytests: ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore \ t_enctypes t_err t_export_cred t_export_name t_imp_cred t_inq_cred \ - t_inq_ctx t_inq_mechs_name t_iov t_pcontok t_s4u t_s4u2proxy_krb5 \ - t_spnego t_srcattrs + t_inq_ctx t_inq_mechs_name t_iov t_lifetime t_pcontok t_s4u \ + t_s4u2proxy_krb5 t_spnego t_srcattrs $(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS) @@ -88,6 +89,8 @@ t_inq_mechs_name: t_inq_mechs_name.o $(COMMON_DEPS) $(CC_LINK) -o $@ t_inq_mechs_name.o $(COMMON_LIBS) t_iov: t_iov.o $(COMMON_DEPS) $(CC_LINK) -o $@ t_iov.o $(COMMON_LIBS) +t_lifetime: t_lifetime.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_lifetime.o $(COMMON_LIBS) t_namingexts: t_namingexts.o $(COMMON_DEPS) $(CC_LINK) -o $@ t_namingexts.o $(COMMON_LIBS) t_pcontok: t_pcontok.o $(COMMON_DEPS) @@ -111,5 +114,5 @@ clean: $(RM) ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore $(RM) t_enctypes t_err t_export_cred t_export_name t_gssexts t_imp_cred $(RM) t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov - $(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 - $(RM) t_saslname t_spnego t_srcattrs + $(RM) t_lifetime t_namingexts t_oid t_pcontok t_prf t_s4u + $(RM) t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs diff --git a/src/tests/gssapi/deps b/src/tests/gssapi/deps index be3cefbb456b..b784deb638d0 100644 --- a/src/tests/gssapi/deps +++ b/src/tests/gssapi/deps @@ -45,7 +45,8 @@ $(OUTPRE)t_enctypes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ - $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(COM_ERR_DEPS) $(srcdir)/../../lib/gssapi/generic/gssapi_ext.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ @@ -113,6 +114,10 @@ $(OUTPRE)t_iov.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ common.h t_iov.c +$(OUTPRE)t_lifetime.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_lifetime.c $(OUTPRE)t_namingexts.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ diff --git a/src/tests/gssapi/t_authind.py b/src/tests/gssapi/t_authind.py index 316bc4093801..84793beb623f 100644 --- a/src/tests/gssapi/t_authind.py +++ b/src/tests/gssapi/t_authind.py @@ -24,9 +24,8 @@ if ('Attribute auth-indicators Authenticated Complete') not in out: if '73757065727374726f6e67' not in out: fail('Expected auth indicator not seen in name attributes') -out = realm.run(['./t_srcattrs', 'p:service/2'], expected_code=1) -if 'gss_init_sec_context: KDC policy rejects request' not in out: - fail('Expected error message not seen for indicator mismatch') +msg = 'gss_init_sec_context: KDC policy rejects request' +realm.run(['./t_srcattrs', 'p:service/2'], expected_code=1, expected_msg=msg) realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=one two']) out = realm.run(['./t_srcattrs', 'p:service/2']) @@ -35,4 +34,19 @@ if '6f6e65' not in out or '74776f' not in out: fail('Expected auth indicator not seen in name attributes') realm.stop() + +# Test the FAST encrypted challenge auth indicator. +kdcconf = {'realms': {'$realm': {'encrypted_challenge_indicator': 'fast'}}} +realm = K5Realm(kdc_conf=kdcconf) +realm.run([kadminl, 'modprinc', '+requires_preauth', realm.user_princ]) +realm.run([kadminl, 'xst', realm.host_princ]) +realm.kinit(realm.user_princ, password('user')) +realm.kinit(realm.user_princ, password('user'), ['-T', realm.ccache]) +out = realm.run(['./t_srcattrs', 'p:' + realm.host_princ]) +if ('Attribute auth-indicators Authenticated Complete') not in out: + fail('Expected attribute type not seen') +if '66617374' not in out: + fail('Expected auth indicator not seen in name attributes') + +realm.stop() success('GSSAPI auth indicator tests') diff --git a/src/tests/gssapi/t_ccselect.py b/src/tests/gssapi/t_ccselect.py index 6be6b4ec06c1..3503f92699b1 100755 --- a/src/tests/gssapi/t_ccselect.py +++ b/src/tests/gssapi/t_ccselect.py @@ -31,12 +31,20 @@ r2 = K5Realm(create_user=False, realm='KRBTEST2.COM', portbase=62000, host1 = 'p:' + r1.host_princ host2 = 'p:' + r2.host_princ - -# gsserver specifies the target as a GSS name. The resulting -# principal will have the host-based type, but the realm won't be -# known before the client cache is selected (since k5test realms have -# no domain-realm mapping by default). -gssserver = 'h:host@' + hostname +foo = 'foo.krbtest.com' +foo2 = 'foo.krbtest2.com' +foobar = "foo.bar.krbtest.com" + +# These strings specify the target as a GSS name. The resulting +# principal will have the host-based type, with the referral realm +# (since k5test realms have no domain-realm mapping by default). +# krb5_cc_select() will use the fallback realm, which is either the +# uppercased parent domain, or the default realm if the hostname is a +# single component. +gssserver = 'h:host@' + foo +gssserver2 = 'h:host@' + foo2 +gssserver_bar = 'h:host@' + foobar +gsslocal = 'h:host@localhost' # refserver specifies the target as a principal in the referral realm. # The principal won't be treated as a host principal by the @@ -45,9 +53,8 @@ refserver = 'p:host/' + hostname + '@' # Verify that we can't get initiator creds with no credentials in the # collection. -output = r1.run(['./t_ccselect', host1, '-'], expected_code=1) -if 'No Kerberos credentials available' not in output: - fail('Expected error not seen in output when no credentials available') +r1.run(['./t_ccselect', host1, '-'], expected_code=1, + expected_msg='No Kerberos credentials available') # Make a directory collection and use it for client commands in both realms. ccdir = os.path.join(r1.testdir, 'cc') @@ -67,6 +74,18 @@ r1.addprinc(alice, password('alice')) r1.addprinc(bob, password('bob')) r2.addprinc(zaphod, password('zaphod')) +# Create host principals and keytabs for fallback realm tests. +r1.addprinc('host/localhost') +r2.addprinc('host/localhost') +r1.addprinc('host/' + foo) +r2.addprinc('host/' + foo2) +r1.addprinc('host/' + foobar) +r1.extract_keytab('host/localhost', r1.keytab) +r2.extract_keytab('host/localhost', r2.keytab) +r1.extract_keytab('host/' + foo, r1.keytab) +r2.extract_keytab('host/' + foo2, r2.keytab) +r1.extract_keytab('host/' + foobar, r1.keytab) + # Get tickets for one user in each realm (zaphod will be primary). r1.kinit(alice, password('alice')) r2.kinit(zaphod, password('zaphod')) @@ -94,10 +113,29 @@ if output != (zaphod + '\n'): fail('zaphod not chosen as default initiator name for server in r1') # Check that primary cache is used if server realm is unknown. -output = r2.run(['./t_ccselect', gssserver]) +output = r2.run(['./t_ccselect', refserver]) if output != (zaphod + '\n'): fail('zaphod not chosen via primary cache for unknown server realm') -r1.run(['./t_ccselect', gssserver], expected_code=1) +r1.run(['./t_ccselect', gssserver2], expected_code=1) +# Check ccache selection using a fallback realm. +output = r1.run(['./t_ccselect', gssserver]) +if output != (alice + '\n'): + fail('alice not chosen via parent domain fallback') +output = r2.run(['./t_ccselect', gssserver2]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via parent domain fallback') +# Check ccache selection using a fallback realm (default realm). +output = r1.run(['./t_ccselect', gsslocal]) +if output != (alice + '\n'): + fail('alice not chosen via default realm fallback') +output = r2.run(['./t_ccselect', gsslocal]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via default realm fallback') + +# Check that realm ccselect fallback works correctly +r1.run(['./t_ccselect', gssserver_bar], expected_msg=alice) +r2.kinit(zaphod, password('zaphod')) +r1.run(['./t_ccselect', gssserver_bar], expected_msg=alice) # Get a second cred in r1 (bob will be primary). r1.kinit(bob, password('bob')) @@ -105,20 +143,19 @@ r1.kinit(bob, password('bob')) # Try some cache selections using .k5identity. k5id = open(os.path.join(r1.testdir, '.k5identity'), 'w') k5id.write('%s realm=%s\n' % (alice, r1.realm)) -k5id.write('%s service=ho*t host=%s\n' % (zaphod, hostname)) +k5id.write('%s service=ho*t host=localhost\n' % zaphod) k5id.write('noprinc service=bogus') k5id.close() output = r1.run(['./t_ccselect', host1]) if output != (alice + '\n'): fail('alice not chosen via .k5identity realm line.') -output = r2.run(['./t_ccselect', gssserver]) +output = r2.run(['./t_ccselect', gsslocal]) if output != (zaphod + '\n'): fail('zaphod not chosen via .k5identity service/host line.') output = r1.run(['./t_ccselect', refserver]) if output != (bob + '\n'): fail('bob not chosen via primary cache when no .k5identity line matches.') -output = r1.run(['./t_ccselect', 'h:bogus@' + hostname], expected_code=1) -if 'Can\'t find client principal noprinc' not in output: - fail('Expected error not seen when k5identity selects bad principal.') +r1.run(['./t_ccselect', 'h:bogus@' + foo2], expected_code=1, + expected_msg="Can't find client principal noprinc") success('GSSAPI credential selection tests') diff --git a/src/tests/gssapi/t_client_keytab.py b/src/tests/gssapi/t_client_keytab.py index 4c8747a506c1..2da87f45b5b2 100755 --- a/src/tests/gssapi/t_client_keytab.py +++ b/src/tests/gssapi/t_client_keytab.py @@ -15,9 +15,7 @@ realm.extract_keytab(realm.user_princ, realm.client_keytab) realm.extract_keytab(bob, realm.client_keytab) # Test 1: no name/cache specified, pick first principal from client keytab -out = realm.run(['./t_ccselect', phost]) -if realm.user_princ not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost], expected_msg=realm.user_princ) realm.run([kdestroy]) # Test 2: no name/cache specified, pick principal from k5identity @@ -25,36 +23,27 @@ k5idname = os.path.join(realm.testdir, '.k5identity') k5id = open(k5idname, 'w') k5id.write('%s service=host host=%s\n' % (bob, hostname)) k5id.close() -out = realm.run(['./t_ccselect', gssserver]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', gssserver], expected_msg=bob) os.remove(k5idname) realm.run([kdestroy]) # Test 3: no name/cache specified, default ccache has name but no creds realm.run(['./ccinit', realm.ccache, bob]) -out = realm.run(['./t_ccselect', phost]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost], expected_msg=bob) # Leave tickets for next test. # Test 4: name specified, non-collectable default cache doesn't match -out = realm.run(['./t_ccselect', phost, puser], expected_code=1) -if 'Principal in credential cache does not match desired name' not in out: - fail('Expected error not seen') +msg = 'Principal in credential cache does not match desired name' +realm.run(['./t_ccselect', phost, puser], expected_code=1, expected_msg=msg) realm.run([kdestroy]) # Test 5: name specified, nonexistent default cache -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) # Leave tickets for next test. # Test 6: name specified, matches default cache, time to refresh realm.run(['./ccrefresh', realm.ccache, '1']) -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) out = realm.run(['./ccrefresh', realm.ccache]) if int(out) < 1000: fail('Credentials apparently not refreshed') @@ -67,9 +56,8 @@ realm.run([kdestroy]) # Test 8: ccache specified with name but no creds; name not in client keytab realm.run(['./ccinit', realm.ccache, realm.host_princ]) -out = realm.run(['./t_imp_cred', phost], expected_code=1) -if 'Credential cache is empty' not in out: - fail('Expected error not seen') +realm.run(['./t_imp_cred', phost], expected_code=1, + expected_msg='Credential cache is empty') realm.run([kdestroy]) # Test 9: ccache specified with name but no creds; name in client keytab @@ -104,16 +92,12 @@ realm.env['KRB5CCNAME'] = ccname # Test 12: name specified, matching cache in collection with no creds bobcache = os.path.join(ccdir, 'tktbob') realm.run(['./ccinit', bobcache, bob]) -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) # Leave tickets for next test. # Test 13: name specified, matching cache in collection, time to refresh realm.run(['./ccrefresh', bobcache, '1']) -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) out = realm.run(['./ccrefresh', bobcache]) if int(out) < 1000: fail('Credentials apparently not refreshed') @@ -121,22 +105,15 @@ realm.run([kdestroy, '-A']) # Test 14: name specified, collection has default for different principal realm.kinit(realm.user_princ, password('user')) -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') -out = realm.run([klist]) -if 'Default principal: %s\n' % realm.user_princ not in out: - fail('Default cache overwritten by acquire_cred') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) +msg = 'Default principal: %s\n' % realm.user_princ +realm.run([klist], expected_msg=msg) realm.run([kdestroy, '-A']) # Test 15: name specified, collection has no default cache -out = realm.run(['./t_ccselect', phost, pbob]) -if bob not in out: - fail('Authenticated as wrong principal') +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) # Make sure the tickets we acquired didn't become the default -out = realm.run([klist], expected_code=1) -if 'No credentials cache found' not in out: - fail('Expected error not seen') +realm.run([klist], expected_code=1, expected_msg='No credentials cache found') realm.run([kdestroy, '-A']) # Test 16: default client keytab cannot be resolved, but valid @@ -145,8 +122,7 @@ conf = {'libdefaults': {'default_client_keytab_name': '%{'}} bad_cktname = realm.special_env('bad_cktname', False, krb5_conf=conf) del bad_cktname['KRB5_CLIENT_KTNAME'] realm.kinit(realm.user_princ, password('user')) -out = realm.run(['./t_ccselect', phost], env=bad_cktname) -if realm.user_princ not in out: - fail('Expected principal not seen for bad client keytab name') +realm.run(['./t_ccselect', phost], env=bad_cktname, + expected_msg=realm.user_princ) success('Client keytab tests') diff --git a/src/tests/gssapi/t_enctypes.c b/src/tests/gssapi/t_enctypes.c index a2ad18f47aba..3fd31e2f8cd5 100644 --- a/src/tests/gssapi/t_enctypes.c +++ b/src/tests/gssapi/t_enctypes.c @@ -32,6 +32,7 @@ #include "k5-int.h" #include "common.h" +#include "gssapi_ext.h" /* * This test program establishes contexts with the krb5 mech, the default @@ -86,6 +87,9 @@ main(int argc, char *argv[]) gss_krb5_lucid_context_v1_t *ilucid, *alucid; gss_krb5_rfc1964_keydata_t *i1964, *a1964; gss_krb5_cfx_keydata_t *icfx, *acfx; + gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET; + gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF; + unsigned int ssf; size_t count; void *lptr; int c; @@ -139,6 +143,16 @@ main(int argc, char *argv[]) establish_contexts(&mech_krb5, icred, acred, tname, flags, &ictx, &actx, NULL, NULL, NULL); + /* Query the SSF value and range-check the result. */ + major = gss_inquire_sec_context_by_oid(&minor, ictx, ssf_oid, &bufset); + check_gsserr("gss_inquire_sec_context_by_oid(ssf)", major, minor); + if (bufset->elements[0].length != 4) + errout("SSF buffer has unexpected length"); + ssf = load_32_be(bufset->elements[0].value); + if (ssf < 56 || ssf > 256) + errout("SSF value not within acceptable range (56-256)"); + (void)gss_release_buffer_set(&minor, &bufset); + /* Export to lucid contexts. */ major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr); check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor); diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py index 862f229895b2..f513db2b55cf 100755 --- a/src/tests/gssapi/t_enctypes.py +++ b/src/tests/gssapi/t_enctypes.py @@ -58,9 +58,7 @@ def test(msg, ienc, aenc, tktenc='', tktsession='', proto='', isubkey='', # and check that it fails with the expected error message. def test_err(msg, ienc, aenc, expected_err): shutil.copyfile(os.path.join(realm.testdir, 'save'), realm.ccache) - out = realm.run(cmdline(ienc, aenc), expected_code=1) - if expected_err not in out: - fail(msg) + realm.run(cmdline(ienc, aenc), expected_code=1, expected_msg=expected_err) # By default, all of the key enctypes should be aes256. diff --git a/src/tests/gssapi/t_export_cred.py b/src/tests/gssapi/t_export_cred.py index 698835928901..b98962788b58 100755 --- a/src/tests/gssapi/t_export_cred.py +++ b/src/tests/gssapi/t_export_cred.py @@ -23,9 +23,7 @@ def ccache_restore(realm): def check(realm, args): ccache_restore(realm) realm.run(['./t_export_cred'] + args) - output = realm.run([klist, '-f']) - if 'Flags: Ff' not in output: - fail('Forwarded tickets not found in ccache after t_export_cred') + realm.run([klist, '-f'], expected_msg='Flags: Ff') # Check a given set of arguments with no specified mech and with krb5 # and SPNEGO as the specified mech. diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py index e23c936d7f44..6da5fceff3be 100755 --- a/src/tests/gssapi/t_gssapi.py +++ b/src/tests/gssapi/t_gssapi.py @@ -28,57 +28,40 @@ realm.run([kadminl, 'renprinc', 'service1/abraham', 'service1/andrew']) # Test with no acceptor name, including client/keytab principal # mismatch (non-fatal) and missing keytab entry (fatal). -output = realm.run(['./t_accname', 'p:service1/andrew']) -if 'service1/abraham' not in output: - fail('Expected service1/abraham in t_accname output') -output = realm.run(['./t_accname', 'p:service1/barack']) -if 'service1/barack' not in output: - fail('Expected service1/barack in t_accname output') -output = realm.run(['./t_accname', 'p:service2/calvin']) -if 'service2/calvin' not in output: - fail('Expected service1/barack in t_accname output') -output = realm.run(['./t_accname', 'p:service2/dwight'], expected_code=1) -if ' not found in keytab' not in output: - fail('Expected error message not seen in t_accname output') +realm.run(['./t_accname', 'p:service1/andrew'], + expected_msg='service1/abraham') +realm.run(['./t_accname', 'p:service1/barack'], expected_msg='service1/barack') +realm.run(['./t_accname', 'p:service2/calvin'], expected_msg='service2/calvin') +realm.run(['./t_accname', 'p:service2/dwight'], expected_code=1, + expected_msg=' not found in keytab') # Test with acceptor name containing service only, including # client/keytab hostname mismatch (non-fatal) and service name # mismatch (fatal). -output = realm.run(['./t_accname', 'p:service1/andrew', 'h:service1']) -if 'service1/abraham' not in output: - fail('Expected service1/abraham in t_accname output') -output = realm.run(['./t_accname', 'p:service1/andrew', 'h:service2'], - expected_code=1) -if ' not found in keytab' not in output: - fail('Expected error message not seen in t_accname output') -output = realm.run(['./t_accname', 'p:service2/calvin', 'h:service2']) -if 'service2/calvin' not in output: - fail('Expected service2/calvin in t_accname output') -output = realm.run(['./t_accname', 'p:service2/calvin', 'h:service1'], - expected_code=1) -if ' found in keytab but does not match server principal' not in output: - fail('Expected error message not seen in t_accname output') +realm.run(['./t_accname', 'p:service1/andrew', 'h:service1'], + expected_msg='service1/abraham') +realm.run(['./t_accname', 'p:service1/andrew', 'h:service2'], expected_code=1, + expected_msg=' not found in keytab') +realm.run(['./t_accname', 'p:service2/calvin', 'h:service2'], + expected_msg='service2/calvin') +realm.run(['./t_accname', 'p:service2/calvin', 'h:service1'], expected_code=1, + expected_msg=' found in keytab but does not match server principal') # Test with acceptor name containing service and host. Use the # client's un-canonicalized hostname as acceptor input to mirror what # many servers do. -output = realm.run(['./t_accname', 'p:' + realm.host_princ, - 'h:host@%s' % socket.gethostname()]) -if realm.host_princ not in output: - fail('Expected %s in t_accname output' % realm.host_princ) -output = realm.run(['./t_accname', 'p:host/-nomatch-', - 'h:host@%s' % socket.gethostname()], - expected_code=1) -if ' not found in keytab' not in output: - fail('Expected error message not seen in t_accname output') +realm.run(['./t_accname', 'p:' + realm.host_princ, + 'h:host@%s' % socket.gethostname()], expected_msg=realm.host_princ) +realm.run(['./t_accname', 'p:host/-nomatch-', + 'h:host@%s' % socket.gethostname()], expected_code=1, + expected_msg=' not found in keytab') # Test krb5_gss_import_cred. realm.run(['./t_imp_cred', 'p:service1/barack']) realm.run(['./t_imp_cred', 'p:service1/barack', 'service1/barack']) realm.run(['./t_imp_cred', 'p:service1/andrew', 'service1/abraham']) -output = realm.run(['./t_imp_cred', 'p:service2/dwight'], expected_code=1) -if ' not found in keytab' not in output: - fail('Expected error message not seen in t_imp_cred output') +realm.run(['./t_imp_cred', 'p:service2/dwight'], expected_code=1, + expected_msg=' not found in keytab') # Test credential store extension. tmpccname = 'FILE:' + os.path.join(realm.testdir, 'def_cache') @@ -116,10 +99,8 @@ ignore_conf = {'libdefaults': {'ignore_acceptor_hostname': 'true'}} realm = K5Realm(krb5_conf=ignore_conf) realm.run([kadminl, 'addprinc', '-randkey', 'host/-nomatch-']) realm.run([kadminl, 'xst', 'host/-nomatch-']) -output = realm.run(['./t_accname', 'p:host/-nomatch-', - 'h:host@%s' % socket.gethostname()]) -if 'host/-nomatch-' not in output: - fail('Expected host/-nomatch- in t_accname output') +realm.run(['./t_accname', 'p:host/-nomatch-', + 'h:host@%s' % socket.gethostname()], expected_msg='host/-nomatch-') realm.stop() @@ -141,41 +122,25 @@ r3.stop() realm = K5Realm() # Test deferred resolution of the default ccache for initiator creds. -output = realm.run(['./t_inq_cred']) -if realm.user_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.user_princ) -output = realm.run(['./t_inq_cred', '-k']) -if realm.user_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.user_princ) -output = realm.run(['./t_inq_cred', '-s']) -if realm.user_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.user_princ) +realm.run(['./t_inq_cred'], expected_msg=realm.user_princ) +realm.run(['./t_inq_cred', '-k'], expected_msg=realm.user_princ) +realm.run(['./t_inq_cred', '-s'], expected_msg=realm.user_princ) # Test picking a name from the keytab for acceptor creds. -output = realm.run(['./t_inq_cred', '-a']) -if realm.host_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.host_princ) -output = realm.run(['./t_inq_cred', '-k', '-a']) -if realm.host_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.host_princ) -output = realm.run(['./t_inq_cred', '-s', '-a']) -if realm.host_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.host_princ) +realm.run(['./t_inq_cred', '-a'], expected_msg=realm.host_princ) +realm.run(['./t_inq_cred', '-k', '-a'], expected_msg=realm.host_princ) +realm.run(['./t_inq_cred', '-s', '-a'], expected_msg=realm.host_princ) # Test client keytab initiation (non-deferred) with a specified name. realm.extract_keytab(realm.user_princ, realm.client_keytab) os.remove(realm.ccache) -output = realm.run(['./t_inq_cred', '-k']) -if realm.user_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.user_princ) +realm.run(['./t_inq_cred', '-k'], expected_msg=realm.user_princ) # Test deferred client keytab initiation and GSS_C_BOTH cred usage. os.remove(realm.client_keytab) os.remove(realm.ccache) shutil.copyfile(realm.keytab, realm.client_keytab) -output = realm.run(['./t_inq_cred', '-k', '-b']) -if realm.host_princ not in output: - fail('Expected %s in t_inq_cred output' % realm.host_princ) +realm.run(['./t_inq_cred', '-k', '-b'], expected_msg=realm.host_princ) # Test gss_export_name behavior. out = realm.run(['./t_export_name', 'u:x']) @@ -220,4 +185,37 @@ realm.run(['./t_ciflags', 'p:' + realm.host_princ]) # contexts. realm.run(['./t_inq_ctx', 'user', password('user'), 'p:%s' % realm.host_princ]) +if runenv.sizeof_time_t <= 4: + skip_rest('y2038 GSSAPI tests', 'platform has 32-bit time_t') + +# Test lifetime results, using a realm with a large maximum lifetime +# so that we can test ticket end dates after y2038. +realm.stop() +conf = {'realms': {'$realm': {'max_life': '9000d'}}} +realm = K5Realm(kdc_conf=conf, get_creds=False) + +# Check a lifetime string result against an expected number value (or None). +# Allow some variance due to time elapsed during the tests. +def check_lifetime(msg, val, expected): + if expected is None and val != 'indefinite': + fail('%s: expected indefinite, got %s' % (msg, val)) + if expected is not None and val == 'indefinite': + fail('%s: expected %d, got indefinite' % (msg, expected)) + if expected is not None and abs(int(val) - expected) > 100: + fail('%s: expected %d, got %s' % (msg, expected, val)) + +realm.kinit(realm.user_princ, password('user'), flags=['-l', '8500d']) +out = realm.run(['./t_lifetime', 'p:' + realm.host_princ, str(8000 * 86400)]) +ln = out.split('\n') +check_lifetime('icred gss_acquire_cred', ln[0], 8500 * 86400) +check_lifetime('icred gss_inquire_cred', ln[1], 8500 * 86400) +check_lifetime('acred gss_acquire_cred', ln[2], None) +check_lifetime('acred gss_inquire_cred', ln[3], None) +check_lifetime('ictx gss_init_sec_context', ln[4], 8000 * 86400) +check_lifetime('ictx gss_inquire_context', ln[5], 8000 * 86400) +check_lifetime('ictx gss_context_time', ln[6], 8000 * 86400) +check_lifetime('actx gss_accept_sec_context', ln[7], 8000 * 86400 + 300) +check_lifetime('actx gss_inquire_context', ln[8], 8000 * 86400 + 300) +check_lifetime('actx gss_context_time', ln[9], 8000 * 86400 + 300) + success('GSSAPI tests') diff --git a/src/tests/gssapi/t_invalid.c b/src/tests/gssapi/t_invalid.c index 5c8ddac8dc84..2a332a8ae048 100644 --- a/src/tests/gssapi/t_invalid.c +++ b/src/tests/gssapi/t_invalid.c @@ -31,8 +31,8 @@ */ /* - * This file contains regression tests for some GSSAPI krb5 invalid per-message - * token vulnerabilities. + * This file contains regression tests for some GSSAPI invalid token + * vulnerabilities. * * 1. A pre-CFX wrap or MIC token processed with a CFX-only context causes a * null pointer dereference. (The token must use SEAL_ALG_NONE or it will @@ -54,10 +54,13 @@ * causes an integer underflow when computing the original message length, * leading to an allocation error. * + * 5. In the mechglue, truncated encapsulation in the initial context token can + * cause input buffer overruns in gss_accept_sec_context(). + * * Vulnerabilities #1 and #2 also apply to IOV unwrap, although tokens with - * fewer than 16 bytes after the ASN.1 header will be rejected. Vulnerability - * #2 can only be robustly detected using a memory-checking environment such as - * valgrind. + * fewer than 16 bytes after the ASN.1 header will be rejected. + * Vulnerabilities #2 and #5 can only be robustly detected using a + * memory-checking environment such as valgrind. */ #include "k5-int.h" @@ -406,6 +409,48 @@ test_bad_pad(gss_ctx_id_t ctx, const struct test *test) (void)gss_release_buffer(&minor, &out); } +static void +try_accept(void *value, size_t len) +{ + OM_uint32 minor; + gss_buffer_desc in, out; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + + /* Copy the provided value to make input overruns more obvious. */ + in.value = malloc(len); + if (in.value == NULL) + abort(); + memcpy(in.value, value, len); + in.length = len; + (void)gss_accept_sec_context(&minor, &ctx, GSS_C_NO_CREDENTIAL, &in, + GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, + &out, NULL, NULL, NULL); + gss_release_buffer(&minor, &out); + gss_delete_sec_context(&minor, &ctx, GSS_C_NO_BUFFER); + free(in.value); +} + +/* Accept contexts using superficially valid but truncated encapsulations. */ +static void +test_short_encapsulation() +{ + /* Include just the initial application tag, to see if we overrun reading + * the sequence length. */ + try_accept("\x60", 1); + + /* Indicate four additional sequence length bytes, to see if we overrun + * reading them (or skipping them and reading the next byte). */ + try_accept("\x60\x84", 2); + + /* Include an object identifier tag but no length, to see if we overrun + * reading the length. */ + try_accept("\x60\x40\x06", 3); + + /* Include an object identifier tag with a length matching the krb5 mech, + * but no OID bytes, to see if we overrun comparing against mechs. */ + try_accept("\x60\x40\x06\x09", 4); +} + int main(int argc, char **argv) { @@ -425,5 +470,7 @@ main(int argc, char **argv) free_fake_context(ctx); } + test_short_encapsulation(); + return 0; } diff --git a/src/tests/gssapi/t_lifetime.c b/src/tests/gssapi/t_lifetime.c new file mode 100644 index 000000000000..8dcf18621bbf --- /dev/null +++ b/src/tests/gssapi/t_lifetime.c @@ -0,0 +1,140 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_lifetime.c - display cred and context lifetimes */ +/* + * Copyright (C) 2017 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include "common.h" + +/* + * Using the default credential, exercise the GSS functions which accept or + * produce lifetimes. Display the following results, one per line, as ASCII + * integers or the string "indefinite": + * + * initiator cred lifetime according to gss_acquire_cred() + * initiator cred lifetime according to gss_inquire_cred() + * acceptor cred lifetime according to gss_acquire_cred() + * acceptor cred lifetime according to gss_inquire_cred() + * initiator context lifetime according to gss_init_sec_context() + * initiator context lifetime according to gss_inquire_context() + * initiator context lifetime according to gss_context_time() + * acceptor context lifetime according to gss_init_sec_context() + * acceptor context lifetime according to gss_inquire_context() + * acceptor context lifetime according to gss_context_time() + */ + +static void +display_time(OM_uint32 tval) +{ + if (tval == GSS_C_INDEFINITE) + puts("indefinite"); + else + printf("%u\n", (unsigned int)tval); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_cred_id_t icred, acred; + gss_name_t tname; + gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT; + gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok = GSS_C_EMPTY_BUFFER; + OM_uint32 time_req = GSS_C_INDEFINITE, time_rec; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s targetname [time_req]\n", argv[0]); + return 1; + } + tname = import_name(argv[1]); + if (argc >= 3) + time_req = atoll(argv[2]); + + /* Get initiator cred and display its lifetime according to + * gss_acquire_cred and gss_inquire_cred. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5, + GSS_C_INITIATE, &icred, NULL, &time_rec); + check_gsserr("gss_acquire_cred(initiate)", major, minor); + display_time(time_rec); + major = gss_inquire_cred(&minor, icred, NULL, &time_rec, NULL, NULL); + check_gsserr("gss_inquire_cred(initiate)", major, minor); + display_time(time_rec); + + /* Get acceptor cred and display its lifetime according to gss_acquire_cred + * and gss_inquire_cred. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5, + GSS_C_ACCEPT, &acred, NULL, &time_rec); + check_gsserr("gss_acquire_cred(accept)", major, minor); + display_time(time_rec); + major = gss_inquire_cred(&minor, acred, NULL, &time_rec, NULL, NULL); + check_gsserr("gss_inquire_cred(accept)", major, minor); + display_time(time_rec); + + /* Make an initiator context and display its lifetime according to + * gss_init_sec_context, gss_inquire_context, and gss_context_time. */ + major = gss_init_sec_context(&minor, icred, &ictx, tname, &mech_krb5, 0, + time_req, GSS_C_NO_CHANNEL_BINDINGS, &atok, + NULL, &itok, NULL, &time_rec); + check_gsserr("gss_init_sec_context", major, minor); + assert(major == GSS_S_COMPLETE); + display_time(time_rec); + major = gss_inquire_context(&minor, ictx, NULL, NULL, &time_rec, NULL, + NULL, NULL, NULL); + check_gsserr("gss_inquire_context(initiate)", major, minor); + display_time(time_rec); + major = gss_context_time(&minor, ictx, &time_rec); + check_gsserr("gss_context_time(initiate)", major, minor); + display_time(time_rec); + + major = gss_accept_sec_context(&minor, &actx, acred, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, + NULL, &atok, NULL, &time_rec, NULL); + check_gsserr("gss_accept_sec_context", major, minor); + assert(major == GSS_S_COMPLETE); + display_time(time_rec); + major = gss_inquire_context(&minor, actx, NULL, NULL, &time_rec, NULL, + NULL, NULL, NULL); + check_gsserr("gss_inquire_context(accept)", major, minor); + display_time(time_rec); + major = gss_context_time(&minor, actx, &time_rec); + check_gsserr("gss_context_time(accept)", major, minor); + display_time(time_rec); + + (void)gss_release_buffer(&minor, &itok); + (void)gss_release_buffer(&minor, &atok); + (void)gss_release_name(&minor, &tname); + (void)gss_release_cred(&minor, &icred); + (void)gss_release_cred(&minor, &acred); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + return 0; +} diff --git a/src/tests/gssapi/t_s4u.c b/src/tests/gssapi/t_s4u.c index 5bc1e4470bdc..0400f8f61f41 100644 --- a/src/tests/gssapi/t_s4u.c +++ b/src/tests/gssapi/t_s4u.c @@ -242,6 +242,7 @@ main(int argc, char *argv[]) gss_cred_id_t delegated_cred_handle = GSS_C_NO_CREDENTIAL; gss_name_t user = GSS_C_NO_NAME, target = GSS_C_NO_NAME; gss_OID_set mechs; + gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET; if (argc < 2 || argc > 5) { fprintf(stderr, "Usage: %s [--spnego] [user] " @@ -305,6 +306,25 @@ main(int argc, char *argv[]) fprintf(stderr, "\n"); } + if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) { + /* Inquire impersonator status. */ + major = gss_inquire_cred_by_oid(&minor, user_cred_handle, + GSS_KRB5_GET_CRED_IMPERSONATOR, + &bufset); + check_gsserr("gss_inquire_cred_by_oid", major, minor); + if (bufset->count == 0) + errout("gss_inquire_cred_by_oid(user) returned NO impersonator"); + (void)gss_release_buffer_set(&minor, &bufset); + + major = gss_inquire_cred_by_oid(&minor, impersonator_cred_handle, + GSS_KRB5_GET_CRED_IMPERSONATOR, + &bufset); + check_gsserr("gss_inquire_cred_by_oid", major, minor); + if (bufset->count != 0) + errout("gss_inquire_cred_by_oid(svc) returned an impersonator"); + (void)gss_release_buffer_set(&minor, &bufset); + } + (void)gss_release_name(&minor, &user); (void)gss_release_name(&minor, &target); (void)gss_release_cred(&minor, &delegated_cred_handle); diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py index 7366e3915ee3..e4cd68469300 100755 --- a/src/tests/gssapi/t_s4u.py +++ b/src/tests/gssapi/t_s4u.py @@ -42,10 +42,8 @@ if ('auth1: ' + realm.user_princ not in output or # result in no delegated credential being created by # accept_sec_context. realm.kinit(realm.user_princ, password('user'), ['-c', usercache]) -output = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, pservice1, - pservice1, pservice2]) -if 'no credential delegated' not in output: - fail('krb5 -> no delegated cred') +realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, pservice1, + pservice1, pservice2], expected_msg='no credential delegated') # Try S4U2Self. Ask for an S4U2Proxy step; this won't happen because # service/1 isn't allowed to get a forwardable S4U2Self ticket. @@ -61,17 +59,15 @@ if ('Warning: no delegated cred handle' not in output or # Correct that problem and try again. As above, the S4U2Proxy step # won't actually succeed since we don't support that in DB2. realm.run([kadminl, 'modprinc', '+ok_to_auth_as_delegate', service1]) -output = realm.run(['./t_s4u', puser, pservice2], expected_code=1) -if 'NOT_ALLOWED_TO_DELEGATE' not in output: - fail('s4u2self') +realm.run(['./t_s4u', puser, pservice2], expected_code=1, + expected_msg='NOT_ALLOWED_TO_DELEGATE') # Again with SPNEGO. This uses SPNEGO for the initial authentication, # but still uses krb5 for S4U2Proxy--the delegated cred is returned as # a krb5 cred, not a SPNEGO cred, and t_s4u uses the delegated cred # directly rather than saving and reacquiring it. -output = realm.run(['./t_s4u', '--spnego', puser, pservice2], expected_code=1) -if 'NOT_ALLOWED_TO_DELEGATE' not in output: - fail('s4u2self') +realm.run(['./t_s4u', '--spnego', puser, pservice2], expected_code=1, + expected_msg='NOT_ALLOWED_TO_DELEGATE') realm.stop() @@ -148,9 +144,8 @@ realm.stop() # fail, but we can check that the right server principal was used. r1, r2 = cross_realms(2, create_user=False) r1.run([kinit, '-k', r1.host_princ]) -out = r1.run(['./t_s4u', 'p:' + r2.host_princ], expected_code=1) -if 'Server not found in Kerberos database' not in out: - fail('cross-realm s4u2self (t_s4u output)') +r1.run(['./t_s4u', 'p:' + r2.host_princ], expected_code=1, + expected_msg='Server not found in Kerberos database') r1.stop() r2.stop() with open(os.path.join(r2.testdir, 'kdc.log')) as f: diff --git a/src/tests/hammer/kdc5_hammer.c b/src/tests/hammer/kdc5_hammer.c index 0934f33fd340..efb4271e587c 100644 --- a/src/tests/hammer/kdc5_hammer.c +++ b/src/tests/hammer/kdc5_hammer.c @@ -436,12 +436,11 @@ int get_tgt (context, p_client_str, p_client, ccache) { char *cache_name = NULL; /* -f option */ long lifetime = KRB5_DEFAULT_LIFE; /* -l option */ - int options = KRB5_DEFAULT_OPTIONS; krb5_error_code code; krb5_creds my_creds; krb5_timestamp start; - krb5_principal tgt_server; float dt; + krb5_get_init_creds_opt *options; if (!brief) fprintf(stderr, "\tgetting TGT for %s\n", p_client_str); @@ -458,22 +457,6 @@ int get_tgt (context, p_client_str, p_client, ccache) return(-1); } - - if ((code = krb5_build_principal_ext(context, &tgt_server, - krb5_princ_realm(context, *p_client)->length, - krb5_princ_realm(context, *p_client)->data, - tgtname.length, - tgtname.data, - krb5_princ_realm(context, *p_client)->length, - krb5_princ_realm(context, *p_client)->data, - 0))) { - com_err(prog, code, "when setting up tgt principal"); - return(-1); - } - - my_creds.client = *p_client; - my_creds.server = tgt_server; - code = krb5_cc_initialize (context, ccache, *p_client); if (code != 0) { com_err (prog, code, "when initializing cache %s", @@ -481,17 +464,26 @@ int get_tgt (context, p_client_str, p_client, ccache) return(-1); } - my_creds.times.starttime = 0; /* start timer when request - gets to KDC */ - my_creds.times.endtime = start + lifetime; - my_creds.times.renew_till = 0; - if (do_timer) swatch_on(); - code = krb5_get_in_tkt_with_password(context, options, 0, - NULL, patype, p_client_str, ccache, - &my_creds, 0); + code = krb5_get_init_creds_opt_alloc(context, &options); + if (code != 0) { + com_err(prog, code, "when allocating init cred options"); + return(-1); + } + + krb5_get_init_creds_opt_set_tkt_life(options, lifetime); + + code = krb5_get_init_creds_opt_set_out_ccache(context, options, ccache); + if (code != 0) { + com_err(prog, code, "when setting init cred output ccache"); + return(-1); + } + + code = krb5_get_init_creds_password(context, &my_creds, *p_client, + p_client_str, NULL, NULL, 0, NULL, + options); if (do_timer) { dt = swatch_eltime(); in_tkt_times.ht_cumulative += dt; @@ -501,8 +493,7 @@ int get_tgt (context, p_client_str, p_client, ccache) if (dt < in_tkt_times.ht_min) in_tkt_times.ht_min = dt; } - my_creds.server = my_creds.client = 0; - krb5_free_principal(context, tgt_server); + krb5_get_init_creds_opt_free(context, options); krb5_free_cred_contents(context, &my_creds); if (code != 0) { com_err (prog, code, "while getting initial credentials"); diff --git a/src/tests/icinterleave.c b/src/tests/icinterleave.c new file mode 100644 index 000000000000..a1bdd3547f08 --- /dev/null +++ b/src/tests/icinterleave.c @@ -0,0 +1,128 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/icinterleave.c - interleaved init_creds_step test harness */ +/* + * Copyright (C) 2017 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This test harness performs multiple initial creds operations using + * krb5_init_creds_step(), interleaving the operations to test the scoping of + * the preauth state. All principals must have the same password (or not + * require a password). + */ + +#include "k5-int.h" + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +int +main(int argc, char **argv) +{ + const char *password; + char **princstrs; + krb5_principal client; + krb5_init_creds_context *iccs; + krb5_data req, *reps, realm; + krb5_boolean any_left; + int i, nclients, master; + unsigned int flags; + + if (argc < 3) { + fprintf(stderr, "Usage: icinterleave password princ1 princ2 ...\n"); + exit(1); + } + password = argv[1]; + princstrs = argv + 2; + nclients = argc - 2; + + check(krb5_init_context(&ctx)); + + /* Create an initial creds context for each client principal. */ + iccs = calloc(nclients, sizeof(*iccs)); + assert(iccs != NULL); + for (i = 0; i < nclients; i++) { + check(krb5_parse_name(ctx, princstrs[i], &client)); + check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL, + &iccs[i])); + check(krb5_init_creds_set_password(ctx, iccs[i], password)); + krb5_free_principal(ctx, client); + } + + reps = calloc(nclients, sizeof(*reps)); + assert(reps != NULL); + + any_left = TRUE; + while (any_left) { + any_left = FALSE; + for (i = 0; i < nclients; i++) { + if (iccs[i] == NULL) + continue; + any_left = TRUE; + + printf("step %d\n", i + 1); + + req = empty_data(); + realm = empty_data(); + check(krb5_init_creds_step(ctx, iccs[i], &reps[i], &req, &realm, + &flags)); + if (!(flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE)) { + printf("finish %d\n", i + 1); + krb5_init_creds_free(ctx, iccs[i]); + iccs[i] = NULL; + continue; + } + + master = 0; + krb5_free_data_contents(ctx, &reps[i]); + check(krb5_sendto_kdc(ctx, &req, &realm, &reps[i], &master, 0)); + krb5_free_data_contents(ctx, &req); + krb5_free_data_contents(ctx, &realm); + } + } + + for (i = 0; i < nclients; i++) + krb5_free_data_contents(ctx, &reps[i]); + free(reps); + free(iccs); + krb5_free_context(ctx); + return 0; +} diff --git a/src/tests/icred.c b/src/tests/icred.c index 071f91c80219..55f929cd7e77 100644 --- a/src/tests/icred.c +++ b/src/tests/icred.c @@ -35,8 +35,8 @@ * it is very simplistic, but it can be extended as needed. */ +#include "k5-platform.h" #include <krb5.h> -#include <stdio.h> static krb5_context ctx; @@ -59,29 +59,64 @@ main(int argc, char **argv) const char *princstr, *password; krb5_principal client; krb5_init_creds_context icc; + krb5_get_init_creds_opt *opt; krb5_creds creds; + krb5_boolean stepwise = FALSE; + krb5_preauthtype ptypes[64]; + int c, nptypes = 0; + char *val; - if (argc != 3) { - fprintf(stderr, "Usage: icred princname password\n"); - exit(1); + check(krb5_init_context(&ctx)); + check(krb5_get_init_creds_opt_alloc(ctx, &opt)); + + while ((c = getopt(argc, argv, "so:X:")) != -1) { + switch (c) { + case 's': + stepwise = TRUE; + break; + case 'o': + assert(nptypes < 64); + ptypes[nptypes++] = atoi(optarg); + break; + case 'X': + val = strchr(optarg, '='); + if (val != NULL) + *val++ = '\0'; + else + val = "yes"; + check(krb5_get_init_creds_opt_set_pa(ctx, opt, optarg, val)); + break; + default: + abort(); + } } - princstr = argv[1]; - password = argv[2]; - check(krb5_init_context(&ctx)); + argc -= optind; + argv += optind; + if (argc != 2) + abort(); + princstr = argv[0]; + password = argv[1]; + check(krb5_parse_name(ctx, princstr, &client)); - /* Try once with the traditional interface. */ - check(krb5_get_init_creds_password(ctx, &creds, client, password, NULL, - NULL, 0, NULL, NULL)); - krb5_free_cred_contents(ctx, &creds); + if (nptypes > 0) + krb5_get_init_creds_opt_set_preauth_list(opt, ptypes, nptypes); - /* Try again with the step interface. */ - check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL, &icc)); - check(krb5_init_creds_set_password(ctx, icc, password)); - check(krb5_init_creds_get(ctx, icc)); - krb5_init_creds_free(ctx, icc); + if (stepwise) { + /* Use the stepwise interface. */ + check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL, &icc)); + check(krb5_init_creds_set_password(ctx, icc, password)); + check(krb5_init_creds_get(ctx, icc)); + krb5_init_creds_free(ctx, icc); + } else { + /* Use the traditional one-shot interface. */ + check(krb5_get_init_creds_password(ctx, &creds, client, password, NULL, + NULL, 0, NULL, opt)); + krb5_free_cred_contents(ctx, &creds); + } + krb5_get_init_creds_opt_free(ctx, opt); krb5_free_principal(ctx, client); krb5_free_context(ctx); return 0; diff --git a/src/tests/kdbtest.c b/src/tests/kdbtest.c index 3f63cfb5d102..3f61f3e83bbd 100644 --- a/src/tests/kdbtest.c +++ b/src/tests/kdbtest.c @@ -243,8 +243,9 @@ check_entry(krb5_db_entry *ent) static void sim_preauth(krb5_timestamp authtime, krb5_boolean ok, krb5_db_entry **entp) { - /* Both back ends ignore the request parameter for now. */ - krb5_db_audit_as_req(ctx, NULL, *entp, *entp, authtime, + /* Both back ends ignore the request, local_addr, and remote_addr + * parameters for now. */ + krb5_db_audit_as_req(ctx, NULL, NULL, NULL, *entp, *entp, authtime, ok ? 0 : KRB5KDC_ERR_PREAUTH_FAILED); krb5_db_free_principal(ctx, *entp); CHECK(krb5_db_get_principal(ctx, &sample_princ, 0, entp)); diff --git a/src/tests/responder.c b/src/tests/responder.c index 21aae65c65af..82f870ea5d4b 100644 --- a/src/tests/responder.c +++ b/src/tests/responder.c @@ -226,7 +226,7 @@ responder(krb5_context ctx, void *rawdata, krb5_responder_context rctx) if (chl != NULL && chl->identities != NULL && chl->identities[0] != NULL) { - if (strncmp(chl->identities[0]->identity, "PKCS12:", 5) == 0) + if (strncmp(chl->identities[0]->identity, "PKCS12:", 7) == 0) krb5_responder_pkinit_set_answer(ctx, rctx, "foo", "bar"); } krb5_responder_pkinit_challenge_free(ctx, rctx, chl); diff --git a/src/tests/t_audit.py b/src/tests/t_audit.py index 69c9251e0428..00e96bfea69d 100755 --- a/src/tests/t_audit.py +++ b/src/tests/t_audit.py @@ -14,18 +14,15 @@ realm.run([kvno, 'target']) # Make S4U2Self and S4U2Proxy requests so they will be audited. The # S4U2Proxy request is expected to fail. -out = realm.run([kvno, '-k', realm.keytab, '-U', 'user', '-P', 'target'], - expected_code=1) -if 'NOT_ALLOWED_TO_DELEGATE' not in out: - fail('Unexpected error for S4U2Proxy') +realm.run([kvno, '-k', realm.keytab, '-U', 'user', '-P', 'target'], + expected_code=1, expected_msg='NOT_ALLOWED_TO_DELEGATE') # Make a U2U request so it will be audited. uuserver = os.path.join(buildtop, 'appl', 'user_user', 'uuserver') uuclient = os.path.join(buildtop, 'appl', 'user_user', 'uuclient') port_arg = str(realm.server_port()) realm.start_server([uuserver, port_arg], 'Server started') -output = realm.run([uuclient, hostname, 'testing message', port_arg]) -if 'Hello' not in output: - fail('U2U request failed unexpectedly') +realm.run([uuclient, hostname, 'testing message', port_arg], + expected_msg='Hello') success('Audit tests') diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py index 33525022ba84..8a577b4b18ee 100644 --- a/src/tests/t_authdata.py +++ b/src/tests/t_authdata.py @@ -24,10 +24,8 @@ if ' -5: test1' not in out or '?-6: test2' not in out: if 'fake' in out: fail('KDC-only authdata not filtered for request with authdata') -out = realm.run(['./adata', realm.host_princ, '!-1', 'mandatoryforkdc'], - expected_code=1) -if 'KDC policy rejects request' not in out: - fail('Wrong error seen for mandatory-for-kdc failure') +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 SIGNTICKET, # but not module or request authdata. @@ -88,6 +86,7 @@ realm, realm2 = cross_realms(2, args=({'realm': 'LOCAL'}, realm.run([kadminl, 'modprinc', '+requires_preauth', '-maxrenewlife', '2 days', realm.user_princ]) realm.run([kadminl, 'modprinc', '-maxrenewlife', '2 days', realm.host_princ]) +realm.run([kadminl, 'modprinc', '-maxrenewlife', '2 days', realm.krbtgt_princ]) realm.extract_keytab(realm.krbtgt_princ, realm.keytab) realm.extract_keytab(realm.host_princ, realm.keytab) realm.extract_keytab('krbtgt/FOREIGN', realm.keytab) @@ -98,45 +97,32 @@ realm2.extract_keytab('krbtgt/LOCAL', realm.keytab) # AS request to local-realm service realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=indcl', '-r', '2d', '-S', realm.host_princ]) -out = realm.run(['./adata', realm.host_princ]) -if '+97: [indcl]' not in out: - fail('auth-indicator not seen for AS req to service') +realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]') # Ticket modification request realm.kinit(realm.user_princ, None, ['-R', '-S', realm.host_princ]) -out = realm.run(['./adata', realm.host_princ]) -if '+97: [indcl]' not in out: - fail('auth-indicator not seen for ticket modification request') +realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]') # AS request to cross TGT realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=indcl', '-S', 'krbtgt/FOREIGN']) -out = realm.run(['./adata', 'krbtgt/FOREIGN']) -if '+97: [indcl]' not in out: - fail('auth-indicator not seen for AS req to cross-realm TGT') +realm.run(['./adata', 'krbtgt/FOREIGN'], expected_msg='+97: [indcl]') # Multiple indicators realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=indcl indcl2 indcl3']) -out = realm.run(['./adata', realm.krbtgt_princ]) -if '+97: [indcl, indcl2, indcl3]' not in out: - fail('multiple auth-indicators not seen for normal AS req') +realm.run(['./adata', realm.krbtgt_princ], + expected_msg='+97: [indcl, indcl2, indcl3]') # AS request to local TGT (resulting creds are used for TGS tests) realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=indcl']) -out = realm.run(['./adata', realm.krbtgt_princ]) -if '+97: [indcl]' not in out: - fail('auth-indicator not seen for normal AS req') +realm.run(['./adata', realm.krbtgt_princ], expected_msg='+97: [indcl]') # Local TGS request for local realm service -out = realm.run(['./adata', realm.host_princ]) -if '+97: [indcl]' not in out: - fail('auth-indicator not seen for local TGS req') +realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]') # Local TGS request for cross TGT service -out = realm.run(['./adata', 'krbtgt/FOREIGN']) -if '+97: [indcl]' not in out: - fail('auth-indicator not seen for TGS req to cross-realm TGT') +realm.run(['./adata', 'krbtgt/FOREIGN'], expected_msg='+97: [indcl]') # We don't yet have support for passing auth indicators across realms, # so just verify that indicators don't survive cross-realm requests. @@ -152,16 +138,13 @@ if '97:' in out: # Test that the CAMMAC signature still works during a krbtgt rollover. realm.run([kadminl, 'cpw', '-randkey', '-keepold', realm.krbtgt_princ]) -out = realm.run(['./adata', realm.host_princ]) -if '+97: [indcl]' not in out: - fail('auth-indicator not seen for local TGS req after krbtgt rotation') +realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]') # Test indicator enforcement. realm.addprinc('restricted') realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'superstrong']) -out = realm.run([kvno, 'restricted'], expected_code=1) -if 'KDC policy rejects request' not in out: - fail('expected error not seen for auth indicator enforcement') +realm.run([kvno, 'restricted'], expected_code=1, + expected_msg='KDC policy rejects request') realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'indcl']) realm.run([kvno, 'restricted']) realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=ind1 ind2']) @@ -178,6 +161,13 @@ realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'des3-cbc-sha1', realm.run(['./forward']) realm.run([kvno, realm.host_princ]) +# Repeat the above test using a renewed TGT. +realm.kinit(realm.user_princ, password('user'), ['-r', '2d']) +realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes128-cts', + realm.krbtgt_princ]) +realm.kinit(realm.user_princ, None, ['-R']) +realm.run([kvno, realm.host_princ]) + realm.stop() realm2.stop() @@ -222,13 +212,11 @@ if '+97: [indcl]' not in out or '[inds1]' in out: # Test that KDB module authdata is included in an AS request, by # default or with an explicit PAC request. realm.kinit(realm.user_princ, None, ['-k']) -out = realm.run(['./adata', realm.krbtgt_princ]) -if '-456: db-authdata-test' not in out: - fail('DB authdata not seen in default AS request') +realm.run(['./adata', realm.krbtgt_princ], + expected_msg='-456: db-authdata-test') realm.kinit(realm.user_princ, None, ['-k', '--request-pac']) -out = realm.run(['./adata', realm.krbtgt_princ]) -if '-456: db-authdata-test' not in out: - fail('DB authdata not seen with --request-pac') +realm.run(['./adata', realm.krbtgt_princ], + expected_msg='-456: db-authdata-test') # Test that KDB module authdata is suppressed in an AS request by a # negative PAC request. @@ -238,9 +226,7 @@ if '-456: db-authdata-test' in out: fail('DB authdata not suppressed by --no-request-pac') # Test that KDB authdata is included in a TGS request by default. -out = realm.run(['./adata', 'service/1']) -if '-456: db-authdata-test' not in out: - fail('DB authdata not seen in TGS request') +realm.run(['./adata', 'service/1'], expected_msg='-456: db-authdata-test') # Test that KDB authdata is suppressed in a TGS request by the # +no_auth_data_required flag. diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py index 47d96313085e..61d549b7b6a8 100755 --- a/src/tests/t_ccache.py +++ b/src/tests/t_ccache.py @@ -35,15 +35,11 @@ if not test_keyring: # Test kdestroy and klist of a non-existent ccache. realm.run([kdestroy]) -output = realm.run([klist], expected_code=1) -if 'No credentials cache found' not in output: - fail('Expected error message not seen in klist output') +realm.run([klist], expected_code=1, expected_msg='No credentials cache found') # Test kinit with an inaccessible ccache. -out = realm.run([kinit, '-c', 'testdir/xx/yy', realm.user_princ], - input=(password('user') + '\n'), expected_code=1) -if 'Failed to store credentials' not in out: - fail('Expected error message not seen in kinit output') +realm.kinit(realm.user_princ, password('user'), flags=['-c', 'testdir/xx/yy'], + expected_code=1, expected_msg='Failed to store credentials') # Test klist -s with a single ccache. realm.run([klist, '-s'], expected_code=1) @@ -61,13 +57,12 @@ realm.addprinc('bob', password('bob')) realm.addprinc('carol', password('carol')) def collection_test(realm, ccname): + oldccname = realm.env['KRB5CCNAME'] realm.env['KRB5CCNAME'] = ccname realm.run([klist, '-A', '-s'], expected_code=1) realm.kinit('alice', password('alice')) - output = realm.run([klist]) - if 'Default principal: alice@' not in output: - fail('Initial kinit failed to get credentials for alice.') + realm.run([klist], expected_msg='Default principal: alice@') realm.run([klist, '-A', '-s']) realm.run([kdestroy]) output = realm.run([klist], expected_code=1) @@ -88,7 +83,7 @@ def collection_test(realm, ccname): if '---\nalice@' not in output or output.count('\n') != 4: fail('klist -l did not show expected output after re-kinit for alice.') realm.kinit('bob', password('bob')) - output = realm.run([klist, '-A']) + output = realm.run([klist, '-A', ccname]) if 'bob@' not in output.splitlines()[1] or 'alice@' not in output or \ 'carol' not in output or output.count('Default principal:') != 3: fail('klist -A did not show expected output after kinit for bob.') @@ -96,17 +91,22 @@ def collection_test(realm, ccname): output = realm.run([klist, '-l']) if '---\ncarol@' not in output or output.count('\n') != 5: fail('klist -l did not show expected output after kswitch to carol.') - realm.run([kdestroy]) - output = realm.run([klist, '-l']) + + # Switch to specifying the collection name on the command line + # (only works with klist/kdestroy for now, not kinit/kswitch). + realm.env['KRB5CCNAME'] = oldccname + + realm.run([kdestroy, '-c', ccname]) + output = realm.run([klist, '-l', ccname]) if 'carol@' in output or 'bob@' not in output or output.count('\n') != 4: fail('kdestroy failed to remove only primary ccache.') - realm.run([klist, '-s'], expected_code=1) - realm.run([klist, '-A', '-s']) - realm.run([kdestroy, '-A']) - output = realm.run([klist, '-l'], expected_code=1) + realm.run([klist, '-s', ccname], expected_code=1) + realm.run([klist, '-A', '-s', ccname]) + realm.run([kdestroy, '-A', '-c', ccname]) + output = realm.run([klist, '-l', ccname], expected_code=1) if not output.endswith('---\n') or output.count('\n') != 2: fail('kdestroy -a failed to empty cache collection.') - realm.run([klist, '-A', '-s'], expected_code=1) + realm.run([klist, '-A', '-s', ccname], expected_code=1) collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc')) @@ -130,25 +130,20 @@ if test_keyring: realm.env['KRB5CCNAME'] = 'KEYRING:' + cname realm.run([kdestroy, '-A']) realm.kinit(realm.user_princ, password('user')) - out = realm.run([klist, '-l']) - if 'KEYRING:legacy:' + cname + ':' + cname not in out: - fail('Wrong initial primary name in keyring legacy collection') + msg = 'KEYRING:legacy:' + cname + ':' + cname + realm.run([klist, '-l'], expected_msg=msg) # Make sure this cache is linked to the session keyring. id = realm.run([keyctl, 'search', '@s', 'keyring', cname]) - out = realm.run([keyctl, 'list', id.strip()]) - if 'user: __krb5_princ__' not in out: - fail('Legacy cache not linked into session keyring') + realm.run([keyctl, 'list', id.strip()], + expected_msg='user: __krb5_princ__') # Remove the collection keyring. When the collection is # reinitialized, the legacy cache should reappear inside it # automatically as the primary cache. cleanup_keyring('@s', col_ringname) - out = realm.run([klist]) - if realm.user_princ not in out: - fail('Cannot see legacy cache after removing collection') + realm.run([klist], expected_msg=realm.user_princ) coll_id = realm.run([keyctl, 'search', '@s', 'keyring', '_krb_' + cname]) - out = realm.run([keyctl, 'list', coll_id.strip()]) - if (id.strip() + ':') not in out: - fail('Legacy cache did not reappear in collection after klist') + msg = id.strip() + ':' + realm.run([keyctl, 'list', coll_id.strip()], expected_msg=msg) # Destroy the cache and check that it is unlinked from the session keyring. realm.run([kdestroy]) realm.run([keyctl, 'search', '@s', 'keyring', cname], expected_code=1) @@ -160,8 +155,7 @@ conf = {'libdefaults': {'default_ccache_name': 'testdir/%{null}abc%{uid}'}} realm = K5Realm(krb5_conf=conf, create_kdb=False) del realm.env['KRB5CCNAME'] uidstr = str(os.getuid()) -out = realm.run([klist], expected_code=1) -if 'testdir/abc%s' % uidstr not in out: - fail('Wrong ccache in klist') +msg = 'testdir/abc%s' % uidstr +realm.run([klist], expected_code=1, expected_msg=msg) success('Credential cache tests') diff --git a/src/tests/t_certauth.py b/src/tests/t_certauth.py new file mode 100644 index 000000000000..e64a57b0d5eb --- /dev/null +++ b/src/tests/t_certauth.py @@ -0,0 +1,47 @@ +#!/usr/bin/python +from k5test import * + +# Skip this test if pkinit wasn't built. +if not os.path.exists(os.path.join(plugins, 'preauth', 'pkinit.so')): + skip_rest('certauth tests', 'PKINIT module not built') + +certs = os.path.join(srctop, 'tests', 'dejagnu', 'pkinit-certs') +ca_pem = os.path.join(certs, 'ca.pem') +kdc_pem = os.path.join(certs, 'kdc.pem') +privkey_pem = os.path.join(certs, 'privkey.pem') +user_pem = os.path.join(certs, 'user.pem') + +modpath = os.path.join(buildtop, 'plugins', 'certauth', 'test', + 'certauth_test.so') +pkinit_krb5_conf = {'realms': {'$realm': { + 'pkinit_anchors': 'FILE:%s' % ca_pem}}, + 'plugins': {'certauth': {'module': ['test1:' + modpath, + 'test2:' + modpath], + 'enable_only': ['test1', 'test2']}}} +pkinit_kdc_conf = {'realms': {'$realm': { + 'default_principal_flags': '+preauth', + 'pkinit_eku_checking': 'none', + 'pkinit_identity': 'FILE:%s,%s' % (kdc_pem, privkey_pem), + 'pkinit_indicator': ['indpkinit1', 'indpkinit2']}}} + +file_identity = 'FILE:%s,%s' % (user_pem, privkey_pem) + +realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf, + get_creds=False) + +# Let the test module match user to CN=user, with indicators. +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % file_identity]) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) +realm.run(['./adata', realm.host_princ], + expected_msg='+97: [test1, test2, user, indpkinit1, indpkinit2]') + +# Let the test module mismatch with user2 to CN=user. +realm.addprinc("user2@KRBTEST.COM") +out = realm.kinit("user2@KRBTEST.COM", + flags=['-X', 'X509_user_identity=%s' % file_identity], + expected_code=1, + expected_msg='kinit: Certificate mismatch') + +success("certauth tests") diff --git a/src/tests/t_crossrealm.py b/src/tests/t_crossrealm.py index 0d967b8a50f2..e7ddb05254d8 100755 --- a/src/tests/t_crossrealm.py +++ b/src/tests/t_crossrealm.py @@ -25,9 +25,7 @@ from k5test import * def test_kvno(r, princ, test, env=None): - output = r.run([kvno, princ], env=env) - if princ not in output: - fail('%s: principal %s not in kvno output' % (test, princ)) + r.run([kvno, princ], env=env, expected_msg=princ) def stop(*realms): @@ -35,10 +33,39 @@ def stop(*realms): r.stop() +# Verify that the princs appear as the service principals in the klist +# output for the realm r, in order. +def check_klist(r, princs): + out = r.run([klist]) + count = 0 + seen_header = False + for l in out.split('\n'): + if l.startswith('Valid starting'): + seen_header = True + continue + if not seen_header or l == '': + continue + if count >= len(princs): + fail('too many entries in klist output') + svcprinc = l.split()[4] + if svcprinc != princs[count]: + fail('saw service princ %s in klist output, expected %s' % + (svcprinc, princs[count])) + count += 1 + if count != len(princs): + fail('not enough entries in klist output') + + +def tgt(r1, r2): + return 'krbtgt/%s@%s' % (r1.realm, r2.realm) + + # Basic two-realm test with cross TGTs in both directions. r1, r2 = cross_realms(2) test_kvno(r1, r2.host_princ, 'basic r1->r2') +check_klist(r1, (tgt(r1, r1), tgt(r2, r1), r2.host_princ)) test_kvno(r2, r1.host_princ, 'basic r2->r1') +check_klist(r2, (tgt(r2, r2), tgt(r1, r2), r1.host_princ)) stop(r1, r2) # Test the KDC domain walk for hierarchically arranged realms. The @@ -49,6 +76,7 @@ r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)), args=({'realm': 'A.X'}, {'realm': 'X'}, {'realm': 'B.X'})) test_kvno(r1, r3.host_princ, 'KDC domain walk') +check_klist(r1, (tgt(r1, r1), r3.host_princ)) stop(r1, r2, r3) # Test client capaths. The client in A will ask for a cross TGT to D, @@ -64,6 +92,8 @@ r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)), {'realm': 'D', 'krb5_conf': capaths})) r1client = r1.special_env('client', False, krb5_conf=capaths) test_kvno(r1, r4.host_princ, 'client capaths', r1client) +check_klist(r1, (tgt(r1, r1), tgt(r2, r1), tgt(r3, r2), tgt(r4, r3), + r4.host_princ)) stop(r1, r2, r3, r4) # Test KDC capaths. The KDCs for A and B have appropriate capaths @@ -76,6 +106,7 @@ r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)), {'realm': 'C', 'krb5_conf': capaths}, {'realm': 'D', 'krb5_conf': capaths})) test_kvno(r1, r4.host_princ, 'KDC capaths') +check_klist(r1, (tgt(r1, r1), tgt(r4, r3), r4.host_princ)) stop(r1, r2, r3, r4) # Test transited error. The KDC for C does not recognize B as an @@ -85,9 +116,9 @@ capaths = {'capaths': {'A': {'C': 'B'}}} r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)), args=({'realm': 'A', 'krb5_conf': capaths}, {'realm': 'B'}, {'realm': 'C'})) -output = r1.run([kvno, r3.host_princ], expected_code=1) -if 'KDC policy rejects request' not in output: - fail('transited 1: Expected error message not in output') +r1.run([kvno, r3.host_princ], expected_code=1, + expected_msg='KDC policy rejects request') +check_klist(r1, (tgt(r1, r1), tgt(r3, r2))) stop(r1, r2, r3) # Test a different kind of transited error. The KDC for D does not @@ -99,9 +130,9 @@ r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)), {'realm': 'B', 'krb5_conf': capaths}, {'realm': 'C', 'krb5_conf': capaths}, {'realm': 'D'})) -output = r1.run([kvno, r4.host_princ], expected_code=1) -if 'Illegal cross-realm ticket' not in output: - fail('transited 2: Expected error message not in output') +r1.run([kvno, r4.host_princ], expected_code=1, + expected_msg='Illegal cross-realm ticket') +check_klist(r1, (tgt(r1, r1), tgt(r4, r3))) stop(r1, r2, r3, r4) success('Cross-realm tests') diff --git a/src/tests/t_dump.py b/src/tests/t_dump.py index 5d3a437625e2..8a9462bd8eaf 100755 --- a/src/tests/t_dump.py +++ b/src/tests/t_dump.py @@ -36,12 +36,10 @@ if 'Expiration date: [never]' not in out or 'MKey: vno 1' not in out: out = realm.run([kadminl, 'getpols']) if 'fred\n' not in out or 'barney\n' not in out: fail('Missing policy after load') -out = realm.run([kadminl, 'getpol', 'compat']) -if 'Number of old keys kept: 5' not in out: - fail('Policy (1.8 format) has wrong value after load') -out = realm.run([kadminl, 'getpol', 'barney']) -if 'Number of old keys kept: 1' not in out: - fail('Policy has wrong value after load') +realm.run([kadminl, 'getpol', 'compat'], + expected_msg='Number of old keys kept: 5') +realm.run([kadminl, 'getpol', 'barney'], + expected_msg='Number of old keys kept: 1') # Dump/load again, and make sure everything is still there. realm.run([kdb5_util, 'dump', dumpfile]) @@ -81,15 +79,10 @@ dump_compare(realm, ['-ov'], srcdump_ov) def load_dump_check_compare(realm, opt, srcfile): realm.run([kdb5_util, 'destroy', '-f']) realm.run([kdb5_util, 'load'] + opt + [srcfile]) - out = realm.run([kadminl, 'getprincs']) - if 'user@' not in out: - fail('Loaded dumpfile missing user principal') - out = realm.run([kadminl, 'getprinc', 'nokeys']) - if 'Number of keys: 0' not in out: - fail('Loading dumpfile did not process zero-key principal') - out = realm.run([kadminl, 'getpols']) - if 'testpol' not in out: - fail('Loaded dumpfile missing test policy') + realm.run([kadminl, 'getprincs'], expected_msg='user@') + realm.run([kadminl, 'getprinc', 'nokeys'], + expected_msg='Number of keys: 0') + realm.run([kadminl, 'getpols'], expected_msg='testpol') dump_compare(realm, opt, srcfile) # Load each format of dump, check it, re-dump it, and compare. @@ -99,12 +92,8 @@ load_dump_check_compare(realm, ['-b7'], srcdump_b7) # Loading the last (-b7 format) dump won't have loaded the # per-principal kadm data. Load that incrementally with -ov. -out = realm.run([kadminl, 'getprinc', 'user']) -if 'Policy: [none]' not in out: - fail('Loaded b7 dump unexpectedly contains user policy reference') +realm.run([kadminl, 'getprinc', 'user'], expected_msg='Policy: [none]') realm.run([kdb5_util, 'load', '-update', '-ov', srcdump_ov]) -out = realm.run([kadminl, 'getprinc', 'user']) -if 'Policy: testpol' not in out: - fail('Loading ov dump did not add user policy reference') +realm.run([kadminl, 'getprinc', 'user'], expected_msg='Policy: testpol') success('Dump/load tests') diff --git a/src/tests/t_general.py b/src/tests/t_general.py index 6d523fe4513d..91ad0cb8a060 100755 --- a/src/tests/t_general.py +++ b/src/tests/t_general.py @@ -3,10 +3,9 @@ from k5test import * for realm in multipass_realms(create_host=False): # Check that kinit fails appropriately with the wrong password. - output = realm.run([kinit, realm.user_princ], input='wrong\n', - expected_code=1) - if 'Password incorrect while getting initial credentials' not in output: - fail('Expected error message not seen in kinit output') + msg = 'Password incorrect while getting initial credentials' + realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1, + expected_msg=msg) # Check that we can kinit as a different principal. realm.kinit(realm.admin_princ, password('admin')) @@ -30,6 +29,7 @@ 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) @@ -42,26 +42,17 @@ realm.run(['./responder', '-r', 'password=%s' % password('user'), # Test that WRONG_REALM responses aren't treated as referrals unless # they contain a crealm field pointing to a different realm. # (Regression test for #8060.) -out = realm.run([kinit, '-C', 'notfoundprinc'], expected_code=1) -if 'not found in Kerberos database' not in out: - fail('Expected error message not seen in kinit -C output') +realm.run([kinit, '-C', 'notfoundprinc'], expected_code=1, + expected_msg='not found in Kerberos database') # Spot-check KRB5_TRACE output -tracefile = os.path.join(realm.testdir, 'trace') -realm.run(['env', 'KRB5_TRACE=' + tracefile, kinit, realm.user_princ], - input=(password('user') + "\n")) -f = open(tracefile, 'r') -trace = f.read() -f.close() -expected = ('Sending initial UDP request', - 'Received answer', - 'Selected etype info', - 'AS key obtained', - 'Decrypted AS reply', - 'FAST negotiation: available', - 'Storing user@KRBTEST.COM') -for e in expected: - if e not in trace: - fail('Expected output not in kinit trace log') +expected_trace = ('Sending initial UDP request', + 'Received answer', + 'Selected etype info', + 'AS key obtained', + 'Decrypted AS reply', + 'FAST negotiation: available', + 'Storing user@KRBTEST.COM') +realm.kinit(realm.user_princ, password('user'), expected_trace=expected_trace) success('FAST kinit, trace logging') diff --git a/src/tests/t_hostrealm.py b/src/tests/t_hostrealm.py index 76b282d2ac6e..224c067ef424 100755 --- a/src/tests/t_hostrealm.py +++ b/src/tests/t_hostrealm.py @@ -20,9 +20,8 @@ def test(realm, args, expected_realms, msg, env=None): fail(msg) def test_error(realm, args, expected_error, msg, env=None): - out = realm.run(['./hrealm'] + args, env=env, expected_code=1) - if expected_error not in out: - fail(msg) + realm.run(['./hrealm'] + args, env=env, expected_code=1, + expected_msg=expected_error) def testh(realm, host, expected_realms, msg, env=None): test(realm, ['-h', host], expected_realms, msg, env=env) diff --git a/src/tests/t_iprop.py b/src/tests/t_iprop.py index e64fdd27993c..8e23cd5de9db 100755 --- a/src/tests/t_iprop.py +++ b/src/tests/t_iprop.py @@ -214,9 +214,8 @@ check_ulog(7, 1, 7, [None, pr1, pr3, pr2, pr2, pr2, pr2]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, False, 6, 7) check_ulog(2, 6, 7, [None, pr2], slave1) -out = realm.run([kadminl, 'getprinc', pr2], env=slave1) -if 'Attributes: DISALLOW_ALL_TIX' not in out: - fail('slave1 does not have modification from master') +realm.run([kadminl, 'getprinc', pr2], env=slave1, + expected_msg='Attributes: DISALLOW_ALL_TIX') # Start kadmind -proponly for slave1. (Use the slave1m environment # which defines iprop_port to $port8.) @@ -245,15 +244,13 @@ check_ulog(8, 1, 8, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, False, 7, 8) check_ulog(3, 6, 8, [None, pr2, pr1], slave1) -out = realm.run([kadminl, 'getprinc', pr1], env=slave1) -if 'Maximum ticket life: 0 days 00:20:00' not in out: - fail('slave1 does not have modification from master') +realm.run([kadminl, 'getprinc', pr1], env=slave1, + expected_msg='Maximum ticket life: 0 days 00:20:00') kpropd3.send_signal(signal.SIGUSR1) wait_for_prop(kpropd3, False, 7, 8) check_ulog(2, 7, 8, [None, pr1], slave3) -out = realm.run([kadminl, '-r', realm.realm, 'getprinc', pr1], env=slave3) -if 'Maximum ticket life: 0 days 00:20:00' not in out: - fail('slave3 does not have modification from slave1') +realm.run([kadminl, '-r', realm.realm, 'getprinc', pr1], env=slave3, + expected_msg='Maximum ticket life: 0 days 00:20:00') stop_daemon(kpropd3) # Test dissimilar default_realm and domain_realm map settings (no -r realm). @@ -287,15 +284,13 @@ check_ulog(9, 1, 9, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1, pr1]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, False, 8, 9) check_ulog(4, 6, 9, [None, pr2, pr1, pr1], slave1) -out = realm.run([kadminl, 'getprinc', pr1], env=slave1) -if 'Maximum renewable life: 0 days 22:00:00\n' not in out: - fail('slave1 does not have modification from master') +realm.run([kadminl, 'getprinc', pr1], env=slave1, + expected_msg='Maximum renewable life: 0 days 22:00:00\n') kpropd2.send_signal(signal.SIGUSR1) wait_for_prop(kpropd2, False, 8, 9) check_ulog(3, 7, 9, [None, pr1, pr1], slave2) -out = realm.run([kadminl, 'getprinc', pr1], env=slave2) -if 'Maximum renewable life: 0 days 22:00:00\n' not in out: - fail('slave2 does not have modification from slave1') +realm.run([kadminl, 'getprinc', pr1], env=slave2, + expected_msg='Maximum renewable life: 0 days 22:00:00\n') # Reset the ulog on slave1 to force a full resync from master. The # resync will use the old dump file and then propagate changes. @@ -317,15 +312,11 @@ check_ulog(10, 1, 10, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1, pr1, pr2]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, False, 9, 10) check_ulog(5, 6, 10, [None, pr2, pr1, pr1, pr2], slave1) -out = realm.run([kadminl, 'getprinc', pr2], env=slave1) -if 'Attributes:\n' not in out: - fail('slave1 does not have modification from master') +realm.run([kadminl, 'getprinc', pr2], env=slave1, expected_msg='Attributes:\n') kpropd2.send_signal(signal.SIGUSR1) wait_for_prop(kpropd2, False, 9, 10) check_ulog(4, 7, 10, [None, pr1, pr1, pr2], slave2) -out = realm.run([kadminl, 'getprinc', pr2], env=slave2) -if 'Attributes:\n' not in out: - fail('slave2 does not have modification from slave1') +realm.run([kadminl, 'getprinc', pr2], env=slave2, expected_msg='Attributes:\n') # Create a policy and check that it propagates via full resync. realm.run([kadminl, 'addpol', '-minclasses', '2', 'testpol']) @@ -333,15 +324,13 @@ check_ulog(1, 1, 1, [None]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, True, 10, 1) check_ulog(1, 1, 1, [None], slave1) -out = realm.run([kadminl, 'getpol', 'testpol'], env=slave1) -if 'Minimum number of password character classes: 2' not in out: - fail('slave1 does not have policy from master') +realm.run([kadminl, 'getpol', 'testpol'], env=slave1, + expected_msg='Minimum number of password character classes: 2') kpropd2.send_signal(signal.SIGUSR1) wait_for_prop(kpropd2, True, 10, 1) check_ulog(1, 1, 1, [None], slave2) -out = realm.run([kadminl, 'getpol', 'testpol'], env=slave2) -if 'Minimum number of password character classes: 2' not in out: - fail('slave2 does not have policy from slave1') +realm.run([kadminl, 'getpol', 'testpol'], env=slave2, + expected_msg='Minimum number of password character classes: 2') # Modify the policy and test that it also propagates via full resync. realm.run([kadminl, 'modpol', '-minlength', '17', 'testpol']) @@ -349,15 +338,13 @@ check_ulog(1, 1, 1, [None]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, True, 1, 1) check_ulog(1, 1, 1, [None], slave1) -out = realm.run([kadminl, 'getpol', 'testpol'], env=slave1) -if 'Minimum password length: 17' not in out: - fail('slave1 does not have policy change from master') +realm.run([kadminl, 'getpol', 'testpol'], env=slave1, + expected_msg='Minimum password length: 17') kpropd2.send_signal(signal.SIGUSR1) wait_for_prop(kpropd2, True, 1, 1) check_ulog(1, 1, 1, [None], slave2) -out = realm.run([kadminl, 'getpol', 'testpol'], env=slave2) -if 'Minimum password length: 17' not in out: - fail('slave2 does not have policy change from slave1') +realm.run([kadminl, 'getpol', 'testpol'], env=slave2, + expected_msg='Minimum password length: 17') # Delete the policy and test that it propagates via full resync. realm.run([kadminl, 'delpol', 'testpol']) @@ -365,15 +352,13 @@ check_ulog(1, 1, 1, [None]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, True, 1, 1) check_ulog(1, 1, 1, [None], slave1) -out = realm.run([kadminl, 'getpol', 'testpol'], env=slave1, expected_code=1) -if 'Policy does not exist' not in out: - fail('slave1 did not get policy deletion from master') +realm.run([kadminl, 'getpol', 'testpol'], env=slave1, expected_code=1, + expected_msg='Policy does not exist') kpropd2.send_signal(signal.SIGUSR1) wait_for_prop(kpropd2, True, 1, 1) check_ulog(1, 1, 1, [None], slave2) -out = realm.run([kadminl, 'getpol', 'testpol'], env=slave2, expected_code=1) -if 'Policy does not exist' not in out: - fail('slave2 did not get policy deletion from slave1') +realm.run([kadminl, 'getpol', 'testpol'], env=slave2, expected_code=1, + expected_msg='Policy does not exist') # Modify a principal on the master and test that it propagates incrementally. realm.run([kadminl, 'modprinc', '-maxlife', '10 minutes', pr1]) @@ -381,15 +366,13 @@ check_ulog(2, 1, 2, [None, pr1]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, False, 1, 2) check_ulog(2, 1, 2, [None, pr1], slave1) -out = realm.run([kadminl, 'getprinc', pr1], env=slave1) -if 'Maximum ticket life: 0 days 00:10:00' not in out: - fail('slave1 does not have modification from master') +realm.run([kadminl, 'getprinc', pr1], env=slave1, + expected_msg='Maximum ticket life: 0 days 00:10:00') kpropd2.send_signal(signal.SIGUSR1) wait_for_prop(kpropd2, False, 1, 2) check_ulog(2, 1, 2, [None, pr1], slave2) -out = realm.run([kadminl, 'getprinc', pr1], env=slave2) -if 'Maximum ticket life: 0 days 00:10:00' not in out: - fail('slave2 does not have modification from slave1') +realm.run([kadminl, 'getprinc', pr1], env=slave2, + expected_msg='Maximum ticket life: 0 days 00:10:00') # Delete a principal and test that it propagates incrementally. realm.run([kadminl, 'delprinc', pr3]) @@ -397,15 +380,13 @@ check_ulog(3, 1, 3, [None, pr1, pr3]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, False, 2, 3) check_ulog(3, 1, 3, [None, pr1, pr3], slave1) -out = realm.run([kadminl, 'getprinc', pr3], env=slave1, expected_code=1) -if 'Principal does not exist' not in out: - fail('slave1 does not have principal deletion from master') +realm.run([kadminl, 'getprinc', pr3], env=slave1, expected_code=1, + expected_msg='Principal does not exist') kpropd2.send_signal(signal.SIGUSR1) wait_for_prop(kpropd2, False, 2, 3) check_ulog(3, 1, 3, [None, pr1, pr3], slave2) -out = realm.run([kadminl, 'getprinc', pr3], env=slave2, expected_code=1) -if 'Principal does not exist' not in out: - fail('slave2 does not have principal deletion from slave1') +realm.run([kadminl, 'getprinc', pr3], env=slave2, expected_code=1, + expected_msg='Principal does not exist') # Rename a principal and test that it propagates incrementally. renpr = "quacked@" + realm.realm @@ -414,16 +395,14 @@ check_ulog(6, 1, 6, [None, pr1, pr3, renpr, pr1, renpr]) kpropd1.send_signal(signal.SIGUSR1) wait_for_prop(kpropd1, False, 3, 6) check_ulog(6, 1, 6, [None, pr1, pr3, renpr, pr1, renpr], slave1) -out = realm.run([kadminl, 'getprinc', pr1], env=slave1, expected_code=1) -if 'Principal does not exist' not in out: - fail('slave1 does not have principal deletion from master') +realm.run([kadminl, 'getprinc', pr1], env=slave1, expected_code=1, + expected_msg='Principal does not exist') realm.run([kadminl, 'getprinc', renpr], env=slave1) kpropd2.send_signal(signal.SIGUSR1) wait_for_prop(kpropd2, False, 3, 6) check_ulog(6, 1, 6, [None, pr1, pr3, renpr, pr1, renpr], slave2) -out = realm.run([kadminl, 'getprinc', pr1], env=slave2, expected_code=1) -if 'Principal does not exist' not in out: - fail('slave2 does not have principal deletion from master') +realm.run([kadminl, 'getprinc', pr1], env=slave2, expected_code=1, + expected_msg='Principal does not exist') realm.run([kadminl, 'getprinc', renpr], env=slave2) pr1 = renpr @@ -455,9 +434,8 @@ out = realm.run_kpropd_once(slave1, ['-d']) if 'Got incremental updates (sno=2 ' not in out: fail('Expected full dump and synchronized from kpropd -t') check_ulog(2, 1, 2, [None, pr1], slave1) -out = realm.run([kadminl, 'getprinc', pr1], env=slave1) -if 'Maximum ticket life: 0 days 00:05:00' not in out: - fail('slave1 does not have modification from master after kpropd -t') +realm.run([kadminl, 'getprinc', pr1], env=slave1, + expected_msg='Maximum ticket life: 0 days 00:05:00') # Propagate a policy change via full resync. realm.run([kadminl, 'addpol', '-minclasses', '3', 'testpol']) @@ -467,8 +445,7 @@ if ('Full propagation transfer finished' not in out or 'KDC is synchronized' not in out): fail('Expected full dump and synchronized from kpropd -t') check_ulog(1, 1, 1, [None], slave1) -out = realm.run([kadminl, 'getpol', 'testpol'], env=slave1) -if 'Minimum number of password character classes: 3' not in out: - fail('slave1 does not have policy from master after kpropd -t') +realm.run([kadminl, 'getpol', 'testpol'], env=slave1, + expected_msg='Minimum number of password character classes: 3') success('iprop tests') diff --git a/src/tests/t_kadm5_auth.py b/src/tests/t_kadm5_auth.py new file mode 100644 index 000000000000..ba4ab8ef10cf --- /dev/null +++ b/src/tests/t_kadm5_auth.py @@ -0,0 +1,81 @@ +#!/usr/bin/python +from k5test import * + +# Create a realm with the welcomer and bouncer kadm5_auth test modules +# in place of the builtin modules. +modpath = os.path.join(buildtop, 'plugins', 'kadm5_auth', 'test', + 'kadm5_auth_test.so') +conf = {'plugins': {'kadm5_auth': {'module': ['welcomer:' + modpath, + 'bouncer:' + modpath], + 'enable_only': ['welcomer', 'bouncer']}}} +realm = K5Realm(krb5_conf=conf, create_host=False) +realm.start_kadmind() +realm.prep_kadmin() + +# addprinc: welcomer accepts with policy VIP, bouncer denies maxlife. +realm.run_kadmin(['addprinc', '-randkey', 'princ'], expected_code=1) +realm.run_kadmin(['addprinc', '-randkey', '-policy', 'VIP', 'princ']) +realm.run_kadmin(['addprinc', '-randkey', '-policy', 'VIP', '-maxlife', '3', + 'princ'], expected_code=1) + +# modprinc: welcomer accepts with only maxrenewlife, bouncer denies +# with even-component target principal. +realm.run_kadmin(['modprinc', '-maxlife', '3', 'princ'], expected_code=1) +realm.run_kadmin(['modprinc', '-maxrenewlife', '3', 'princ']) +realm.run_kadmin(['modprinc', '-maxrenewlife', '3', 'user/admin'], + expected_code=1) + +# setstr: welcomer accepts with key 'note', bouncer denies with value +# length > 10. +realm.run_kadmin(['setstr', 'princ', 'somekey', 'someval'], expected_code=1) +realm.run_kadmin(['setstr', 'princ', 'note', 'abc']) +realm.run_kadmin(['setstr', 'princ', 'note', 'abcdefghijkl'], expected_code=1) + +# delprinc: welcomer accepts with target principal beginning with 'd', +# bouncer denies with "nodelete" string attribute. +realm.run_kadmin(['delprinc', 'user'], expected_code=1) +realm.run([kadminl, 'addprinc', '-randkey', 'deltest']) +realm.run_kadmin(['delprinc', 'deltest']) +realm.run([kadminl, 'addprinc', '-randkey', 'deltest']) +realm.run([kadminl, 'setstr', 'deltest', 'nodelete', 'yes']) +realm.run_kadmin(['delprinc', 'deltest'], expected_code=1) + +# renprinc: welcomer accepts with same-length first components, bouncer +# refuses with source principal beginning with 'a'. +realm.run_kadmin(['renprinc', 'princ', 'xyz'], expected_code=1) +realm.run_kadmin(['renprinc', 'princ', 'abcde']) +realm.run_kadmin(['renprinc', 'abcde', 'fghij'], expected_code=1) + +# addpol: welcomer accepts with minlength 3, bouncer denies with name +# length <= 3. +realm.run_kadmin(['addpol', 'testpol'], expected_code=1) +realm.run_kadmin(['addpol', '-minlength', '3', 'testpol']) +realm.run_kadmin(['addpol', '-minlength', '3', 'abc'], expected_code=1) + +# modpol: welcomer accepts changes to minlife, bouncer denies with +# minlife > 10. +realm.run_kadmin(['modpol', '-minlength', '4', 'testpol'], expected_code=1) +realm.run_kadmin(['modpol', '-minlife', '8', 'testpol']) +realm.run_kadmin(['modpol', '-minlife', '11', 'testpol'], expected_code=1) + +# getpol: welcomer accepts if policy and client policy have same length, +# bouncer denies if policy name begins with 'x'. +realm.run([kadminl, 'addpol', 'aaaa']) +realm.run([kadminl, 'addpol', 'bbbb']) +realm.run([kadminl, 'addpol', 'xxxx']) +realm.run([kadminl, 'modprinc', '-policy', 'aaaa', 'user/admin']) +realm.run_kadmin(['getpol', 'testpol'], expected_code=1) +realm.run_kadmin(['getpol', 'bbbb']) +realm.run_kadmin(['getpol', 'xxxx'], expected_code=1) + +# end: welcomer counts operations using "ends" string attribute on +# "opcount" principal. kadmind is dumb and invokes the end method for +# every RPC operation including init, so we expect four calls to the +# end operation. +realm.run([kadminl, 'addprinc', '-nokey', 'opcount']) +realm.run([kadminl, 'setstr', 'opcount', 'ends', '0']) +realm.run_kadmin(['getprinc', 'user']) +realm.run_kadmin(['getpol', 'bbbb']) +realm.run([kadminl, 'getstrs', 'opcount'], expected_msg='ends: 4') + +success('kadm5_auth pluggable interface tests') diff --git a/src/tests/t_kadm5_hook.py b/src/tests/t_kadm5_hook.py index 708e328b000b..c1c8c9419c09 100755 --- a/src/tests/t_kadm5_hook.py +++ b/src/tests/t_kadm5_hook.py @@ -7,12 +7,10 @@ plugin = os.path.join(buildtop, "plugins", "kadm5_hook", "test", hook_krb5_conf = {'plugins': {'kadm5_hook': { 'module': 'test:' + plugin}}} realm = K5Realm(krb5_conf=hook_krb5_conf, create_user=False, create_host=False) -output = realm.run([kadminl, 'addprinc', '-randkey', 'test']) -if "create: stage precommit" not in output: - fail('kadm5_hook test output not found') +realm.run([kadminl, 'addprinc', '-randkey', 'test'], + expected_msg='create: stage precommit') -output = realm.run([kadminl, 'renprinc', 'test', 'test2']) -if "rename: stage precommit" not in output: - fail('kadm5_hook test output not found') +realm.run([kadminl, 'renprinc', 'test', 'test2'], + expected_msg='rename: stage precommit') success('kadm5_hook') diff --git a/src/tests/t_kadmin_acl.py b/src/tests/t_kadmin_acl.py index 188929a76c91..42bdf423c393 100755 --- a/src/tests/t_kadmin_acl.py +++ b/src/tests/t_kadmin_acl.py @@ -87,27 +87,24 @@ for pw in (['-pw', 'newpw'], ['-randkey']): args = pw + ks kadmin_as(all_changepw, ['cpw'] + args + ['unselected']) kadmin_as(some_changepw, ['cpw'] + args + ['selected']) - out = kadmin_as(none, ['cpw'] + args + ['selected'], expected_code=1) - if 'Operation requires ``change-password\'\' privilege' not in out: - fail('cpw failure (no perms)') - out = kadmin_as(some_changepw, ['cpw'] + args + ['unselected'], - expected_code=1) - if 'Operation requires ``change-password\'\' privilege' not in out: - fail('cpw failure (target)') - out = kadmin_as(none, ['cpw'] + args + ['none']) + msg = "Operation requires ``change-password'' privilege" + kadmin_as(none, ['cpw'] + args + ['selected'], expected_code=1, + expected_msg=msg) + kadmin_as(some_changepw, ['cpw'] + args + ['unselected'], + expected_code=1, expected_msg=msg) + kadmin_as(none, ['cpw'] + args + ['none']) realm.run([kadminl, 'modprinc', '-policy', 'minlife', 'none']) - out = kadmin_as(none, ['cpw'] + args + ['none'], expected_code=1) - if 'Current password\'s minimum life has not expired' not in out: - fail('cpw failure (minimum life)') + msg = "Current password's minimum life has not expired" + kadmin_as(none, ['cpw'] + args + ['none'], expected_code=1, + expected_msg=msg) realm.run([kadminl, 'modprinc', '-clearpolicy', 'none']) realm.run([kadminl, 'delprinc', 'selected']) realm.run([kadminl, 'delprinc', 'unselected']) kadmin_as(all_add, ['addpol', 'policy']) realm.run([kadminl, 'delpol', 'policy']) -out = kadmin_as(none, ['addpol', 'policy'], expected_code=1) -if 'Operation requires ``add\'\' privilege' not in out: - fail('addpol failure (no perms)') +kadmin_as(none, ['addpol', 'policy'], expected_code=1, + expected_msg="Operation requires ``add'' privilege") # addprinc can generate two different RPC calls depending on options. for ks in ([], ['-e', 'aes256-cts']): @@ -117,89 +114,62 @@ for ks in ([], ['-e', 'aes256-cts']): kadmin_as(some_add, ['addprinc'] + args + ['selected']) realm.run([kadminl, 'delprinc', 'selected']) kadmin_as(restricted_add, ['addprinc'] + args + ['unselected']) - out = realm.run([kadminl, 'getprinc', 'unselected']) - if 'REQUIRES_PRE_AUTH' not in out: - fail('addprinc success (restrictions) -- restriction check') + realm.run([kadminl, 'getprinc', 'unselected'], + expected_msg='REQUIRES_PRE_AUTH') realm.run([kadminl, 'delprinc', 'unselected']) - out = kadmin_as(none, ['addprinc'] + args + ['selected'], expected_code=1) - if 'Operation requires ``add\'\' privilege' not in out: - fail('addprinc failure (no perms)') - out = kadmin_as(some_add, ['addprinc'] + args + ['unselected'], - expected_code=1) - if 'Operation requires ``add\'\' privilege' not in out: - fail('addprinc failure (target)') + kadmin_as(none, ['addprinc'] + args + ['selected'], expected_code=1, + expected_msg="Operation requires ``add'' privilege") + kadmin_as(some_add, ['addprinc'] + args + ['unselected'], expected_code=1, + expected_msg="Operation requires ``add'' privilege") realm.addprinc('unselected', 'pw') kadmin_as(all_delete, ['delprinc', 'unselected']) realm.addprinc('selected', 'pw') kadmin_as(some_delete, ['delprinc', 'selected']) realm.addprinc('unselected', 'pw') -out = kadmin_as(none, ['delprinc', 'unselected'], expected_code=1) -if 'Operation requires ``delete\'\' privilege' not in out: - fail('delprinc failure (no perms)') -out = kadmin_as(some_delete, ['delprinc', 'unselected'], expected_code=1) -if 'Operation requires ``delete\'\' privilege' not in out: - fail('delprinc failure (no target)') +kadmin_as(none, ['delprinc', 'unselected'], expected_code=1, + expected_msg="Operation requires ``delete'' privilege") +kadmin_as(some_delete, ['delprinc', 'unselected'], expected_code=1, + expected_msg="Operation requires ``delete'' privilege") realm.run([kadminl, 'delprinc', 'unselected']) -out = kadmin_as(all_inquire, ['getpol', 'minlife']) -if 'Policy: minlife' not in out: - fail('getpol success (acl)') -out = kadmin_as(none, ['getpol', 'minlife'], expected_code=1) -if 'Operation requires ``get\'\' privilege' not in out: - fail('getpol failure (no perms)') +kadmin_as(all_inquire, ['getpol', 'minlife'], expected_msg='Policy: minlife') +kadmin_as(none, ['getpol', 'minlife'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") realm.run([kadminl, 'modprinc', '-policy', 'minlife', 'none']) -out = kadmin_as(none, ['getpol', 'minlife']) -if 'Policy: minlife' not in out: - fail('getpol success (self policy exemption)') +kadmin_as(none, ['getpol', 'minlife'], expected_msg='Policy: minlife') realm.run([kadminl, 'modprinc', '-clearpolicy', 'none']) realm.addprinc('selected', 'pw') realm.addprinc('unselected', 'pw') -out = kadmin_as(all_inquire, ['getprinc', 'unselected']) -if 'Principal: unselected@KRBTEST.COM' not in out: - fail('getprinc success (acl)') -out = kadmin_as(some_inquire, ['getprinc', 'selected']) -if 'Principal: selected@KRBTEST.COM' not in out: - fail('getprinc success (target)') -out = kadmin_as(none, ['getprinc', 'selected'], expected_code=1) -if 'Operation requires ``get\'\' privilege' not in out: - fail('getprinc failure (no perms)') -out = kadmin_as(some_inquire, ['getprinc', 'unselected'], expected_code=1) -if 'Operation requires ``get\'\' privilege' not in out: - fail('getprinc failure (target)') -out = kadmin_as(none, ['getprinc', 'none']) -if 'Principal: none@KRBTEST.COM' not in out: - fail('getprinc success (self exemption)') +kadmin_as(all_inquire, ['getprinc', 'unselected'], + expected_msg='Principal: unselected@KRBTEST.COM') +kadmin_as(some_inquire, ['getprinc', 'selected'], + expected_msg='Principal: selected@KRBTEST.COM') +kadmin_as(none, ['getprinc', 'selected'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +kadmin_as(some_inquire, ['getprinc', 'unselected'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +kadmin_as(none, ['getprinc', 'none'], + expected_msg='Principal: none@KRBTEST.COM') realm.run([kadminl, 'delprinc', 'selected']) realm.run([kadminl, 'delprinc', 'unselected']) -out = kadmin_as(all_list, ['listprincs']) -if 'K/M@KRBTEST.COM' not in out: - fail('listprincs success (acl)') -out = kadmin_as(none, ['listprincs'], expected_code=1) -if 'Operation requires ``list\'\' privilege' not in out: - fail('listprincs failure (no perms)') +kadmin_as(all_list, ['listprincs'], expected_msg='K/M@KRBTEST.COM') +kadmin_as(none, ['listprincs'], expected_code=1, + expected_msg="Operation requires ``list'' privilege") realm.addprinc('selected', 'pw') realm.addprinc('unselected', 'pw') realm.run([kadminl, 'setstr', 'selected', 'key', 'value']) realm.run([kadminl, 'setstr', 'unselected', 'key', 'value']) -out = kadmin_as(all_inquire, ['getstrs', 'unselected']) -if 'key: value' not in out: - fail('getstrs success (acl)') -out = kadmin_as(some_inquire, ['getstrs', 'selected']) -if 'key: value' not in out: - fail('getstrs success (target)') -out = kadmin_as(none, ['getstrs', 'selected'], expected_code=1) -if 'Operation requires ``get\'\' privilege' not in out: - fail('getstrs failure (no perms)') -out = kadmin_as(some_inquire, ['getstrs', 'unselected'], expected_code=1) -if 'Operation requires ``get\'\' privilege' not in out: - fail('getstrs failure (target)') -out = kadmin_as(none, ['getstrs', 'none']) -if '(No string attributes.)' not in out: - fail('getstrs success (self exemption)') +kadmin_as(all_inquire, ['getstrs', 'unselected'], expected_msg='key: value') +kadmin_as(some_inquire, ['getstrs', 'selected'], expected_msg='key: value') +kadmin_as(none, ['getstrs', 'selected'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +kadmin_as(some_inquire, ['getstrs', 'unselected'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +kadmin_as(none, ['getstrs', 'none'], expected_msg='(No string attributes.)') realm.run([kadminl, 'delprinc', 'selected']) realm.run([kadminl, 'delprinc', 'unselected']) @@ -207,27 +177,21 @@ out = kadmin_as(all_modify, ['modpol', '-maxlife', '1 hour', 'policy'], expected_code=1) if 'Operation requires' in out: fail('modpol success (acl)') -out = kadmin_as(none, ['modpol', '-maxlife', '1 hour', 'policy'], - expected_code=1) -if 'Operation requires ``modify\'\' privilege' not in out: - fail('modpol failure (no perms)') +kadmin_as(none, ['modpol', '-maxlife', '1 hour', 'policy'], expected_code=1, + expected_msg="Operation requires ``modify'' privilege") realm.addprinc('selected', 'pw') realm.addprinc('unselected', 'pw') 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']) -out = realm.run([kadminl, 'getprinc', 'unselected']) -if 'REQUIRES_PRE_AUTH' not in out: - fail('addprinc success (restrictions) -- restriction check') -out = kadmin_as(all_inquire, ['modprinc', '-maxlife', '1 hour', 'selected'], - expected_code=1) -if 'Operation requires ``modify\'\' privilege' not in out: - fail('addprinc failure (no perms)') -out = kadmin_as(some_modify, ['modprinc', '-maxlife', '1 hour', 'unselected'], - expected_code=1) -if 'Operation requires' not in out: - fail('modprinc failure (target)') +realm.run([kadminl, 'getprinc', 'unselected'], + expected_msg='REQUIRES_PRE_AUTH') +kadmin_as(all_inquire, ['modprinc', '-maxlife', '1 hour', 'selected'], + expected_code=1, + expected_msg="Operation requires ``modify'' privilege") +kadmin_as(some_modify, ['modprinc', '-maxlife', '1 hour', 'unselected'], + expected_code=1, expected_msg='Operation requires') realm.run([kadminl, 'delprinc', 'selected']) realm.run([kadminl, 'delprinc', 'unselected']) @@ -235,12 +199,10 @@ realm.addprinc('selected', 'pw') realm.addprinc('unselected', 'pw') kadmin_as(all_modify, ['purgekeys', 'unselected']) kadmin_as(some_modify, ['purgekeys', 'selected']) -out = kadmin_as(none, ['purgekeys', 'selected'], expected_code=1) -if 'Operation requires ``modify\'\' privilege' not in out: - fail('purgekeys failure (no perms)') -out = kadmin_as(some_modify, ['purgekeys', 'unselected'], expected_code=1) -if 'Operation requires ``modify\'\' privilege' not in out: - fail('purgekeys failure (target)') +kadmin_as(none, ['purgekeys', 'selected'], expected_code=1, + expected_msg="Operation requires ``modify'' privilege") +kadmin_as(some_modify, ['purgekeys', 'unselected'], expected_code=1, + expected_msg="Operation requires ``modify'' privilege") kadmin_as(none, ['purgekeys', 'none']) realm.run([kadminl, 'delprinc', 'selected']) realm.run([kadminl, 'delprinc', 'unselected']) @@ -250,36 +212,27 @@ kadmin_as(all_rename, ['renprinc', 'from', 'to']) realm.run([kadminl, 'renprinc', 'to', 'from']) kadmin_as(some_rename, ['renprinc', 'from', 'to']) realm.run([kadminl, 'renprinc', 'to', 'from']) -out = kadmin_as(all_add, ['renprinc', 'from', 'to'], expected_code=1) -if 'Operation requires ``delete\'\' privilege' not in out: - fail('renprinc failure (no delete perms)') -out = kadmin_as(all_delete, ['renprinc', 'from', 'to'], expected_code=1) -if 'Operation requires ``add\'\' privilege' not in out: - fail('renprinc failure (no add perms)') -out = kadmin_as(some_rename, ['renprinc', 'from', 'notto'], expected_code=1) -if 'Operation requires ``add\'\' privilege' not in out: - fail('renprinc failure (new target)') +kadmin_as(all_add, ['renprinc', 'from', 'to'], expected_code=1, + expected_msg="Insufficient authorization for operation") +kadmin_as(all_delete, ['renprinc', 'from', 'to'], expected_code=1, + expected_msg="Insufficient authorization for operation") +kadmin_as(some_rename, ['renprinc', 'from', 'notto'], expected_code=1, + expected_msg="Insufficient authorization for operation") realm.run([kadminl, 'renprinc', 'from', 'notfrom']) -out = kadmin_as(some_rename, ['renprinc', 'notfrom', 'to'], expected_code=1) -if 'Operation requires ``delete\'\' privilege' not in out: - fail('renprinc failure (old target)') -out = kadmin_as(restricted_rename, ['renprinc', 'notfrom', 'to'], - expected_code=1) -if 'Operation requires ``add\'\' privilege' not in out: - fail('renprinc failure (restrictions)') +kadmin_as(some_rename, ['renprinc', 'notfrom', 'to'], expected_code=1, + expected_msg="Insufficient authorization for operation") +kadmin_as(restricted_rename, ['renprinc', 'notfrom', 'to'], expected_code=1, + expected_msg="Insufficient authorization for operation") realm.run([kadminl, 'delprinc', 'notfrom']) realm.addprinc('selected', 'pw') realm.addprinc('unselected', 'pw') kadmin_as(all_modify, ['setstr', 'unselected', 'key', 'value']) kadmin_as(some_modify, ['setstr', 'selected', 'key', 'value']) -out = kadmin_as(none, ['setstr', 'selected', 'key', 'value'], expected_code=1) -if 'Operation requires ``modify\'\' privilege' not in out: - fail('addprinc failure (no perms)') -out = kadmin_as(some_modify, ['setstr', 'unselected', 'key', 'value'], - expected_code=1) -if 'Operation requires' not in out: - fail('modprinc failure (target)') +kadmin_as(none, ['setstr', 'selected', 'key', 'value'], expected_code=1, + expected_msg="Operation requires ``modify'' privilege") +kadmin_as(some_modify, ['setstr', 'unselected', 'key', 'value'], + expected_code=1, expected_msg='Operation requires') realm.run([kadminl, 'delprinc', 'selected']) realm.run([kadminl, 'delprinc', 'unselected']) @@ -287,28 +240,21 @@ kadmin_as(admin, ['addprinc', '-pw', 'pw', 'anytarget']) realm.run([kadminl, 'delprinc', 'anytarget']) kadmin_as(wctarget, ['addprinc', '-pw', 'pw', 'wild/card']) realm.run([kadminl, 'delprinc', 'wild/card']) -out = kadmin_as(wctarget, ['addprinc', '-pw', 'pw', 'wild/card/extra'], - expected_code=1) -if 'Operation requires' not in out: - fail('addprinc failure (target wildcard extra component)') +kadmin_as(wctarget, ['addprinc', '-pw', 'pw', 'wild/card/extra'], + expected_code=1, expected_msg='Operation requires') realm.addprinc('admin/user', 'pw') kadmin_as(admin, ['delprinc', 'admin/user']) -out = kadmin_as(admin, ['delprinc', 'none'], expected_code=1) -if 'Operation requires' not in out: - fail('delprinc failure (wildcard backreferences not matched)') +kadmin_as(admin, ['delprinc', 'none'], expected_code=1, + expected_msg='Operation requires') realm.addprinc('four/one/three', 'pw') kadmin_as(onetwothreefour, ['delprinc', 'four/one/three']) kadmin_as(restrictions, ['addprinc', '-pw', 'pw', 'type1']) -out = realm.run([kadminl, 'getprinc', 'type1']) -if 'Policy: minlife' not in out: - fail('restriction (policy)') +realm.run([kadminl, 'getprinc', 'type1'], expected_msg='Policy: minlife') realm.run([kadminl, 'delprinc', 'type1']) kadmin_as(restrictions, ['addprinc', '-pw', 'pw', '-policy', 'minlife', 'type2']) -out = realm.run([kadminl, 'getprinc', 'type2']) -if 'Policy: [none]' not in out: - fail('restriction (clearpolicy)') +realm.run([kadminl, 'getprinc', 'type2'], expected_msg='Policy: [none]') realm.run([kadminl, 'delprinc', 'type2']) kadmin_as(restrictions, ['addprinc', '-pw', 'pw', '-maxlife', '1 minute', 'type3']) @@ -319,43 +265,50 @@ if ('Maximum ticket life: 0 days 00:01:00' not in out or realm.run([kadminl, 'delprinc', 'type3']) kadmin_as(restrictions, ['addprinc', '-pw', 'pw', '-maxrenewlife', '1 day', 'type3']) -out = realm.run([kadminl, 'getprinc', 'type3']) -if 'Maximum renewable life: 0 days 02:00:00' not in out: - fail('restriction (maxrenewlife high)') +realm.run([kadminl, 'getprinc', 'type3'], + expected_msg='Maximum renewable life: 0 days 02:00:00') realm.run([kadminl, 'addprinc', '-pw', 'pw', 'extractkeys']) -out = kadmin_as(all_wildcard, ['ktadd', '-norandkey', 'extractkeys'], - expected_code=1) -if 'Operation requires ``extract-keys\'\' privilege' not in out: - fail('extractkeys failure (all_wildcard)') +kadmin_as(all_wildcard, ['ktadd', '-norandkey', 'extractkeys'], + expected_code=1, + expected_msg="Operation requires ``extract-keys'' privilege") kadmin_as(all_extract, ['ktadd', '-norandkey', 'extractkeys']) realm.kinit('extractkeys', flags=['-k']) os.remove(realm.keytab) kadmin_as(all_modify, ['modprinc', '+lockdown_keys', 'extractkeys']) -out = kadmin_as(all_changepw, ['cpw', '-pw', 'newpw', 'extractkeys'], - expected_code=1) -if 'Operation requires ``change-password\'\' privilege' not in out: - fail('extractkeys failure (all_changepw)') +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']) -out = kadmin_as(all_extract, ['ktadd', '-norandkey', 'extractkeys'], - expected_code=1) -if 'Operation requires ``extract-keys\'\' privilege' not in out: - fail('extractkeys failure (all_extract)') -out = kadmin_as(all_delete, ['delprinc', 'extractkeys'], expected_code=1) -if 'Operation requires ``delete\'\' privilege' not in out: - fail('extractkeys failure (all_delete)') -out = kadmin_as(all_rename, ['renprinc', 'extractkeys', 'renamedprinc'], - expected_code=1) -if 'Operation requires ``delete\'\' privilege' not in out: - fail('extractkeys failure (all_rename)') -out = kadmin_as(all_modify, ['modprinc', '-lockdown_keys', 'extractkeys'], - expected_code=1) -if 'Operation requires ``modify\'\' privilege' not in out: - fail('extractkeys failure (all_modify)') +kadmin_as(all_extract, ['ktadd', '-norandkey', 'extractkeys'], expected_code=1, + expected_msg="Operation requires ``extract-keys'' privilege") +kadmin_as(all_delete, ['delprinc', 'extractkeys'], expected_code=1, + expected_msg="Operation requires ``delete'' privilege") +kadmin_as(all_rename, ['renprinc', 'extractkeys', 'renamedprinc'], + expected_code=1, + expected_msg="Operation requires ``delete'' privilege") +kadmin_as(all_modify, ['modprinc', '-lockdown_keys', 'extractkeys'], + expected_code=1, + expected_msg="Operation requires ``modify'' privilege") realm.run([kadminl, 'modprinc', '-lockdown_keys', 'extractkeys']) kadmin_as(all_extract, ['ktadd', '-norandkey', 'extractkeys']) realm.kinit('extractkeys', flags=['-k']) os.remove(realm.keytab) +# Verify that self-service key changes require an initial ticket. +realm.run([kadminl, 'cpw', '-pw', password('none'), 'none']) +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'], + expected_code=1, expected_msg=msg) +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) +realm.run([kadmin, '-c', realm.ccache, 'cpw', '-randkey', '-e', 'aes256-cts', + 'none'], expected_code=1, expected_msg=msg) + success('kadmin ACL enforcement') diff --git a/src/tests/t_kadmin_parsing.py b/src/tests/t_kadmin_parsing.py index 92d72d2b08a8..8de387c647a3 100644 --- a/src/tests/t_kadmin_parsing.py +++ b/src/tests/t_kadmin_parsing.py @@ -57,33 +57,27 @@ realm = K5Realm(create_host=False, get_creds=False) realm.run([kadminl, 'addpol', 'pol']) for instr, outstr in intervals: realm.run([kadminl, 'modprinc', '-maxlife', instr, realm.user_princ]) - out = realm.run([kadminl, 'getprinc', realm.user_princ]) - if 'Maximum ticket life: ' + outstr + '\n' not in out: - fail('princ maxlife: ' + instr) + msg = 'Maximum ticket life: ' + outstr + '\n' + realm.run([kadminl, 'getprinc', realm.user_princ], expected_msg=msg) realm.run([kadminl, 'modprinc', '-maxrenewlife', instr, realm.user_princ]) - out = realm.run([kadminl, 'getprinc', realm.user_princ]) - if 'Maximum renewable life: ' + outstr + '\n' not in out: - fail('princ maxrenewlife: ' + instr) + msg = 'Maximum renewable life: ' + outstr + '\n' + realm.run([kadminl, 'getprinc', realm.user_princ], expected_msg=msg) realm.run([kadminl, 'modpol', '-maxlife', instr, 'pol']) - out = realm.run([kadminl, 'getpol', 'pol']) - if 'Maximum password life: ' + outstr + '\n' not in out: - fail('pol maxlife: ' + instr) + msg = 'Maximum password life: ' + outstr + '\n' + realm.run([kadminl, 'getpol', 'pol'], expected_msg=msg) realm.run([kadminl, 'modpol', '-minlife', instr, 'pol']) - out = realm.run([kadminl, 'getpol', 'pol']) - if 'Minimum password life: ' + outstr + '\n' not in out: - fail('pol maxlife: ' + instr) + msg = 'Minimum password life: ' + outstr + '\n' + realm.run([kadminl, 'getpol', 'pol'], expected_msg=msg) realm.run([kadminl, 'modpol', '-failurecountinterval', instr, 'pol']) - out = realm.run([kadminl, 'getpol', 'pol']) - if 'Password failure count reset interval: ' + outstr + '\n' not in out: - fail('pol maxlife: ' + instr) + msg = 'Password failure count reset interval: ' + outstr + '\n' + realm.run([kadminl, 'getpol', 'pol'], expected_msg=msg) realm.run([kadminl, 'modpol', '-lockoutduration', instr, 'pol']) - out = realm.run([kadminl, 'getpol', 'pol']) - if 'Password lockout duration: ' + outstr + '\n' not in out: - fail('pol maxlife: ' + instr) + msg = 'Password lockout duration: ' + outstr + '\n' + realm.run([kadminl, 'getpol', 'pol'], expected_msg=msg) success('kadmin command parsing tests') diff --git a/src/tests/t_kdb.py b/src/tests/t_kdb.py index 185225afa5a3..217f2cdc3bdc 100755 --- a/src/tests/t_kdb.py +++ b/src/tests/t_kdb.py @@ -16,22 +16,27 @@ if (not os.path.exists(os.path.join(plugins, 'kdb', 'kldap.so')) and if 'SLAPD' not in os.environ and not which('slapd'): skip_rest('LDAP KDB tests', 'slapd not found') +slapadd = which('slapadd') +if not slapadd: + skip_rest('LDAP KDB tests', 'slapadd not found') + ldapdir = os.path.abspath('ldap') dbdir = os.path.join(ldapdir, 'ldap') -slapd_conf = os.path.join(ldapdir, 'slapd.conf') +slapd_conf = os.path.join(ldapdir, 'slapd.d') slapd_out = os.path.join(ldapdir, 'slapd.out') slapd_pidfile = os.path.join(ldapdir, 'pid') ldap_pwfile = os.path.join(ldapdir, 'pw') ldap_sock = os.path.join(ldapdir, 'sock') ldap_uri = 'ldapi://%s/' % ldap_sock.replace(os.path.sep, '%2F') schema = os.path.join(srctop, 'plugins', 'kdb', 'ldap', 'libkdb_ldap', - 'kerberos.schema') + 'kerberos.openldap.ldif') top_dn = 'cn=krb5' admin_dn = 'cn=admin,cn=krb5' admin_pw = 'admin' shutil.rmtree(ldapdir, True) os.mkdir(ldapdir) +os.mkdir(slapd_conf) os.mkdir(dbdir) if 'SLAPD' in os.environ: @@ -44,32 +49,61 @@ else: slapd = os.path.join(ldapdir, 'slapd') shutil.copy(system_slapd, slapd) -# Find the core schema file if we can. +def slap_add(ldif): + proc = subprocess.Popen([slapadd, '-b', 'cn=config', '-F', slapd_conf], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + (out, dummy) = proc.communicate(ldif) + output(out) + return proc.wait() + + +# Configure the pid file and some authorization rules we will need for +# SASL testing. +if slap_add('dn: cn=config\n' + 'objectClass: olcGlobal\n' + 'olcPidFile: %s\n' + 'olcAuthzRegexp: ' + '".*uidNumber=%d,cn=peercred,cn=external,cn=auth" "%s"\n' + 'olcAuthzRegexp: "uid=digestuser,cn=digest-md5,cn=auth" "%s"\n' % + (slapd_pidfile, os.geteuid(), admin_dn, admin_dn)) != 0: + skip_rest('LDAP KDB tests', 'slapd basic configuration failed') + +# Find a working writable database type, trying mdb (added in OpenLDAP +# 2.4.27) and bdb (deprecated and sometimes not built due to licensing +# incompatibilities). +for dbtype in ('mdb', 'bdb'): + # Try to load the module. This could fail if OpenLDAP is built + # without module support, so ignore errors. + slap_add('dn: cn=module,cn=config\n' + 'objectClass: olcModuleList\n' + 'olcModuleLoad: back_%s\n' % dbtype) + + dbclass = 'olc%sConfig' % dbtype.capitalize() + if slap_add('dn: olcDatabase=%s,cn=config\n' + 'objectClass: olcDatabaseConfig\n' + 'objectClass: %s\n' + 'olcSuffix: %s\n' + 'olcRootDN: %s\n' + 'olcRootPW: %s\n' + 'olcDbDirectory: %s\n' % + (dbtype, dbclass, top_dn, admin_dn, admin_pw, dbdir)) == 0: + break +else: + skip_rest('LDAP KDB tests', 'could not find working slapd db type') + +if slap_add('include: file://%s\n' % schema) != 0: + skip_rest('LDAP KDB tests', 'failed to load Kerberos schema') + +# Load the core schema if we can. ldap_homes = ['/etc/ldap', '/etc/openldap', '/usr/local/etc/openldap', '/usr/local/etc/ldap'] -local_schema_path = '/schema/core.schema' +local_schema_path = '/schema/core.ldif' core_schema = next((i for i in imap(lambda x:x+local_schema_path, ldap_homes) if os.path.isfile(i)), None) - -# Make a slapd config file. This is deprecated in OpenLDAP 2.3 and -# later, but it's easier than using LDIF and slapadd. Include some -# authz-regexp entries for SASL authentication tests. Load the core -# schema if we found it, for use in the DIGEST-MD5 test. -file = open(slapd_conf, 'w') -file.write('pidfile %s\n' % slapd_pidfile) -file.write('include %s\n' % schema) if core_schema: - file.write('include %s\n' % core_schema) -file.write('moduleload back_bdb\n') -file.write('database bdb\n') -file.write('suffix %s\n' % top_dn) -file.write('rootdn %s\n' % admin_dn) -file.write('rootpw %s\n' % admin_pw) -file.write('directory %s\n' % dbdir) -file.write('authz-regexp .*uidNumber=%d,cn=peercred,cn=external,cn=auth %s\n' % - (os.geteuid(), admin_dn)) -file.write('authz-regexp uid=digestuser,cn=digest-md5,cn=auth %s\n' % admin_dn) -file.close() + if slap_add('include: file://%s\n' % core_schema) != 0: + core_schema = None slapd_pid = -1 def kill_slapd(): @@ -80,7 +114,7 @@ def kill_slapd(): atexit.register(kill_slapd) out = open(slapd_out, 'w') -subprocess.call([slapd, '-h', ldap_uri, '-f', slapd_conf], stdout=out, +subprocess.call([slapd, '-h', ldap_uri, '-F', slapd_conf], stdout=out, stderr=out) out.close() pidf = open(slapd_pidfile, 'r') @@ -167,47 +201,31 @@ if out != 'KRBTEST.COM\n': # because we're sticking a krbPrincipalAux objectclass onto a subtree # krbContainer, but it works and it avoids having to load core.schema # in the test LDAP server. -out = realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=krb5', 'princ1'], - expected_code=1) -if 'DN is out of the realm subtree' not in out: - fail('Unexpected kadmin.local output for out-of-realm dn') +realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=krb5', 'princ1'], + expected_code=1, expected_msg='DN is out of the realm subtree') realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=t2,cn=krb5', 'princ1']) -out = realm.run([kadminl, 'getprinc', 'princ1']) -if 'Principal: princ1' not in out: - fail('Unexpected kadmin.local output after creating princ1') -out = realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=t2,cn=krb5', - 'again'], expected_code=1) -if 'ldap object is already kerberized' not in out: - fail('Unexpected kadmin.local output trying to re-kerberize DN') +realm.run([kadminl, 'getprinc', 'princ1'], expected_msg='Principal: princ1') +realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=t2,cn=krb5', 'again'], + expected_code=1, expected_msg='ldap object is already kerberized') # Check that we can't set linkdn on a non-standalone object. -out = realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t1,cn=krb5', 'princ1'], - expected_code=1) -if 'link information can not be set' not in out: - fail('Unexpected kadmin.local output trying to set linkdn on princ1') +realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t1,cn=krb5', 'princ1'], + expected_code=1, expected_msg='link information can not be set') # Create a principal with a specified linkdn. -out = realm.run([kadminl, 'ank', '-randkey', '-x', 'linkdn=cn=krb5', 'princ2'], - expected_code=1) -if 'DN is out of the realm subtree' not in out: - fail('Unexpected kadmin.local output for out-of-realm linkdn') +realm.run([kadminl, 'ank', '-randkey', '-x', 'linkdn=cn=krb5', 'princ2'], + expected_code=1, expected_msg='DN is out of the realm subtree') realm.run([kadminl, 'ank', '-randkey', '-x', 'linkdn=cn=t1,cn=krb5', 'princ2']) # Check that we can't reset linkdn. -out = realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t2,cn=krb5', 'princ2'], - expected_code=1) -if 'kerberos principal is already linked' not in out: - fail('Unexpected kadmin.local output for re-specified linkdn') +realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t2,cn=krb5', 'princ2'], + expected_code=1, expected_msg='kerberos principal is already linked') # Create a principal with a specified containerdn. -out = realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=krb5', - 'princ3'], expected_code=1) -if 'DN is out of the realm subtree' not in out: - fail('Unexpected kadmin.local output for out-of-realm containerdn') +realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=krb5', 'princ3'], + expected_code=1, expected_msg='DN is out of the realm subtree') realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=t1,cn=krb5', 'princ3']) -out = realm.run([kadminl, 'modprinc', '-x', 'containerdn=cn=t2,cn=krb5', - 'princ3'], expected_code=1) -if 'containerdn option not supported' not in out: - fail('Unexpected kadmin.local output trying to reset containerdn') +realm.run([kadminl, 'modprinc', '-x', 'containerdn=cn=t2,cn=krb5', 'princ3'], + expected_code=1, expected_msg='containerdn option not supported') # Create and modify a ticket policy. kldaputil(['create_policy', '-maxtktlife', '3hour', '-maxrenewlife', '6hour', @@ -255,9 +273,8 @@ if out: kldaputil(['create_policy', 'tktpol2']) # Try to create a password policy conflicting with a ticket policy. -out = realm.run([kadminl, 'addpol', 'tktpol2'], expected_code=1) -if 'Already exists while creating policy "tktpol2"' not in out: - fail('Expected error not seen in kadmin.local output') +realm.run([kadminl, 'addpol', 'tktpol2'], expected_code=1, + expected_msg='Already exists while creating policy "tktpol2"') # Try to create a ticket policy conflicting with a password policy. realm.run([kadminl, 'addpol', 'pwpol']) @@ -266,16 +283,13 @@ if 'Already exists while creating policy object' not in out: fail('Expected error not seen in kdb5_ldap_util output') # Try to use a password policy as a ticket policy. -out = realm.run([kadminl, 'modprinc', '-x', 'tktpolicy=pwpol', 'princ4'], - expected_code=1) -if 'Object class violation' not in out: - fail('Expected error not seem in kadmin.local output') +realm.run([kadminl, 'modprinc', '-x', 'tktpolicy=pwpol', 'princ4'], + expected_code=1, expected_msg='Object class violation') # Use a ticket policy as a password policy (CVE-2014-5353). This # works with a warning; use kadmin.local -q so the warning is shown. -out = realm.run([kadminl, '-q', 'modprinc -policy tktpol2 princ4']) -if 'WARNING: policy "tktpol2" does not exist' not in out: - fail('Expected error not seen in kadmin.local output') +realm.run([kadminl, '-q', 'modprinc -policy tktpol2 princ4'], + expected_msg='WARNING: policy "tktpol2" does not exist') # Do some basic tests with a KDC against the LDAP module, exercising the # db_args processing code. @@ -298,9 +312,8 @@ if 'krbPrincipalAuthInd: otp' not in out: if 'krbPrincipalAuthInd: radius' not in out: fail('Expected krbPrincipalAuthInd value not in output') -out = realm.run([kadminl, 'getstrs', 'authind']) -if 'require_auth: otp radius' not in out: - fail('Expected auth indicators value not in output') +realm.run([kadminl, 'getstrs', 'authind'], + expected_msg='require_auth: otp radius') # Test service principal aliases. realm.addprinc('canon', password('canon')) @@ -311,14 +324,11 @@ ldap_modify('dn: krbPrincipalName=canon@KRBTEST.COM,cn=t1,cn=krb5\n' '-\n' 'add: krbCanonicalName\n' 'krbCanonicalName: canon@KRBTEST.COM\n') -out = realm.run([kadminl, 'getprinc', 'alias']) -if 'Principal: canon@KRBTEST.COM\n' not in out: - fail('Could not fetch canon through alias') -out = realm.run([kadminl, 'getprinc', 'canon']) -if 'Principal: canon@KRBTEST.COM\n' not in out: - fail('Could not fetch canon through canon') -realm.run([kvno, 'alias']) -realm.run([kvno, 'canon']) +realm.run([kadminl, 'getprinc', 'alias'], + expected_msg='Principal: canon@KRBTEST.COM\n') +realm.run([kadminl, 'getprinc', 'canon'], + expected_msg='Principal: canon@KRBTEST.COM\n') +realm.run([kvno, 'alias', 'canon']) out = realm.run([klist]) if 'alias@KRBTEST.COM\n' not in out or 'canon@KRBTEST.COM' not in out: fail('After fetching alias and canon, klist is missing one or both') @@ -334,9 +344,8 @@ ldap_modify('dn: krbPrincipalName=krbtgt/KRBTEST.COM@KRBTEST.COM,' '-\n' 'add: krbCanonicalName\n' 'krbCanonicalName: krbtgt/KRBTEST.COM@KRBTEST.COM\n') -out = realm.run([kadminl, 'getprinc', 'tgtalias']) -if 'Principal: krbtgt/KRBTEST.COM@KRBTEST.COM' not in out: - fail('Could not fetch krbtgt through tgtalias') +realm.run([kadminl, 'getprinc', 'tgtalias'], + expected_msg='Principal: krbtgt/KRBTEST.COM@KRBTEST.COM') realm.kinit(realm.user_princ, password('user')) realm.run([kvno, 'tgtalias']) realm.klist(realm.user_princ, 'tgtalias@KRBTEST.COM') @@ -352,9 +361,8 @@ realm.klist(realm.user_princ, 'alias@KRBTEST.COM') # Test client principal aliases, with and without preauth. realm.kinit('canon', password('canon')) -out = realm.kinit('alias', password('canon'), expected_code=1) -if 'not found in Kerberos database' not in out: - fail('Wrong error message for kinit to alias without -C flag') +realm.kinit('alias', password('canon'), expected_code=1, + expected_msg='not found in Kerberos database') realm.kinit('alias', password('canon'), ['-C']) realm.run([kvno, 'alias']) realm.klist('canon@KRBTEST.COM', 'alias@KRBTEST.COM') @@ -413,31 +421,24 @@ realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts,aes128-cts', 'kvnoprinc']) realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-cts,aes128-cts', 'kvnoprinc']) -out = realm.run([kadminl, 'getprinc', 'kvnoprinc']) -if 'Number of keys: 4' not in out: - fail('After cpw -keepold, wrong number of keys') +realm.run([kadminl, 'getprinc', 'kvnoprinc'], expected_msg='Number of keys: 4') realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-cts,aes128-cts', 'kvnoprinc']) -out = realm.run([kadminl, 'getprinc', 'kvnoprinc']) -if 'Number of keys: 6' not in out: - fail('After cpw -keepold, wrong number of keys') +realm.run([kadminl, 'getprinc', 'kvnoprinc'], expected_msg='Number of keys: 6') # Regression test for #8041 (NULL dereference on keyless principals). realm.run([kadminl, 'addprinc', '-nokey', 'keylessprinc']) -out = realm.run([kadminl, 'getprinc', 'keylessprinc']) -if 'Number of keys: 0' not in out: - fail('Failed to create a principal with no keys') +realm.run([kadminl, 'getprinc', 'keylessprinc'], + expected_msg='Number of keys: 0') realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts,aes128-cts', 'keylessprinc']) realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-cts,aes128-cts', 'keylessprinc']) -out = realm.run([kadminl, 'getprinc', 'keylessprinc']) -if 'Number of keys: 4' not in out: - fail('Failed to add keys to keylessprinc') +realm.run([kadminl, 'getprinc', 'keylessprinc'], + expected_msg='Number of keys: 4') realm.run([kadminl, 'purgekeys', '-all', 'keylessprinc']) -out = realm.run([kadminl, 'getprinc', 'keylessprinc']) -if 'Number of keys: 0' not in out: - fail('After purgekeys -all, keys remain') +realm.run([kadminl, 'getprinc', 'keylessprinc'], + expected_msg='Number of keys: 0') # Test for 8354 (old password history entries when -keepold is used) realm.run([kadminl, 'addpol', '-history', '2', 'keepoldpasspol']) @@ -446,14 +447,20 @@ realm.run([kadminl, 'addprinc', '-policy', 'keepoldpasspol', '-pw', 'aaaa', for p in ('bbbb', 'cccc', 'aaaa'): realm.run([kadminl, 'cpw', '-keepold', '-pw', p, 'keepoldpassprinc']) +if runenv.sizeof_time_t <= 4: + skipped('y2038 LDAP test', 'platform has 32-bit time_t') +else: + # Test storage of timestamps after y2038. + realm.run([kadminl, 'modprinc', '-pwexpire', '2040-02-03', 'user']) + realm.run([kadminl, 'getprinc', 'user'], expected_msg=' 2040\n') + realm.stop() # Briefly test dump and load. dumpfile = os.path.join(realm.testdir, 'dump') realm.run([kdb5_util, 'dump', dumpfile]) -out = realm.run([kdb5_util, 'load', dumpfile], expected_code=1) -if 'KDB module requires -update argument' not in out: - fail('Unexpected error from kdb5_util load without -update') +realm.run([kdb5_util, 'load', dumpfile], expected_code=1, + expected_msg='KDB module requires -update argument') realm.run([kdb5_util, 'load', '-update', dumpfile]) # Destroy the realm. @@ -501,14 +508,10 @@ realm.addprinc(realm.user_princ, password('user')) realm.kinit(realm.user_princ, password('user')) realm.stop() # Exercise DB options, which should cause binding to fail. -out = realm.run([kadminl, '-x', 'sasl_authcid=ab', 'getprinc', 'user'], - expected_code=1) -if 'Cannot bind to LDAP server' not in out: - fail('Expected error not seen in kadmin.local output') -out = realm.run([kadminl, '-x', 'bindpwd=wrong', 'getprinc', 'user'], - expected_code=1) -if 'Cannot bind to LDAP server' not in out: - fail('Expected error not seen in kadmin.local output') +realm.run([kadminl, '-x', 'sasl_authcid=ab', 'getprinc', 'user'], + expected_code=1, expected_msg='Cannot bind to LDAP server') +realm.run([kadminl, '-x', 'bindpwd=wrong', 'getprinc', 'user'], + expected_code=1, expected_msg='Cannot bind to LDAP server') realm.run([kdb5_ldap_util, 'destroy', '-f']) # We could still use tests to exercise: diff --git a/src/tests/t_kdb_locking.py b/src/tests/t_kdb_locking.py index e8d86e09bfd5..aac0a220f424 100755 --- a/src/tests/t_kdb_locking.py +++ b/src/tests/t_kdb_locking.py @@ -21,9 +21,8 @@ if not os.path.exists(kadm5_lock): fail('kadm5 lock file not created: ' + kadm5_lock) os.unlink(kadm5_lock) -output = realm.kinit(p, p, [], expected_code=1) -if 'A service is not available' not in output: - fail('krb5kdc should have returned service not available error') +realm.kinit(p, p, [], expected_code=1, + expected_msg='A service is not available') f = open(kadm5_lock, 'w') f.close() diff --git a/src/tests/t_kdcpolicy.py b/src/tests/t_kdcpolicy.py new file mode 100644 index 000000000000..5b198bb430c5 --- /dev/null +++ b/src/tests/t_kdcpolicy.py @@ -0,0 +1,62 @@ +#!/usr/bin/python +from k5test import * +from datetime import datetime +import re + +testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so') +testpolicy = os.path.join(buildtop, 'plugins', 'kdcpolicy', 'test', + 'kdcpolicy_test.so') +krb5_conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth}, + 'clpreauth': {'module': 'test:' + testpreauth}, + 'kdcpolicy': {'module': 'test:' + testpolicy}}} +kdc_conf = {'realms': {'$realm': {'default_principal_flags': '+preauth', + 'max_renewable_life': '1d'}}} +realm = K5Realm(krb5_conf=krb5_conf, kdc_conf=kdc_conf) + +realm.run([kadminl, 'addprinc', '-pw', password('fail'), 'fail']) + +def verify_time(out, target_time): + times = re.findall(r'\d\d/\d\d/\d\d \d\d:\d\d:\d\d', out) + times = [datetime.strptime(t, '%m/%d/%y %H:%M:%S') for t in times] + divisor = 1 + while len(times) > 0: + starttime = times.pop(0) + endtime = times.pop(0) + renewtime = times.pop(0) + + if str((endtime - starttime) * divisor) != target_time: + fail('unexpected lifetime value') + if str((renewtime - endtime) * divisor) != target_time: + fail('unexpected renewable value') + + # Service tickets should have half the lifetime of initial + # tickets. + divisor = 2 + +rflags = ['-r', '1d', '-l', '12h'] + +# Test AS+TGS success path. +realm.kinit(realm.user_princ, password('user'), + rflags + ['-X', 'indicators=SEVEN_HOURS']) +realm.run([kvno, realm.host_princ]) +realm.run(['./adata', realm.host_princ], expected_msg='+97: [SEVEN_HOURS]') +out = realm.run([klist, '-e', realm.ccache]) +verify_time(out, '7:00:00') + +# Test AS+TGS success path with different values. +realm.kinit(realm.user_princ, password('user'), + rflags + ['-X', 'indicators=ONE_HOUR']) +realm.run([kvno, realm.host_princ]) +realm.run(['./adata', realm.host_princ], expected_msg='+97: [ONE_HOUR]') +out = realm.run([klist, '-e', realm.ccache]) +verify_time(out, '1:00:00') + +# Test TGS failure path (using previous creds). +realm.run([kvno, 'fail@%s' % realm.realm], expected_code=1, + expected_msg='KDC policy rejects request') + +# Test AS failure path. +realm.kinit('fail@%s' % realm.realm, password('fail'), + expected_code=1, expected_msg='KDC policy rejects request') + +success('kdcpolicy tests') diff --git a/src/tests/t_keydata.py b/src/tests/t_keydata.py index 686e543bd4dd..5c04a8523f08 100755 --- a/src/tests/t_keydata.py +++ b/src/tests/t_keydata.py @@ -5,27 +5,19 @@ realm = K5Realm(create_user=False, create_host=False) # Create a principal with no keys. realm.run([kadminl, 'addprinc', '-nokey', 'user']) -out = realm.run([kadminl, 'getprinc', 'user']) -if 'Number of keys: 0' not in out: - fail('getprinc (addprinc -nokey)') +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']) -out = realm.run([kadminl, 'getprinc', 'user']) -if 'vno 1' not in out: - fail('getprinc (cpw -pw)') +realm.run([kadminl, 'getprinc', 'user'], expected_msg='vno 1') # Delete all of its keys. realm.run([kadminl, 'purgekeys', '-all', 'user']) -out = realm.run([kadminl, 'getprinc', 'user']) -if 'Number of keys: 0' not in out: - fail('getprinc (purgekeys)') +realm.run([kadminl, 'getprinc', 'user'], expected_msg='Number of keys: 0') # Randomize its keys and check the resulting kvno. realm.run([kadminl, 'cpw', '-randkey', 'user']) -out = realm.run([kadminl, 'getprinc', 'user']) -if 'vno 1' not in out: - fail('getprinc (cpw -randkey)') +realm.run([kadminl, 'getprinc', 'user'], expected_msg='vno 1') # Return true if patype appears to have been received in a hint list # from a KDC error message, based on the trace file fname. diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py index 35d0b61b8056..bfd38914b7a0 100755 --- a/src/tests/t_keyrollover.py +++ b/src/tests/t_keyrollover.py @@ -23,25 +23,17 @@ realm.run([kvno, princ1]) realm.run([kadminl, 'purgekeys', realm.krbtgt_princ]) # Make sure an old TGT fails after purging old TGS key. realm.run([kvno, princ2], expected_code=1) -output = realm.run([klist, '-e']) - -expected = 'krbtgt/%s@%s\n\tEtype (skey, tkt): des-cbc-crc, des-cbc-crc' % \ +msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): des-cbc-crc, des-cbc-crc' % \ (realm.realm, realm.realm) - -if expected not in output: - fail('keyrollover: expected TGS enctype not found') +realm.run([klist, '-e'], expected_msg=msg) # Check that new key actually works. realm.kinit(realm.user_princ, password('user')) realm.run([kvno, realm.host_princ]) -output = realm.run([klist, '-e']) - -expected = 'krbtgt/%s@%s\n\tEtype (skey, tkt): ' \ +msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): ' \ 'aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96' % \ (realm.realm, realm.realm) - -if expected not in output: - fail('keyrollover: expected TGS enctype not found after change') +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 diff --git a/src/tests/t_keytab.py b/src/tests/t_keytab.py index a06e6c29653d..a48740ba532a 100755 --- a/src/tests/t_keytab.py +++ b/src/tests/t_keytab.py @@ -14,9 +14,8 @@ realm.run([ktutil], input=('rkt %s\ndelent 1\nwkt %s\n' % realm.kinit(realm.host_princ, flags=['-k', '-t', pkeytab]) # Test kinit with no keys for client in keytab. -output = realm.kinit(realm.user_princ, flags=['-k'], expected_code=1) -if 'no suitable keys' not in output: - fail('Expected error not seen in kinit output') +realm.kinit(realm.user_princ, flags=['-k'], expected_code=1, + expected_msg='no suitable keys') # Test kinit and klist with client keytab defaults. realm.extract_keytab(realm.user_princ, realm.client_keytab); @@ -31,14 +30,12 @@ if realm.client_keytab not in out or realm.user_princ not in out: # Test implicit request for keytab (-i or -t without -k) realm.run([kdestroy]) -output = realm.kinit(realm.host_princ, flags=['-t', realm.keytab]) -if 'keytab specified, forcing -k' not in output: - fail('Expected output not seen from kinit -t keytab') +realm.kinit(realm.host_princ, flags=['-t', realm.keytab], + expected_msg='keytab specified, forcing -k') realm.klist(realm.host_princ) realm.run([kdestroy]) -output = realm.kinit(realm.user_princ, flags=['-i']) -if 'keytab specified, forcing -k' not in output: - fail('Expected output not seen from kinit -i') +realm.kinit(realm.user_princ, flags=['-i'], + expected_msg='keytab specified, forcing -k') realm.klist(realm.user_princ) # Test extracting keys with multiple key versions present. @@ -70,12 +67,10 @@ def test_key_rotate(realm, princ, expected_kvno): realm.run_kadmin(['ktadd', '-k', realm.keytab, princ]) realm.run([kadminl, 'ktrem', princ, 'old']) realm.kinit(princ, flags=['-k']) - out = realm.run([klist, '-k']) - if ('%d %s' % (expected_kvno, princ)) not in out: - fail('kvno %d not listed in keytab' % expected_kvno) - out = realm.run_kadmin(['getprinc', princ]) - if ('Key: vno %d,' % expected_kvno) not in out: - fail('vno %d not seen in getprinc output' % expected_kvno) + msg = '%d %s' % (expected_kvno, princ) + out = realm.run([klist, '-k'], expected_msg=msg) + msg = 'Key: vno %d,' % expected_kvno + out = realm.run_kadmin(['getprinc', princ], expected_msg=msg) princ = 'foo/bar@%s' % realm.realm realm.addprinc(princ) @@ -109,9 +104,8 @@ f = open(realm.keytab, 'w') f.write('\x05\x02\x00\x00\x00' + chr(len(record))) f.write(record) f.close() -out = realm.run([klist, '-k']) -if (' 2 %s' % realm.user_princ) not in out: - fail('Expected entry not seen in klist -k output') +msg = ' 2 %s' % realm.user_princ +out = realm.run([klist, '-k'], expected_msg=msg) # Make sure zero-fill isn't treated as a 32-bit kvno. f = open(realm.keytab, 'w') @@ -119,9 +113,8 @@ f.write('\x05\x02\x00\x00\x00' + chr(len(record) + 4)) f.write(record) f.write('\x00\x00\x00\x00') f.close() -out = realm.run([klist, '-k']) -if (' 2 %s' % realm.user_princ) not in out: - fail('Expected entry not seen in klist -k output') +msg = ' 2 %s' % realm.user_princ +out = realm.run([klist, '-k'], expected_msg=msg) # Make sure a hand-crafted 32-bit kvno is recognized. f = open(realm.keytab, 'w') @@ -129,9 +122,8 @@ f.write('\x05\x02\x00\x00\x00' + chr(len(record) + 4)) f.write(record) f.write('\x00\x00\x00\x03') f.close() -out = realm.run([klist, '-k']) -if (' 3 %s' % realm.user_princ) not in out: - fail('Expected entry not seen in klist -k output') +msg = ' 3 %s' % realm.user_princ +out = realm.run([klist, '-k'], expected_msg=msg) # Test parameter expansion in profile variables realm.stop() @@ -142,11 +134,9 @@ realm = K5Realm(krb5_conf=conf, create_kdb=False) del realm.env['KRB5_KTNAME'] del realm.env['KRB5_CLIENT_KTNAME'] uidstr = str(os.getuid()) -out = realm.run([klist, '-k'], expected_code=1) -if 'FILE:testdir/abc%s' % uidstr not in out: - fail('Wrong keytab in klist -k output') -out = realm.run([klist, '-ki'], expected_code=1) -if 'FILE:testdir/xyz%s' % uidstr not in out: - fail('Wrong keytab in klist -ki output') +msg = 'FILE:testdir/abc%s' % uidstr +out = realm.run([klist, '-k'], expected_code=1, expected_msg=msg) +msg = 'FILE:testdir/xyz%s' % uidstr +out = realm.run([klist, '-ki'], expected_code=1, expected_msg=msg) success('Keytab-related tests') diff --git a/src/tests/t_kprop.py b/src/tests/t_kprop.py index 02cdfeec245f..39169675d6c4 100755 --- a/src/tests/t_kprop.py +++ b/src/tests/t_kprop.py @@ -43,9 +43,7 @@ for realm in multipass_realms(create_user=False): realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname]) check_output(kpropd) - out = realm.run([kadminl, 'listprincs'], slave) - if 'wakawaka' not in out: - fail('Slave does not have all principals from master') + realm.run([kadminl, 'listprincs'], slave, expected_msg='wakawaka') # default_realm tests follow. # default_realm and domain_realm different than realm.realm (test -r argument). @@ -79,9 +77,8 @@ realm.run([kdb5_util, 'dump', dumpfile]) realm.run([kprop, '-r', realm.realm, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname]) check_output(kpropd) -out = realm.run([kadminl, '-r', realm.realm, 'listprincs'], slave2) -if 'wakawaka' not in out: - fail('Slave does not have all principals from master') +realm.run([kadminl, '-r', realm.realm, 'listprincs'], slave2, + expected_msg='wakawaka') stop_daemon(kpropd) @@ -90,8 +87,6 @@ kpropd = realm.start_kpropd(slave3, ['-d']) realm.run([kdb5_util, 'dump', dumpfile]) realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname]) check_output(kpropd) -out = realm.run([kadminl, 'listprincs'], slave3) -if 'wakawaka' not in out: - fail('Slave does not have all principals from master') +realm.run([kadminl, 'listprincs'], slave3, expected_msg='wakawaka') success('kprop tests') diff --git a/src/tests/t_localauth.py b/src/tests/t_localauth.py index 4590485ac55d..aa625d038f38 100755 --- a/src/tests/t_localauth.py +++ b/src/tests/t_localauth.py @@ -14,9 +14,8 @@ def test_an2ln(env, aname, result, msg): fail(msg) def test_an2ln_err(env, aname, err, msg): - out = realm.run(['./localauth', aname], env=env, expected_code=1) - if err not in out: - fail(msg) + realm.run(['./localauth', aname], env=env, expected_code=1, + expected_msg=err) def test_userok(env, aname, lname, ok, msg): out = realm.run(['./localauth', aname, lname], env=env) diff --git a/src/tests/t_mkey.py b/src/tests/t_mkey.py index c53b71b45ca4..615cd91cac6e 100755 --- a/src/tests/t_mkey.py +++ b/src/tests/t_mkey.py @@ -92,9 +92,8 @@ def check_stash(*expected): # Verify that the user principal has the expected mkvno. def check_mkvno(princ, expected_mkvno): - out = realm.run([kadminl, 'getprinc', princ]) - if ('MKey: vno %d\n' % expected_mkvno) not in out: - fail('Unexpected mkvno in user DB entry') + msg = 'MKey: vno %d\n' % expected_mkvno + realm.run([kadminl, 'getprinc', princ], expected_msg=msg) # Change the password using either kadmin.local or kadmin, then check @@ -160,9 +159,8 @@ check_mkvno(realm.user_princ, 1) collisionfile = os.path.join(realm.testdir, 'stash_tmp') f = open(collisionfile, 'w') f.close() -output = realm.run([kdb5_util, 'stash'], expected_code=1) -if 'Temporary stash file already exists' not in output: - fail('Did not detect temp stash file collision') +realm.run([kdb5_util, 'stash'], expected_code=1, + expected_msg='Temporary stash file already exists') os.unlink(collisionfile) # Add a new master key with no options. Verify that: @@ -179,9 +177,8 @@ change_password_check_mkvno(True, realm.user_princ, 'abcd', 1) change_password_check_mkvno(False, realm.user_princ, 'user', 1) # Verify that use_mkey won't make all master keys inactive. -out = realm.run([kdb5_util, 'use_mkey', '1', 'now+1day'], expected_code=1) -if 'there must be one master key currently active' not in out: - fail('Unexpected error from use_mkey making all mkeys inactive') +realm.run([kdb5_util, 'use_mkey', '1', 'now+1day'], expected_code=1, + expected_msg='there must be one master key currently active') check_mkey_list((2, defetype, False, False), (1, defetype, True, True)) # Make the new master key active. Verify that: @@ -194,9 +191,8 @@ change_password_check_mkvno(True, realm.user_princ, 'abcd', 2) change_password_check_mkvno(False, realm.user_princ, 'user', 2) # Check purge_mkeys behavior with both master keys still in use. -out = realm.run([kdb5_util, 'purge_mkeys', '-f', '-v']) -if 'All keys in use, nothing purged.' not in out: - fail('Unexpected output from purge_mkeys with both mkeys in use') +realm.run([kdb5_util, 'purge_mkeys', '-f', '-v'], + expected_msg='All keys in use, nothing purged.') # Do an update_princ_encryption dry run and for real. Verify that: # 1. The target master key is 2 (the active mkvno). @@ -226,9 +222,8 @@ update_princ_encryption(False, 2, nprincs - 1, 0) check_mkvno(realm.user_princ, 2) # Test the safety check for purging with an outdated stash file. -out = realm.run([kdb5_util, 'purge_mkeys', '-f'], expected_code=1) -if 'stash file needs updating' not in out: - fail('Unexpected error from purge_mkeys safety check') +realm.run([kdb5_util, 'purge_mkeys', '-f'], expected_code=1, + expected_msg='stash file needs updating') # Update the master stash file and check it. Save a copy of the old # one for a later test. @@ -253,18 +248,15 @@ check_mkey_list((2, defetype, True, True)) check_master_dbent(2, (2, defetype)) os.rename(stash_file, stash_file + '.save') os.rename(stash_file + '.old', stash_file) -out = realm.run([kadminl, 'getprinc', 'user'], expected_code=1) -if 'Unable to decrypt latest master key' not in out: - fail('Unexpected error from kadmin.local with old stash file') +realm.run([kadminl, 'getprinc', 'user'], expected_code=1, + expected_msg='Unable to decrypt latest master key') os.rename(stash_file + '.save', stash_file) realm.run([kdb5_util, 'stash']) check_stash((2, defetype)) -out = realm.run([kdb5_util, 'use_mkey', '1'], expected_code=1) -if '1 is an invalid KVNO value' not in out: - fail('Unexpected error from use_mkey with invalid kvno') -out = realm.run([kdb5_util, 'purge_mkeys', '-f', '-v']) -if 'There is only one master key which can not be purged.' not in out: - fail('Unexpected output from purge_mkeys with one mkey') +realm.run([kdb5_util, 'use_mkey', '1'], expected_code=1, + expected_msg='1 is an invalid KVNO value') +realm.run([kdb5_util, 'purge_mkeys', '-f', '-v'], + expected_msg='There is only one master key which can not be purged.') # Add a third master key with a specified enctype. Verify that: # 1. The new master key receives the correct number. @@ -331,8 +323,7 @@ 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. realm.run([kadminl, 'purgekeys', '-all', 'K/M']) -out = realm.run([kadminl, 'getprinc', realm.user_princ], expected_code=1) -if 'Cannot find master key record in database' not in out: - fail('Unexpected output from failed master key fetch') +realm.run([kadminl, 'getprinc', realm.user_princ], expected_code=1, + expected_msg='Cannot find master key record in database') success('Master key rollover tests') diff --git a/src/tests/t_otp.py b/src/tests/t_otp.py index f098374f9e61..9b18ff94b9cc 100755 --- a/src/tests/t_otp.py +++ b/src/tests/t_otp.py @@ -199,9 +199,8 @@ realm.run([kadminl, 'setstr', realm.user_princ, 'otp', otpconfig('udp')]) realm.kinit(realm.user_princ, 'accept', flags=flags) verify(daemon, queue, True, realm.user_princ.split('@')[0], 'accept') realm.extract_keytab(realm.krbtgt_princ, realm.keytab) -out = realm.run(['./adata', realm.krbtgt_princ]) -if '+97: [indotp1, indotp2]' not in out: - fail('auth indicators not seen in OTP ticket') +realm.run(['./adata', realm.krbtgt_princ], + expected_msg='+97: [indotp1, indotp2]') # Repeat with an indicators override in the string attribute. daemon = UDPRadiusDaemon(args=(server_addr, secret_file, 'accept', queue)) @@ -212,9 +211,8 @@ realm.run([kadminl, 'setstr', realm.user_princ, 'otp', oconf]) realm.kinit(realm.user_princ, 'accept', flags=flags) verify(daemon, queue, True, realm.user_princ.split('@')[0], 'accept') realm.extract_keytab(realm.krbtgt_princ, realm.keytab) -out = realm.run(['./adata', realm.krbtgt_princ]) -if '+97: [indtok1, indtok2]' not in out: - fail('auth indicators not seen in OTP ticket') +realm.run(['./adata', realm.krbtgt_princ], + expected_msg='+97: [indtok1, indtok2]') # Detect upstream pyrad bug # https://github.com/wichert/pyrad/pull/18 diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py index 526473b429f8..b790a7cda071 100755 --- a/src/tests/t_pkinit.py +++ b/src/tests/t_pkinit.py @@ -23,6 +23,10 @@ privkey_pem = os.path.join(certs, 'privkey.pem') privkey_enc_pem = os.path.join(certs, 'privkey-enc.pem') user_p12 = os.path.join(certs, 'user.p12') user_enc_p12 = os.path.join(certs, 'user-enc.p12') +user_upn_p12 = os.path.join(certs, 'user-upn.p12') +user_upn2_p12 = os.path.join(certs, 'user-upn2.p12') +user_upn3_p12 = os.path.join(certs, 'user-upn3.p12') +generic_p12 = os.path.join(certs, 'generic.p12') path = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs') path_enc = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs-enc') @@ -36,6 +40,20 @@ pkinit_kdc_conf = {'realms': {'$realm': { restrictive_kdc_conf = {'realms': {'$realm': { 'restrict_anonymous_to_tgt': 'true' }}} +testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'user2': {'keys': 'aes128-cts', 'flags': '+preauth'}} +alias_kdc_conf = {'realms': {'$realm': { + 'default_principal_flags': '+preauth', + 'pkinit_eku_checking': 'none', + 'pkinit_allow_upn': 'true', + 'pkinit_identity': 'FILE:%s,%s' % (kdc_pem, privkey_pem), + 'database_module': 'test'}}, + 'dbmodules': {'test': { + 'db_library': 'test', + 'alias': {'user@krbtest.com': 'user'}, + 'princs': testprincs}}} + file_identity = 'FILE:%s,%s' % (user_pem, privkey_pem) file_enc_identity = 'FILE:%s,%s' % (user_pem, privkey_enc_pem) dir_identity = 'DIR:%s' % path @@ -45,11 +63,51 @@ dir_file_identity = 'FILE:%s,%s' % (os.path.join(path, 'user.crt'), dir_file_enc_identity = 'FILE:%s,%s' % (os.path.join(path_enc, 'user.crt'), os.path.join(path_enc, 'user.key')) p12_identity = 'PKCS12:%s' % user_p12 +p12_upn_identity = 'PKCS12:%s' % user_upn_p12 +p12_upn2_identity = 'PKCS12:%s' % user_upn2_p12 +p12_upn3_identity = 'PKCS12:%s' % user_upn3_p12 +p12_generic_identity = 'PKCS12:%s' % generic_p12 p12_enc_identity = 'PKCS12:%s' % user_enc_p12 p11_identity = 'PKCS11:soft-pkcs11.so' p11_token_identity = ('PKCS11:module_name=soft-pkcs11.so:' 'slotid=1:token=SoftToken (token)') +# Start a realm with the test kdb module for the following UPN SAN tests. +realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=alias_kdc_conf, + create_kdb=False) +realm.start_kdc() + +# Compatibility check: cert contains UPN "user", which matches the +# request principal user@KRBTEST.COM if parsed as a normal principal. +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_upn2_identity]) + +# Compatibility check: cert contains UPN "user@KRBTEST.COM", which matches +# the request principal user@KRBTEST.COM if parsed as a normal principal. +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_upn3_identity]) + +# Cert contains UPN "user@krbtest.com" which is aliased to the request +# principal. +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_upn_identity]) + +# Test an id-pkinit-san match to a post-canonical principal. +realm.kinit('user@krbtest.com', + flags=['-E', '-X', 'X509_user_identity=%s' % p12_identity]) + +# Test a UPN match to a post-canonical principal. (This only works +# for the cert with the UPN containing just "user", as we don't allow +# UPN reparsing when comparing to the canonicalized client principal.) +realm.kinit('user@krbtest.com', + flags=['-E', '-X', 'X509_user_identity=%s' % p12_upn2_identity]) + +# Test a mismatch. +msg = 'kinit: Client name mismatch while getting initial credentials' +realm.run([kinit, '-X', 'X509_user_identity=%s' % p12_upn2_identity, 'user2'], + expected_code=1, expected_msg=msg) +realm.stop() + realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf, get_creds=False) @@ -61,9 +119,8 @@ realm.klist(realm.user_princ) realm.run([kvno, realm.host_princ]) # Test anonymous PKINIT. -out = realm.kinit('@%s' % realm.realm, flags=['-n'], expected_code=1) -if 'not found in Kerberos database' not in out: - fail('Wrong error for anonymous PKINIT without anonymous enabled') +realm.kinit('@%s' % realm.realm, flags=['-n'], expected_code=1, + expected_msg='not found in Kerberos database') realm.addprinc('WELLKNOWN/ANONYMOUS') realm.kinit('@%s' % realm.realm, flags=['-n']) realm.klist('WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS') @@ -78,9 +135,8 @@ f.write('WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS a *') f.close() realm.start_kadmind() realm.run([kadmin, '-n', 'addprinc', '-pw', 'test', 'testadd']) -out = realm.run([kadmin, '-n', 'getprinc', 'testadd'], expected_code=1) -if "Operation requires ``get'' privilege" not in out: - fail('Anonymous kadmin has too much privilege') +realm.run([kadmin, '-n', 'getprinc', 'testadd'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") realm.stop_kadmind() # Test with anonymous restricted; FAST should work but kvno should fail. @@ -89,9 +145,8 @@ realm.stop_kdc() realm.start_kdc(env=r_env) realm.kinit('@%s' % realm.realm, flags=['-n']) realm.kinit('@%s' % realm.realm, flags=['-n', '-T', realm.ccache]) -out = realm.run([kvno, realm.host_princ], expected_code=1) -if 'KDC policy rejects request' not in out: - fail('Wrong error for restricted anonymous PKINIT') +realm.run([kvno, realm.host_princ], expected_code=1, + expected_msg='KDC policy rejects request') # Regression test for #8458: S4U2Self requests crash the KDC if # anonymous is restricted. @@ -117,6 +172,29 @@ realm.kinit(realm.user_princ, '-X', 'flag_RSA_PROTOCOL=yes']) realm.klist(realm.user_princ) +# Test a DH parameter renegotiation by temporarily setting a 4096-bit +# minimum on the KDC. (Preauth type 16 is PKINIT PA_PK_AS_REQ; +# 109 is PKINIT TD_DH_PARAMETERS; 133 is FAST PA-FX-COOKIE.) +minbits_kdc_conf = {'realms': {'$realm': {'pkinit_dh_min_bits': '4096'}}} +minbits_env = realm.special_env('restrict', True, kdc_conf=minbits_kdc_conf) +realm.stop_kdc() +realm.start_kdc(env=minbits_env) +expected_trace = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Preauth module pkinit (16) (real) returned: 0/Success', + 'Produced preauth for next request: 133, 16', + '/Key parameters not accepted', + 'Preauth tryagain input types (16): 109, 133', + 'trying again with KDC-provided parameters', + 'Preauth module pkinit (16) tryagain returned: 0/Success', + 'Followup preauth for next request: 16, 133') +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % file_identity], + expected_trace=expected_trace) +realm.stop_kdc() +realm.start_kdc() + # Run the basic test - PKINIT with FILE: identity, with a password on the key, # supplied by the prompter. # Expect failure if the responder does nothing, and we have no prompter. @@ -128,9 +206,8 @@ realm.kinit(realm.user_princ, password='encrypted') realm.klist(realm.user_princ) realm.run([kvno, realm.host_princ]) -out = realm.run(['./adata', realm.host_princ]) -if '+97: [indpkinit1, indpkinit2]' not in out: - fail('auth indicators not seen in PKINIT ticket') +realm.run(['./adata', realm.host_princ], + expected_msg='+97: [indpkinit1, indpkinit2]') # Run the basic test - PKINIT with FILE: identity, with a password on the key, # supplied by the responder. @@ -217,6 +294,51 @@ realm.run(['./responder', '-X', 'X509_user_identity=%s' % p12_enc_identity, realm.klist(realm.user_princ) realm.run([kvno, realm.host_princ]) +# Match a single rule. +rule = '<SAN>^user@KRBTEST.COM$' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity]) +realm.klist(realm.user_princ) + +# Match a combined rule (default prefix is &&). +rule = '<SUBJECT>CN=user$<KU>digitalSignature,keyEncipherment' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity]) +realm.klist(realm.user_princ) + +# Fail an && rule. +rule = '&&<SUBJECT>O=OTHER.COM<SAN>^user@KRBTEST.COM$' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +msg = 'kinit: Certificate mismatch while getting initial credentials' +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity], + expected_code=1, expected_msg=msg) + +# Pass an || rule. +rule = '||<SUBJECT>O=KRBTEST.COM<SAN>^otheruser@KRBTEST.COM$' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity]) +realm.klist(realm.user_princ) + +# Fail an || rule. +rule = '||<SUBJECT>O=OTHER.COM<SAN>^otheruser@KRBTEST.COM$' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +msg = 'kinit: Certificate mismatch while getting initial credentials' +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity], + expected_code=1, expected_msg=msg) + +# Authorize a client cert with no PKINIT extensions using subject and +# issuer. (Relies on EKU checking being turned off.) +rule = '&&<SUBJECT>CN=user$<ISSUER>O=MIT,' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_generic_identity]) +realm.klist(realm.user_princ) + if not have_soft_pkcs11: skip_rest('PKINIT PKCS11 tests', 'soft-pkcs11.so not found') @@ -251,6 +373,14 @@ realm.kinit(realm.user_princ, realm.klist(realm.user_princ) realm.run([kvno, realm.host_princ]) +# Supply the wrong PIN, and verify that we ignore the draft9 padata offer +# in the KDC method data after RFC 4556 PKINIT fails. +expected_trace = ('PKINIT client has no configured identity; giving up', + 'PKINIT client ignoring draft 9 offer from RFC 4556 KDC') +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p11_identity], + password='wrong', expected_code=1, expected_trace=expected_trace) + # PKINIT with PKCS11: identity, with a PIN supplied by the responder. # Supply the response in raw form. realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % p11_token_identity, diff --git a/src/tests/t_policy.py b/src/tests/t_policy.py index bfec96a93212..26c4e466e4f0 100755 --- a/src/tests/t_policy.py +++ b/src/tests/t_policy.py @@ -7,35 +7,27 @@ realm = K5Realm(create_host=False, start_kadmind=True) # Test password quality enforcement. realm.run([kadminl, 'addpol', '-minlength', '6', '-minclasses', '2', 'pwpol']) realm.run([kadminl, 'addprinc', '-randkey', '-policy', 'pwpol', 'pwuser']) -out = realm.run([kadminl, 'cpw', '-pw', 'sh0rt', 'pwuser'], expected_code=1) -if 'Password is too short' not in out: - fail('short password') -out = realm.run([kadminl, 'cpw', '-pw', 'longenough', 'pwuser'], - expected_code=1) -if 'Password does not contain enough character classes' not in out: - fail('insufficient character classes') +realm.run([kadminl, 'cpw', '-pw', 'sh0rt', 'pwuser'], expected_code=1, + expected_msg='Password is too short') +realm.run([kadminl, 'cpw', '-pw', 'longenough', 'pwuser'], expected_code=1, + expected_msg='Password does not contain enough character classes') realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser']) # Test some password history enforcement. Even with no history value, # the current password should be denied. -out = realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'], - expected_code=1) -if 'Cannot reuse password' not in out: - fail('reuse of current password') +realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'], expected_code=1, + expected_msg='Cannot reuse password') realm.run([kadminl, 'modpol', '-history', '2', 'pwpol']) realm.run([kadminl, 'cpw', '-pw', 'an0therpw', 'pwuser']) -out = realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'], - expected_code=1) -if 'Cannot reuse password' not in out: - fail('reuse of old password') +realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'], expected_code=1, + expected_msg='Cannot reuse password') realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser']) realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser']) # Test references to nonexistent policies. realm.run([kadminl, 'addprinc', '-randkey', '-policy', 'newpol', 'newuser']) -out = realm.run([kadminl, 'getprinc', 'newuser']) -if 'Policy: newpol [does not exist]\n' not in out: - fail('getprinc output for principal referencing nonexistent policy') +realm.run([kadminl, 'getprinc', 'newuser'], + expected_msg='Policy: newpol [does not exist]\n') realm.run([kadminl, 'modprinc', '-policy', 'newpol', 'pwuser']) # pwuser should allow reuse of the current password since newpol doesn't exist. realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser']) @@ -45,29 +37,20 @@ realm.run([kadmin, '-p', 'pwuser', '-w', '3rdpassword', 'cpw', '-pw', # Create newpol and verify that it is enforced. realm.run([kadminl, 'addpol', '-minlength', '3', 'newpol']) -out = realm.run([kadminl, 'getprinc', 'pwuser']) -if 'Policy: newpol\n' not in out: - fail('getprinc after creating policy (pwuser)') -out = realm.run([kadminl, 'cpw', '-pw', 'aa', 'pwuser'], expected_code=1) -if 'Password is too short' not in out: - fail('short password after creating policy (pwuser)') -out = realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser'], - expected_code=1) -if 'Cannot reuse password' not in out: - fail('reuse of current password after creating policy') +realm.run([kadminl, 'getprinc', 'pwuser'], expected_msg='Policy: newpol\n') +realm.run([kadminl, 'cpw', '-pw', 'aa', 'pwuser'], expected_code=1, + expected_msg='Password is too short') +realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser'], expected_code=1, + expected_msg='Cannot reuse password') -out = realm.run([kadminl, 'getprinc', 'newuser']) -if 'Policy: newpol\n' not in out: - fail('getprinc after creating policy (newuser)') -out = realm.run([kadminl, 'cpw', '-pw', 'aa', 'newuser'], expected_code=1) -if 'Password is too short' not in out: - fail('short password after creating policy (newuser)') +realm.run([kadminl, 'getprinc', 'newuser'], expected_msg='Policy: newpol\n') +realm.run([kadminl, 'cpw', '-pw', 'aa', 'newuser'], expected_code=1, + expected_msg='Password is too short') # Delete the policy and verify that it is no longer enforced. realm.run([kadminl, 'delpol', 'newpol']) -out = realm.run([kadminl, 'getpol', 'newpol'], expected_code=1) -if 'Policy does not exist' not in out: - fail('deletion of referenced policy') +realm.run([kadminl, 'getpol', 'newpol'], expected_code=1, + expected_msg='Policy does not exist') realm.run([kadminl, 'cpw', '-pw', 'aa', 'pwuser']) # Test basic password lockout support. @@ -78,18 +61,14 @@ realm.run([kadminl, 'modprinc', '+requires_preauth', '-policy', 'lockout', 'user']) # kinit twice with the wrong password. -output = realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1) -if 'Password incorrect while getting initial credentials' not in output: - fail('Expected error message not seen in kinit output') -output = realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1) -if 'Password incorrect while getting initial credentials' not in output: - fail('Expected error message not seen in kinit output') +realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1, + expected_msg='Password incorrect while getting initial credentials') +realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1, + expected_msg='Password incorrect while getting initial credentials') # Now the account should be locked out. -output = realm.run([kinit, realm.user_princ], expected_code=1) -if 'Client\'s credentials have been revoked while getting initial credentials' \ - not in output: - fail('Expected lockout error message not seen in kinit output') +m = 'Client\'s credentials have been revoked while getting initial credentials' +realm.run([kinit, realm.user_princ], expected_code=1, expected_msg=m) # Check that modprinc -unlock allows a further attempt. realm.run([kadminl, 'modprinc', '-unlock', 'user']) @@ -113,10 +92,8 @@ realm.run([kadminl, 'cpw', '-pw', 'pw2', 'user']) # Swap the keys, simulating older kadmin having chosen the second entry. realm.run(['./hist', 'swap']) # Make sure we can read the history entry. -out = realm.run([kadminl, 'cpw', '-pw', password('user'), 'user'], - expected_code=1) -if 'Cannot reuse password' not in out: - fail('Expected error not seen in output') +realm.run([kadminl, 'cpw', '-pw', password('user'), 'user'], expected_code=1, + expected_msg='Cannot reuse password') # Test key/salt constraints. @@ -142,9 +119,8 @@ realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts', 'server']) # Test modpol. realm.run([kadminl, 'modpol', '-allowedkeysalts', 'aes256-cts,rc4-hmac', 'ak']) -out = realm.run([kadminl, 'getpol', 'ak']) -if not 'Allowed key/salt types: aes256-cts,rc4-hmac' in out: - fail('getpol does not implement allowedkeysalts?') +realm.run([kadminl, 'getpol', 'ak'], + expected_msg='Allowed key/salt types: aes256-cts,rc4-hmac') # Test subsets and full set. realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac', 'server']) @@ -153,19 +129,14 @@ realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts,rc4-hmac', 'server']) realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes256-cts', 'server']) # Check that the order we got is the one from the policy. -out = realm.run([kadminl, 'getprinc', '-terse', 'server']) -if not '2\t1\t6\t18\t0\t1\t6\t23\t0' in out: - fail('allowed_keysalts policy did not preserve order') +realm.run([kadminl, 'getprinc', '-terse', 'server'], + expected_msg='2\t1\t6\t18\t0\t1\t6\t23\t0') # Test partially intersecting sets. -out = realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes128-cts', - 'server'], expected_code=1) -if not 'Invalid key/salt tuples' in out: - fail('allowed_keysalts policy not applied properly') -out = realm.run([kadminl, 'cpw', '-randkey', '-e', - 'rc4-hmac,aes256-cts,aes128-cts', 'server'], expected_code=1) -if not 'Invalid key/salt tuples' in out: - fail('allowed_keysalts policy not applied properly') +realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes128-cts', 'server'], + expected_code=1, expected_msg='Invalid key/salt tuples') +realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes256-cts,aes128-cts', + 'server'], expected_code=1, expected_msg='Invalid key/salt tuples') # Test reset of allowedkeysalts. realm.run([kadminl, 'modpol', '-allowedkeysalts', '-', 'ak']) diff --git a/src/tests/t_preauth.py b/src/tests/t_preauth.py index 0ef8bbca4c4f..fec0bf619ed8 100644 --- a/src/tests/t_preauth.py +++ b/src/tests/t_preauth.py @@ -10,18 +10,177 @@ realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf) realm.run([kadminl, 'modprinc', '+requires_preauth', realm.user_princ]) realm.run([kadminl, 'setstr', realm.user_princ, 'teststring', 'testval']) realm.run([kadminl, 'addprinc', '-nokey', '+requires_preauth', 'nokeyuser']) -out = realm.run([kinit, realm.user_princ], input=password('user')+'\n') -if 'testval' not in out: - fail('Decrypted string attribute not in kinit output') -out = realm.run([kinit, 'nokeyuser'], input=password('user')+'\n', - expected_code=1) -if 'no key' not in out: - fail('Expected "no key" message not in kinit output') - -# Exercise KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and secure cookies. +realm.kinit(realm.user_princ, password('user'), expected_msg='testval') +realm.kinit('nokeyuser', password('user'), expected_code=1, + expected_msg='no key') + +# Preauth type -123 is the test preauth module type; 133 is FAST +# PA-FX-COOKIE; 2 is encrypted timestamp. + +# Test normal preauth flow. +expected_trace = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: 133, -123', + 'Decrypted AS reply') +realm.run(['./icred', realm.user_princ, password('user')], + expected_msg='testval', expected_trace=expected_trace) + +# Test successful optimistic preauth. +expected_trace = ('Attempting optimistic preauth', + 'Processing preauth types: -123', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: -123', + 'Decrypted AS reply') +realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')], + expected_trace=expected_trace) + +# Test optimistic preauth failing on client, followed by successful +# preauth using the same module. +expected_trace = ('Attempting optimistic preauth', + 'Processing preauth types: -123', + '/induced optimistic fail', + 'Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: 133, -123', + 'Decrypted AS reply') +realm.run(['./icred', '-o', '-123', '-X', 'fail_optimistic', realm.user_princ, + password('user')], expected_msg='testval', + expected_trace=expected_trace) + +# Test optimistic preauth failing on KDC, followed by successful preauth +# using the same module. +realm.run([kadminl, 'setstr', realm.user_princ, 'failopt', 'yes']) +expected_trace = ('Attempting optimistic preauth', + 'Processing preauth types: -123', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: -123', + '/Preauthentication failed', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: 133, -123', + 'Decrypted AS reply') +realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')], + expected_msg='testval', expected_trace=expected_trace) +realm.run([kadminl, 'delstr', realm.user_princ, 'failopt']) + +# Test KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and secure cookies. realm.run([kadminl, 'setstr', realm.user_princ, '2rt', 'secondtrip']) -out = realm.run([kinit, realm.user_princ], input=password('user')+'\n') -if '2rt: secondtrip' not in out: - fail('multi round-trip cookie test') +expected_trace = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: 133, -123', + '/More preauthentication data is required', + 'Continuing preauth mech -123', + 'Processing preauth types: -123, 133', + 'Produced preauth for next request: 133, -123', + 'Decrypted AS reply') +realm.run(['./icred', realm.user_princ, password('user')], + expected_msg='2rt: secondtrip', expected_trace=expected_trace) + +# Test client-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, +# falling back to encrypted timestamp. +expected_trace = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: 133, -123', + '/More preauthentication data is required', + 'Continuing preauth mech -123', + 'Processing preauth types: -123, 133', + '/induced 2rt fail', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Encrypted timestamp (for ', + 'module encrypted_timestamp (2) (real) returned: 0/Success', + 'Produced preauth for next request: 133, 2', + 'Decrypted AS reply') +realm.run(['./icred', '-X', 'fail_2rt', realm.user_princ, password('user')], + expected_msg='2rt: secondtrip', expected_trace=expected_trace) + +# Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, +# falling back to encrypted timestamp. +realm.run([kadminl, 'setstr', realm.user_princ, 'fail2rt', 'yes']) +expected_trace = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: 133, -123', + '/More preauthentication data is required', + 'Continuing preauth mech -123', + 'Processing preauth types: -123, 133', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: 133, -123', + '/Preauthentication failed', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Encrypted timestamp (for ', + 'module encrypted_timestamp (2) (real) returned: 0/Success', + 'Produced preauth for next request: 133, 2', + 'Decrypted AS reply') +realm.run(['./icred', realm.user_princ, password('user')], + expected_msg='2rt: secondtrip', expected_trace=expected_trace) +realm.run([kadminl, 'delstr', realm.user_princ, 'fail2rt']) + +# Test tryagain flow by inducing a KDC_ERR_ENCTYPE_NOSUPP error on the KDC. +realm.run([kadminl, 'setstr', realm.user_princ, 'err', 'testagain']) +expected_trace = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: 133, -123', + '/KDC has no support for encryption type', + 'Recovering from KDC error 14 using preauth mech -123', + 'Preauth tryagain input types (-123): -123, 133', + 'Preauth module test (-123) tryagain returned: 0/Success', + 'Followup preauth for next request: -123, 133', + 'Decrypted AS reply') +realm.run(['./icred', realm.user_princ, password('user')], + expected_msg='tryagain: testagain', expected_trace=expected_trace) + +# Test a client-side tryagain failure, falling back to encrypted +# timestamp. +expected_trace = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: 133, -123', + '/KDC has no support for encryption type', + 'Recovering from KDC error 14 using preauth mech -123', + 'Preauth tryagain input types (-123): -123, 133', + '/induced tryagain fail', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Encrypted timestamp (for ', + 'module encrypted_timestamp (2) (real) returned: 0/Success', + 'Produced preauth for next request: 133, 2', + 'Decrypted AS reply') +realm.run(['./icred', '-X', 'fail_tryagain', realm.user_princ, + password('user')], expected_trace=expected_trace) + +# Test that multiple stepwise initial creds operations can be +# performed with the same krb5_context, with proper tracking of +# clpreauth module request handles. +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_pwqual.py b/src/tests/t_pwqual.py index 0d1d387d820d..011110bd1acf 100755 --- a/src/tests/t_pwqual.py +++ b/src/tests/t_pwqual.py @@ -18,29 +18,24 @@ f.close() realm.run([kadminl, 'addpol', 'pol']) # The built-in "empty" module rejects empty passwords even without a policy. -out = realm.run([kadminl, 'addprinc', '-pw', '', 'p1'], expected_code=1) -if 'Empty passwords are not allowed' not in out: - fail('Expected error not seen for empty password') +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']) -out = realm.run([kadminl, 'addprinc', '-pw', 'birds', '-policy', 'pol', 'p3'], - expected_code=1) -if 'Password is in the password dictionary' not in out: - fail('Expected error not seen from dictionary password') +realm.run([kadminl, 'addprinc', '-pw', 'birds', '-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']) -out = realm.run([kadminl, 'addprinc', '-pw', 'p5', '-policy', 'pol', 'p5'], - expected_code=1) -if 'Password may not match principal name' not in out: - fail('Expected error not seen from principal component') +realm.run([kadminl, 'addprinc', '-pw', 'p5', '-policy', 'pol', 'p5'], + expected_code=1, + expected_msg='Password may not match principal name') # The dynamic "combo" module rejects pairs of dictionary words. -out = realm.run([kadminl, 'addprinc', '-pw', 'birdsoranges', 'p6'], - expected_code=1) -if 'Password may not be a pair of dictionary words' not in out: - fail('Expected error not seen from combo module') +realm.run([kadminl, 'addprinc', '-pw', 'birdsoranges', '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 # password quality interface, but are convenient to put here. diff --git a/src/tests/t_referral.py b/src/tests/t_referral.py index 559fbd5f7c73..98fdf2925616 100755 --- a/src/tests/t_referral.py +++ b/src/tests/t_referral.py @@ -17,15 +17,18 @@ os.rename(realm.ccache, savefile) # Get credentials and check that we got a referral to REFREALM. def testref(realm, nametype): shutil.copyfile(savefile, realm.ccache) - realm.run(['./gcred', nametype, 'a/x.d']) - realm.klist(realm.user_princ, 'a/x.d@REFREALM') + realm.run(['./gcred', nametype, 'a/x.d@']) + out = realm.run([klist]).split('\n') + if len(out) != 8: + fail('unexpected number of lines in klist output') + if out[5].split()[4] != 'a/x.d@' or out[6].split()[4] != 'a/x.d@REFREALM': + fail('unexpected service principals in klist output') # Get credentials and check that we get an error, not a referral. def testfail(realm, nametype): shutil.copyfile(savefile, realm.ccache) - out = realm.run(['./gcred', nametype, 'a/x.d'], expected_code=1) - if 'not found in Kerberos database' not in out: - fail('unexpected error') + realm.run(['./gcred', nametype, 'a/x.d@'], expected_code=1, + expected_msg='not found in Kerberos database') # Create a modified KDC environment and restart the KDC. def restart_kdc(realm, kdc_conf): @@ -116,9 +119,8 @@ r1, r2 = cross_realms(2, xtgts=(), create_host=False) r2.addprinc('abc\@XYZ', 'pw') r1.start_kdc() -out = r1.kinit('user', expected_code=1) -if 'not found in Kerberos database' not in out: - fail('Expected error not seen for referral without canonicalize flag') +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']) diff --git a/src/tests/t_renew.py b/src/tests/t_renew.py index a5f0d4bc1479..034190c80e78 100755 --- a/src/tests/t_renew.py +++ b/src/tests/t_renew.py @@ -1,26 +1,55 @@ #!/usr/bin/python from k5test import * +from datetime import datetime +import re conf = {'realms': {'$realm': {'max_life': '20h', 'max_renewable_life': '20h'}}} realm = K5Realm(create_host=False, get_creds=False, kdc_conf=conf) -def test(testname, life, rlife, expect_renewable, env=None): +def test(testname, life, rlife, exp_life, exp_rlife, env=None): global realm flags = ['-l', life] if rlife is not None: flags += ['-r', rlife] realm.kinit(realm.user_princ, password('user'), flags=flags, env=env) - out = realm.run([klist]) + out = realm.run([klist, '-f']) + if ('Default principal: %s\n' % realm.user_princ) not in out: fail('%s: did not get tickets' % testname) - renewable = 'renew until' in out - if renewable and not expect_renewable: - fail('%s: tickets unexpectedly renewable' % testname) - elif not renewable and expect_renewable: - fail('%s: tickets unexpectedly non-renewable' % testname) + + # Extract flags and check the renewable flag against expectations. + flags = re.findall(r'Flags: ([a-zA-Z]*)', out)[0] + if exp_rlife is None and 'R' in flags: + fail('%s: ticket unexpectedly renewable' % testname) + if exp_rlife is not None and 'R' not in flags: + fail('%s: ticket unexpectedly non-renewable' % testname) + + # Extract the start time, end time, and renewable end time if present. + times = re.findall(r'\d\d/\d\d/\d\d \d\d:\d\d:\d\d', out) + times = [datetime.strptime(t, '%m/%d/%y %H:%M:%S') for t in times] + starttime = times[0] + endtime = times[1] + rtime = times[2] if len(times) >= 3 else None + + # Check the ticket lifetime against expectations. If the lifetime + # was determined by the request, there may be a small error + # because KDC requests contain an end time rather than a lifetime. + life = (endtime - starttime).seconds + if abs(life - exp_life) > 5: + fail('%s: expected life %d, got %d' % (testname, exp_life, life)) + + # Check the ticket renewable lifetime against expectations. + if exp_rlife is None and rtime is not None: + fail('%s: ticket has unexpected renew_till' % testname) + if exp_rlife is not None and rtime is None: + fail('%s: ticket is renewable but has no renew_till' % testname) + if rtime is not None: + rlife = (rtime - starttime).seconds + if abs(rlife - exp_rlife) > 5: + fail('%s: expected rlife %d, got %d' (testname, exp_rlife, rlife)) # Get renewable tickets. -test('simple', '1h', '2h', True) +test('simple', '1h', '2h', 3600, 7200) # Renew twice, to test that renewed tickets are renewable. realm.kinit(realm.user_princ, flags=['-R']) @@ -31,49 +60,50 @@ realm.klist(realm.user_princ) realm.run([kvno, realm.user_princ]) # Make sure we can't renew non-renewable tickets. -test('non-renewable', '1h', '1h', False) -out = realm.kinit(realm.user_princ, flags=['-R'], expected_code=1) -if "KDC can't fulfill requested option" not in out: - fail('expected error not seen renewing non-renewable ticket') +test('non-renewable', '1h', None, 3600, None) +realm.kinit(realm.user_princ, flags=['-R'], expected_code=1, + expected_msg="KDC can't fulfill requested option") # Test that -allow_renewable on the client principal works. realm.run([kadminl, 'modprinc', '-allow_renewable', 'user']) -test('disallowed client', '1h', '2h', False) +test('disallowed client', '1h', '2h', 3600, None) realm.run([kadminl, 'modprinc', '+allow_renewable', 'user']) # Test that -allow_renewable on the server principal works. realm.run([kadminl, 'modprinc', '-allow_renewable', realm.krbtgt_princ]) -test('disallowed server', '1h', '2h', False) +test('disallowed server', '1h', '2h', 3600, None) realm.run([kadminl, 'modprinc', '+allow_renewable', realm.krbtgt_princ]) -# Test that non-renewable tickets are issued if renew_till < till. -test('short', '2h', '1h', False) +# Test that trivially renewable tickets are issued if renew_till <= +# till. (Our client code bumps up the requested renewable life to the +# requested life.) +test('short', '2h', '1h', 7200, 7200) # Test that renewable tickets are issued if till > max life by # default, but not if we configure away the RENEWABLE-OK option. no_opts_conf = {'libdefaults': {'kdc_default_options': '0'}} no_opts = realm.special_env('no_opts', False, krb5_conf=no_opts_conf) realm.run([kadminl, 'modprinc', '-maxlife', '10 hours', 'user']) -test('long', '15h', None, True) -test('long noopts', '15h', None, False, env=no_opts) +test('long', '15h', None, 10 * 3600, 15 * 3600) +test('long noopts', '15h', None, 10 * 3600, None, env=no_opts) realm.run([kadminl, 'modprinc', '-maxlife', '20 hours', 'user']) # Test maximum renewable life on the client principal. realm.run([kadminl, 'modprinc', '-maxrenewlife', '5 hours', 'user']) -test('maxrenewlife client yes', '4h', '5h', True) -test('maxrenewlife client no', '6h', '10h', False) +test('maxrenewlife client 1', '4h', '5h', 4 * 3600, 5 * 3600) +test('maxrenewlife client 2', '6h', '10h', 6 * 3600, 5 * 3600) # Test maximum renewable life on the server principal. realm.run([kadminl, 'modprinc', '-maxrenewlife', '3 hours', realm.krbtgt_princ]) -test('maxrenewlife server yes', '2h', '3h', True) -test('maxrenewlife server no', '4h', '8h', False) +test('maxrenewlife server 1', '2h', '3h', 2 * 3600, 3 * 3600) +test('maxrenewlife server 2', '4h', '8h', 4 * 3600, 3 * 3600) # Test realm maximum life. realm.run([kadminl, 'modprinc', '-maxrenewlife', '40 hours', 'user']) realm.run([kadminl, 'modprinc', '-maxrenewlife', '40 hours', realm.krbtgt_princ]) -test('maxrenewlife realm yes', '10h', '20h', True) -test('maxrenewlife realm no', '21h', '40h', False) +test('maxrenewlife realm 1', '10h', '20h', 10 * 3600, 20 * 3600) +test('maxrenewlife realm 2', '21h', '40h', 20 * 3600, 20 * 3600) success('Renewing credentials') diff --git a/src/tests/t_salt.py b/src/tests/t_salt.py index e923c92d13eb..ddb1905ed567 100755 --- a/src/tests/t_salt.py +++ b/src/tests/t_salt.py @@ -62,13 +62,11 @@ for ks in dup_kstypes: # fails. def test_reject_afs3(realm, etype): query = 'ank -e ' + etype + ':afs3 -pw password princ1' - out = realm.run([kadminl, 'ank', '-e', etype + ':afs3', '-pw', 'password', - 'princ1'], expected_code=1) - if 'Invalid key generation parameters from KDC' not in out: - fail('Allowed afs3 salt for ' + etype) - out = realm.run([kadminl, 'getprinc', 'princ1'], expected_code=1) - if 'Principal does not exist' not in out: - fail('Created principal with afs3 salt and enctype ' + etype) + realm.run([kadminl, 'ank', '-e', etype + ':afs3', '-pw', 'password', + 'princ1'], expected_code=1, + expected_msg='Invalid key generation parameters from KDC') + realm.run([kadminl, 'getprinc', 'princ1'], expected_code=1, + expected_msg='Principal does not exist') # Verify that the afs3 salt is rejected for arcfour and pbkdf2 enctypes. # We do not currently do any verification on the key-generation parameters diff --git a/src/tests/t_skew.py b/src/tests/t_skew.py index b729710702ea..f2ae066951ab 100755 --- a/src/tests/t_skew.py +++ b/src/tests/t_skew.py @@ -37,22 +37,16 @@ realm.kinit(realm.user_princ, password('user'), # kinit should detect too much skew in the KDC response. kinit with # FAST should fail from the KDC since the armor AP-REQ won't be valid. -out = realm.kinit(realm.user_princ, password('user'), expected_code=1) -if 'Clock skew too great in KDC reply' not in out: - fail('Expected error message not seen in kinit skew case') -out = realm.kinit(realm.user_princ, None, flags=['-T', fast_cache], - expected_code=1) -if 'Clock skew too great while' not in out: - fail('Expected error message not seen in kinit FAST skew case') +realm.kinit(realm.user_princ, password('user'), expected_code=1, + expected_msg='Clock skew too great in KDC reply') +realm.kinit(realm.user_princ, None, flags=['-T', fast_cache], expected_code=1, + expected_msg='Clock skew too great while') # kinit (with preauth) should fail from the KDC, with or without FAST. realm.run([kadminl, 'modprinc', '+requires_preauth', 'user']) -out = realm.kinit(realm.user_princ, password('user'), expected_code=1) -if 'Clock skew too great while' not in out: - fail('Expected error message not seen in kinit skew case (preauth)') -out = realm.kinit(realm.user_princ, None, flags=['-T', fast_cache], - expected_code=1) -if 'Clock skew too great while' not in out: - fail('Expected error message not seen in kinit FAST skew case (preauth)') +realm.kinit(realm.user_princ, password('user'), expected_code=1, + expected_msg='Clock skew too great while') +realm.kinit(realm.user_princ, None, flags=['-T', fast_cache], expected_code=1, + expected_msg='Clock skew too great while') success('Clock skew tests') diff --git a/src/tests/t_stringattr.py b/src/tests/t_stringattr.py index 281c8726f629..5672a0f2006b 100755 --- a/src/tests/t_stringattr.py +++ b/src/tests/t_stringattr.py @@ -28,9 +28,7 @@ realm = K5Realm(start_kadmind=True, create_host=False, get_creds=False) realm.prep_kadmin() -out = realm.run_kadmin(['getstrs', 'user']) -if '(No string attributes.)' not in out: - fail('Empty attribute query') +realm.run_kadmin(['getstrs', 'user'], expected_msg='(No string attributes.)') realm.run_kadmin(['setstr', 'user', 'attr1', 'value1']) realm.run_kadmin(['setstr', 'user', 'attr2', 'value2']) diff --git a/src/tests/t_y2038.py b/src/tests/t_y2038.py new file mode 100644 index 000000000000..02e946df46bf --- /dev/null +++ b/src/tests/t_y2038.py @@ -0,0 +1,75 @@ +#!/usr/bin/python +from k5test import * + +# These tests will become much less important after the y2038 boundary +# has elapsed, and may start exhibiting problems around the year 2075. + +if runenv.sizeof_time_t <= 4: + skip_rest('y2038 timestamp tests', 'platform has 32-bit time_t') + +# Start a KDC running roughly 21 years in the future, after the y2038 +# boundary. Set long maximum lifetimes for later tests. +conf = {'realms': {'$realm': {'max_life': '9000d', + 'max_renewable_life': '9000d'}}} +realm = K5Realm(start_kdc=False, kdc_conf=conf) +realm.start_kdc(['-T', '662256000']) + +# kinit without preauth should succeed with clock skew correction, but +# will result in an expired ticket, because we sent an absolute end +# time and didn't get a chance to correct it.. +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, realm.host_princ], expected_code=1, + expected_msg='Ticket expired') + +# kinit with preauth should succeed and result in a valid ticket, as +# we get a chance to correct the end time based on the KDC time. Try +# with encrypted timestamp and encrypted challenge. +realm.run([kadminl, 'modprinc', '+requires_preauth', 'user']) +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, realm.host_princ]) +realm.kinit(realm.user_princ, password('user'), flags=['-T', realm.ccache]) +realm.run([kvno, realm.host_princ]) + +# Test that expiration warning works after y2038, by setting a +# password expiration time ten minutes after the KDC time. +realm.run([kadminl, 'modprinc', '-pwexpire', '662256600 seconds', 'user']) +out = realm.kinit(realm.user_princ, password('user')) +if 'will expire in less than one hour' not in out: + fail('password expiration message') +year = int(out.split()[-1]) +if year < 2038 or year > 9999: + fail('password expiration year') + +realm.stop_kdc() +realm.start_kdc() +realm.start_kadmind() +realm.prep_kadmin() + +# Test getdate parsing of absolute timestamps after 2038 and +# marshalling over the kadmin protocol. The local time zone will +# affect the display time by a little bit, so just look for the year. +realm.run_kadmin(['modprinc', '-pwexpire', '2040-02-03', realm.host_princ]) +realm.run_kadmin(['getprinc', realm.host_princ], expected_msg=' 2040\n') + +# Get a ticket whose lifetime crosses the y2038 boundary and +# range-check the expiration year as reported by klist. +realm.kinit(realm.user_princ, password('user'), + flags=['-l', '8000d', '-r', '8500d']) +realm.run([kvno, realm.host_princ]) +out = realm.run([klist]) +if int(out.split('\n')[4].split()[2].split('/')[2]) < 39: + fail('unexpected tgt expiration year') +if int(out.split('\n')[5].split()[2].split('/')[2]) < 40: + fail('unexpected tgt rtill year') +if int(out.split('\n')[6].split()[2].split('/')[2]) < 39: + fail('unexpected service ticket expiration year') +if int(out.split('\n')[7].split()[2].split('/')[2]) < 40: + fail('unexpected service ticket rtill year') +realm.kinit(realm.user_princ, None, ['-R']) +out = realm.run([klist]) +if int(out.split('\n')[4].split()[2].split('/')[2]) < 39: + fail('unexpected renewed tgt expiration year') +if int(out.split('\n')[5].split()[2].split('/')[2]) < 40: + fail('unexpected renewed tgt rtill year') + +success('y2038 tests') |