#include "heim.h"
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <pthread.h>
#include <dispatch/dispatch.h>
#include <CommonCrypto/CommonDigest.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Heimdal/gkrb5_err.h>
#include <Heimdal/wind_err.h>
#include <Heimdal/krb_err.h>
#include <Heimdal/hx509_err.h>
const char *__KerberosInternal_krb5_defkeyname = "FILE:/etc/krb5.keytab";
int krb5_use_broken_arcfour_string2key = 0;
static int do_log = 0;
static CFTypeRef
CopyKeyFromFile(CFStringRef domain, CFStringRef key)
{
CFReadStreamRef s;
CFDictionaryRef d;
CFStringRef file;
CFErrorRef e;
CFURLRef url;
CFTypeRef val;
file = CFStringCreateWithFormat(NULL, 0, CFSTR("/Library/Preferences/%@.plist"), domain);
if (file == NULL)
return NULL;
url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, domain, kCFURLPOSIXPathStyle, false);
CFRelease(file);
if (url == NULL)
return NULL;
s = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
CFRelease(url);
if (s == NULL)
return NULL;
if (!CFReadStreamOpen(s)) {
CFRelease(s);
return NULL;
}
d = (CFDictionaryRef)CFPropertyListCreateWithStream (kCFAllocatorDefault, s, 0, kCFPropertyListImmutable, NULL, &e);
CFRelease(s);
if (d == NULL)
return NULL;
if (CFGetTypeID(d) != CFDictionaryGetTypeID()) {
CFRelease(d);
return NULL;
}
val = CFDictionaryGetValue(d, key);
if (val)
CFRetain(val);
CFRelease(d);
return val;
}
static void
init_log(void)
{
static dispatch_once_t once = 0;
dispatch_once(&once, ^{
CFBooleanRef b;
b = CopyKeyFromFile(CFSTR("com.apple.MITKerberosShim"),
CFSTR("EnableDebugging"));
if (b && CFGetTypeID(b) == CFBooleanGetTypeID())
do_log = CFBooleanGetValue(b);
if (b)
CFRelease(b);
});
}
void
mshim_log_entry(const char *msg, ...)
{
init_log();
if (do_log) {
va_list ap;
va_start(ap, msg);
vsyslog(LOG_DEBUG, msg, ap);
va_end(ap);
}
}
int
mshim_failure(const char *func, int error, const char *subsystem)
{
init_log();
if (do_log && error)
syslog(LOG_DEBUG, "%s failed with %d for '%s'", func, error, subsystem);
return error;
}
static void
destroy_ctx(void *ptr)
{
heim_krb5_free_context(ptr);
}
krb5_context
mshim_ctx(void)
{
static dispatch_once_t once;
static pthread_key_t key;
krb5_context ctx = NULL;
dispatch_once(&once, ^{
if (pthread_key_create(&key, destroy_ctx) != 0)
abort();
});
ctx = pthread_getspecific(key);
if (ctx == NULL) {
krb5_error_code ret;
ret = heim_krb5_init_context(&ctx);
if (ret)
ret = heim_krb5_init_context_flags(KRB5_CONTEXT_FLAG_NO_CONFIG, &ctx);
if (ret) {
syslog(LOG_ERR, "Failed to create kerberos context for thread (milcontext): %d", ret);
abort();
}
pthread_setspecific(key, ctx);
}
return ctx;
}
void *
mshim_malloc(size_t size)
{
void *ptr = malloc(size);
if (ptr == NULL) {
syslog(LOG_DEBUG, "mshim_malloc: can't allocate %d", (int)size);
abort();
}
memset(ptr, 0, size);
return ptr;
}
krb5_error_code
mshim_hdata2mdata(const krb5_data *h, mit_krb5_data *m)
{
m->magic = MIT_KV5M_DATA;
m->length = h->length;
m->data = mshim_malloc(h->length);
memcpy(m->data, h->data, h->length);
return 0;
}
krb5_error_code
mshim_mdata2hdata(const mit_krb5_data *m, krb5_data *h)
{
h->length = m->length;
h->data = mshim_malloc(m->length);
memcpy(h->data, m->data, m->length);
return 0;
}
void
mshim_hkeyblock2mkeyblock(const krb5_keyblock *h, mit_krb5_keyblock *m)
{
m->magic = MIT_KV5M_KEYBLOCK;
m->enctype = h->keytype;
m->length = h->keyvalue.length;
m->contents = mshim_malloc(h->keyvalue.length);
memcpy(m->contents, h->keyvalue.data, h->keyvalue.length);
}
void
mshim_mkeyblock2hkeyblock(const mit_krb5_keyblock *m, krb5_keyblock *h)
{
h->keytype = m->enctype;
h->keyvalue.length = m->length;
h->keyvalue.data = mshim_malloc(h->keyvalue.length);
memcpy(h->keyvalue.data, m->contents, h->keyvalue.length);
}
mit_krb5_error_code KRB5_CALLCONV
krb5_copy_keyblock_contents(mit_krb5_context context,
const mit_krb5_keyblock *from,
mit_krb5_keyblock *to)
{
LOG_ENTRY();
to->magic = MIT_KV5M_KEYBLOCK;
to->enctype = from->enctype;
to->length = from->length;
to->contents = mshim_malloc(from->length);
memcpy(to->contents, from->contents, from->length);
return 0;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_copy_keyblock(mit_krb5_context context,
const mit_krb5_keyblock *from,
mit_krb5_keyblock **to)
{
LOG_ENTRY();
*to = mshim_malloc(sizeof(**to));
return krb5_copy_keyblock_contents(context, from, *to);
}
void
mshim_mcred2hcred(krb5_context context, mit_krb5_creds *m, krb5_creds *h)
{
struct comb_principal *p;
memset(h, 0, sizeof(*h));
p = (struct comb_principal *)m->client;
if (p)
heim_krb5_copy_principal(context, p->heim, &h->client);
p = (struct comb_principal *)m->server;
if (p)
heim_krb5_copy_principal(context, p->heim, &h->server);
h->session.keytype = m->keyblock.enctype;
heim_krb5_data_copy(&h->session.keyvalue, m->keyblock.contents, m->keyblock.length);
heim_krb5_data_copy(&h->ticket, m->ticket.data, m->ticket.length);
h->times.authtime = m->times.authtime;
h->times.starttime = m->times.starttime;
h->times.endtime = m->times.endtime;
h->times.renew_till = m->times.renew_till;
h->flags.i = 0;
if (m->ticket_flags & MIT_TKT_FLG_FORWARDABLE)
h->flags.b.forwardable = 1;
if (m->ticket_flags & MIT_TKT_FLG_FORWARDED)
h->flags.b.forwarded = 1;
if (m->ticket_flags & MIT_TKT_FLG_PROXIABLE)
h->flags.b.proxiable = 1;
if (m->ticket_flags & MIT_TKT_FLG_PROXY)
h->flags.b.proxy = 1;
if (m->ticket_flags & MIT_TKT_FLG_MAY_POSTDATE)
h->flags.b.may_postdate = 1;
if (m->ticket_flags & MIT_TKT_FLG_POSTDATED)
h->flags.b.postdated = 1;
if (m->ticket_flags & MIT_TKT_FLG_INVALID)
h->flags.b.invalid = 1;
if (m->ticket_flags & MIT_TKT_FLG_RENEWABLE)
h->flags.b.renewable = 1;
if (m->ticket_flags & MIT_TKT_FLG_INITIAL)
h->flags.b.initial = 1;
if (m->ticket_flags & MIT_TKT_FLG_PRE_AUTH)
h->flags.b.pre_authent = 1;
if (m->ticket_flags & MIT_TKT_FLG_HW_AUTH)
h->flags.b.hw_authent = 1;
if (m->ticket_flags & MIT_TKT_FLG_TRANSIT_POLICY_CHECKED)
h->flags.b.transited_policy_checked = 1;
if (m->ticket_flags & MIT_TKT_FLG_OK_AS_DELEGATE)
h->flags.b.ok_as_delegate = 1;
if (m->ticket_flags & MIT_TKT_FLG_ANONYMOUS)
h->flags.b.anonymous = 1;
}
void
mshim_hcred2mcred(krb5_context context, krb5_creds *h, mit_krb5_creds *m)
{
memset(m, 0, sizeof(*m));
m->magic = MIT_KV5M_CREDS;
if (h->client)
m->client = mshim_hprinc2mprinc(context, h->client);
if (h->server)
m->server = mshim_hprinc2mprinc(context, h->server);
mshim_hkeyblock2mkeyblock(&h->session, &m->keyblock);
mshim_hdata2mdata(&h->ticket, &m->ticket);
m->times.authtime = h->times.authtime;
m->times.starttime = h->times.starttime;
m->times.endtime = h->times.endtime;
m->times.renew_till = h->times.renew_till;
m->ticket_flags = 0;
if (h->flags.b.forwardable)
m->ticket_flags |= MIT_TKT_FLG_FORWARDABLE;
if (h->flags.b.forwarded)
m->ticket_flags |= MIT_TKT_FLG_FORWARDED;
if (h->flags.b.proxiable)
m->ticket_flags |= MIT_TKT_FLG_PROXIABLE;
if (h->flags.b.proxy)
m->ticket_flags |= MIT_TKT_FLG_PROXY;
if (h->flags.b.may_postdate)
m->ticket_flags |= MIT_TKT_FLG_MAY_POSTDATE;
if (h->flags.b.postdated)
m->ticket_flags |= MIT_TKT_FLG_POSTDATED;
if (h->flags.b.invalid)
m->ticket_flags |= MIT_TKT_FLG_INVALID;
if (h->flags.b.renewable)
m->ticket_flags |= MIT_TKT_FLG_RENEWABLE;
if (h->flags.b.initial)
m->ticket_flags |= MIT_TKT_FLG_INITIAL;
if (h->flags.b.pre_authent)
m->ticket_flags |= MIT_TKT_FLG_PRE_AUTH;
if (h->flags.b.hw_authent)
m->ticket_flags |= MIT_TKT_FLG_HW_AUTH;
if (h->flags.b.transited_policy_checked)
m->ticket_flags |= MIT_TKT_FLG_TRANSIT_POLICY_CHECKED;
if (h->flags.b.ok_as_delegate)
m->ticket_flags |= MIT_TKT_FLG_OK_AS_DELEGATE;
if (h->flags.b.anonymous)
m->ticket_flags |= MIT_TKT_FLG_ANONYMOUS;
}
void
mshim_haprepencpart2maprepencpart(const krb5_ap_rep_enc_part *h,
mit_krb5_ap_rep_enc_part *m)
{
m->magic = MIT_KV5M_AP_REP_ENC_PART;
m->ctime = h->ctime;
m->cusec = h->cusec;
if (h->subkey) {
m->subkey = mshim_malloc(sizeof(*m->subkey));
mshim_hkeyblock2mkeyblock(h->subkey, m->subkey);
} else
m->subkey = NULL;
if (h->seq_number) {
m->seq_number = *h->seq_number;
} else
m->seq_number = 0;
}
void
mshim_hreplay2mreplay(const krb5_replay_data *h, mit_krb5_replay_data *m)
{
m->timestamp = h->timestamp;
m->usec = h->usec;
m->seq = h->seq;
}
void KRB5_CALLCONV
krb5_free_ap_rep_enc_part(mit_krb5_context context,
mit_krb5_ap_rep_enc_part *enc_part)
{
LOG_ENTRY();
if (enc_part->subkey)
krb5_free_keyblock(context, enc_part->subkey);
free(enc_part);
}
void KRB5_CALLCONV
krb5_free_error(mit_krb5_context context, mit_krb5_error *error)
{
LOG_ENTRY();
krb5_free_principal(context, error->client);
krb5_free_principal(context, error->server);
krb5_free_data_contents(context, &error->text);
krb5_free_data_contents(context, &error->e_data);
free(error);
}
void
mshim_herror2merror(krb5_context context, const krb5_error *h, mit_krb5_error *m)
{
LOG_ENTRY();
memset(m, 0, sizeof(*m));
m->magic = MIT_KV5M_ERROR;
if (h->ctime)
m->ctime = *h->ctime;
if (h->cusec)
m->cusec = *h->cusec;
m->stime = h->stime;
m->susec = h->susec;
#if 0
m->client = mshim_hprinc2mprinc(context, h->client);
m->server = mshim_hprinc2mprinc(context, h->server);
#endif
m->error = h->error_code;
if (h->e_text) {
m->text.magic = MIT_KV5M_DATA;
m->text.data = strdup(*(h->e_text));
m->text.length = strlen(*(h->e_text));
}
if (h->e_data)
mshim_hdata2mdata(h->e_data, &m->e_data);
#if 0
krb5_principal client;
krb5_principal server;
#endif
}
unsigned long
mshim_remap_flags(unsigned long in, const struct mshim_map_flags *table)
{
unsigned long out = 0;
while(table->in) {
if (table->in & in)
out |= table->out;
table++;
}
return out;
}
mit_krb5_error_code
krb5_init_context(mit_krb5_context *context)
{
LOG_ENTRY();
return heim_krb5_init_context((krb5_context *)context);
}
mit_krb5_error_code
krb5_init_secure_context(mit_krb5_context *context)
{
LOG_ENTRY();
return heim_krb5_init_context((krb5_context *)context);
}
void
krb5_free_context(mit_krb5_context context)
{
LOG_ENTRY();
heim_krb5_free_context(HC(context));
}
const char *
error_message(errcode_t code)
{
static dispatch_once_t once = 0;
static struct et_list *et_list = NULL;
static char buffer[1024];
const char *str;
dispatch_once(&once, ^{
initialize_asn1_error_table_r(&et_list);
initialize_gk5_error_table_r(&et_list);
initialize_wind_error_table_r(&et_list);
initialize_krb5_error_table_r(&et_list);
initialize_krb_error_table_r(&et_list);
initialize_k524_error_table_r(&et_list);
initialize_heim_error_table_r(&et_list);
initialize_hx_error_table_r(&et_list);
});
str = heim_com_right_r(et_list, code, buffer, sizeof(buffer));
if (str == NULL) {
snprintf(buffer, sizeof(buffer), "Unknown error %d", (int)code);
str = buffer;
}
return str;
}
void KRB5_CALLCONV
krb5_free_keyblock(mit_krb5_context context, mit_krb5_keyblock *keyblock)
{
LOG_ENTRY();
krb5_free_keyblock_contents(context, keyblock);
free(keyblock);
}
void KRB5_CALLCONV
krb5_free_keyblock_contents(mit_krb5_context context, mit_krb5_keyblock *keyblock)
{
LOG_ENTRY();
memset(keyblock->contents, 0, keyblock->length);
free(keyblock->contents);
memset(keyblock, 0, sizeof(*keyblock));
}
void KRB5_CALLCONV
krb5_free_data(mit_krb5_context context, mit_krb5_data *data)
{
LOG_ENTRY();
krb5_free_data_contents(context, data);
free(data);
}
void KRB5_CALLCONV
krb5_free_data_contents(mit_krb5_context context, mit_krb5_data *data)
{
LOG_ENTRY();
free(data->data);
memset(data, 0, sizeof(*data));
}
mit_krb5_error_code KRB5_CALLCONV
krb5_copy_data(mit_krb5_context context,
const mit_krb5_data *from,
mit_krb5_data **to)
{
*to = mshim_malloc(sizeof(**to));
(*to)->magic = MIT_KV5M_DATA;
(*to)->length = from->length;
(*to)->data = mshim_malloc(from->length);
memcpy((*to)->data, from->data, from->length);
return 0;
}
void KRB5_CALLCONV
krb5_free_cred_contents(mit_krb5_context context, mit_krb5_creds *cred)
{
LOG_ENTRY();
if (cred == NULL)
return;
krb5_free_principal(context, cred->client);
krb5_free_principal(context, cred->server);
krb5_free_keyblock_contents(context, &cred->keyblock);
krb5_free_data_contents(context, &cred->ticket);
krb5_free_data_contents(context, &cred->second_ticket);
memset(cred, 0, sizeof(*cred));
}
void KRB5_CALLCONV
krb5_free_creds(mit_krb5_context context, mit_krb5_creds *cred)
{
LOG_ENTRY();
krb5_free_cred_contents(context, cred);
free(cred);
}
void KRB5_CALLCONV
krb5_free_enc_tkt_part(mit_krb5_context context, krb5_enc_tkt_part *enc_part2)
{
if (enc_part2->session)
krb5_free_keyblock(context, enc_part2->session);
if (enc_part2->client)
krb5_free_principal(context, enc_part2->client);
memset(enc_part2, 0, sizeof(*enc_part2));
free(enc_part2);
}
void KRB5_CALLCONV
krb5_free_ticket(mit_krb5_context context, mit_krb5_ticket *ticket)
{
LOG_ENTRY();
if (ticket == NULL)
return;
if (ticket->server)
krb5_free_principal(context, ticket->server);
if (ticket->enc_part.ciphertext.data)
krb5_free_data_contents(context, &ticket->enc_part.ciphertext);
if (ticket->enc_part2)
krb5_free_enc_tkt_part(context, ticket->enc_part2);
memset(ticket, 0, sizeof(*ticket));
free(ticket);
}
void KRB5_CALLCONV
krb5_free_authdata(mit_krb5_context context,
mit_krb5_authdata **val)
{
mit_krb5_authdata **ptr;
for (ptr = val; ptr && *ptr; ptr++) {
free((*ptr)->contents);
free(*ptr);
}
free(val);
}
mit_krb5_error_code KRB5_CALLCONV
krb5_us_timeofday(mit_krb5_context context,
mit_krb5_timestamp *outsec,
mit_krb5_int32 *outusec)
{
krb5_timestamp sec;
int32_t usec;
LOG_ENTRY();
heim_krb5_us_timeofday((krb5_context)context, &sec, &usec);
*outsec = sec;
*outusec = usec;
return 0;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_timeofday(mit_krb5_context context,
mit_krb5_timestamp *out)
{
krb5_timestamp ts;
LOG_ENTRY();
heim_krb5_timeofday((krb5_context)context, &ts);
*out = ts;
return 0;
}
char *
krb5_pkinit_cert_hash_str(const mit_krb5_data *cert)
{
CC_SHA1_CTX ctx;
char *outstr, *cpOut;
unsigned char digest[CC_SHA1_DIGEST_LENGTH];
unsigned i;
LOG_ENTRY();
CC_SHA1_Init(&ctx);
CC_SHA1_Update(&ctx, cert->data, cert->length);
CC_SHA1_Final(digest, &ctx);
cpOut = outstr = (char *)malloc((2 * CC_SHA1_DIGEST_LENGTH) + 1);
if(outstr == NULL)
return NULL;
for(i = 0; i < CC_SHA1_DIGEST_LENGTH; i++, cpOut += 2)
sprintf(cpOut, "%02X", (unsigned)digest[i]);
*cpOut = '\0';
return outstr;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_enctype_to_string(mit_krb5_enctype enctype,
char *str,
size_t size)
{
snprintf(str, size, "enctype-%d", enctype);
return 0;
}
void KRB5_CALLCONV
krb5_free_addresses(mit_krb5_context context, mit_krb5_address **addrs)
{
unsigned int i;
for (i = 0; addrs && addrs[i] ; i++) {
free(addrs[i]->contents);
free(addrs[i]);
}
memset(addrs, 0, sizeof(*addrs));
free(addrs);
}
mit_krb5_error_code KRB5_CALLCONV
krb5_get_server_rcache(mit_krb5_context context,
const mit_krb5_data *foo,
mit_krb5_rcache *rcache)
{
*rcache = NULL;
return 0;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_os_localaddr(mit_krb5_context context, mit_krb5_address ***addresses)
{
mit_krb5_address **a;
krb5_addresses addrs;
krb5_error_code ret;
unsigned i;
*addresses = NULL;
addrs.len = 0;
addrs.val = NULL;
ret = heim_krb5_get_all_client_addrs(HC(context), &addrs);
if (ret)
return ret;
a = calloc(addrs.len + 1, sizeof(a[0]));
for (i = 0; i < addrs.len; i++) {
a[i] = calloc(1, sizeof(mit_krb5_address));
a[i]->addrtype = addrs.val[i].addr_type;
a[i]->length = addrs.val[i].address.length;
a[i]->contents = mshim_malloc(addrs.val[i].address.length);
memcpy(a[i]->contents, addrs.val[i].address.data, addrs.val[i].address.length);
}
a[i] = NULL;
*addresses = a;
return 0;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_string_to_deltat(char *str, mit_krb5_deltat *t)
{
krb5_error_code ret;
krb5_deltat ht;
ret = heim_krb5_string_to_deltat(str, &ht);
if (ret)
return ret;
*t = ht;
return 0;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_prompter_posix(mit_krb5_context context,
void *data,
const char *name,
const char *banner,
int num_prompts,
mit_krb5_prompt prompts[])
{
return EINVAL;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_get_validated_creds(mit_krb5_context context,
mit_krb5_creds *creds,
mit_krb5_principal client,
mit_krb5_ccache ccache,
char *in_tkt_service)
{
struct comb_principal *p = (struct comb_principal *)client;
krb5_error_code ret;
krb5_creds hcreds;
mshim_mcred2hcred(HC(context), creds, &hcreds);
ret = heim_krb5_get_validated_creds(HC(context), &hcreds, p->heim, (krb5_ccache)ccache, in_tkt_service);
heim_krb5_free_cred_contents(HC(context), &hcreds);
return ret;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_get_renewed_creds (mit_krb5_context context,
mit_krb5_creds *creds,
mit_krb5_principal client,
mit_krb5_ccache ccache,
char *in_tkt_service)
{
struct comb_principal *p = (struct comb_principal *)client;
krb5_error_code ret;
krb5_creds hcreds;
mshim_mcred2hcred(HC(context), creds, &hcreds);
ret = heim_krb5_get_renewed_creds(HC(context), &hcreds, p->heim, (krb5_ccache)ccache, in_tkt_service);
heim_krb5_free_cred_contents(HC(context), &hcreds);
return ret;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_set_real_time(mit_krb5_context context,
mit_krb5_timestamp ts,
mit_krb5_int32 usec)
{
LOG_ENTRY();
return heim_krb5_set_real_time(HC(context), ts, usec);
}
#include "Kerberos/kim_library.h"
kim_error
kim_library_set_ui_environment(kim_ui_environment in_ui_environment)
{
LOG_ENTRY();
return 0;
}
mit_krb5_boolean KRB5_CALLCONV
krb5_kuserok(mit_krb5_context context,
mit_krb5_principal client,
const char *luser)
{
struct comb_principal *p = (struct comb_principal *)client;
LOG_ENTRY();
return heim_krb5_kuserok(HC(context), p->heim, luser);
}
void KRB5_CALLCONV
krb5_appdefault_string(mit_krb5_context context,
const char *appname,
const mit_krb5_data *realm,
const char *option,
const char *default_value,
char ** ret_value)
{
char *hrealm;
*ret_value = (char *)default_value;
if (realm->length > 5000)
return;
hrealm = mshim_malloc(realm->length + 1);
memcpy(hrealm, realm->data, realm->length);
hrealm[realm->length] = '\0';
(void)heim_krb5_appdefault_string(HC(context),
appname,
hrealm,
option,
default_value,
ret_value);
free(hrealm);
}
void KRB5_CALLCONV
krb5_appdefault_boolean(mit_krb5_context context,
const char *appname,
const mit_krb5_data *realm,
const char *option,
int default_value,
int *ret_value)
{
char *hrealm;
*ret_value = default_value;
if (realm->length > 5000)
return;
hrealm = mshim_malloc(realm->length + 1);
memcpy(hrealm, realm->data, realm->length);
hrealm[realm->length] = '\0';
(void)heim_krb5_appdefault_boolean(HC(context),
appname,
hrealm,
option,
default_value,
ret_value);
free(hrealm);
}
#define ddebuglevel __KerberosDebugLogLevel
#define dprintf __KerberosDebugPrint
#define dvprintf __KerberosDebugVAPrint
#define dprintmem __KerberosDebugPrintMemory
#define dprintsession __KerberosDebugPrintSession
int ddebuglevel (void);
void dprintf (const char *in_format, ...) __attribute__ ((format (printf, 1, 2)));
void dvprintf (const char *in_format, va_list in_args);
void dprintmem (const void *in_data, size_t in_length);
void dprintsession (void);
int ddebuglevel (void)
{
return 0;
}
void dprintf (const char *in_format, ...)
{
}
void dvprintf (const char *in_format, va_list in_args)
{
}
void dprintmem (const void *in_data, size_t in_length)
{
}
void dprintsession (void)
{
}
const char * KRB5_CALLCONV
krb5_get_error_message(mit_krb5_context context, mit_krb5_error_code code)
{
LOG_ENTRY();
return heim_krb5_get_error_message(HC(context), code);
}