/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* tests/asn.1/krb5_decode_leak.c */
/*
 * Copyright (C) 2009 by the Massachusetts Institute of Technology.
 * All rights reserved.
 *
 * Export of this software from the United States of America may
 *   require a specific license from the United States Government.
 *   It is the responsibility of any person or organization contemplating
 *   export to obtain such a license before exporting.
 *
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 * distribute this software and its documentation for any purpose and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of M.I.T. not be used in advertising or publicity pertaining
 * to distribution of the software without specific, written prior
 * permission.  Furthermore if you modify this software you must label
 * your software as modified software and not distribute it in such a
 * fashion that it might be confused with the original M.I.T. software.
 * M.I.T. makes no representations about the suitability of
 * this software for any purpose.  It is provided "as is" without express
 * or implied warranty.
 */

/*
 * This program is intended to help detect memory leaks in the ASN.1
 * decoder functions by exercising their failure paths.  The setup
 * code for the test cases is copied from krb5_encode_test.c.
 *
 * This code does not actually detect leaks by itself; it must be run
 * through a leak-detection tool such as valgrind to do so.  Simply
 * running the program will exercise a bunch of ASN.1 encoder and
 * decoder code paths but won't validate the results.
 */

#include "k5-int.h"
#include "com_err.h"
#include "utility.h"
#include "ktest.h"
#include "debug.h"

krb5_context test_context;

/*
 * Contrary to our usual convention, krb5_free_cred_enc_part is a
 * contents-only free function (and is assumed to be by mk_cred and
 * rd_cred) and we have no whole-structure free function for that data
 * type.  So create one here.
 */
static void
free_cred_enc_part_whole(krb5_context ctx,
                         krb5_cred_enc_part *val)
{
    krb5_free_cred_enc_part(ctx, val);
    free(val);
}

int
main(int argc, char **argv)
{
    krb5_data *code;
    krb5_error_code retval;
    unsigned int i;

    retval = krb5_init_context(&test_context);
    if (retval) {
        com_err(argv[0], retval, "while initializing krb5");
        exit(1);
    }
    init_access(argv[0]);

#define encode_run(value,type,typestring,description,encoder)

    /*
     * Encode a value.  Then attempt to trigger most failure paths of
     * the decoder function by passing in corrupt encodings, which we
     * generate by perturbing each byte of the encoding in turn.  Some
     * of the perturbed encodings are expected to decode successfully,
     * so we need a free function to discard successful results.  Make
     * sure to define a pointer named "tmp" of the correct type in the
     * enclosing block.
     */
#define leak_test(value, encoder, decoder, freefn)              \
    retval = encoder(&(value),&(code));                         \
    if (retval) {                                               \
        com_err("krb5_decode_leak", retval, "while encoding");  \
        exit(1);                                                \
    }                                                           \
    for (i = 0; i < code->length; i++) {                        \
        code->data[i] = (char)~((unsigned char)code->data[i]);  \
        retval = decoder(code, &tmp);                           \
        code->data[i] = (char)~((unsigned char)code->data[i]);  \
        if (retval == 0)                                        \
            freefn(test_context, tmp);                          \
    }                                                           \
    krb5_free_data(test_context, code);

    /****************************************************************/
    /* encode_krb5_authenticator */
    {
        krb5_authenticator authent, *tmp;

        ktest_make_sample_authenticator(&authent);
        leak_test(authent, encode_krb5_authenticator,
                  decode_krb5_authenticator, krb5_free_authenticator);

        ktest_destroy_checksum(&(authent.checksum));
        ktest_destroy_keyblock(&(authent.subkey));
        authent.seq_number = 0;
        ktest_empty_authorization_data(authent.authorization_data);
        leak_test(authent, encode_krb5_authenticator,
                  decode_krb5_authenticator, krb5_free_authenticator);

        ktest_destroy_authorization_data(&(authent.authorization_data));
        leak_test(authent, encode_krb5_authenticator,
                  decode_krb5_authenticator, krb5_free_authenticator);
        ktest_empty_authenticator(&authent);
    }

    /****************************************************************/
    /* encode_krb5_ticket */
    {
        krb5_ticket tkt, *tmp;

        ktest_make_sample_ticket(&tkt);
        leak_test(tkt, encode_krb5_ticket, decode_krb5_ticket,
                  krb5_free_ticket);
        ktest_empty_ticket(&tkt);
    }

    /****************************************************************/
    /* encode_krb5_encryption_key */
    {
        krb5_keyblock keyblk, *tmp;

        ktest_make_sample_keyblock(&keyblk);
        leak_test(keyblk, encode_krb5_encryption_key,
                  decode_krb5_encryption_key, krb5_free_keyblock);
        ktest_empty_keyblock(&keyblk);
    }

    /****************************************************************/
    /* encode_krb5_enc_tkt_part */
    {
        krb5_ticket tkt;
        krb5_enc_tkt_part *tmp;

        memset(&tkt, 0, sizeof(krb5_ticket));
        tkt.enc_part2 = ealloc(sizeof(krb5_enc_tkt_part));
        ktest_make_sample_enc_tkt_part(tkt.enc_part2);

        leak_test(*(tkt.enc_part2), encode_krb5_enc_tkt_part,
                  decode_krb5_enc_tkt_part, krb5_free_enc_tkt_part);

        tkt.enc_part2->times.starttime = 0;
        tkt.enc_part2->times.renew_till = 0;
        ktest_destroy_address(&(tkt.enc_part2->caddrs[1]));
        ktest_destroy_address(&(tkt.enc_part2->caddrs[0]));
        ktest_destroy_authdata(&(tkt.enc_part2->authorization_data[1]));
        ktest_destroy_authdata(&(tkt.enc_part2->authorization_data[0]));

        /* ISODE version fails on the empty caddrs field */
        ktest_destroy_addresses(&(tkt.enc_part2->caddrs));
        ktest_destroy_authorization_data(&(tkt.enc_part2->authorization_data));

        leak_test(*(tkt.enc_part2), encode_krb5_enc_tkt_part,
                  decode_krb5_enc_tkt_part, krb5_free_enc_tkt_part);
        ktest_empty_ticket(&tkt);
    }

    /****************************************************************/
    /* encode_krb5_enc_kdc_rep_part */
    {
        krb5_kdc_rep kdcr;
        krb5_enc_kdc_rep_part *tmp;

        memset(&kdcr, 0, sizeof(kdcr));

        kdcr.enc_part2 = ealloc(sizeof(krb5_enc_kdc_rep_part));
        ktest_make_sample_enc_kdc_rep_part(kdcr.enc_part2);

        leak_test(*(kdcr.enc_part2), encode_krb5_enc_kdc_rep_part,
                  decode_krb5_enc_kdc_rep_part, krb5_free_enc_kdc_rep_part);

        kdcr.enc_part2->key_exp = 0;
        kdcr.enc_part2->times.starttime = 0;
        kdcr.enc_part2->flags &= ~TKT_FLG_RENEWABLE;
        ktest_destroy_addresses(&(kdcr.enc_part2->caddrs));

        leak_test(*(kdcr.enc_part2), encode_krb5_enc_kdc_rep_part,
                  decode_krb5_enc_kdc_rep_part, krb5_free_enc_kdc_rep_part);

        ktest_empty_kdc_rep(&kdcr);
    }

    /****************************************************************/
    /* encode_krb5_as_rep */
    {
        krb5_kdc_rep kdcr, *tmp;

        ktest_make_sample_kdc_rep(&kdcr);
        kdcr.msg_type = KRB5_AS_REP;
        leak_test(kdcr, encode_krb5_as_rep, decode_krb5_as_rep,
                  krb5_free_kdc_rep);

        ktest_destroy_pa_data_array(&(kdcr.padata));
        leak_test(kdcr, encode_krb5_as_rep, decode_krb5_as_rep,
                  krb5_free_kdc_rep);

        ktest_empty_kdc_rep(&kdcr);

    }

    /****************************************************************/
    /* encode_krb5_tgs_rep */
    {
        krb5_kdc_rep kdcr, *tmp;

        ktest_make_sample_kdc_rep(&kdcr);
        kdcr.msg_type = KRB5_TGS_REP;
        leak_test(kdcr, encode_krb5_tgs_rep, decode_krb5_tgs_rep,
                  krb5_free_kdc_rep);

        ktest_destroy_pa_data_array(&(kdcr.padata));
        leak_test(kdcr, encode_krb5_tgs_rep, decode_krb5_tgs_rep,
                  krb5_free_kdc_rep);

        ktest_empty_kdc_rep(&kdcr);

    }

    /****************************************************************/
    /* encode_krb5_ap_req */
    {
        krb5_ap_req apreq, *tmp;

        ktest_make_sample_ap_req(&apreq);
        leak_test(apreq, encode_krb5_ap_req, decode_krb5_ap_req,
                  krb5_free_ap_req);
        ktest_empty_ap_req(&apreq);
    }

    /****************************************************************/
    /* encode_krb5_ap_rep */
    {
        krb5_ap_rep aprep, *tmp;

        ktest_make_sample_ap_rep(&aprep);
        leak_test(aprep, encode_krb5_ap_rep, decode_krb5_ap_rep,
                  krb5_free_ap_rep);
        ktest_empty_ap_rep(&aprep);
    }

    /****************************************************************/
    /* encode_krb5_ap_rep_enc_part */
    {
        krb5_ap_rep_enc_part apenc, *tmp;

        ktest_make_sample_ap_rep_enc_part(&apenc);
        leak_test(apenc, encode_krb5_ap_rep_enc_part,
                  decode_krb5_ap_rep_enc_part, krb5_free_ap_rep_enc_part);

        ktest_destroy_keyblock(&(apenc.subkey));
        apenc.seq_number = 0;
        leak_test(apenc, encode_krb5_ap_rep_enc_part,
                  decode_krb5_ap_rep_enc_part, krb5_free_ap_rep_enc_part);
        ktest_empty_ap_rep_enc_part(&apenc);
    }

    /****************************************************************/
    /* encode_krb5_as_req */
    {
        krb5_kdc_req asreq, *tmp;

        ktest_make_sample_kdc_req(&asreq);
        asreq.msg_type = KRB5_AS_REQ;
        asreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
        leak_test(asreq, encode_krb5_as_req, decode_krb5_as_req,
                  krb5_free_kdc_req);

        ktest_destroy_pa_data_array(&(asreq.padata));
        ktest_destroy_principal(&(asreq.client));
#ifndef ISODE_SUCKS
        ktest_destroy_principal(&(asreq.server));
#endif
        asreq.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY;
        asreq.from = 0;
        asreq.rtime = 0;
        ktest_destroy_addresses(&(asreq.addresses));
        ktest_destroy_enc_data(&(asreq.authorization_data));
        leak_test(asreq, encode_krb5_as_req, decode_krb5_as_req,
                  krb5_free_kdc_req);

        ktest_destroy_sequence_of_ticket(&(asreq.second_ticket));
#ifndef ISODE_SUCKS
        ktest_make_sample_principal(&(asreq.server));
#endif
        asreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
        leak_test(asreq, encode_krb5_as_req, decode_krb5_as_req,
                  krb5_free_kdc_req);
        ktest_empty_kdc_req(&asreq);
    }

    /****************************************************************/
    /* encode_krb5_tgs_req */
    {
        krb5_kdc_req tgsreq, *tmp;

        ktest_make_sample_kdc_req(&tgsreq);
        tgsreq.msg_type = KRB5_TGS_REQ;
        tgsreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
        leak_test(tgsreq, encode_krb5_tgs_req, decode_krb5_tgs_req,
                  krb5_free_kdc_req);

        ktest_destroy_pa_data_array(&(tgsreq.padata));
        ktest_destroy_principal(&(tgsreq.client));
#ifndef ISODE_SUCKS
        ktest_destroy_principal(&(tgsreq.server));
#endif
        tgsreq.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY;
        tgsreq.from = 0;
        tgsreq.rtime = 0;
        ktest_destroy_addresses(&(tgsreq.addresses));
        ktest_destroy_enc_data(&(tgsreq.authorization_data));
        leak_test(tgsreq, encode_krb5_tgs_req, decode_krb5_tgs_req,
                  krb5_free_kdc_req);

        ktest_destroy_sequence_of_ticket(&(tgsreq.second_ticket));
#ifndef ISODE_SUCKS
        ktest_make_sample_principal(&(tgsreq.server));
#endif
        tgsreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
        leak_test(tgsreq, encode_krb5_tgs_req, decode_krb5_tgs_req,
                  krb5_free_kdc_req);
        ktest_empty_kdc_req(&tgsreq);
    }

    /****************************************************************/
    /* encode_krb5_kdc_req_body */
    {
        krb5_kdc_req kdcrb, *tmp;

        memset(&kdcrb, 0, sizeof(kdcrb));
        ktest_make_sample_kdc_req_body(&kdcrb);
        kdcrb.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
        leak_test(kdcrb, encode_krb5_kdc_req_body, decode_krb5_kdc_req_body,
                  krb5_free_kdc_req);

        ktest_destroy_principal(&(kdcrb.client));
#ifndef ISODE_SUCKS
        ktest_destroy_principal(&(kdcrb.server));
#endif
        kdcrb.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY;
        kdcrb.from = 0;
        kdcrb.rtime = 0;
        ktest_destroy_addresses(&(kdcrb.addresses));
        ktest_destroy_enc_data(&(kdcrb.authorization_data));
        leak_test(kdcrb, encode_krb5_kdc_req_body, decode_krb5_kdc_req_body,
                  krb5_free_kdc_req);

        ktest_destroy_sequence_of_ticket(&(kdcrb.second_ticket));
#ifndef ISODE_SUCKS
        ktest_make_sample_principal(&(kdcrb.server));
#endif
        kdcrb.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY;
        leak_test(kdcrb, encode_krb5_kdc_req_body, decode_krb5_kdc_req_body,
                  krb5_free_kdc_req);
        ktest_empty_kdc_req(&kdcrb);
    }

    /****************************************************************/
    /* encode_krb5_safe */
    {
        krb5_safe s, *tmp;

        ktest_make_sample_safe(&s);
        leak_test(s, encode_krb5_safe, decode_krb5_safe, krb5_free_safe);

        s.timestamp = 0;
        /* s.usec should be opted out by the timestamp */
        s.seq_number = 0;
        ktest_destroy_address(&(s.r_address));
        leak_test(s, encode_krb5_safe, decode_krb5_safe, krb5_free_safe);
        ktest_empty_safe(&s);
    }

    /****************************************************************/
    /* encode_krb5_priv */
    {
        krb5_priv p, *tmp;

        ktest_make_sample_priv(&p);
        leak_test(p, encode_krb5_priv, decode_krb5_priv, krb5_free_priv);
        ktest_empty_priv(&p);
    }

    /****************************************************************/
    /* encode_krb5_enc_priv_part */
    {
        krb5_priv_enc_part ep, *tmp;

        ktest_make_sample_priv_enc_part(&ep);
        leak_test(ep, encode_krb5_enc_priv_part, decode_krb5_enc_priv_part,
                  krb5_free_priv_enc_part);

        ep.timestamp = 0;
        /* ep.usec should be opted out along with timestamp */
        ep.seq_number = 0;
        ktest_destroy_address(&(ep.r_address));
        leak_test(ep, encode_krb5_enc_priv_part, decode_krb5_enc_priv_part,
                  krb5_free_priv_enc_part);
        ktest_empty_priv_enc_part(&ep);
    }

    /****************************************************************/
    /* encode_krb5_cred */
    {
        krb5_cred c, *tmp;

        ktest_make_sample_cred(&c);
        leak_test(c, encode_krb5_cred, decode_krb5_cred, krb5_free_cred);
        ktest_empty_cred(&c);
    }

    /****************************************************************/
    /* encode_krb5_enc_cred_part */
    {
        krb5_cred_enc_part cep, *tmp;

        ktest_make_sample_cred_enc_part(&cep);
        leak_test(cep, encode_krb5_enc_cred_part, decode_krb5_enc_cred_part,
                  free_cred_enc_part_whole);

        ktest_destroy_principal(&(cep.ticket_info[0]->client));
        ktest_destroy_principal(&(cep.ticket_info[0]->server));
        cep.ticket_info[0]->flags = 0;
        cep.ticket_info[0]->times.authtime = 0;
        cep.ticket_info[0]->times.starttime = 0;
        cep.ticket_info[0]->times.endtime = 0;
        cep.ticket_info[0]->times.renew_till = 0;
        ktest_destroy_addresses(&(cep.ticket_info[0]->caddrs));
        cep.nonce = 0;
        cep.timestamp = 0;
        ktest_destroy_address(&(cep.s_address));
        ktest_destroy_address(&(cep.r_address));
        leak_test(cep, encode_krb5_enc_cred_part, decode_krb5_enc_cred_part,
                  free_cred_enc_part_whole);
        ktest_empty_cred_enc_part(&cep);
    }

    /****************************************************************/
    /* encode_krb5_error */
    {
        krb5_error kerr, *tmp;

        ktest_make_sample_error(&kerr);
        leak_test(kerr, encode_krb5_error, decode_krb5_error, krb5_free_error);

        kerr.ctime = 0;
        ktest_destroy_principal(&(kerr.client));
        ktest_empty_data(&(kerr.text));
        ktest_empty_data(&(kerr.e_data));
        leak_test(kerr, encode_krb5_error, decode_krb5_error, krb5_free_error);

        ktest_empty_error(&kerr);
    }

    /****************************************************************/
    /* encode_krb5_authdata */
    {
        krb5_authdata **ad, **tmp;

        ktest_make_sample_authorization_data(&ad);
        leak_test(*ad, encode_krb5_authdata, decode_krb5_authdata,
                  krb5_free_authdata);
        ktest_destroy_authorization_data(&ad);
    }

    /****************************************************************/
    /* encode_padata_sequence and encode_typed_data */
    {
        krb5_pa_data **pa, **tmp;

        ktest_make_sample_pa_data_array(&pa);
        leak_test(*pa, encode_krb5_padata_sequence,
                  decode_krb5_padata_sequence, krb5_free_pa_data);
        leak_test(*pa, encode_krb5_typed_data,
                  decode_krb5_typed_data, krb5_free_pa_data);
        ktest_destroy_pa_data_array(&pa);
    }

    /****************************************************************/
    /* encode_padata_sequence (empty) */
    {
        krb5_pa_data **pa, **tmp;

        ktest_make_sample_empty_pa_data_array(&pa);
        leak_test(*pa, encode_krb5_padata_sequence,
                  decode_krb5_padata_sequence, krb5_free_pa_data);
        ktest_destroy_pa_data_array(&pa);
    }

    /****************************************************************/
    /* encode_etype_info */
    {
        krb5_etype_info_entry **info, **tmp;

        ktest_make_sample_etype_info(&info);
        leak_test(*info, encode_krb5_etype_info, decode_krb5_etype_info,
                  krb5_free_etype_info);

        ktest_destroy_etype_info_entry(info[2]);      info[2] = 0;
        ktest_destroy_etype_info_entry(info[1]);      info[1] = 0;
        leak_test(*info, encode_krb5_etype_info, decode_krb5_etype_info,
                  krb5_free_etype_info);

        ktest_destroy_etype_info_entry(info[0]);      info[0] = 0;
        leak_test(*info, encode_krb5_etype_info, decode_krb5_etype_info,
                  krb5_free_etype_info);

        ktest_destroy_etype_info(info);
    }

    /* encode_etype_info 2*/
    {
        krb5_etype_info_entry **info, **tmp;

        ktest_make_sample_etype_info2(&info);
        leak_test(*info, encode_krb5_etype_info2, decode_krb5_etype_info2,
                  krb5_free_etype_info);

        ktest_destroy_etype_info_entry(info[2]);      info[2] = 0;
        ktest_destroy_etype_info_entry(info[1]);      info[1] = 0;
        leak_test(*info, encode_krb5_etype_info2, decode_krb5_etype_info2,
                  krb5_free_etype_info);

        ktest_destroy_etype_info(info);
    }

    /****************************************************************/
    /* encode_pa_enc_ts */
    {
        krb5_pa_enc_ts pa_enc, *tmp;

        ktest_make_sample_pa_enc_ts(&pa_enc);
        leak_test(pa_enc, encode_krb5_pa_enc_ts, decode_krb5_pa_enc_ts,
                  krb5_free_pa_enc_ts);
        pa_enc.pausec = 0;
        leak_test(pa_enc, encode_krb5_pa_enc_ts, decode_krb5_pa_enc_ts,
                  krb5_free_pa_enc_ts);
    }

    /****************************************************************/
    /* encode_enc_data */
    {
        krb5_enc_data enc_data, *tmp;

        ktest_make_sample_enc_data(&enc_data);
        leak_test(enc_data, encode_krb5_enc_data, decode_krb5_enc_data,
                  krb5_free_enc_data);
        ktest_destroy_enc_data(&enc_data);
    }
    /****************************************************************/
    /* encode_krb5_sam_challenge_2 */
    {
        krb5_sam_challenge_2 sam_ch2, *tmp;

        ktest_make_sample_sam_challenge_2(&sam_ch2);
        leak_test(sam_ch2, encode_krb5_sam_challenge_2,
                  decode_krb5_sam_challenge_2, krb5_free_sam_challenge_2);
        ktest_empty_sam_challenge_2(&sam_ch2);
    }
    /****************************************************************/
    /* encode_krb5_sam_challenge_2 */
    {
        krb5_sam_challenge_2_body body, *tmp;

        ktest_make_sample_sam_challenge_2_body(&body);
        leak_test(body, encode_krb5_sam_challenge_2_body,
                  decode_krb5_sam_challenge_2_body,
                  krb5_free_sam_challenge_2_body);
        ktest_empty_sam_challenge_2_body(&body);
    }
    /****************************************************************/
    /* encode_krb5_sam_response_2 */
    {
        krb5_sam_response_2 sam_ch2, *tmp;

        ktest_make_sample_sam_response_2(&sam_ch2);
        leak_test(sam_ch2, encode_krb5_sam_response_2,
                  decode_krb5_sam_response_2, krb5_free_sam_response_2);
        ktest_empty_sam_response_2(&sam_ch2);
    }
    /****************************************************************/
    /* encode_krb5_sam_response_enc_2 */
    {
        krb5_enc_sam_response_enc_2 sam_ch2, *tmp;

        ktest_make_sample_enc_sam_response_enc_2(&sam_ch2);
        leak_test(sam_ch2, encode_krb5_enc_sam_response_enc_2,
                  decode_krb5_enc_sam_response_enc_2,
                  krb5_free_enc_sam_response_enc_2);
        ktest_empty_enc_sam_response_enc_2(&sam_ch2);
    }
    /****************************************************************/
    /* encode_krb5_pa_for_user */
    {
        krb5_pa_for_user foru, *tmp;
        ktest_make_sample_pa_for_user(&foru);
        leak_test(foru, encode_krb5_pa_for_user, decode_krb5_pa_for_user,
                  krb5_free_pa_for_user);
        ktest_empty_pa_for_user(&foru);
    }
    /****************************************************************/
    /* encode_krb5_pa_s4u_x509_user */
    {
        krb5_pa_s4u_x509_user s4u, *tmp;
        ktest_make_sample_pa_s4u_x509_user(&s4u);
        leak_test(s4u, encode_krb5_pa_s4u_x509_user,
                  decode_krb5_pa_s4u_x509_user,
                  krb5_free_pa_s4u_x509_user);
        ktest_empty_pa_s4u_x509_user(&s4u);
    }
    /****************************************************************/
    /* encode_krb5_ad_kdcissued */
    {
        krb5_ad_kdcissued kdci, *tmp;
        ktest_make_sample_ad_kdcissued(&kdci);
        leak_test(kdci, encode_krb5_ad_kdcissued,
                  decode_krb5_ad_kdcissued,
                  krb5_free_ad_kdcissued);
        ktest_empty_ad_kdcissued(&kdci);
    }
    /****************************************************************/
    /* encode_krb5_iakerb_header */
    {
        krb5_iakerb_header ih, *tmp;
        ktest_make_sample_iakerb_header(&ih);
        leak_test(ih, encode_krb5_iakerb_header,
                  decode_krb5_iakerb_header,
                  krb5_free_iakerb_header);
        ktest_empty_iakerb_header(&ih);
    }
    /****************************************************************/
    /* encode_krb5_iakerb_finished */
    {
        krb5_iakerb_finished ih, *tmp;
        ktest_make_sample_iakerb_finished(&ih);
        leak_test(ih, encode_krb5_iakerb_finished,
                  decode_krb5_iakerb_finished,
                  krb5_free_iakerb_finished);
        ktest_empty_iakerb_finished(&ih);
    }
    /****************************************************************/
    /* encode_krb5_fast_response */
    {
        krb5_fast_response fr, *tmp;
        ktest_make_sample_fast_response(&fr);
        leak_test(fr, encode_krb5_fast_response, decode_krb5_fast_response,
                  krb5_free_fast_response);
        ktest_empty_fast_response(&fr);
    }
    /****************************************************************/
    /* encode_krb5_pa_fx_fast_reply */
    {
        krb5_enc_data enc, *tmp;
        ktest_make_sample_enc_data(&enc);
        leak_test(enc, encode_krb5_pa_fx_fast_reply,
                  decode_krb5_pa_fx_fast_reply, krb5_free_enc_data);
        ktest_destroy_enc_data(&enc);
    }
    krb5_free_context(test_context);
    return 0;
}
