diff options
Diffstat (limited to '')
-rw-r--r-- | third_party/heimdal/tests/kdc/check-bx509.in | 1127 |
1 files changed, 1127 insertions, 0 deletions
diff --git a/third_party/heimdal/tests/kdc/check-bx509.in b/third_party/heimdal/tests/kdc/check-bx509.in new file mode 100644 index 0000000..6d894ef --- /dev/null +++ b/third_party/heimdal/tests/kdc/check-bx509.in @@ -0,0 +1,1127 @@ +#!/bin/sh +# +# Copyright (c) 2019 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + +top_builddir="@top_builddir@" +env_setup="@env_setup@" +objdir="@objdir@" + +testfailed="echo test failed; cat messages.log; exit 1" + +. ${env_setup} + +# If there is no useful db support compiled in, disable test +${have_db} || exit 77 + +umask 077 + +R=TEST.H5L.SE +DCs="DC=test,DC=h5l,DC=se" + +port=@port@ +bx509port=@bx509port@ + +server=datan.test.h5l.se +otherserver=other.test.h5l.se + +kadmin="${kadmin} -l -r $R" +bx509d="${bx509d} --allow-GET --reverse-proxied -p $bx509port -H $server --cert=${objdir}/bx509.pem -t" +kdc="${kdc} --addresses=localhost -P $port" + +cachefile="${objdir}/cache.krb5" +cache="FILE:${cachefile}" +cachefile2="${objdir}/cache2.krb5" +cache2="FILE:${cachefile2}" +keyfile="${hx509_data}/key.der" +keyfile2="${hx509_data}/key2.der" +kt=${objdir}/kt +keytab=FILE:${kt} +ukt=${objdir}/ukt +ukeytab=FILE:${ukt} + +kinit="${kinit} -c $cache ${afs_no_afslog}" +klist2="${klist} --hidden -v -c $cache2" +klistjson="${klist} --json -c $cache" +klist="${klist} --hidden -v -c $cache" +kgetcred="${kgetcred} -c $cache" +kdestroy="${kdestroy} -c $cache ${afs_no_unlog}" +test_csr_authorizer="$test_csr_authorizer -A $objdir/authz_dir -S $objdir" +kx509="${kx509} -c $cache" + +KRB5_CONFIG="${objdir}/krb5-bx509.conf" +export KRB5_CONFIG + +HEIM_PIDFILE_DIR="${objdir}/" +export HEIM_PIDFILE_DIR + +HEIM_IPC_DIR=$objdir +export HEIM_IPC_DIR + +rsa=yes +pkinit=no +if ${hxtool} info | grep 'rsa: hx509 null RSA' > /dev/null ; then + rsa=no +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + rsa=no +fi + +if ${kinit} --help 2>&1 | grep "CA certificates" > /dev/null; then + pkinit=yes +fi + +# If we doesn't support pkinit and have RSA, give up +if test "$pkinit" != yes -o "$rsa" != yes ; then + exit 77 +fi + + +rm -f current-db* +rm -f out-* +rm -f mkey.file* +rm -f *.pem *.crt *.der +rm -rf authz_dir + +mkdir -p authz_dir + +> messages.log + +kdcpid= +bx509pid= +test_csr_authorizer_pid= +trap 'kill -9 ${kdcpid} ${bx509pid} ${test_csr_authorizer_pid}; echo signal killing kdc, bx509d, and test_csr_authorizer; exit 1;' EXIT + +# csr_grant ext-type value grantee_principal +csr_grant() { + mkdir -p "${objdir}/authz_dir/${3}" + touch "${objdir}/authz_dir/${3}/${1}=${2}" +} + +csr_revoke() { + rm -rf "${objdir}/authz_dir" + mkdir -p "${objdir}/authz_dir" +} + +# get_cert "" curl-opts +# get_cert "&qparams" curl-opts +get_cert() { + url="http://${server}:${bx509port}/bx509?csr=$csr${1}" + shift + curl -g --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "$@" "$url" +} + +get_with_token() { + if [ -n "$csr" ]; then + url="http://${server}:${bx509port}/${1}?csr=$csr${2}" + else + url="http://${server}:${bx509port}/${1}?${2}" + fi + shift 2 + + curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + -D response-headers \ + "$@" "$url" && + { echo "GET w/o CSRF token succeeded!"; exit 2; } + curl -g --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + -D response-headers \ + "$@" "$url" + grep ^X-CSRF-Token: response-headers >/dev/null || + { echo "GET w/o CSRF token did not output a CSRF token!"; exit 2; } + curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" \ + "$@" "$url" || + { echo "GET w/ CSRF failed"; exit 2; } +} + +get_via_POST() { + endpoint=$1 + shift + + curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + -X POST -D response-headers \ + "$@" "http://${server}:${bx509port}/${endpoint}" && + { echo "POST w/o CSRF token succeeded!"; exit 2; } + curl -g --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + -X POST -D response-headers \ + "$@" "http://${server}:${bx509port}/${endpoint}" + grep ^X-CSRF-Token: response-headers >/dev/null || + { echo "POST w/o CSRF token did not output a CSRF token!"; exit 2; } + curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" \ + -X POST \ + "$@" "http://${server}:${bx509port}/${endpoint}" || + { echo "POST w/ CSRF failed"; exit 2; } +} + +rm -f $kt $ukt +$ktutil -k $keytab add -r -V 1 -e aes128-cts-hmac-sha1-96 \ + -p HTTP/datan.test.h5l.se@${R} || + { echo "failed to setup kimpersonate credentials"; exit 2; } +$ktutil -k $keytab list || + { echo "failed to setup kimpersonate credentials"; exit 2; } +$kimpersonate --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \ + -c foo@${R} -s HTTP/datan.test.h5l.se@${R} || + { echo "failed to setup kimpersonate credentials"; exit 2; } +$klist || + { echo "failed to setup kimpersonate credentials"; exit 2; } + +echo "Setting up certificates" +# We need: +# +# - a CA certificate for issuing client certificates +# - a CA certificate for issuing server certificates +# - a CA certificate for issuing mixed certificates +# - a certificate for bx509 itself (well, not in reverse proxy mode, but we'll +# make one anyways) + +# Make the realm's user cert issuer CA certificate. +# +# NOTE WELL: We need all three KeyUsage values listed below! +# We also need this to be of type "pkinit-kdc", +# which means we'll get an appropriate EKU OID as +# well. +$hxtool ca --issue-ca --self-signed --type=pkinit-kdc \ + --ku=digitalSignature --ku=keyCertSign --ku=cRLSign \ + --pk-init-principal=krbtgt/${R}@${R} \ + --generate-key=rsa --key-bits=1024 \ + --subject="OU=Users,CN=KDC,${DCs}" \ + --certificate=PEM-FILE:"${objdir}/user-issuer.pem" || + { echo "failed to setup CA certificate"; exit 2; } + +# We'll use the user cert issuer as the PKINIT anchor, allowing bx509-issued +# certificates to be used for PKINIT. Though we won't be testing PKINIT here +# -- we test kx509->PKINIT in check-pkinit. +cp ${objdir}/user-issuer.pem ${objdir}/pkinit-anchor.pem + +# Put the cert alone in the trust anchors file +ex "${objdir}/pkinit-anchor.pem" <<"EOF" +/-----BEGIN CERTIFICATE----- +1,.-1 d +wq +EOF + +$hxtool ca --issue-ca --self-signed \ + --ku=digitalSignature --ku=keyCertSign --ku=cRLSign \ + --generate-key=rsa --key-bits=1024 \ + --subject="OU=Servers,CN=KDC,${DCs}" \ + --certificate=PEM-FILE:"${objdir}/server-issuer.pem" || + { echo "failed to setup CA certificate"; exit 2; } + +$hxtool ca --issue-ca --self-signed \ + --ku=digitalSignature --ku=keyCertSign --ku=cRLSign \ + --generate-key=rsa --key-bits=1024 \ + --subject="OU=Users,CN=KDC,${DCs}" \ + --certificate=PEM-FILE:"${objdir}/mixed-issuer.pem" || + { echo "failed to setup CA certificate"; exit 2; } + +$hxtool ca --issue-ca --type=https-negotiate-server \ + --ca-certificate=PEM-FILE:"${objdir}/server-issuer.pem" \ + --ku=digitalSignature --pk-init-principal=HTTP/${server}@${R}\ + --generate-key=rsa --key-bits=1024 --subject="" \ + --certificate=PEM-FILE:"${objdir}/bx509.pem" || + { echo "failed to setup CA certificate"; exit 2; } + +# XXX Before starting bx509d let us use kdc test programs to check that: +# +# - the negotiate token validator plugin works +# - the authz_dir CSR authorizer plugin works +# - the KDC CA tester program works + +echo "Check gss-token and Negotiate token validator plugin" +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server | tr A B) +$test_token_validator -a datan.test.h5l.se Negotiate "$token" && + { echo "Negotiate token validator accepted invalid token"; exit 2; } +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +$test_token_validator -a datan.test.h5l.se Negotiate "$token" || + { echo "Negotiate token validator failed to validate valid token"; exit 2; } + + +echo "Starting CSR authorizer IPC service" +$test_csr_authorizer --server --daemon || + { echo "Failed to start test_csr_authorizer service"; exit 2; } +test_csr_authorizer_pid=`getpid test_csr_authorizer` + +# Make a CSR for foo@$R +$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \ + --key=FILE:"${objdir}/k.der" --kerberos=foo@$R \ + ${objdir}/req || + { echo "Failed to make a CSR"; exit 2; } + +echo "Test CSR authorizer IPC service (deny foo@$R to san_pkinit=foo@$R)" +csr_revoke +$test_csr_authorizer PKCS10:${objdir}/req foo@$R && + { echo "CSR authorizer IPC service granted foo@$R"; exit 2; } + +echo "Test CSR authorizer IPC service (grant foo@$R to san_pkinit=foo@$R)" +csr_grant san_pkinit foo@$R foo@${R} +$test_csr_authorizer PKCS10:${objdir}/req foo@$R || + { echo "CSR authorizer IPC service rejected foo@$R"; exit 2; } + +# Make a CSR for bar@$R +$hxtool request-create --subject='' --key-bits=1024 \ + --key=FILE:"${objdir}/k.der" --kerberos=bar@$R \ + ${objdir}/req || + { echo "Failed to make a CSR"; exit 2; } + +echo "Test CSR authorizer IPC service (deny foo@$R to san_pkinit=bar@$R)" +$test_csr_authorizer PKCS10:${objdir}/req foo@$R && + { echo "CSR authorizer IPC service accepted foo@$R"; exit 2; } + +echo "Test CSR authorizer IPC service (grant foo@$R to san_pkinit=bar@$R)" +csr_grant san_pkinit foo@$R bar@${R} +$test_csr_authorizer PKCS10:${objdir}/req foo@$R && + { echo "CSR authorizer IPC service accepted foo@$R"; exit 2; } + +# Make a CSR for foo@$R and bar@$R +$hxtool request-create --subject='' --key-bits=1024 \ + --key=FILE:"${objdir}/k.der" \ + --kerberos=foo@$R --kerberos=bar@$R \ + ${objdir}/req || + { echo "Failed to make a CSR"; exit 2; } + +# Check that the authorizer does mark foo@$R as approved even though it denies +# the overall request because it rejects bar@$R +echo "Test CSR authorizer IPC service (partial authz)" +csr_revoke +csr_grant san_pkinit foo@$R foo@${R} +# Check that the authorizer grants foo@$R +$test_csr_authorizer PKCS10:${objdir}/req foo@$R san_pkinit=foo@$R || + { echo "CSR authorizer IPC service partial approval check fail"; exit 2; } +# Check that the authorizer rejects bar@$R +$test_csr_authorizer PKCS10:${objdir}/req foo@$R san_pkinit=bar@$R && + { echo "CSR authorizer IPC service partial approval check fail"; exit 2; } +$test_csr_authorizer PKCS10:${objdir}/req foo@$R san_pkinit=foo@$R san_pkinit=bar@$R && + { echo "CSR authorizer IPC service partial approval check fail"; exit 2; } + +echo "Making a plain CSR" +$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \ + --key=FILE:"${objdir}/k.der" "${objdir}/req" || + { echo "Failed to make a CSR"; exit 2; } + +rm -f trivial.pem server.pem email.pem + +echo "Testing plain user cert issuance KDC CA" +$test_kdc_ca -a bx509 -A foo@${R} PKCS10:${objdir}/req \ + PEM-FILE:${objdir}/trivial.pem || + { echo "Trivial offline CA test failed"; exit 2; } +$hxtool print --content PEM-FILE:${objdir}/trivial.pem || + { echo "Trivial offline CA test failed"; exit 2; } +$hxtool acert --end-entity \ + --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \ + -P "foo@${R}" "FILE:${objdir}/trivial.pem" || + { echo "Trivial offline CA test failed"; exit 2; } +$hxtool acert --expr="%{certificate.subject} == \"OU=Users,CN=KDC,$DCs\"" \ + --lacks-private-key "FILE:${objdir}/trivial.pem" || + { echo "Trivial offline CA test failed (issuer private keys included!!)"; exit 2; } + +echo "Testing other cert issuance KDC CA" +csr_revoke +# https server cert +$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \ + --key=FILE:"${objdir}/k.der" \ + --eku=id_pkix_kp_serverAuth \ + --dnsname=foo.test.h5l.se "${objdir}/req" || + { echo "Failed to make a CSR with a dNSName SAN request"; exit 2; } +$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \ + PEM-FILE:${objdir}/server.pem && + { echo "Trivial offline CA test failed: unauthorized issuance (dNSName)"; exit 2; } +csr_grant san_dnsname foo.test.h5l.se foo@${R} +csr_grant eku 1.3.6.1.5.5.7.3.1 foo@${R} +$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \ + PEM-FILE:${objdir}/server.pem || + { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; } +$hxtool print --content PEM-FILE:${objdir}/server.pem || + { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; } +$hxtool acert --expr="%{certificate.subject} == \"OU=Servers,CN=KDC,$DCs\"" \ + --lacks-private-key "FILE:${objdir}/server.pem" || + { echo "Trivial offline CA test failed (issuer private keys included!!)"; exit 2; } +# email cert +$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \ + --key=FILE:"${objdir}/k.der" \ + --eku=id_pkix_kp_clientAuth \ + --email=foo@test.h5l.se "${objdir}/req" || + { echo "Failed to make a CSR with an rfc822Name SAN request"; exit 2; } +$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \ + PEM-FILE:${objdir}/email.pem && + { echo "Offline CA test failed: unauthorized issuance (dNSName)"; exit 2; } +csr_grant san_email foo@test.h5l.se foo@${R} +csr_grant eku 1.3.6.1.5.5.7.3.2 foo@${R} +$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \ + PEM-FILE:${objdir}/email.pem || + { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; } +$hxtool print --content PEM-FILE:${objdir}/email.pem || + { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; } +$hxtool acert --expr="%{certificate.subject} == \"OU=Users,CN=KDC,$DCs\"" \ + --lacks-private-key "FILE:${objdir}/email.pem" || + { echo "Offline CA test failed (issuer private keys included!!)"; exit 2; } + +if ! which curl; then + echo "curl is not available -- not testing bx509d" + sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1 + trap '' EXIT + exit 77 +fi + +if ! test -x ${objdir}/../../kdc/bx509d; then + echo "Configured w/o libmicrohttpd -- not testing bx509d" + sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1 + trap '' EXIT + exit 77 +fi + +echo "Creating database" +rm -f $kt $ukt +${kadmin} <<EOF || exit 1 +init --realm-max-ticket-life=1day --realm-max-renewable-life=1month ${R} +add -r --use-defaults foo@${R} +add -r --use-defaults bar@${R} +add -r --use-defaults baz@${R} +add -r --use-defaults raz@${R} +modify --pkinit-acl="CN=foo,DC=test,DC=h5l,DC=se" foo@${R} +add -r --use-defaults HTTP/${server}@${R} +ext_keytab -r -k $keytab HTTP/${server}@${R} +add -r --use-defaults HTTP/${otherserver}@${R} +ext_keytab -r -k $ukeytab foo@${R} +EOF + +echo "Starting kdc"; +${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } +kdcpid=`getpid kdc` + +${kdestroy} +${kinit} -kt $ukeytab foo@${R} || exit 1 +$klist || { echo "failed to kinit"; exit 2; } + + +echo "Starting bx509d" +${bx509d} --daemon || { echo "bx509 failed to start"; exit 2; } +bx509pid=`getpid bx509d` + +ec=0 + +rm -f trivial.pem server.pem email.pem + +echo "Making a plain CSR (with BasicConstraints requesting CA cert)" +csr_revoke +$hxtool request-create --subject='CN=H5LCA' --generate-key=rsa --key-bits=1024 \ + --ca --key=FILE:"${objdir}/k.der" "${objdir}/req" || + { echo "Failed to make a CSR"; exit 2; } + +# XXX Add autoconf check for curl? +# Create a barebones bx509 HTTP/1.1 client test program? + +echo "Fail to get a certificate using a CSR requesting a CA cert" +# Encode the CSR in base64, then URL-encode it +csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin) +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if (set -vx; get_cert '' -sf -o "${objdir}/trivial.pem"); then + echo 'Issued a certificate for a CSR that requested a CA cert!' + exit 1 +else + echo 'CSRs requesting CA certs properly rejected' +fi + +echo "Making a plain CSR (with BasicConstraints requesting EE cert)" +csr_revoke +$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \ + --ee --key=FILE:"${objdir}/k.der" "${objdir}/req" || + { echo "Failed to make a CSR"; exit 2; } + +echo "Fetching a trivial user certificate" +# Encode the CSR in base64, then URL-encode it +csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin) +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if (set -vx; get_cert '' -sf -o "${objdir}/trivial.pem"); then + $hxtool print --content "FILE:${objdir}/trivial.pem" + if $hxtool acert --end-entity \ + --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \ + -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate with a CSR w/ BasicConstraints requesting EE cert!' + else + echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)' + exit 1 + fi + if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \ + --has-private-key "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate!' + fi +else + echo 'Failed to get a certificate with a CSR w/ BasicConstraints requesting EE cert!' + exit 1 +fi + +echo "Making a plain CSR" +csr_revoke +$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \ + --key=FILE:"${objdir}/k.der" "${objdir}/req" || + { echo "Failed to make a CSR"; exit 2; } + +echo "Fetching a trivial user certificate (no authentication, must fail)" +# Encode the CSR in base64, then URL-encode it +csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin) +if (set -vx; + curl -g --resolve ${server}:${bx509port}:127.0.0.1 \ + -sf -o "${objdir}/trivial.pem" \ + "http://${server}:${bx509port}/bx509?csr=$csr"); then + $hxtool print --content "FILE:${objdir}/trivial.pem" + echo 'Got a certificate without authenticating!' + exit 1 +fi + +echo "Fetching a trivial user certificate" +# Encode the CSR in base64, then URL-encode it +csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin) +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if (set -vx; get_cert '' -sf -o "${objdir}/trivial.pem"); then + $hxtool print --content "FILE:${objdir}/trivial.pem" + if $hxtool acert --end-entity \ + --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \ + -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate!' + else + echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)' + exit 1 + fi + if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \ + --has-private-key "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate!' + fi +else + echo 'Failed to get a certificate!' + exit 1 +fi + +echo "Fetching a trivial user certificate (with POST, no auth, must fail)" +# Encode the CSR in base64; curl will URL-encode it for us +csr=$($rkbase64 -- ${objdir}/req) +if (set -vx; + curl -fg --resolve ${server}:${bx509port}:127.0.0.1 \ + -X POST -D response-headers \ + -F csr="$csr" -o "${objdir}/trivial.pem" \ + "http://${server}:${bx509port}/bx509" ); then + $hxtool print --content "FILE:${objdir}/trivial.pem" + echo 'Got a certificate without authenticating!' + exit 1 +fi + +echo "Fetching a trivial user certificate (with POST)" +# Encode the CSR in base64; curl will URL-encode it for us +csr=$($rkbase64 -- ${objdir}/req) +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if (set -vx; + get_via_POST bx509 -F csr="$csr" -o "${objdir}/trivial.pem"); then + $hxtool print --content "FILE:${objdir}/trivial.pem" + if $hxtool acert --end-entity \ + --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \ + -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate!' + else + echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)' + exit 1 + fi + if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \ + --has-private-key "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate!' + fi +else + echo 'Failed to get a certificate!' + exit 1 +fi + +echo "Checking that authorization is enforced" +csr_revoke +get_cert '&rfc822Name=foo@bar.example' -vvv -o "${objdir}/bad1.pem" +if (set -vx; get_cert '&rfc822Name=foo@bar.example' -sf -o "${objdir}/trivial.pem"); then + $hxtool print --content "FILE:${objdir}/bad1.pem" + echo 'Obtained a client certificate for a non-granted name!' + exit 1 +else + echo 'Correctly failed to get a client certificate for a non-granted name' +fi + +if (set -vx; get_cert "&dNSName=$server" -sf -o "${objdir}/bad2.pem"); then + $hxtool print --content "FILE:${objdir}/bad2.pem" + echo 'Obtained a server certificate for a non-granted name!' + exit 1 +else + echo 'Correctly failed to get a server certificate for a non-granted name' +fi + +echo "Fetching a server certificate with one dNSName SAN" +csr_grant san_dnsname $server foo@${R} +if (set -vx; get_cert "&dNSName=$server" -sf -o "${objdir}/server.pem"); then + $hxtool print --content "FILE:${objdir}/server.pem" + if (set -vx; $hxtool acert --expr="%{certificate.subject} == \"\"" \ + --end-entity -P foo@${R} \ + "FILE:${objdir}/server.pem"); then + echo 'Got a broken server certificate (has PKINIT SAN)' + exit 1 + elif $hxtool acert --end-entity -D $server "FILE:${objdir}/server.pem"; then + echo 'Successfully obtained a server certificate!' + else + echo 'Got a broken server certificate' + exit 1 + fi +else + echo 'Failed to get a server certificate!' + exit 1 +fi + +echo "Fetching a server certificate with two dNSName SANs" +csr_grant san_dnsname "second-$server" foo@${R} +if (set -vx; + get_cert "&dNSName=${server}&dNSName=second-$server" -sf \ + -o "${objdir}/server2.pem"); then + $hxtool print --content "FILE:${objdir}/server2.pem" + if $hxtool acert --expr="%{certificate.subject} == \"\"" \ + --end-entity -P foo@${R} \ + "FILE:${objdir}/server2.pem"; then + echo 'Got a broken server certificate (has PKINIT SAN)' + exit 1 + elif $hxtool acert --end-entity -D "$server" \ + -D "second-$server" \ + "FILE:${objdir}/server2.pem"; then + echo 'Successfully obtained a server certificate with two dNSName SANs!' + else + echo 'Got a broken server certificate (wanted two dNSName SANs)' + exit 1 + fi +else + echo 'Failed to get a server certificate with two dNSName SANs!' + exit 1 +fi + +echo "Fetching an email certificate" +csr_grant san_email foo@bar.example foo@${R} +if (set -vx; get_cert "&rfc822Name=foo@bar.example" -sf -o "${objdir}/email.pem"); then + $hxtool print --content "FILE:${objdir}/email.pem" + if $hxtool acert --end-entity -P "foo@${R}" "FILE:${objdir}/email.pem"; then + echo 'Got a broken email certificate (has PKINIT SAN)' + exit 1 + elif $hxtool acert --expr="%{certificate.subject} == \"\"" \ + --end-entity -M foo@bar.example \ + "FILE:${objdir}/email.pem"; then + echo 'Successfully obtained a email certificate!' + else + echo 'Got a broken email certificate' + exit 1 + fi +else + echo 'Failed to get an email certificate!' + exit 1 +fi + +echo "Fetch TGT (not granted for other)" +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if (set -vx; + curl -o "${cachefile2}" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8"); then + echo "Got a TGT with /get-tgt end-point when not granted!" + exit 2 +fi + +echo "Fetch TGT" +csr_grant san_pkinit foo@${R} foo@${R} +csr_grant eku 1.3.6.1.5.2.3.4 foo@${R} +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if ! (set -vx; + curl -o "${cachefile2}" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgt?address=8.8.8.8"); then + echo "Failed to get a TGT with /get-tgt end-point" + exit 2 +fi + +${klist2} | grep Addresses:.IPv4:8.8.8.8 || + { echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; } + +echo "Fetch TGT (inception)" +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +if ! (set -vx; + curl -o "${cachefile}" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgt?address=8.8.8.8"); then + echo "Failed to get a TGT with /get-tgt end-point" + exit 2 +fi +${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } +${klist} | grep Addresses:.IPv4:8.8.8.8 || + { echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; } + +echo "Fetch TGT (for other)" +csr_grant san_pkinit bar@${R} foo@${R} +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +if ! (set -vx; + curl -o "${cachefile}" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8"); then + echo "Failed to get a TGT with /get-tgt end-point" + exit 2 +fi +${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } +${klist} | grep Addresses:.IPv4:8.8.8.8 || + { echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; } + +echo "Fetch TGT (for other, w/ lifetime req under max)" +${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R} +csr_grant san_pkinit bar@${R} foo@${R} +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +if ! (set -vx; + curl -o "${cachefile}" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8&lifetime=3d"); then + echo "Failed to get a TGT with /get-tgt end-point" + exit 2 +fi +${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } +if which jq >/dev/null; then + if ! ${klistjson} | jq -e ' + (reduce (.tickets[0]|(.Issued,.Expires)| + strptime("%b %e %H:%M:%S %Y")|mktime) as $t + (0; if .==0 then $t else $t - . end) / 86400) | floor | + . == 3'; then + echo "Incorrect lifetime" + exit 2 + fi +fi + +echo "Fetch TGT (for other, w/ lifetime req over max)" +${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R} +csr_grant san_pkinit bar@${R} foo@${R} +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +if ! (set -vx; + curl -o "${cachefile}" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8&lifetime=10d"); then + echo "Failed to get a TGT with /get-tgt end-point" + exit 2 +fi +${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } +if which jq >/dev/null; then + if ! ${klistjson} | jq -e ' + (.tickets[0].Issued | strptime("%b %e %H:%M:%S %Y")|mktime) as $iat + | (.tickets[0].Expires | strptime("%b %e %H:%M:%S %Y")|mktime) as $exp + | (($exp - $iat) / 86400) as $life_days + | ($life_days > 4 and $life_days <= 5)'; then + echo "Incorrect lifetime" + exit 2 + fi +fi + +echo "Fetch TGT (for other, w/ lifetime req under max)" +${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R} +csr_grant san_pkinit bar@${R} foo@${R} +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +if ! (set -vx; + curl -o "${cachefile}" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8&address=8.9.10.11&address=11.11.11.11&address=12.12.12.12&lifetime=5d"); then + echo "Failed to get a TGT with /get-tgt end-point" + exit 2 +fi +${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } +if which jq >/dev/null; then + if ! ${klistjson} | jq -e ' + (reduce (.tickets[0]|(.Issued,.Expires)| + strptime("%b %e %H:%M:%S %Y")|mktime) as $t + (0; if .==0 then $t else $t - . end) / 86400) | + . >= 4'; then + echo "Failed to get a TGT with /get-tgt end-point with addresses" + exit 2 + fi +fi + +echo "Fetch TGTs (batch, authz fail)" +${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R} +csr_revoke +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +rm -f "${cachefile}.json" +if (set -vx; + curl -o "${cachefile}.json" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgts?cname=bar@${R}&cname=baz@${R}"); then + # 200 Ok is not a problem. We have to check that the result is sane. + true +else + if grep ccache "${cachefile}.json"; then + echo "Got TGTs with /get-tgts end-point that should have been denied" + exit 2; + fi + if ! grep error_code "${cachefile}.json" > /dev/null; then + cat "${cachefile}.json" + echo "Request failed w/o error information" + exit 2; + fi +fi +cat "${cachefile}.json" +if grep ccache "${cachefile}.json"; then + echo "Got TGTs with /get-tgts end-point that should have been denied" + exit 2; +fi + +echo "Fetch TGTs (batch, partial authz with IPC authorizer)" +${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R} +csr_revoke +csr_grant san_pkinit bar@${R} foo@${R} +csr_grant san_pkinit baz@${R} foo@${R} +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +if ! (set -vx; + curl -vvvo "${cachefile}.json" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgts?cname=bar@${R}&cname=raz@${R}&cname=baz@${R}"); then + echo "Failed to get TGTs batch including non-existent principal" + exit 2 +fi +if which jq >/dev/null; then + set -vx + jq -e . "${cachefile}.json" > /dev/null || + { echo "/get-tgts produced non-JSON"; exit 2; } + jq -es '.[]|select(.name|startswith("raz@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null || + { echo "No error was reported for raz@${R}!"; exit 2; } + jq -es '.[]|select(.name|startswith("raz@"))|(.ccache//"")|(length==0)' "${cachefile}.json" > /dev/null || + { echo "Non-empty ccache included for raz@${R}!"; exit 2; } + + # Check bar@$R's tickets: + jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" | + $rkbase64 -d -- - > "${cachefile}" + ${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } + ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null || + { echo "/get-tgts produced wrong TGTs"; exit 2; } + + # Check baz@$R's tickets: + jq -r 'select(.name|startswith("baz@")).ccache' "${cachefile}.json" | + $rkbase64 -d -- - > "${cachefile}" + ${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } + ${klistjson} | jq -e --arg p baz@$R '.principal == $p' > /dev/null || + { echo "/get-tgts produced wrong TGTs"; exit 2; } +fi + +echo "Fetch TGTs (batch, partial authz)" +${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R} +csr_revoke +csr_grant san_pkinit bar@${R} foo@${R} +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +if ! (set -vx; + curl -vvvo "${cachefile}.json" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgts?cname=not@${R}&cname=bar@${R}&cname=baz@${R}"); then + echo "Failed to get TGTs batch including non-existent principal" + exit 2 +fi +if which jq >/dev/null; then + set -vx + jq -e . "${cachefile}.json" > /dev/null || + { echo "/get-tgts produced non-JSON"; exit 2; } + jq -es '.[]|select(.name|startswith("not@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null || + { echo "No error was reported for not@${R}!"; exit 2; } + jq -es '.[]|select(.name|startswith("not@"))|(.ccache//"")|(length==0)' "${cachefile}.json" > /dev/null || + { echo "Non-empty ccache included for not@${R}!"; exit 2; } + jq -es '.[]|select(.name|startswith("baz@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null || + { echo "No error was reported for baz@${R}!"; exit 2; } + jq -es '.[]|select(.name|startswith("baz@"))|(.ccache//"")|(length==0)' "${cachefile}.json" > /dev/null || + { echo "Non-empty ccache included for baz@${R}!"; exit 2; } + + # Check bar@$R's tickets: + jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" | + $rkbase64 -d -- - > "${cachefile}" + ${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } + ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null || + { echo "/get-tgts produced wrong TGTs"; exit 2; } +fi + +echo "Fetch TGTs (batch, authz pass)" +${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R} +csr_grant san_pkinit bar@${R} foo@${R} +csr_grant san_pkinit baz@${R} foo@${R} +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +if ! (set -vx; + curl -vvvo "${cachefile}.json" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgts?cname=bar@${R}&cname=baz@${R}"); then + echo "Failed to get TGTs batch" + exit 2 +fi +if which jq >/dev/null; then + jq -e . "${cachefile}.json" > /dev/null || + { echo "/get-tgts produced non-JSON"; exit 2; } + + # Check bar@$R's tickets: + jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" | + $rkbase64 -d -- - > "${cachefile}" + ${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } + ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null || + { echo "/get-tgts produced wrong TGTs"; exit 2; } + + # Check baz@$R's tickets: + jq -r 'select(.name|startswith("baz@")).ccache' "${cachefile}.json" | + $rkbase64 -d -- - > "${cachefile}" + ${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } + ${klistjson} | jq -e --arg p baz@$R '.principal == $p' > /dev/null || + { echo "/get-tgts produced wrong TGTs"; exit 2; } +fi + +echo "Fetch TGTs (batch, authz pass, one non-existent principal)" +${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R} +csr_grant san_pkinit bar@${R} foo@${R} +csr_grant san_pkinit baz@${R} foo@${R} +csr_grant san_pkinit not@${R} foo@${R} +${kdestroy} +token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server) +if ! (set -vx; + curl -vvvo "${cachefile}.json" -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/get-tgts?cname=not@${R}&cname=bar@${R}&cname=baz@${R}"); then + echo "Failed to get TGTs batch including non-existent principal" + exit 2 +fi +if which jq >/dev/null; then + set -vx + jq -e . "${cachefile}.json" > /dev/null || + { echo "/get-tgts produced non-JSON"; exit 2; } + jq -es '.[]|select(.name|startswith("not@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null || + { echo "No error was reported for not@${R}!"; exit 2; } + + # Check bar@$R's tickets: + jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" | + $rkbase64 -d -- - > "${cachefile}" + ${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } + ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null || + { echo "/get-tgts produced wrong TGTs"; exit 2; } + + # Check baz@$R's tickets: + jq -r 'select(.name|startswith("baz@")).ccache' "${cachefile}.json" | + $rkbase64 -d -- - > "${cachefile}" + ${kgetcred} -H HTTP/${server}@${R} || + { echo "Fetched TGT didn't work"; exit 2; } + ${klistjson} | jq -e --arg p baz@$R '.principal == $p' > /dev/null || + { echo "/get-tgts produced wrong TGTs"; exit 2; } +fi + +echo "killing bx509d (${bx509pid})" +sh ${leaks_kill} bx509d $bx509pid || ec=1 + +echo "Starting bx509d (csrf-protection-type=GET-with-token, POST-with-header)" +${bx509d} --csrf-protection-type=GET-with-token \ + --csrf-protection-type=POST-with-header --daemon || { + echo "bx509 failed to start" + exit 2 +} +bx509pid=`getpid bx509d` + +${kinit} -kt $ukeytab foo@${R} || exit 1 +$klist || { echo "failed to kinit"; exit 2; } + +echo "Fetching a trivial user certificate (GET with CSRF token)" +csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin) +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if (set -vx; get_with_token get-cert '' -o "${objdir}/trivial.pem"); then + $hxtool print --content "FILE:${objdir}/trivial.pem" + if $hxtool acert --end-entity \ + --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \ + -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate!' + else + echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)' + exit 1 + fi + if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \ + --has-private-key "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate!' + fi +else + echo 'Failed to get a certificate!' + exit 1 +fi + +echo "Fetching a trivial user certificate (POST with X-CSRF header, no token)" +# Encode the CSR in base64, then URL-encode it +csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin) +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if (set -vx; get_cert '' -H 'X-CSRF: junk' -X POST -sf -o "${objdir}/trivial.pem"); then + $hxtool print --content "FILE:${objdir}/trivial.pem" + if $hxtool acert --end-entity \ + --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \ + -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate!' + else + echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)' + exit 1 + fi + if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \ + --has-private-key "FILE:${objdir}/trivial.pem"; then + echo 'Successfully obtained a trivial client certificate!' + fi +else + echo 'Failed to get a certificate!' + exit 1 +fi + +echo "Fetch negotiate token (pre-test)" +# Do what /bnegotiate does, roughly, prior to testing /bnegotiate +$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \ + --key=PEM-FILE:"${objdir}/k.pem" "${objdir}/req" || + { echo "Failed to make a CSR"; exit 2; } +$test_kdc_ca -a bx509 -A foo@${R} PKCS10:${objdir}/req \ + PEM-FILE:${objdir}/pkinit-test.pem || + { echo "Trivial offline CA test failed (CA)"; exit 2; } +cat ${objdir}/k.pem >> ${objdir}/pkinit-test.pem +${kinit} -C PEM-FILE:${objdir}/pkinit-test.pem foo@${R} || + { echo "Trivial offline CA test failed (PKINIT)"; exit 2; } +${kgetcred} -H HTTP/${server}@${R} || + { echo "Trivial offline CA test failed (TGS)"; exit 2; } +KRB5CCNAME=$cache $gsstoken HTTP@$server | KRB5_KTNAME="$keytab" $gsstoken -r || + { echo "Trivial offline CA test failed (gss-token)"; exit 2; } + +# Check that we get up to three tixaddrs k/v in the log +grep 'REQ.*wrongaddr=true' ${objdir}/messages.log | + grep 'tixaddrs=IPv4:11.11.11.11' || + { echo "KDC not warning about requests from wrong address"; exit 2; } + +echo "Fetching a Negotiate token" +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +csr= +if (set -vx; + get_with_token get-negotiate-token "target=HTTP%40${server}" -o "${objdir}/negotiate-token"); then + # bx509 sends us a token w/o a newline for now; we add one because + # gss-token expects it. + test -s negotiate-token && echo >> negotiate-token + if test -s negotiate-token && KRB5_KTNAME="$keytab" $gsstoken -Nr < negotiate-token; then + echo 'Successfully obtained a Negotiate token!' + else + echo 'Failed to get a Negotiate token (got an unacceptable token)!' + exit 1 + fi +else + echo 'Failed to get a Negotiate token!' + exit 1 +fi + +referer=https://${otherserver}/blah +redirect=$(${rkvis} -h https://${otherserver}/blah?q=whatever) +if (set -vx; + curl -o negotiate-token -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/bnegotiate?target=HTTP%40${server}&redirect=${redirect}"); then + echo "Error: /bnegotiate with target and redirect succeeded" + exit 1 +fi + +if (set -vx; + curl -o negotiate-token -Lgsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + "http://${server}:${bx509port}/bnegotiate?redirect=${redirect}"); then + echo "Error: /bnegotiate with redirect but no Referer succeeded" + exit 1 +fi + +referer=http://${otherserver}/blah +redirect=$(${rkvis} -h http://${otherserver}/blah?q=whatever) +if (set -vx; + curl -gsf \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + -H "Referer: $referer" \ + "http://${server}:${bx509port}/bnegotiate?redirect=${redirect}"); then + echo "Error: redirect for non-https referer" + exit 1 +fi + +referer=https://${otherserver}/blah +redirect=$(${rkvis} -h https://${otherserver}/blah?q=whatever) +if (set -vx; + curl -gfs -D curlheaders \ + --resolve ${server}:${bx509port}:127.0.0.1 \ + -H "Authorization: Negotiate $token" \ + -H "Referer: $referer" \ + "http://${server}:${bx509port}/bnegotiate?redirect=${redirect}"); then + read junk code junk < curlheaders + if test "$code" = 307; then + echo "Got a proper redirect" + else + echo "Error: unexpected status code $code (wanted 307)" + fi +else + echo "Error: no redirect" + exit 1 +fi + +echo "killing kdc (${kdcpid}) and bx509d (${bx509pid}) and test_csr_authorizer (${test_csr_authorizer_pid})" +sh ${leaks_kill} kdc $kdcpid || ec=1 +sh ${leaks_kill} bx509d $bx509pid || ec=1 +sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1 + +trap "" EXIT + +exit $ec |