#include "k5-int.h"
void KRB5_CALLCONV
krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
{
opt->flags = KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, krb5_deltat tkt_life)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE;
opt->tkt_life = tkt_life;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, krb5_deltat renew_life)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE;
opt->renew_life = renew_life;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, int forwardable)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE;
opt->forwardable = forwardable;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, int proxiable)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE;
opt->proxiable = proxiable;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, krb5_enctype *etype_list, int etype_list_length)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST;
opt->etype_list = etype_list;
opt->etype_list_length = etype_list_length;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, krb5_address **addresses)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST;
opt->address_list = addresses;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, krb5_preauthtype *preauth_list, int preauth_list_length)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST;
opt->preauth_list = preauth_list;
opt->preauth_list_length = preauth_list_length;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, krb5_data *salt)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT;
opt->salt = salt;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_change_password_prompt(krb5_get_init_creds_opt *opt, int prompt)
{
if (prompt)
opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
else
opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
}
static void
free_gic_opt_ext_preauth_data(krb5_context context,
krb5_gic_opt_ext *opte);
static krb5_error_code
krb5int_gic_opte_private_alloc(krb5_context context, krb5_gic_opt_ext *opte)
{
if (NULL == opte || !krb5_gic_opt_is_extended(opte))
return EINVAL;
opte->opt_private = calloc(1, sizeof(*opte->opt_private));
if (NULL == opte->opt_private) {
return ENOMEM;
}
opte->opt_private->num_preauth_data = 0;
opte->opt_private->preauth_data = NULL;
return 0;
}
static krb5_error_code
krb5int_gic_opte_private_free(krb5_context context, krb5_gic_opt_ext *opte)
{
if (NULL == opte || !krb5_gic_opt_is_extended(opte))
return EINVAL;
if (opte->opt_private->preauth_data != NULL)
free_gic_opt_ext_preauth_data(context, opte);
free(opte->opt_private);
opte->opt_private = NULL;
return 0;
}
static krb5_gic_opt_ext *
krb5int_gic_opte_alloc(krb5_context context)
{
krb5_gic_opt_ext *opte;
krb5_error_code code;
opte = calloc(1, sizeof(*opte));
if (NULL == opte)
return NULL;
opte->flags = KRB5_GET_INIT_CREDS_OPT_EXTENDED;
code = krb5int_gic_opte_private_alloc(context, opte);
if (code) {
krb5int_set_error(&context->err, code,
"krb5int_gic_opte_alloc: krb5int_gic_opte_private_alloc failed");
free(opte);
return NULL;
}
return(opte);
}
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_alloc(krb5_context context,
krb5_get_init_creds_opt **opt)
{
krb5_gic_opt_ext *opte;
if (NULL == opt)
return EINVAL;
*opt = NULL;
opte = krb5int_gic_opte_alloc(context);
if (NULL == opte)
return ENOMEM;
*opt = (krb5_get_init_creds_opt *) opte;
return 0;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_free(krb5_context context,
krb5_get_init_creds_opt *opt)
{
krb5_gic_opt_ext *opte;
if (NULL == opt)
return;
if (!krb5_gic_opt_is_extended(opt))
return;
opte = (krb5_gic_opt_ext *)opt;
if (opte->opt_private)
krb5int_gic_opte_private_free(context, opte);
free(opte);
}
static krb5_error_code
krb5int_gic_opte_copy(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_gic_opt_ext **opte)
{
krb5_gic_opt_ext *oe;
oe = krb5int_gic_opte_alloc(context);
if (NULL == oe)
return ENOMEM;
if (opt)
memcpy(oe, opt, sizeof(*opt));
oe->flags |= ( KRB5_GET_INIT_CREDS_OPT_EXTENDED |
KRB5_GET_INIT_CREDS_OPT_SHADOWED);
*opte = oe;
return 0;
}
krb5_error_code
krb5int_gic_opt_to_opte(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_gic_opt_ext **opte,
unsigned int force,
const char *where)
{
if (!krb5_gic_opt_is_extended(opt)) {
if (force) {
return krb5int_gic_opte_copy(context, opt, opte);
} else {
krb5int_set_error(&context->err, EINVAL,
"%s: attempt to convert non-extended krb5_get_init_creds_opt",
where);
return EINVAL;
}
}
*opte = (krb5_gic_opt_ext *)opt;
return 0;
}
static void
free_gic_opt_ext_preauth_data(krb5_context context,
krb5_gic_opt_ext *opte)
{
int i;
if (NULL == opte || !krb5_gic_opt_is_extended(opte))
return;
if (NULL == opte->opt_private || NULL == opte->opt_private->preauth_data)
return;
for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
if (opte->opt_private->preauth_data[i].attr != NULL)
free(opte->opt_private->preauth_data[i].attr);
if (opte->opt_private->preauth_data[i].value != NULL)
free(opte->opt_private->preauth_data[i].value);
}
free(opte->opt_private->preauth_data);
opte->opt_private->preauth_data = NULL;
opte->opt_private->num_preauth_data = 0;
}
static krb5_error_code
add_gic_opt_ext_preauth_data(krb5_context context,
krb5_gic_opt_ext *opte,
const char *attr,
const char *value)
{
size_t newsize;
int i;
krb5_gic_opt_pa_data *newpad;
newsize = opte->opt_private->num_preauth_data + 1;
newsize = newsize * sizeof(*opte->opt_private->preauth_data);
if (opte->opt_private->preauth_data == NULL)
newpad = malloc(newsize);
else
newpad = realloc(opte->opt_private->preauth_data, newsize);
if (newpad == NULL)
return ENOMEM;
i = opte->opt_private->num_preauth_data;
newpad[i].attr = strdup(attr);
if (newpad[i].attr == NULL)
return ENOMEM;
newpad[i].value = strdup(value);
if (newpad[i].value == NULL) {
free(newpad[i].attr);
return ENOMEM;
}
opte->opt_private->num_preauth_data += 1;
opte->opt_private->preauth_data = newpad;
return 0;
}
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_pa(krb5_context context,
krb5_get_init_creds_opt *opt,
const char *attr,
const char *value)
{
krb5_error_code retval;
krb5_gic_opt_ext *opte;
retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
"krb5_get_init_creds_opt_set_pa");
if (retval)
return retval;
retval = add_gic_opt_ext_preauth_data(context, opte, attr, value);
if (retval)
return retval;
retval = krb5_preauth_supply_preauth_data(context, opte, attr, value);
return retval;
}
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_get_pa(krb5_context context,
krb5_get_init_creds_opt *opt,
int *num_preauth_data,
krb5_gic_opt_pa_data **preauth_data)
{
krb5_error_code retval;
krb5_gic_opt_ext *opte;
krb5_gic_opt_pa_data *p = NULL;
int i;
size_t allocsize;
retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
"krb5_get_init_creds_opt_get_pa");
if (retval)
return retval;
if (num_preauth_data == NULL || preauth_data == NULL)
return EINVAL;
*num_preauth_data = 0;
*preauth_data = NULL;
if (opte->opt_private->num_preauth_data == 0)
return 0;
allocsize =
opte->opt_private->num_preauth_data * sizeof(krb5_gic_opt_pa_data);
p = malloc(allocsize);
if (p == NULL)
return ENOMEM;
for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
p[i].attr = NULL;
p[i].value = NULL;
}
for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
p[i].attr = strdup(opte->opt_private->preauth_data[i].attr);
p[i].value = strdup(opte->opt_private->preauth_data[i].value);
if (p[i].attr == NULL || p[i].value == NULL)
goto cleanup;
}
*num_preauth_data = i;
*preauth_data = p;
return 0;
cleanup:
for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
if (p[i].attr != NULL)
free(p[i].attr);
if (p[i].value != NULL)
free(p[i].value);
}
free(p);
return ENOMEM;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_free_pa(krb5_context context,
int num_preauth_data,
krb5_gic_opt_pa_data *preauth_data)
{
int i;
if (num_preauth_data <= 0 || preauth_data == NULL)
return;
for (i = 0; i < num_preauth_data; i++) {
if (preauth_data[i].attr != NULL)
free(preauth_data[i].attr);
if (preauth_data[i].value != NULL)
free(preauth_data[i].value);
}
free(preauth_data);
}