#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 (namelen < sizeof("KDB:"))
return KRB5_KT_NAME_TOOLONG;
strcpy(name, "KDB:");
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,
NULL,
};
typedef struct krb5_ktkdb_data {
char * name;
} krb5_ktkdb_data;
krb5_error_code
krb5_ktkdb_resolve(context, name, id)
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(context, kt)
krb5_context context;
krb5_keytab kt;
{
kt->ops = NULL;
krb5_xfree(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(in_context, id, principal, kvno, enctype, 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_keyblock * master_key;
krb5_error_code kerror = 0;
krb5_key_data * key_data;
krb5_db_entry db_entry;
krb5_boolean more = 0;
int n = 0;
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, &
db_entry, &n, &more);
if (kerror) {
return(kerror);
}
if (n != 1) {
return KRB5_KT_NOTFOUND;
}
if (db_entry.attributes & KRB5_KDB_DISALLOW_SVR
|| db_entry.attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
kerror = KRB5_KT_NOTFOUND;
goto error;
}
kerror = krb5_db_get_mkey(context, &master_key);
if (kerror)
goto error;
kerror = krb5_dbe_find_enctype(context, &db_entry,
xrealm_tgt?enctype:-1,
-1, kvno, &key_data);
if (kerror)
goto error;
kerror = krb5_dbekd_decrypt_key_data(context, master_key,
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, 1);
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;
}