#include "k5-int.h"
#include "int-proto.h"
static krb5_error_code
get_new_creds(krb5_context context, krb5_ccache ccache, krb5_creds *in_creds,
krb5_flags kdcopt, krb5_creds **out_creds)
{
krb5_error_code code;
krb5_creds old_creds, *new_creds = NULL;
*out_creds = NULL;
code = krb5_cc_retrieve_cred(context, ccache, KRB5_TC_SUPPORTED_KTYPES,
in_creds, &old_creds);
if (code != 0)
return code;
kdcopt |= (old_creds.ticket_flags & KDC_TKT_COMMON_MASK);
code = krb5_get_cred_via_tkt(context, &old_creds, kdcopt,
old_creds.addresses, in_creds, &new_creds);
krb5_free_cred_contents(context, &old_creds);
if (code != 0)
return code;
*out_creds = new_creds;
return code;
}
static krb5_error_code
gc_valrenew(krb5_context context, krb5_ccache ccache, krb5_creds *in_creds,
krb5_flags kdcopt, krb5_creds **out_creds)
{
krb5_error_code code;
krb5_creds *new_creds = NULL;
krb5_principal default_princ = NULL;
code = get_new_creds(context, ccache, in_creds, kdcopt, &new_creds);
if (code != 0)
goto cleanup;
code = krb5_cc_get_principal(context, ccache, &default_princ);
if (code != 0)
goto cleanup;
code = krb5_cc_initialize(context, ccache, default_princ);
if (code != 0)
goto cleanup;
code = krb5_cc_store_cred(context, ccache, new_creds);
if (code != 0)
goto cleanup;
*out_creds = new_creds;
new_creds = NULL;
cleanup:
krb5_free_principal(context, default_princ);
krb5_free_creds(context, new_creds);
return code;
}
krb5_error_code KRB5_CALLCONV
krb5_get_credentials_validate(krb5_context context, krb5_flags options,
krb5_ccache ccache, krb5_creds *in_creds,
krb5_creds **out_creds)
{
return gc_valrenew(context, ccache, in_creds, KDC_OPT_VALIDATE, out_creds);
}
krb5_error_code KRB5_CALLCONV
krb5_get_credentials_renew(krb5_context context, krb5_flags options,
krb5_ccache ccache, krb5_creds *in_creds,
krb5_creds **out_creds)
{
return gc_valrenew(context, ccache, in_creds, KDC_OPT_RENEW, out_creds);
}
static krb5_error_code
get_valrenewed_creds(krb5_context context, krb5_creds *out_creds,
krb5_principal client, krb5_ccache ccache,
const char *in_tkt_service, int kdcopt)
{
krb5_error_code code;
krb5_creds in_creds, *new_creds;
krb5_principal server = NULL;
if (in_tkt_service != NULL) {
code = krb5_parse_name(context, in_tkt_service, &server);
if (code != 0)
goto cleanup;
krb5_free_data_contents(context, &server->realm);
code = krb5int_copy_data_contents(context, &client->realm,
&server->realm);
if (code != 0)
goto cleanup;
} else {
code = krb5int_tgtname(context, &client->realm, &client->realm,
&server);
if (code != 0)
goto cleanup;
}
memset(&in_creds, 0, sizeof(krb5_creds));
in_creds.client = client;
in_creds.server = server;
code = get_new_creds(context, ccache, &in_creds, kdcopt, &new_creds);
if (code != 0)
goto cleanup;
*out_creds = *new_creds;
free(new_creds);
cleanup:
krb5_free_principal(context, server);
return code;
}
krb5_error_code KRB5_CALLCONV
krb5_get_validated_creds(krb5_context context, krb5_creds *creds,
krb5_principal client, krb5_ccache ccache,
const char *in_tkt_service)
{
return get_valrenewed_creds(context, creds, client, ccache,
in_tkt_service, KDC_OPT_VALIDATE);
}
krb5_error_code KRB5_CALLCONV
krb5_get_renewed_creds(krb5_context context, krb5_creds *creds,
krb5_principal client, krb5_ccache ccache,
const char *in_tkt_service)
{
return get_valrenewed_creds(context, creds, client, ccache,
in_tkt_service, KDC_OPT_RENEW);
}