
Split Windows PAC signing and verification logic, as the signing has to be when the ticket is ready. Create sign and verify the PAC KDC signature if the plugin did not, allowing for S4U2Proxy to work, instead of KRB5SignedPath. Use the header key to verify PAC server signature, as the same key used to encrypt/decrypt the ticket should be used for PAC server signature, like U2U tickets are signed witht the tgt session-key and not with the longterm key, and so krbtgt should be no different and the header key should be used. Lookup the delegated client in DB instead of passing the delegator DB entry. Add PAC ticket-signatures and related functions. Note: due to the change from KRB5SignedPath to PAC, S4U2Proxy requests against new KDC will not work if the evidence ticket was acquired from an old KDC, and vide versa. Closes: #767
142 lines
3.0 KiB
C
142 lines
3.0 KiB
C
#include <string.h>
|
|
#include <krb5_locl.h>
|
|
#include <hdb.h>
|
|
#include <hx509.h>
|
|
#include <kdc.h>
|
|
#include <windc_plugin.h>
|
|
|
|
static krb5_error_code
|
|
windc_init(krb5_context context, void **ctx)
|
|
{
|
|
krb5_warnx(context, "windc init");
|
|
*ctx = NULL;
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
windc_fini(void *ctx)
|
|
{
|
|
}
|
|
|
|
static krb5_error_code
|
|
pac_generate(void *ctx, krb5_context context,
|
|
struct hdb_entry_ex *client, krb5_pac *pac)
|
|
{
|
|
krb5_error_code ret;
|
|
krb5_data data;
|
|
|
|
krb5_warnx(context, "pac generate");
|
|
|
|
data.data = "\x00\x01";
|
|
data.length = 2;
|
|
|
|
ret = krb5_pac_init(context, pac);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = krb5_pac_add_buffer(context, *pac, 1, &data);
|
|
if (ret)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static krb5_error_code
|
|
pac_verify(void *ctx, krb5_context context,
|
|
const krb5_principal new_ticket_client,
|
|
const krb5_principal delegation_proxy,
|
|
struct hdb_entry_ex * client,
|
|
struct hdb_entry_ex * server,
|
|
struct hdb_entry_ex * krbtgt,
|
|
krb5_pac *pac)
|
|
{
|
|
krb5_error_code ret;
|
|
krb5_data data;
|
|
krb5_cksumtype cstype;
|
|
uint16_t rodc_id;
|
|
krb5_enctype etype;
|
|
Key *key;
|
|
|
|
krb5_warnx(context, "pac_verify");
|
|
|
|
ret = krb5_pac_get_buffer(context, *pac, 1, &data);
|
|
if (ret)
|
|
return ret;
|
|
krb5_data_free(&data);
|
|
|
|
ret = _krb5_pac_get_kdc_checksum_info(context, *pac, &cstype, &rodc_id);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (rodc_id == 0 || rodc_id != krbtgt->entry.kvno >> 16) {
|
|
krb5_warnx(context, "Wrong RODCIdentifier");
|
|
return EINVAL;
|
|
}
|
|
|
|
ret = krb5_cksumtype_to_enctype(context, cstype, &etype);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = hdb_enctype2key(context, &krbtgt->entry, NULL, etype, &key);
|
|
if (ret)
|
|
return ret;
|
|
|
|
return krb5_pac_verify(context, *pac, 0, NULL, NULL, &key->key);
|
|
}
|
|
|
|
static krb5_error_code
|
|
client_access(void *ctx,
|
|
krb5_context context,
|
|
krb5_kdc_configuration *config,
|
|
hdb_entry_ex *client, const char *client_name,
|
|
hdb_entry_ex *server, const char *server_name,
|
|
KDC_REQ *req,
|
|
METHOD_DATA *data)
|
|
{
|
|
krb5_warnx(context, "client_access");
|
|
return 0;
|
|
}
|
|
|
|
static krb5plugin_windc_ftable windc = {
|
|
KRB5_WINDC_PLUGING_MINOR,
|
|
windc_init,
|
|
windc_fini,
|
|
pac_generate,
|
|
pac_verify,
|
|
client_access
|
|
};
|
|
|
|
static const krb5plugin_windc_ftable *const windc_plugins[] = {
|
|
&windc
|
|
};
|
|
|
|
krb5_error_code
|
|
windc_plugin_load(krb5_context context,
|
|
krb5_get_instance_func_t *get_instance,
|
|
size_t *num_plugins,
|
|
const krb5plugin_windc_ftable *const **plugins);
|
|
|
|
static uintptr_t
|
|
windc_get_instance(const char *libname)
|
|
{
|
|
if (strcmp(libname, "hdb") == 0)
|
|
return hdb_get_instance(libname);
|
|
else if (strcmp(libname, "krb5") == 0)
|
|
return krb5_get_instance(libname);
|
|
|
|
return 0;
|
|
}
|
|
|
|
krb5_error_code
|
|
windc_plugin_load(krb5_context context,
|
|
krb5_get_instance_func_t *get_instance,
|
|
size_t *num_plugins,
|
|
const krb5plugin_windc_ftable *const **plugins)
|
|
{
|
|
*get_instance = windc_get_instance;
|
|
*num_plugins = sizeof(windc_plugins) / sizeof(windc_plugins[0]);
|
|
*plugins = windc_plugins;
|
|
|
|
return 0;
|
|
}
|