#include <string.h>
#include "k5-int.h"
#include "kdb_kt.h"
static int
is_xrealm_tgt(krb5_context, krb5_const_principal);
krb5_error_code krb5_ktkdb_close (krb5_context, krb5_keytab);
krb5_error_code krb5_ktkdb_get_entry (krb5_context, krb5_keytab, krb5_const_principal,
krb5_kvno, krb5_enctype, krb5_keytab_entry *);
static krb5_error_code
krb5_ktkdb_get_name(krb5_context context, krb5_keytab keytab,
char *name, unsigned int namelen)
{
if (strlcpy(name, "KDB:", namelen) >= namelen)
return KRB5_KT_NAME_TOOLONG;
return 0;
}
krb5_kt_ops krb5_kt_kdb_ops = {
0,
"KDB",
krb5_ktkdb_resolve,
krb5_ktkdb_get_name,
krb5_ktkdb_close,
krb5_ktkdb_get_entry,
NULL,
NULL,
NULL,
NULL,
NULL,
};
typedef struct krb5_ktkdb_data {
char * name;
} krb5_ktkdb_data;
krb5_error_code
krb5_db_register_keytab(krb5_context context)
{
return krb5_kt_register(context, &krb5_kt_kdb_ops);
}
krb5_error_code
krb5_ktkdb_resolve(krb5_context context, const char *name, krb5_keytab *id)
{
if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
return(ENOMEM);
(*id)->ops = &krb5_kt_kdb_ops;
(*id)->magic = KV5M_KEYTAB;
return(0);
}
krb5_error_code
krb5_ktkdb_close(krb5_context context, krb5_keytab kt)
{
kt->ops = NULL;
free(kt);
return 0;
}
static krb5_context ktkdb_ctx = NULL;
krb5_error_code
krb5_ktkdb_set_context(krb5_context ctx)
{
ktkdb_ctx = ctx;
return 0;
}
krb5_error_code
krb5_ktkdb_get_entry(krb5_context in_context, krb5_keytab id,
krb5_const_principal principal, krb5_kvno kvno,
krb5_enctype enctype, krb5_keytab_entry *entry)
{
krb5_context context;
krb5_error_code kerror = 0;
krb5_key_data * key_data;
krb5_db_entry * db_entry;
int xrealm_tgt;
krb5_boolean similar;
if (ktkdb_ctx)
context = ktkdb_ctx;
else
context = in_context;
xrealm_tgt = is_xrealm_tgt(context, principal);
if ((kerror = krb5_db_inited(context)))
return(kerror);
kerror = krb5_db_get_principal(context, principal, 0, &db_entry);
if (kerror == KRB5_KDB_NOENTRY)
return(KRB5_KT_NOTFOUND);
if (kerror)
return(kerror);
if (db_entry->attributes & KRB5_KDB_DISALLOW_SVR
|| db_entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
kerror = KRB5_KT_NOTFOUND;
goto error;
}
kerror = krb5_dbe_find_enctype(context, db_entry,
xrealm_tgt?enctype:-1,
-1, kvno, &key_data);
if (kerror == KRB5_KDB_NO_MATCHING_KEY)
kerror = KRB5_KT_KVNONOTFOUND;
if (kerror)
goto error;
kerror = krb5_dbe_decrypt_key_data(context, NULL, key_data,
&entry->key, NULL);
if (kerror)
goto error;
if (enctype > 0) {
kerror = krb5_c_enctype_compare(context, enctype,
entry->key.enctype, &similar);
if (kerror)
goto error;
if (!similar) {
kerror = KRB5_KDB_NO_PERMITTED_KEY;
goto error;
}
}
entry->key.enctype = enctype;
kerror = krb5_copy_principal(context, principal, &entry->principal);
if (kerror)
goto error;
error:
krb5_db_free_principal(context, db_entry);
return(kerror);
}
static int
is_xrealm_tgt(krb5_context context, krb5_const_principal princ)
{
krb5_data *dat;
if (krb5_princ_size(context, princ) != 2)
return 0;
dat = krb5_princ_component(context, princ, 0);
if (strncmp("krbtgt", dat->data, dat->length) != 0)
return 0;
dat = krb5_princ_component(context, princ, 1);
if (dat->length != princ->realm.length)
return 1;
if (strncmp(dat->data, princ->realm.data, dat->length) == 0)
return 0;
return 1;
}