|
Packit Service |
99d1c0 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit Service |
99d1c0 |
/* lib/kdb/keytab.c */
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Copyright 1995 by the Massachusetts Institute of Technology.
|
|
Packit Service |
99d1c0 |
* All Rights Reserved.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* Export of this software from the United States of America may
|
|
Packit Service |
99d1c0 |
* require a specific license from the United States Government.
|
|
Packit Service |
99d1c0 |
* It is the responsibility of any person or organization contemplating
|
|
Packit Service |
99d1c0 |
* export to obtain such a license before exporting.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
|
Packit Service |
99d1c0 |
* distribute this software and its documentation for any purpose and
|
|
Packit Service |
99d1c0 |
* without fee is hereby granted, provided that the above copyright
|
|
Packit Service |
99d1c0 |
* notice appear in all copies and that both that copyright notice and
|
|
Packit Service |
99d1c0 |
* this permission notice appear in supporting documentation, and that
|
|
Packit Service |
99d1c0 |
* the name of M.I.T. not be used in advertising or publicity pertaining
|
|
Packit Service |
99d1c0 |
* to distribution of the software without specific, written prior
|
|
Packit Service |
99d1c0 |
* permission. Furthermore if you modify this software you must label
|
|
Packit Service |
99d1c0 |
* your software as modified software and not distribute it in such a
|
|
Packit Service |
99d1c0 |
* fashion that it might be confused with the original M.I.T. software.
|
|
Packit Service |
99d1c0 |
* M.I.T. makes no representations about the suitability of
|
|
Packit Service |
99d1c0 |
* this software for any purpose. It is provided "as is" without express
|
|
Packit Service |
99d1c0 |
* or implied warranty.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#include <string.h>
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#include "k5-int.h"
|
|
Packit Service |
99d1c0 |
#include "kdb_kt.h"
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static int
|
|
Packit Service |
99d1c0 |
is_xrealm_tgt(krb5_context, krb5_const_principal);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code krb5_ktkdb_close (krb5_context, krb5_keytab);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code krb5_ktkdb_get_entry (krb5_context, krb5_keytab, krb5_const_principal,
|
|
Packit Service |
99d1c0 |
krb5_kvno, krb5_enctype, krb5_keytab_entry *);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_ktkdb_get_name(krb5_context context, krb5_keytab keytab,
|
|
Packit Service |
99d1c0 |
char *name, unsigned int namelen)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if (strlcpy(name, "KDB:", namelen) >= namelen)
|
|
Packit Service |
99d1c0 |
return KRB5_KT_NAME_TOOLONG;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_kt_ops krb5_kt_kdb_ops = {
|
|
Packit Service |
99d1c0 |
0,
|
|
Packit Service |
99d1c0 |
"KDB", /* Prefix -- this string should not appear anywhere else! */
|
|
Packit Service |
99d1c0 |
krb5_ktkdb_resolve, /* resolve */
|
|
Packit Service |
99d1c0 |
krb5_ktkdb_get_name, /* get_name */
|
|
Packit Service |
99d1c0 |
krb5_ktkdb_close, /* close */
|
|
Packit Service |
99d1c0 |
krb5_ktkdb_get_entry, /* get */
|
|
Packit Service |
99d1c0 |
NULL, /* start_seq_get */
|
|
Packit Service |
99d1c0 |
NULL, /* get_next */
|
|
Packit Service |
99d1c0 |
NULL, /* end_get */
|
|
Packit Service |
99d1c0 |
NULL, /* add (extended) */
|
|
Packit Service |
99d1c0 |
NULL, /* remove (extended) */
|
|
Packit Service |
99d1c0 |
};
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
typedef struct krb5_ktkdb_data {
|
|
Packit Service |
99d1c0 |
char * name;
|
|
Packit Service |
99d1c0 |
} krb5_ktkdb_data;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db_register_keytab(krb5_context context)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
return krb5_kt_register(context, &krb5_kt_kdb_ops);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_ktkdb_resolve(context, name, id)
|
|
Packit Service |
99d1c0 |
krb5_context context;
|
|
Packit Service |
99d1c0 |
const char * name;
|
|
Packit Service |
99d1c0 |
krb5_keytab * id;
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
|
|
Packit Service |
99d1c0 |
return(ENOMEM);
|
|
Packit Service |
99d1c0 |
(*id)->ops = &krb5_kt_kdb_ops;
|
|
Packit Service |
99d1c0 |
(*id)->magic = KV5M_KEYTAB;
|
|
Packit Service |
99d1c0 |
return(0);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_ktkdb_close(context, kt)
|
|
Packit Service |
99d1c0 |
krb5_context context;
|
|
Packit Service |
99d1c0 |
krb5_keytab kt;
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* This routine is responsible for freeing all memory allocated
|
|
Packit Service |
99d1c0 |
* for this keytab. There are no system resources that need
|
|
Packit Service |
99d1c0 |
* to be freed nor are there any open files.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* This routine should undo anything done by krb5_ktkdb_resolve().
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
kt->ops = NULL;
|
|
Packit Service |
99d1c0 |
free(kt);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static krb5_context ktkdb_ctx = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Set a different context for use with ktkdb_get_entry(). This is
|
|
Packit Service |
99d1c0 |
* primarily useful for kadmind, where the gssapi library context,
|
|
Packit Service |
99d1c0 |
* which will be used for the keytab, will necessarily have a
|
|
Packit Service |
99d1c0 |
* different context than that used by the kadm5 library to access the
|
|
Packit Service |
99d1c0 |
* database for its own purposes.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_ktkdb_set_context(krb5_context ctx)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
ktkdb_ctx = ctx;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry)
|
|
Packit Service |
99d1c0 |
krb5_context in_context;
|
|
Packit Service |
99d1c0 |
krb5_keytab id;
|
|
Packit Service |
99d1c0 |
krb5_const_principal principal;
|
|
Packit Service |
99d1c0 |
krb5_kvno kvno;
|
|
Packit Service |
99d1c0 |
krb5_enctype enctype;
|
|
Packit Service |
99d1c0 |
krb5_keytab_entry * entry;
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_context context;
|
|
Packit Service |
99d1c0 |
krb5_error_code kerror = 0;
|
|
Packit Service |
99d1c0 |
krb5_key_data * key_data;
|
|
Packit Service |
99d1c0 |
krb5_db_entry * db_entry;
|
|
Packit Service |
99d1c0 |
int xrealm_tgt;
|
|
Packit Service |
99d1c0 |
krb5_boolean similar;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (ktkdb_ctx)
|
|
Packit Service |
99d1c0 |
context = ktkdb_ctx;
|
|
Packit Service |
99d1c0 |
else
|
|
Packit Service |
99d1c0 |
context = in_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
xrealm_tgt = is_xrealm_tgt(context, principal);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Check whether database is inited. Open is commented */
|
|
Packit Service |
99d1c0 |
if ((kerror = krb5_db_inited(context)))
|
|
Packit Service |
99d1c0 |
return(kerror);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* get_principal */
|
|
Packit Service |
99d1c0 |
kerror = krb5_db_get_principal(context, principal, 0, &db_entry);
|
|
Packit Service |
99d1c0 |
if (kerror == KRB5_KDB_NOENTRY)
|
|
Packit Service |
99d1c0 |
return(KRB5_KT_NOTFOUND);
|
|
Packit Service |
99d1c0 |
if (kerror)
|
|
Packit Service |
99d1c0 |
return(kerror);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (db_entry->attributes & KRB5_KDB_DISALLOW_SVR
|
|
Packit Service |
99d1c0 |
|| db_entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
|
|
Packit Service |
99d1c0 |
kerror = KRB5_KT_NOTFOUND;
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* match key */
|
|
Packit Service |
99d1c0 |
/* For cross realm tgts, we match whatever enctype is provided;
|
|
Packit Service |
99d1c0 |
* for other principals, we only match the first enctype that is
|
|
Packit Service |
99d1c0 |
* found. Since the TGS and AS code do the same thing, then we
|
|
Packit Service |
99d1c0 |
* will only successfully decrypt tickets we have issued.*/
|
|
Packit Service |
99d1c0 |
kerror = krb5_dbe_find_enctype(context, db_entry,
|
|
Packit Service |
99d1c0 |
xrealm_tgt?enctype:-1,
|
|
Packit Service |
99d1c0 |
-1, kvno, &key_data);
|
|
Packit Service |
99d1c0 |
if (kerror == KRB5_KDB_NO_MATCHING_KEY)
|
|
Packit Service |
99d1c0 |
kerror = KRB5_KT_KVNONOTFOUND;
|
|
Packit Service |
99d1c0 |
if (kerror)
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
kerror = krb5_dbe_decrypt_key_data(context, NULL, key_data,
|
|
Packit Service |
99d1c0 |
&entry->key, NULL);
|
|
Packit Service |
99d1c0 |
if (kerror)
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (enctype > 0) {
|
|
Packit Service |
99d1c0 |
kerror = krb5_c_enctype_compare(context, enctype,
|
|
Packit Service |
99d1c0 |
entry->key.enctype, &similar);
|
|
Packit Service |
99d1c0 |
if (kerror)
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (!similar) {
|
|
Packit Service |
99d1c0 |
kerror = KRB5_KDB_NO_PERMITTED_KEY;
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Coerce the enctype of the output keyblock in case we got an
|
|
Packit Service |
99d1c0 |
* inexact match on the enctype.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
entry->key.enctype = enctype;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
kerror = krb5_copy_principal(context, principal, &entry->principal);
|
|
Packit Service |
99d1c0 |
if (kerror)
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Close database */
|
|
Packit Service |
99d1c0 |
error:
|
|
Packit Service |
99d1c0 |
krb5_db_free_principal(context, db_entry);
|
|
Packit Service |
99d1c0 |
/* krb5_db_close_database(context); */
|
|
Packit Service |
99d1c0 |
return(kerror);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* is_xrealm_tgt: Returns true if the principal is a cross-realm TGT
|
|
Packit Service |
99d1c0 |
* principal-- a principal with first component krbtgt and second
|
|
Packit Service |
99d1c0 |
* component not equal to realm.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static int
|
|
Packit Service |
99d1c0 |
is_xrealm_tgt(krb5_context context, krb5_const_principal princ)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_data *dat;
|
|
Packit Service |
99d1c0 |
if (krb5_princ_size(context, princ) != 2)
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
dat = krb5_princ_component(context, princ, 0);
|
|
Packit Service |
99d1c0 |
if (strncmp("krbtgt", dat->data, dat->length) != 0)
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
dat = krb5_princ_component(context, princ, 1);
|
|
Packit Service |
99d1c0 |
if (dat->length != princ->realm.length)
|
|
Packit Service |
99d1c0 |
return 1;
|
|
Packit Service |
99d1c0 |
if (strncmp(dat->data, princ->realm.data, dat->length) == 0)
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
return 1;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
}
|