1cef2e0e766de168cfeac462201307b0be6f2849
[samba.git] / source4 / heimdal / tests / kdc / check-bx509.in
1 #!/bin/sh
2 #
3 # Copyright (c) 2019 Kungliga Tekniska Högskolan
4 # (Royal Institute of Technology, Stockholm, Sweden). 
5 # All rights reserved. 
6 #
7 # Redistribution and use in source and binary forms, with or without 
8 # modification, are permitted provided that the following conditions 
9 # are met: 
10 #
11 # 1. Redistributions of source code must retain the above copyright 
12 #    notice, this list of conditions and the following disclaimer. 
13 #
14 # 2. Redistributions in binary form must reproduce the above copyright 
15 #    notice, this list of conditions and the following disclaimer in the 
16 #    documentation and/or other materials provided with the distribution. 
17 #
18 # 3. Neither the name of the Institute nor the names of its contributors 
19 #    may be used to endorse or promote products derived from this software 
20 #    without specific prior written permission. 
21 #
22 # THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
23 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
24 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
25 # ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
26 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
27 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
28 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
29 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
31 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
32 # SUCH DAMAGE. 
33
34 top_builddir="@top_builddir@"
35 env_setup="@env_setup@"
36 objdir="@objdir@"
37
38 testfailed="echo test failed; cat messages.log; exit 1"
39
40 . ${env_setup}
41
42 # If there is no useful db support compiled in, disable test
43 ${have_db} || exit 77
44
45 R=TEST.H5L.SE
46 DCs="DC=test,DC=h5l,DC=se"
47
48 port=@port@
49 bx509port=@bx509port@
50
51 kadmin="${kadmin} -l -r $R"
52 bx509d="${bx509d} --reverse-proxied -p $bx509port"
53 kdc="${kdc} --addresses=localhost -P $port"
54
55 server=datan.test.h5l.se
56 otherserver=other.test.h5l.se
57 cachefile="${objdir}/cache.krb5"
58 cache="FILE:${cachefile}"
59 cachefile2="${objdir}/cache2.krb5"
60 cache2="FILE:${cachefile2}"
61 keyfile="${hx509_data}/key.der"
62 keyfile2="${hx509_data}/key2.der"
63 kt=${objdir}/kt
64 keytab=FILE:${kt}
65 ukt=${objdir}/ukt
66 ukeytab=FILE:${ukt}
67
68 kinit="${kinit} -c $cache ${afs_no_afslog}"
69 klist2="${klist} --hidden -v -c $cache2"
70 klistjson="${klist} --json -c $cache"
71 klist="${klist} --hidden -v -c $cache"
72 kgetcred="${kgetcred} -c $cache"
73 kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
74 kx509="${kx509} -c $cache"
75
76 KRB5_CONFIG="${objdir}/krb5-bx509.conf"
77 export KRB5_CONFIG
78
79 rsa=yes
80 pkinit=no
81 if ${hxtool} info | grep 'rsa: hx509 null RSA' > /dev/null ; then
82     rsa=no
83 fi
84 if ${hxtool} info | grep 'rand: not available' > /dev/null ; then
85     rsa=no
86 fi
87
88 if ${kinit} --help 2>&1 | grep "CA certificates" > /dev/null; then
89     pkinit=yes
90 fi
91
92 # If we doesn't support pkinit and have RSA, give up
93 if test "$pkinit" != yes -o "$rsa" != yes ; then
94     exit 77
95 fi
96
97
98 rm -f current-db*
99 rm -f out-*
100 rm -f mkey.file*
101 rm -f *.pem *.crt *.der
102 rm -rf simple_csr_authz
103
104 mkdir -p simple_csr_authz
105
106 > messages.log
107
108 # We'll avoid using a KDC for now.  For testing /bx509 we only need keys for
109 # Negotiate tokens, and we'll use ktutil and kimpersonate to make it possible
110 # to create and accept those without a KDC.  When we test /bnegotiate, however,
111 # we'll start a KDC.
112
113 # csr_grant ext-type value grantee_principal
114 csr_grant() {
115     mkdir -p "${objdir}/simple_csr_authz/${3}"
116     touch "${objdir}/simple_csr_authz/${3}/${1}-${2}"
117 }
118
119 csr_revoke() {
120     rm -rf "${objdir}/simple_csr_authz"
121     mkdir -p "${objdir}/simple_csr_authz"
122 }
123
124 # get_cert ""         curl-opts
125 # get_cert "&qparams" curl-opts
126 get_cert() {
127     url="http://${server}:${bx509port}/bx509?csr=$csr${1}"
128     shift
129     curl -g --resolve ${server}:${bx509port}:127.0.0.1                  \
130          -H "Authorization: Negotiate $token"                           \
131          "$@" "$url"
132 }
133
134 rm -f $kt $ukt
135 $ktutil -k $keytab add -r -V 1 -e aes128-cts-hmac-sha1-96               \
136     -p HTTP/datan.test.h5l.se@${R} ||
137     { echo "failed to setup kimpersonate credentials"; exit 2; }
138 $ktutil -k $keytab list ||
139     { echo "failed to setup kimpersonate credentials"; exit 2; }
140 $kimpersonate --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96  \
141    -c foo@${R} -s HTTP/datan.test.h5l.se@${R} ||
142     { echo "failed to setup kimpersonate credentials"; exit 2; }
143 $klist ||
144     { echo "failed to setup kimpersonate credentials"; exit 2; }
145
146 echo "Setting up certificates"
147 # We need:
148 #
149 #  - a CA certificate for issuing client certificates
150 #  - a CA certificate for issuing server certificates
151 #  - a CA certificate for issuing mixed  certificates
152 #  - a certificate for bx509 itself (well, not in reverse proxy mode, but we'll
153 #    make one anyways)
154
155 # Make the realm's user cert issuer CA certificate.
156 #
157 # NOTE WELL: We need all three KeyUsage values listed below!
158 #            We also need this to be of type "pkinit-kdc",
159 #            which means we'll get an appropriate EKU OID as
160 #            well.
161 $hxtool ca  --issue-ca --self-signed --type=pkinit-kdc          \
162             --ku=digitalSignature --ku=keyCertSign --ku=cRLSign \
163             --pk-init-principal=krbtgt/${R}@${R}                \
164             --generate-key=rsa --key-bits=1024                  \
165             --subject="OU=Users,CN=KDC,${DCs}"                  \
166             --certificate=PEM-FILE:"${objdir}/user-issuer.pem" ||
167     { echo "failed to setup CA certificate"; exit 2; }
168
169 # We'll use the user cert issuer as the PKINIT anchor, allowing bx509-issued
170 # certificates to be used for PKINIT.  Though we won't be testing PKINIT here
171 # -- we test kx509->PKINIT in check-pkinit.
172 cp ${objdir}/user-issuer.pem ${objdir}/pkinit-anchor.pem
173
174 # Put the cert alone in the trust anchors file
175 ex "${objdir}/pkinit-anchor.pem" <<"EOF"
176 /-----BEGIN CERTIFICATE-----
177 1,.-1 d
178 wq
179 EOF
180
181 $hxtool ca  --issue-ca --self-signed                                \
182             --ku=digitalSignature --ku=keyCertSign --ku=cRLSign     \
183             --generate-key=rsa --key-bits=1024                      \
184             --subject="OU=Servers,CN=KDC,${DCs}"                    \
185             --certificate=PEM-FILE:"${objdir}/server-issuer.pem" ||
186     { echo "failed to setup CA certificate"; exit 2; }
187
188 $hxtool ca  --issue-ca --self-signed                                \
189             --ku=digitalSignature --ku=keyCertSign --ku=cRLSign     \
190             --generate-key=rsa --key-bits=1024                      \
191             --subject="OU=Users,CN=KDC,${DCs}"                      \
192             --certificate=PEM-FILE:"${objdir}/mixed-issuer.pem" ||
193     { echo "failed to setup CA certificate"; exit 2; }
194
195 $hxtool ca  --issue-ca --type=https-negotiate-server                \
196             --ca-certificate=PEM-FILE:"${objdir}/server-issuer.pem" \
197             --ku=digitalSignature --pk-init-principal=HTTP/${server}@${R}\
198             --generate-key=rsa --key-bits=1024 --subject=""         \
199             --certificate=PEM-FILE:"${objdir}/bx509.pem" ||
200     { echo "failed to setup CA certificate"; exit 2; }
201
202 # XXX Before starting bx509d let us use kdc test programs to check that:
203 #
204 #  - the negotiate token validator plugin works
205 #  - the simple CSR authorizer plugin works
206 #  - the KDC CA tester program works
207
208 echo "Check gss-token and Negotiate token validator plugin"
209 token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server | tr A B)
210 $test_token_validator -a datan.test.h5l.se Negotiate "$token" &&
211     { echo "Negotiate token validator accepted invalid token"; exit 2; }
212 token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
213 $test_token_validator -a datan.test.h5l.se Negotiate "$token" ||
214     { echo "Negotiate token validator failed to validate valid token"; exit 2; }
215
216 echo "Making a plain CSR"
217 $hxtool request-create  --subject='' --generate-key=rsa --key-bits=1024 \
218                         --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
219     { echo "Failed to make a CSR"; exit 2; }
220
221 rm -f trivial.pem server.pem email.pem
222
223 echo "Testing plain user cert issuance KDC CA"
224 $test_kdc_ca -a bx509 -A foo@${R} PKCS10:${objdir}/req       \
225              PEM-FILE:${objdir}/trivial.pem ||
226     { echo "Trivial offline CA test failed"; exit 2; }
227 $hxtool print --content PEM-FILE:${objdir}/trivial.pem ||
228     { echo "Trivial offline CA test failed"; exit 2; }
229 $hxtool acert --end-entity                                              \
230               --expr="%{certificate.subject} == \"CN=foo,$DCs\""        \
231               -P "foo@${R}" "FILE:${objdir}/trivial.pem" ||
232     { echo "Trivial offline CA test failed"; exit 2; }
233 $hxtool acert --expr="%{certificate.subject} == \"OU=Users,CN=KDC,$DCs\""   \
234               --lacks-private-key "FILE:${objdir}/trivial.pem" ||
235     { echo "Trivial offline CA test failed (issuer private keys included!!)"; exit 2; }
236
237 echo "Testing other cert issuance KDC CA"
238 csr_revoke
239 # https server cert
240 $hxtool request-create  --subject='' --generate-key=rsa --key-bits=1024 \
241                         --key=FILE:"${objdir}/k.der"                    \
242                         --eku=id_pkix_kp_serverAuth                     \
243                         --dnsname=foo.test.h5l.se "${objdir}/req" ||
244     { echo "Failed to make a CSR with a dNSName SAN request"; exit 2; }
245 $test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req              \
246              PEM-FILE:${objdir}/server.pem &&
247     { echo "Trivial offline CA test failed: unauthorized issuance (dNSName)"; exit 2; }
248 csr_grant dnsname foo.test.h5l.se foo@${R}
249 csr_grant eku 1.3.6.1.5.5.7.3.1 foo@${R}
250 $test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req              \
251              PEM-FILE:${objdir}/server.pem ||
252     { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; }
253 $hxtool print --content PEM-FILE:${objdir}/server.pem ||
254     { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; }
255 $hxtool acert --expr="%{certificate.subject} == \"OU=Servers,CN=KDC,$DCs\""   \
256               --lacks-private-key "FILE:${objdir}/server.pem" ||
257     { echo "Trivial offline CA test failed (issuer private keys included!!)"; exit 2; }
258 # email cert
259 $hxtool request-create  --subject='' --generate-key=rsa --key-bits=1024 \
260                         --key=FILE:"${objdir}/k.der"                    \
261                         --eku=id_pkix_kp_clientAuth                     \
262                         --email=foo@test.h5l.se "${objdir}/req" ||
263     { echo "Failed to make a CSR with an rfc822Name SAN request"; exit 2; }
264 $test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req              \
265              PEM-FILE:${objdir}/email.pem &&
266     { echo "Offline CA test failed: unauthorized issuance (dNSName)"; exit 2; }
267 csr_grant email foo@test.h5l.se foo@${R}
268 csr_grant eku 1.3.6.1.5.5.7.3.2 foo@${R}
269 $test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req              \
270              PEM-FILE:${objdir}/email.pem ||
271     { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; }
272 $hxtool print --content PEM-FILE:${objdir}/email.pem ||
273     { echo "Offline CA test failed for explicitly authorized dNSName"; exit 2; }
274 $hxtool acert --expr="%{certificate.subject} == \"OU=Users,CN=KDC,$DCs\""   \
275               --lacks-private-key "FILE:${objdir}/email.pem" ||
276     { echo "Offline CA test failed (issuer private keys included!!)"; exit 2; }
277
278 if ! which curl; then
279     echo "curl is not available -- not testing bx509d"
280     exit 77
281 fi
282
283 if ! test -x ${objdir}/../../kdc/bx509d; then
284     echo "Configured w/o libmicrohttpd -- not testing bx509d"
285     exit 77
286 fi
287
288 echo "Creating database"
289 ${kadmin} init \
290     --realm-max-ticket-life=1day \
291     --realm-max-renewable-life=1month \
292     ${R} || exit 1
293 ${kadmin} add -r --use-defaults foo@${R} || exit 1
294 ${kadmin} add -r --use-defaults bar@${R} || exit 1
295 ${kadmin} modify --pkinit-acl="CN=foo,DC=test,DC=h5l,DC=se" foo@${R} || exit 1
296
297
298 echo "Starting bx509d"
299 ${bx509d} -H $server --cert=${objdir}/bx509.pem -t --daemon ||
300     { echo "bx509 failed to start"; exit 2; }
301 bx509pid=`getpid bx509d`
302
303 trap "kill -9 ${bx509pid}; echo signal killing bx509d; exit 1;" EXIT
304 ec=0
305
306 rm -f trivial.pem server.pem email.pem
307
308 echo "Making a plain CSR"
309 csr_revoke
310 $hxtool request-create  --subject='' --generate-key=rsa --key-bits=1024 \
311                         --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
312     { echo "Failed to make a CSR"; exit 2; }
313 csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)
314
315 # XXX Add autoconf check for curl?
316 #     Create a barebones bx509 HTTP/1.1 client test program?
317
318 echo "Fetching a trivial user certificate"
319 token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
320 if (set -vx; get_cert '' -sf -o "${objdir}/trivial.pem"); then
321     $hxtool print --content "FILE:${objdir}/trivial.pem"
322     if $hxtool acert --end-entity                                            \
323                     --expr="%{certificate.subject} == \"CN=foo,$DCs\""  \
324                     -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then
325         echo 'Successfully obtained a trivial client certificate!'
326     else
327         echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)'
328         exit 1
329     fi
330     if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\""   \
331                      --has-private-key "FILE:${objdir}/trivial.pem"; then
332         echo 'Successfully obtained a trivial client certificate!'
333     fi
334 else
335     echo 'Failed to get a certificate!'
336     exit 1
337 fi
338
339 echo "Checking that authorization is enforced"
340 csr_revoke
341 get_cert '&rfc822Name=foo@bar.example' -vvv -o "${objdir}/bad1.pem"
342 if (set -vx; get_cert '&rfc822Name=foo@bar.example' -sf -o "${objdir}/trivial.pem"); then
343     $hxtool print --content "FILE:${objdir}/bad1.pem"
344     echo 'Obtained a client certificate for a non-granted name!'
345     exit 1
346 else
347     echo 'Correctly failed to get a client certificate for a non-granted name'
348 fi
349
350 if (set -vx; get_cert "&dNSName=$server" -sf -o "${objdir}/bad2.pem"); then
351     $hxtool print --content "FILE:${objdir}/bad2.pem"
352     echo 'Obtained a server certificate for a non-granted name!'
353     exit 1
354 else
355     echo 'Correctly failed to get a server certificate for a non-granted name'
356 fi
357
358 echo "Fetching a server certificate with one dNSName SAN"
359 csr_grant dnsname $server foo@${R}
360 if (set -vx; get_cert "&dNSName=$server" -sf -o "${objdir}/server.pem"); then
361     $hxtool print --content "FILE:${objdir}/server.pem"
362     if (set -vx; $hxtool acert --expr="%{certificate.subject} == \"\""             \
363                     --end-entity -P foo@${R}               \
364                     "FILE:${objdir}/server.pem"); then
365         echo 'Got a broken server certificate (has PKINIT SAN)'
366         exit 1
367     elif $hxtool acert --end-entity -D $server "FILE:${objdir}/server.pem"; then
368         echo 'Successfully obtained a server certificate!'
369     else
370         echo 'Got a broken server certificate'
371         exit 1
372     fi
373 else
374     echo 'Failed to get a server certificate!'
375     exit 1
376 fi
377
378 echo "Fetching a server certificate with two dNSName SANs"
379 csr_grant dnsname "second-$server" foo@${R}
380 if (set -vx;
381     get_cert "&dNSName=${server}&dNSName=second-$server" -sf \
382         -o "${objdir}/server2.pem"); then
383     $hxtool print --content "FILE:${objdir}/server2.pem"
384     if $hxtool acert --expr="%{certificate.subject} == \"\""             \
385                     --end-entity -P foo@${R}               \
386                     "FILE:${objdir}/server2.pem"; then
387         echo 'Got a broken server certificate (has PKINIT SAN)'
388         exit 1
389     elif $hxtool acert --end-entity -D "$server"                      \
390                                    -D "second-$server"               \
391                                    "FILE:${objdir}/server2.pem"; then
392         echo 'Successfully obtained a server certificate with two dNSName SANs!'
393     else
394         echo 'Got a broken server certificate (wanted two dNSName SANs)'
395         exit 1
396     fi
397 else
398     echo 'Failed to get a server certificate with two dNSName SANs!'
399     exit 1
400 fi
401
402 echo "Fetching an email certificate"
403 csr_grant email foo@bar.example foo@${R}
404 if (set -vx; get_cert "&rfc822Name=foo@bar.example" -sf -o "${objdir}/email.pem"); then
405     $hxtool print --content "FILE:${objdir}/email.pem"
406     if $hxtool acert --end-entity -P "foo@${R}" "FILE:${objdir}/email.pem"; then
407         echo 'Got a broken email certificate (has PKINIT SAN)'
408         exit 1
409     elif $hxtool acert --expr="%{certificate.subject} == \"\""           \
410                       --end-entity -M foo@bar.example                   \
411                       "FILE:${objdir}/email.pem"; then
412         echo 'Successfully obtained a email certificate!'
413     else
414         echo 'Got a broken email certificate'
415         exit 1
416     fi
417 else
418     echo 'Failed to get an email certificate!'
419     exit 1
420 fi
421
422 # Need to start a KDC to test this.
423 rm -f $kt $ukt
424 ${kdestroy}
425 ${kadmin} add -r --use-defaults HTTP/${server}@${R} || exit 1
426 ${kadmin} ext_keytab -r -k $keytab  HTTP/${server}@${R} || exit 1
427 ${kadmin} add -r --use-defaults HTTP/${otherserver}@${R} || exit 1
428 ${kadmin} ext_keytab -r -k $ukeytab foo@${R} || exit 1
429
430 echo "Starting kdc";
431 ${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
432 kdcpid=`getpid kdc`
433 trap "kill -9 ${kdcpid} ${bx509pid}; echo signal killing kdc and bx509d; exit 1;" EXIT
434
435 ${kinit} -kt $ukeytab foo@${R} || exit 1
436 $klist || { echo "failed to setup kimpersonate credentials"; exit 2; }
437
438 echo "Fetch TGT (not granted for other)"
439 token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
440 if (set -vx;
441     curl -o "${cachefile2}" -Lgsf                                       \
442          --resolve ${server}:${bx509port}:127.0.0.1                     \
443          -H "Authorization: Negotiate $token"                           \
444          "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8"); then
445     echo "Got a TGT with /get-tgt end-point when not granted!"
446     exit 2
447 fi
448
449 echo "Fetch TGT"
450 (set -vx; csr_grant pkinit foo@${R} foo@${R})
451 (set -vx; csr_grant eku 1.3.6.1.5.2.3.4 foo@${R})
452 token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
453 if ! (set -vx;
454     curl -o "${cachefile2}" -Lgsf                                       \
455          --resolve ${server}:${bx509port}:127.0.0.1                     \
456          -H "Authorization: Negotiate $token"                           \
457          "http://${server}:${bx509port}/get-tgt?address=8.8.8.8"); then
458     echo "Failed to get a TGT with /get-tgt end-point"
459     exit 2
460 fi
461
462 ${klist2} | grep Addresses:.IPv4:8.8.8.8 ||
463     { echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; }
464
465 echo "Fetch TGT (inception)"
466 ${kdestroy}
467 token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
468 if ! (set -vx;
469     curl -o "${cachefile}" -Lgsf                                        \
470          --resolve ${server}:${bx509port}:127.0.0.1                     \
471          -H "Authorization: Negotiate $token"                           \
472          "http://${server}:${bx509port}/get-tgt?address=8.8.8.8"); then
473     echo "Failed to get a TGT with /get-tgt end-point"
474     exit 2
475 fi
476 ${kgetcred} -H HTTP/${server}@${R} ||
477     { echo "Trivial offline CA test failed (TGS)"; exit 2; }
478 ${klist} | grep Addresses:.IPv4:8.8.8.8 ||
479     { echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; }
480
481 echo "Fetch TGT (for other)"
482 (set -vx; csr_grant pkinit bar@${R} foo@${R})
483 ${kdestroy}
484 token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
485 if ! (set -vx;
486     curl -o "${cachefile}" -Lgsf                                        \
487          --resolve ${server}:${bx509port}:127.0.0.1                     \
488          -H "Authorization: Negotiate $token"                           \
489          "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8"); then
490     echo "Failed to get a TGT with /get-tgt end-point"
491     exit 2
492 fi
493 ${kgetcred} -H HTTP/${server}@${R} ||
494     { echo "Trivial offline CA test failed (TGS)"; exit 2; }
495 ${klist} | grep Addresses:.IPv4:8.8.8.8 ||
496     { echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; }
497
498 echo "Fetch TGT (for other, w/ lifetime req under max)"
499 ${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
500 (set -vx; csr_grant pkinit bar@${R} foo@${R})
501 ${kdestroy}
502 token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
503 if ! (set -vx;
504     curl -o "${cachefile}" -Lgsf                                        \
505          --resolve ${server}:${bx509port}:127.0.0.1                     \
506          -H "Authorization: Negotiate $token"                           \
507          "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8&lifetime=3d"); then
508     echo "Failed to get a TGT with /get-tgt end-point"
509     exit 2
510 fi
511 ${kgetcred} -H HTTP/${server}@${R} ||
512     { echo "Trivial offline CA test failed (TGS)"; exit 2; }
513 if which jq >/dev/null; then
514     if ! ${klistjson} | jq -e '
515             (reduce (.tickets[0]|(.Issued,.Expires)|
516                     strptime("%b %e %H:%M:%S %Y")|mktime) as $t
517                 (0; if .==0 then $t else $t - . end) / 86400) | floor |
518             . == 3'; then
519         echo "Incorrect lifetime"
520         exit 2
521     fi
522 fi
523
524 echo "Fetch TGT (for other, w/ lifetime req over max)"
525 ${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
526 (set -vx; csr_grant pkinit bar@${R} foo@${R})
527 ${kdestroy}
528 token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
529 if ! (set -vx;
530     curl -o "${cachefile}" -Lgsf                                        \
531          --resolve ${server}:${bx509port}:127.0.0.1                     \
532          -H "Authorization: Negotiate $token"                           \
533          "http://${server}:${bx509port}/get-tgt?cname=bar@${R}&address=8.8.8.8&lifetime=10d"); then
534     echo "Failed to get a TGT with /get-tgt end-point"
535     exit 2
536 fi
537 ${kgetcred} -H HTTP/${server}@${R} ||
538     { echo "Trivial offline CA test failed (TGS)"; exit 2; }
539 if which jq >/dev/null; then
540     if ! ${klistjson} | jq -e '
541             (reduce (.tickets[0]|(.Issued,.Expires)|
542                     strptime("%b %e %H:%M:%S %Y")|mktime) as $t
543                 (0; if .==0 then $t else $t - . end) / 86400) | floor |
544             . == 5'; then
545         echo "Incorrect lifetime"
546         exit 2
547     fi
548 fi
549
550 echo "Fetch TGT (for other, w/ lifetime req under max)"
551 ${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
552 (set -vx; csr_grant pkinit bar@${R} foo@${R})
553 ${kdestroy}
554 token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
555 if ! (set -vx;
556     curl -o "${cachefile}" -Lgsf                                        \
557          --resolve ${server}:${bx509port}:127.0.0.1                     \
558          -H "Authorization: Negotiate $token"                           \
559          "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
560     echo "Failed to get a TGT with /get-tgt end-point"
561     exit 2
562 fi
563 ${kgetcred} -H HTTP/${server}@${R} ||
564     { echo "Trivial offline CA test failed (TGS)"; exit 2; }
565 if which jq >/dev/null; then
566     if ! ${klistjson} | jq -e '
567             (reduce (.tickets[0]|(.Issued,.Expires)|
568                     strptime("%b %e %H:%M:%S %Y")|mktime) as $t
569                 (0; if .==0 then $t else $t - . end) / 86400) |
570             . >= 4'; then
571         echo "Failed to get a TGT with /get-tgt end-point with addresses"
572         exit 2
573     fi
574 fi
575
576 echo "Fetch negotiate token (pre-test)"
577 # Do what /bnegotiate does, roughly, prior to testing /bnegotiate
578 $hxtool request-create  --subject='' --generate-key=rsa --key-bits=1024 \
579                         --key=PEM-FILE:"${objdir}/k.pem" "${objdir}/req" ||
580     { echo "Failed to make a CSR"; exit 2; }
581 $test_kdc_ca -a bx509 -A foo@${R} PKCS10:${objdir}/req       \
582              PEM-FILE:${objdir}/pkinit-test.pem ||
583     { echo "Trivial offline CA test failed (CA)"; exit 2; }
584 cat ${objdir}/k.pem >> ${objdir}/pkinit-test.pem
585 ${kinit} -C PEM-FILE:${objdir}/pkinit-test.pem foo@${R} ||
586     { echo "Trivial offline CA test failed (PKINIT)"; exit 2; }
587 ${kgetcred} -H HTTP/${server}@${R} ||
588     { echo "Trivial offline CA test failed (TGS)"; exit 2; }
589 KRB5CCNAME=$cache $gsstoken HTTP@$server | KRB5_KTNAME="$keytab" $gsstoken -r ||
590     { echo "Trivial offline CA test failed (gss-token)"; exit 2; }
591
592 # Check that we get up to three tixaddrs k/v in the log
593 grep 'REQ.*numtixaddrs=4 tixaddrs=IPv4:8.8.8.8 tixaddrs=IPv4:8.9.10.11 tixaddrs=IPv4:11.11.11.11.*wrongaddr=yes' ${objdir}/messages.log ||
594     { echo "KDC not warning about requests from wrong address"; exit 2; }
595
596 echo "Fetching a Negotiate token"
597 token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
598 if (set -vx;
599     curl -o negotiate-token -Lgsf                                       \
600          --resolve ${server}:${bx509port}:127.0.0.1                     \
601          -H "Authorization: Negotiate $token"                           \
602          "http://${server}:${bx509port}/bnegotiate?target=HTTP%40${server}"); then
603     # bx509 sends us a token w/o a newline for now; we add one because
604     # gss-token expects it.
605     test -s negotiate-token && echo >> negotiate-token
606     if test -s negotiate-token && KRB5_KTNAME="$keytab" $gsstoken -Nr < negotiate-token; then
607         echo 'Successfully obtained a Negotiate token!'
608     else
609         echo 'Failed to get a Negotiate token (got an unacceptable token)!'
610         exit 1
611     fi
612 else
613     echo 'Failed to get a Negotiate token!'
614     exit 1
615 fi
616
617 referer=https://${otherserver}/blah
618 redirect=$(${rkvis} -h https://${otherserver}/blah?q=whatever)
619 if (set -vx;
620     curl -o negotiate-token -Lgsf                                       \
621          --resolve ${server}:${bx509port}:127.0.0.1                     \
622         -H "Authorization: Negotiate $token"                            \
623         "http://${server}:${bx509port}/bnegotiate?target=HTTP%40${server}&redirect=${redirect}"); then
624     echo "Error: /bnegotiate with target and redirect succeeded"
625     exit 1
626 fi
627
628 if (set -vx;
629     curl -o negotiate-token -Lgsf                                       \
630          --resolve ${server}:${bx509port}:127.0.0.1                     \
631         -H "Authorization: Negotiate $token"                            \
632         "http://${server}:${bx509port}/bnegotiate?redirect=${redirect}"); then
633     echo "Error: /bnegotiate with redirect but no Referer succeeded"
634     exit 1
635 fi
636
637 referer=http://${otherserver}/blah
638 redirect=$(${rkvis} -h http://${otherserver}/blah?q=whatever)
639 if (set -vx;
640     curl -gsf                                                           \
641          --resolve ${server}:${bx509port}:127.0.0.1                     \
642         -H "Authorization: Negotiate $token"                            \
643         -H "Referer: $referer"                                          \
644         "http://${server}:${bx509port}/bnegotiate?redirect=${redirect}"); then
645     echo "Error: redirect for non-https referer"
646     exit 1
647 fi
648
649 referer=https://${otherserver}/blah
650 redirect=$(${rkvis} -h https://${otherserver}/blah?q=whatever)
651 if (set -vx;
652     curl -gfs -D curlheaders                                            \
653          --resolve ${server}:${bx509port}:127.0.0.1                     \
654         -H "Authorization: Negotiate $token"                            \
655         -H "Referer: $referer"                                          \
656         "http://${server}:${bx509port}/bnegotiate?redirect=${redirect}"); then
657     read junk code junk < curlheaders
658     if test "$code" = 307; then
659         echo "Got a proper redirect"
660     else
661         echo "Error: unexpected status code $code (wanted 307)"
662     fi
663 else
664     echo "Error: no redirect"
665     exit 1
666 fi
667
668 echo "killing kdc (${kdcpid}) and bx509d (${bx509pid})"
669 sh ${leaks_kill} kdc $kdcpid || ec=1
670 sh ${leaks_kill} bx509d $bx509pid || ec=1
671
672 trap "" EXIT
673
674 exit $ec