static inline int krb5_free_keytab_entry_contents(krb5_context ctx, krb5_keytab_entry * ent) { krb5_free_principal(ctx, ent->principal); krb5_free_keyblock_contents(ctx, kte_keyblock(ent)); return 0; }
static int rxkad_keytab_decrypt(int kvno, int et, void *in, size_t inlen, void *out, size_t *outlen) { krb5_error_code code; /* use heimdal api if available, since heimdal's interface to krb5_c_decrypt is non-standard and annoying to use */ #ifdef HAVE_KRB5_CRYPTO_INIT krb5_crypto kcrypto; #else krb5_enc_data ind; #endif krb5_data outd; int i, foundkey; MUTEX_ENTER(&krb5_lock); reload_keys(); if (have_keytab_keys == 0) { MUTEX_EXIT(&krb5_lock); return RXKADUNKNOWNKEY; } foundkey = 0; code = -1; for (i = 0; i < nkeys; i++) { /* foundkey determines what error code we return for failure */ if (ktent[i].vno == kvno) foundkey = 1; /* but check against all keys if the enctype matches, for robustness */ if (kb_enctype(kte_keyblock(ktent[i])) == et) { #ifdef HAVE_KRB5_CRYPTO_INIT code = krb5_crypto_init(k5ctx, kte_keyblock(ktent[i]), et, &kcrypto); if (code == 0) { code = krb5_decrypt(k5ctx, kcrypto, KRB5_KEYUSAGE_KDC_REP_TICKET, in, inlen, &outd); krb5_crypto_destroy(k5ctx, kcrypto); } if (code == 0) { if (outd.length > *outlen) { /* This should never happen, but don't assert since we may * be dealing with untrusted user data. */ code = EINVAL; krb5_data_free(&outd); outd.data = NULL; } } if (code == 0) { /* heimdal allocates new memory for the decrypted data; put * the data back into the requested 'out' buffer */ *outlen = outd.length; memcpy(out, outd.data, outd.length); krb5_data_free(&outd); break; } #else outd.length = *outlen; outd.data = out; ind.ciphertext.length = inlen; ind.ciphertext.data = in; ind.enctype = et; ind.kvno = kvno; code = krb5_c_decrypt(k5ctx, kte_keyblock(ktent[i]), KRB5_KEYUSAGE_KDC_REP_TICKET, NULL, &ind, &outd); if (code == 0) { *outlen = outd.length; break; } #endif } } MUTEX_EXIT(&krb5_lock); if (code == 0) return 0; if (foundkey != 0) return RXKADBADTICKET; return RXKADUNKNOWNKEY; }