make AS work with FAST

This commit is contained in:
Love Hornquist Astrand
2011-05-09 20:46:31 -07:00
committed by Love Hörnquist Åstrand
parent 6c31f5a95f
commit 17d5f8d19e
5 changed files with 500 additions and 289 deletions

View File

@@ -147,6 +147,12 @@ _kdc_fast_mk_error(krb5_context context,
e_text = NULL; e_text = NULL;
} }
ret = krb5_padata_add(context, error_method,
KRB5_PADATA_FX_COOKIE,
NULL, 0);
if (ret)
return ret;
ret = _kdc_fast_mk_response(context, armor_crypto, ret = _kdc_fast_mk_response(context, armor_crypto,
error_method, NULL, NULL, error_method, NULL, NULL,
req_body->nonce, &e_data); req_body->nonce, &e_data);
@@ -157,17 +163,9 @@ _kdc_fast_mk_error(krb5_context context,
ret = krb5_padata_add(context, error_method, ret = krb5_padata_add(context, error_method,
KRB5_PADATA_FX_FAST, KRB5_PADATA_FX_FAST,
e_data.data, e_data.length); e_data.data, e_data.length);
krb5_data_zero(&e_data);
if (ret) if (ret)
return ret; return ret;
/*
* Set cookie to let client know we want conversation to
* continue.
*/
ret = krb5_padata_add(context, error_method,
KRB5_PADATA_FX_COOKIE,
NULL, 0);
if (ret) if (ret)
return ret; return ret;
} }

View File

@@ -271,6 +271,30 @@ _kdc_log_timestamp(krb5_context context,
type, authtime_str, starttime_str, endtime_str, renewtime_str); type, authtime_str, starttime_str, endtime_str, renewtime_str);
} }
struct kdc_patypes {
int type;
char *name;
unsigned int flags;
#define PA_ANNOUNCE 1
#ifdef PKINIT
#define PA_ANNOUNCE_PKINIT PA_ANNOUNCE
#else
#define PA_ANNOUNCE_PKINIT 0
#endif
};
static const struct kdc_patypes pat[] = {
{ KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE_PKINIT },
{ KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE_PKINIT },
{ KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0 },
{ KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS", PA_ANNOUNCE },
{ KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL", PA_ANNOUNCE },
{ KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0 },
{ KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE },
{ KRB5_PADATA_FX_ERROR, "FX-ERROR", 0 },
{ KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0 }
};
static void static void
log_patypes(krb5_context context, log_patypes(krb5_context context,
krb5_kdc_configuration *config, krb5_kdc_configuration *config,
@@ -278,27 +302,18 @@ log_patypes(krb5_context context,
{ {
struct rk_strpool *p = NULL; struct rk_strpool *p = NULL;
char *str; char *str;
size_t i; size_t n, m;
for (i = 0; i < padata->len; i++) { for (n = 0; n < padata->len; n++) {
switch(padata->val[i].padata_type) { for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
case KRB5_PADATA_PK_AS_REQ: if (padata->val[n].padata_type == pat[m].type) {
p = rk_strpoolprintf(p, "PK-INIT(ietf)"); p = rk_strpoolprintf(p, "%s", pat[m].name);
break;
case KRB5_PADATA_PK_AS_REQ_WIN:
p = rk_strpoolprintf(p, "PK-INIT(win2k)");
break;
case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
p = rk_strpoolprintf(p, "OCSP");
break;
case KRB5_PADATA_ENC_TIMESTAMP:
p = rk_strpoolprintf(p, "encrypted-timestamp");
break;
default:
p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
break; break;
} }
if (p && i + 1 < padata->len) }
if (m == sizeof(pat) / sizeof(pat[0]))
p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
if (p && n + 1 < padata->len)
p = rk_strpoolprintf(p, ", "); p = rk_strpoolprintf(p, ", ");
if (p == NULL) { if (p == NULL) {
kdc_log(context, config, 0, "out of memory"); kdc_log(context, config, 0, "out of memory");
@@ -321,8 +336,9 @@ log_patypes(krb5_context context,
krb5_error_code krb5_error_code
_kdc_encode_reply(krb5_context context, _kdc_encode_reply(krb5_context context,
krb5_kdc_configuration *config, krb5_kdc_configuration *config,
const krb5_data *req_buffer,
krb5_crypto armor_crypto, uint32_t nonce, krb5_crypto armor_crypto, uint32_t nonce,
KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek, KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
krb5_enctype etype, krb5_enctype etype,
int skvno, const EncryptionKey *skey, int skvno, const EncryptionKey *skey,
int ckvno, const EncryptionKey *reply_key, int ckvno, const EncryptionKey *reply_key,
@@ -336,25 +352,62 @@ _kdc_encode_reply(krb5_context context,
krb5_error_code ret; krb5_error_code ret;
krb5_crypto crypto; krb5_crypto crypto;
if (rep->msg_type == krb_as_rep && req_buffer) {
Checksum checksum;
krb5_data cdata;
et->flags.enc_pa_rep = 1;
ek->flags.enc_pa_rep = 1;
ret = krb5_crypto_init(context, reply_key, 0, &crypto);
if (ret) {
const char *msg = krb5_get_error_message(context, ret);
free(buf);
kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
krb5_free_error_message(context, msg);
return ret;
}
ret = krb5_create_checksum(context, crypto,
KRB5_KU_AS_REQ, 0,
req_buffer->data, req_buffer->length,
&checksum);
krb5_crypto_destroy(context, crypto);
if (ret) {
return ret;
}
ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
&checksum, &len, ret);
free_Checksum(&checksum);
if (ret) {
return ret;
}
ek->encrypted_pa_data = calloc(1, sizeof(*ek->encrypted_pa_data));
ret = krb5_padata_add(context, ek->encrypted_pa_data,
KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
if (ret) {
return ret;
}
ret = krb5_padata_add(context, ek->encrypted_pa_data,
KRB5_PADATA_FX_FAST, NULL, 0);
if (ret)
return ret;
}
ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret); ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
if(ret) { if(ret) {
const char *msg = krb5_get_error_message(context, ret); const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0, "Failed to encode ticket: %s", msg); kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
krb5_free_error_message(context, msg); krb5_free_error_message(context, msg);
krb5_crypto_destroy(context, crypto);
return ret; return ret;
} }
if(buf_size != len) { if(buf_size != len)
free(buf); krb5_abortx(context, "Internal error in ASN.1 encoder");
kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
*e_text = "KDC internal error";
return KRB5KRB_ERR_GENERIC;
}
ret = krb5_crypto_init(context, skey, etype, &crypto); ret = krb5_crypto_init(context, skey, etype, &crypto);
if (ret) { if (ret) {
const char *msg; const char *msg = krb5_get_error_message(context, ret);
free(buf);
msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
krb5_free_error_message(context, msg); krb5_free_error_message(context, msg);
return ret; return ret;
@@ -381,6 +434,8 @@ _kdc_encode_reply(krb5_context context,
krb5_keyblock *strengthen_key = NULL; krb5_keyblock *strengthen_key = NULL;
KrbFastFinished finished; KrbFastFinished finished;
kdc_log(context, config, 0, "FAST armor protection");
memset(&finished, 0, sizeof(finished)); memset(&finished, 0, sizeof(finished));
krb5_data_zero(&data); krb5_data_zero(&data);
@@ -1048,77 +1103,35 @@ make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
return ret; return ret;
} }
static krb5_error_code
/* unwrap_fast(krb5_context context,
*
*/
krb5_error_code
_kdc_as_rep(krb5_context context,
krb5_kdc_configuration *config, krb5_kdc_configuration *config,
KDC_REQ *req, KDC_REQ *req,
const krb5_data *req_buffer, krb5_crypto *armor_crypto)
krb5_data *reply,
const char *from,
struct sockaddr *from_addr,
int datagram_reply)
{ {
KDC_REQ_BODY *b = NULL;
AS_REP rep;
KDCOptions f;
hdb_entry_ex *client = NULL, *server = NULL, *armor_user = NULL;
HDB *clientdb;
krb5_enctype setype, sessionetype;
EncTicketPart et;
EncKDCRepPart ek;
krb5_principal client_princ = NULL, server_princ = NULL;
char *client_name = NULL, *server_name = NULL;
krb5_error_code ret = 0;
const char *e_text = NULL;
krb5_crypto crypto;
Key *ckey, *skey;
EncryptionKey *reply_key = NULL, session_key;
int flags = 0;
#ifdef PKINIT
pk_client_params *pkp = NULL;
#endif
METHOD_DATA error_method;
krb5_crypto armor_crypto = NULL;
memset(&rep, 0, sizeof(rep));
memset(&et, 0, sizeof(et));
memset(&ek, 0, sizeof(ek));
memset(&session_key, 0, sizeof(session_key));
error_method.len = 0;
error_method.val = NULL;
ALLOC(rep.padata);
rep.padata->len = 0;
rep.padata->val = NULL;
/*
* Look for FAST armor and unwrap
*/
{
const PA_DATA *pa;
int i = 0;
pa = _kdc_find_padata(req, &i, KRB5_PADATA_FX_FAST);
if (pa != NULL) {
krb5_crypto crypto_subkey = NULL, crypto_session = NULL; krb5_crypto crypto_subkey = NULL, crypto_session = NULL;
krb5_principal armor_server = NULL;
hdb_entry_ex *armor_user = NULL;
krb5_data pepper1, pepper2; krb5_data pepper1, pepper2;
PA_FX_FAST_REQUEST fxreq; PA_FX_FAST_REQUEST fxreq;
krb5_principal armor_server;
krb5_auth_context ac = NULL; krb5_auth_context ac = NULL;
krb5_ticket *ticket = NULL; krb5_ticket *ticket = NULL;
krb5_flags ap_req_options; krb5_flags ap_req_options;
Key *armor_key = NULL; Key *armor_key = NULL;
krb5_keyblock armorkey; krb5_keyblock armorkey;
krb5_error_code ret;
krb5_ap_req ap_req; krb5_ap_req ap_req;
unsigned char *buf; unsigned char *buf;
KrbFastReq fastreq; KrbFastReq fastreq;
size_t len, size; size_t len, size;
krb5_data data; krb5_data data;
const PA_DATA *pa;
int i = 0;
pa = _kdc_find_padata(req, &i, KRB5_PADATA_FX_FAST);
if (pa == NULL)
return 0;
ret = decode_PA_FX_FAST_REQUEST(pa->padata_value.data, ret = decode_PA_FX_FAST_REQUEST(pa->padata_value.data,
@@ -1245,7 +1258,7 @@ _kdc_as_rep(krb5_context context,
if (ret) if (ret)
goto out; goto out;
ret = krb5_crypto_init(context, &armorkey, 0, &armor_crypto); ret = krb5_crypto_init(context, &armorkey, 0, armor_crypto);
if (ret) if (ret)
goto out; goto out;
krb5_free_keyblock_contents(context, &armorkey); krb5_free_keyblock_contents(context, &armorkey);
@@ -1260,7 +1273,7 @@ _kdc_as_rep(krb5_context context,
goto out; goto out;
} }
ret = krb5_verify_checksum(context, armor_crypto, ret = krb5_verify_checksum(context, *armor_crypto,
KRB5_KU_FAST_REQ_CHKSUM, KRB5_KU_FAST_REQ_CHKSUM,
buf, len, buf, len,
&fxreq.u.armored_data.req_checksum); &fxreq.u.armored_data.req_checksum);
@@ -1268,7 +1281,7 @@ _kdc_as_rep(krb5_context context,
if (ret) if (ret)
goto out; goto out;
ret = krb5_decrypt_EncryptedData(context, armor_crypto, ret = krb5_decrypt_EncryptedData(context, *armor_crypto,
KRB5_KU_FAST_ENC, KRB5_KU_FAST_ENC,
&fxreq.u.armored_data.enc_fast_req, &fxreq.u.armored_data.enc_fast_req,
&data); &data);
@@ -1308,8 +1321,70 @@ _kdc_as_rep(krb5_context context,
free_KrbFastReq(&fastreq); free_KrbFastReq(&fastreq);
free_PA_FX_FAST_REQUEST(&fxreq); free_PA_FX_FAST_REQUEST(&fxreq);
}
} out:
if (armor_server)
krb5_free_principal(context, armor_server);
if(armor_user)
_kdc_free_ent(context, armor_user);
return ret;
}
/*
*
*/
krb5_error_code
_kdc_as_rep(krb5_context context,
krb5_kdc_configuration *config,
KDC_REQ *req,
const krb5_data *req_buffer,
krb5_data *reply,
const char *from,
struct sockaddr *from_addr,
int datagram_reply)
{
KDC_REQ_BODY *b = NULL;
AS_REP rep;
KDCOptions f;
hdb_entry_ex *client = NULL, *server = NULL;
HDB *clientdb;
krb5_enctype setype, sessionetype;
EncTicketPart et;
EncKDCRepPart ek;
krb5_principal client_princ = NULL, server_princ = NULL;
char *client_name = NULL, *server_name = NULL;
krb5_error_code ret = 0;
const char *e_text = NULL;
krb5_crypto crypto;
Key *ckey, *skey;
EncryptionKey *reply_key = NULL, session_key;
int flags = 0;
#ifdef PKINIT
pk_client_params *pkp = NULL;
#endif
METHOD_DATA error_method;
krb5_crypto armor_crypto = NULL;
memset(&rep, 0, sizeof(rep));
memset(&et, 0, sizeof(et));
memset(&ek, 0, sizeof(ek));
memset(&session_key, 0, sizeof(session_key));
error_method.len = 0;
error_method.val = NULL;
ALLOC(rep.padata);
rep.padata->len = 0;
rep.padata->val = NULL;
/*
* Look for FAST armor and unwrap
*/
ret = unwrap_fast(context, config, req, &armor_crypto);
if (ret)
goto out;
b = &req->req_body; b = &req->req_body;
f = b->kdc_options; f = b->kdc_options;
@@ -1796,42 +1871,16 @@ _kdc_as_rep(krb5_context context,
|| b->kdc_options.request_anonymous /* hack to force anon */ || b->kdc_options.request_anonymous /* hack to force anon */
|| client->entry.flags.require_preauth || client->entry.flags.require_preauth
|| server->entry.flags.require_preauth) { || server->entry.flags.require_preauth) {
PA_DATA *pa; size_t n;
use_pa: use_pa:
for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
ret = realloc_method_data(&error_method); if ((pat[n].flags & PA_ANNOUNCE) == 0)
if (ret) continue;
goto out;
pa = &error_method.val[error_method.len-1];
pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
pa->padata_value.length = 0;
pa->padata_value.data = NULL;
#ifdef PKINIT
ret = realloc_method_data(&error_method);
if (ret)
goto out;
pa = &error_method.val[error_method.len-1];
pa->padata_type = KRB5_PADATA_PK_AS_REQ;
pa->padata_value.length = 0;
pa->padata_value.data = NULL;
ret = realloc_method_data(&error_method);
if (ret)
goto out;
pa = &error_method.val[error_method.len-1];
pa->padata_type = KRB5_PADATA_PK_AS_REQ_WIN;
pa->padata_value.length = 0;
pa->padata_value.data = NULL;
#endif
/*
* Announce FX-FAST
*/
ret = krb5_padata_add(context, &error_method, ret = krb5_padata_add(context, &error_method,
KRB5_PADATA_FX_FAST, NULL, 0); pat[n].type, NULL, 0);
if (ret) if (ret)
goto out; goto out;
}
/* /*
* If there is a client key, send ETYPE_INFO{,2} * If there is a client key, send ETYPE_INFO{,2}
@@ -2239,7 +2288,17 @@ _kdc_as_rep(krb5_context context,
log_as_req(context, config, reply_key->keytype, setype, b); log_as_req(context, config, reply_key->keytype, setype, b);
ret = _kdc_encode_reply(context, config, armor_crypto, req->req_body.nonce, {
PA_DATA *pa;
int i = 0;
pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
if (pa == NULL)
req_buffer = NULL;
}
ret = _kdc_encode_reply(context, config, req_buffer,
armor_crypto, req->req_body.nonce,
&rep, &et, &ek, setype, server->entry.kvno, &rep, &et, &ek, setype, server->entry.kvno,
&skey->key, client->entry.kvno, &skey->key, client->entry.kvno,
reply_key, 0, &e_text, reply); reply_key, 0, &e_text, reply);
@@ -2292,8 +2351,6 @@ out2:
_kdc_free_ent(context, client); _kdc_free_ent(context, client);
if(server) if(server)
_kdc_free_ent(context, server); _kdc_free_ent(context, server);
if(armor_user)
_kdc_free_ent(context, armor_user);
if (armor_crypto) if (armor_crypto)
krb5_crypto_destroy(context, armor_crypto); krb5_crypto_destroy(context, armor_crypto);
return ret; return ret;

View File

@@ -987,7 +987,7 @@ tgs_make_reply(krb5_context context,
CAST session key. Should the DES3 etype be added to the CAST session key. Should the DES3 etype be added to the
etype list, even if we don't want a session key with etype list, even if we don't want a session key with
DES3? */ DES3? */
ret = _kdc_encode_reply(context, config, NULL, 0, ret = _kdc_encode_reply(context, config, NULL, NULL, 0,
&rep, &et, &ek, et.key.keytype, &rep, &et, &ek, et.key.keytype,
kvno, kvno,
serverkey, 0, replykey, rk_is_subkey, serverkey, 0, replykey, rk_is_subkey,

View File

@@ -14,6 +14,7 @@ SCRIPT_TESTS = \
check-delegation \ check-delegation \
check-des \ check-des \
check-digest \ check-digest \
check-fast \
check-kadmin \ check-kadmin \
check-kdc \ check-kdc \
check-kdc-weak \ check-kdc-weak \
@@ -63,6 +64,11 @@ check-des: check-des.in Makefile krb5.conf
chmod +x check-des.tmp chmod +x check-des.tmp
mv check-des.tmp check-des mv check-des.tmp check-des
check-fast: check-fast.in Makefile
$(do_subst) < $(srcdir)/check-fast.in > check-fast.tmp
chmod +x check-fast.tmp
mv check-fast.tmp check-fast
check-kdc: check-kdc.in Makefile check-kdc: check-kdc.in Makefile
$(do_subst) < $(srcdir)/check-kdc.in > check-kdc.tmp $(do_subst) < $(srcdir)/check-kdc.in > check-kdc.tmp
chmod +x check-kdc.tmp chmod +x check-kdc.tmp

150
tests/kdc/check-fast.in Normal file
View File

@@ -0,0 +1,150 @@
#!/bin/sh
#
# Copyright (c) 2006 - 2011 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@"
. ${env_setup}
KRB5_CONFIG="${1-${objdir}/krb5.conf}"
export KRB5_CONFIG
testfailed="echo test failed; cat messages.log; exit 1"
# If there is no useful db support compile in, disable test
${have_db} || exit 77
R=TEST.H5L.SE
port=@port@
kadmin="${kadmin} -l -r $R"
kdc="${kdc} --addresses=localhost -P $port"
server=host/datan.test.h5l.se
cache="FILE:${objdir}/cache.krb5"
acache="FILE:${objdir}/acache.krb5"
kinit="${kinit} -c $cache ${afs_no_afslog}"
klist="${klist} -c $cache"
aklist="${klist} -c $acache"
kgetcred="${kgetcred} -c $cache"
kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
rm -f ${keytabfile}
rm -f current-db*
rm -f out-*
rm -f mkey.file*
> messages.log
echo Creating database
${kadmin} \
init \
--realm-max-ticket-life=1day \
--realm-max-renewable-life=1month \
${R} || exit 1
${kadmin} add -p foo --use-defaults foo@${R} || exit 1
${kadmin} add -p foo --use-defaults ${server}@${R} || exit 1
echo "Doing database check"
${kadmin} check ${R} || exit 1
echo foo > ${objdir}/foopassword
echo Starting kdc
env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
${kdc} &
kdcpid=$!
sh ${wait_kdc}
if [ "$?" != 0 ] ; then
kill -9 ${kdcpid}
exit 1
fi
trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
ec=0
echo "Getting client initial tickets"; > messages.log
${kinit} --password-file=${objdir}/foopassword foo@$R || \
{ ec=1 ; eval "${testfailed}"; }
echo "Getting tickets"; > messages.log
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
echo "Listing tickets"; > messages.log
${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
${kdestroy}
echo foo > ${objdir}/foopassword
kinitpty=${objdir}/foopassword.rkpty
cat > ${kinitpty} <<EOF
expect Password
password foo\n
EOF
mit=/usr/local/mitkerberos/bin
if [ -f ${mit}/kinit ] ; then
echo "Running MIT FAST tests"
echo "Acquire host ticket"
${rkpty} ${kinitpty} ${mit}/kinit -c ${acache} ${server}@${R} >/dev/null|| { exit 1; }
(${aklist} | grep ${server} > /dev/null ) || { exit 1; }
echo "Checking for FAST avail"
${aklist} --hidden | grep fast_avail > /dev/null || { exit 1; }
echo "Using plain to get a initial ticket"
${rkpty} ${kinitpty} ${mit}/kinit -c ${cache} foo@${R} >/dev/null|| { exit 1; }
(${aklist} | grep ${server} > /dev/null ) || { exit 1; }
echo "Using FAST to get a initial ticket"
${rkpty} ${kinitpty} ${mit}/kinit -c ${cache} -T ${acache} foo@${R} >/dev/null || { exit 1; }
(${aklist} | grep ${server} > /dev/null ) || { exit 1; }
echo "Checking for FAST avail"
${klist} --hidden | grep fast_avail > /dev/null || { exit 1; }
fi
echo "killing kdc (${kdcpid})"
sh ${leaks_kill} kdc $kdcpid || exit 1
trap "" EXIT
exit $ec