#include "heim.h"
#include <string.h>
#include <errno.h>
void KRB5_CALLCONV
krb5_get_init_creds_opt_init(mit_krb5_get_init_creds_opt *opt)
{
LOG_ENTRY();
memset(opt, 0, sizeof(*opt));
}
mit_krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_process_last_req(mit_krb5_context context,
mit_krb5_get_init_creds_opt *opt,
mit_krb5_gic_process_last_req req,
void *ctx)
{
LOG_ENTRY();
return 0;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_alloc(mit_krb5_context context,
mit_krb5_get_init_creds_opt **opt)
{
mit_krb5_get_init_creds_opt *c;
LOG_ENTRY();
c = calloc(1, sizeof(*c));
if (c == NULL)
return ENOMEM;
*opt = c;
return 0;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_free(mit_krb5_context context,
mit_krb5_get_init_creds_opt *opt)
{
LOG_ENTRY();
free(opt);
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_tkt_life(mit_krb5_get_init_creds_opt *opt,
mit_krb5_deltat tkt_life)
{
LOG_ENTRY();
opt->flags |= MIT_KRB5_GET_INIT_CREDS_OPT_TKT_LIFE;
opt->tkt_life = tkt_life;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_renew_life(mit_krb5_get_init_creds_opt *opt,
mit_krb5_deltat renew_life)
{
LOG_ENTRY();
opt->flags |= MIT_KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE;
opt->renew_life = renew_life;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_forwardable(mit_krb5_get_init_creds_opt *opt,
int forwardable)
{
LOG_ENTRY();
opt->flags |= MIT_KRB5_GET_INIT_CREDS_OPT_FORWARDABLE;
opt->forwardable = forwardable;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_proxiable(mit_krb5_get_init_creds_opt *opt,
int proxiable)
{
LOG_ENTRY();
opt->flags |= MIT_KRB5_GET_INIT_CREDS_OPT_PROXIABLE;
opt->proxiable = proxiable;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_canonicalize(mit_krb5_get_init_creds_opt *opt,
int canonicalize)
{
LOG_ENTRY();
opt->flags |= MIT_KRB5_GET_INIT_CREDS_OPT_CANONICALIZE;
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_etype_list(mit_krb5_get_init_creds_opt *opt,
mit_krb5_enctype *etype_list,
int etype_list_length)
{
LOG_ENTRY();
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(mit_krb5_get_init_creds_opt *opt,
mit_krb5_address **addresses)
{
LOG_UNIMPLEMENTED();
}
void KRB5_CALLCONV
krb5_get_init_creds_opt_set_preauth_list(mit_krb5_get_init_creds_opt *opt,
mit_krb5_preauthtype *preauth_list,
int preauth_list_length)
{
LOG_ENTRY();
}
static krb5_get_init_creds_opt *
mshim_gic_opt(krb5_context context, mit_krb5_get_init_creds_opt *mopt)
{
krb5_get_init_creds_opt *opt = NULL;
if (mopt) {
heim_krb5_get_init_creds_opt_alloc(context, &opt);
if (mopt->flags & MIT_KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)
heim_krb5_get_init_creds_opt_set_forwardable(opt, mopt->forwardable);
if (mopt->flags & MIT_KRB5_GET_INIT_CREDS_OPT_PROXIABLE)
heim_krb5_get_init_creds_opt_set_proxiable(opt, mopt->proxiable);
if (mopt->flags & MIT_KRB5_GET_INIT_CREDS_OPT_CANONICALIZE)
heim_krb5_get_init_creds_opt_set_canonicalize(HC(context), opt, TRUE);
if (mopt->flags & MIT_KRB5_GET_INIT_CREDS_OPT_TKT_LIFE)
heim_krb5_get_init_creds_opt_set_tkt_life(opt, mopt->tkt_life);
if (mopt->flags & MIT_KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE)
heim_krb5_get_init_creds_opt_set_renew_life(opt, mopt->renew_life);
}
return opt;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_password(mit_krb5_context context,
mit_krb5_creds *creds,
mit_krb5_principal client,
char *password,
mit_krb5_prompter_fct prompter,
void *data,
mit_krb5_deltat start_time,
char *in_tkt_service,
mit_krb5_get_init_creds_opt *mopt)
{
struct comb_principal *p = (struct comb_principal *)client;
krb5_get_init_creds_opt *opt = NULL;
krb5_error_code ret;
krb5_creds hcreds;
krb5_prompter_fct pfct = NULL;
LOG_ENTRY();
opt = mshim_gic_opt(HC(context), mopt);
memset(creds, 0, sizeof(*creds));
memset(&hcreds, 0, sizeof(hcreds));
if (prompter == krb5_prompter_posix)
pfct = heim_krb5_prompter_posix;
else if (prompter == NULL)
pfct = NULL;
else {
if (opt)
heim_krb5_get_init_creds_opt_free(HC(context), opt);
return EINVAL;
}
ret = heim_krb5_get_init_creds_password(HC(context), &hcreds, p->heim, password,
pfct, NULL, start_time, in_tkt_service, opt);
if (opt)
heim_krb5_get_init_creds_opt_free(HC(context), opt);
if (ret)
return ret;
mshim_hcred2mcred(HC(context), &hcreds, creds);
heim_krb5_free_cred_contents(HC(context), &hcreds);
return ret;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_keytab(mit_krb5_context context,
mit_krb5_creds *creds,
mit_krb5_principal client,
mit_krb5_keytab arg_keytab,
mit_krb5_deltat start_time,
char *in_tkt_service,
mit_krb5_get_init_creds_opt *mopt)
{
struct comb_principal *p = (struct comb_principal *)client;
krb5_get_init_creds_opt *opt = NULL;
krb5_error_code ret;
krb5_creds hcreds;
LOG_ENTRY();
opt = mshim_gic_opt(HC(context), mopt);
memset(creds, 0, sizeof(*creds));
memset(&hcreds, 0, sizeof(hcreds));
ret = heim_krb5_get_init_creds_keytab(HC(context), &hcreds, p->heim,
(krb5_keytab)arg_keytab,
start_time, in_tkt_service, opt);
if (opt)
heim_krb5_get_init_creds_opt_free(HC(context), opt);
if (ret)
return ret;
mshim_hcred2mcred(HC(context), &hcreds, creds);
heim_krb5_free_cred_contents(HC(context), &hcreds);
return ret;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_get_in_tkt_with_password(mit_krb5_context context,
mit_krb5_flags flags,
mit_krb5_address * const *addr,
mit_krb5_enctype *enctype,
mit_krb5_preauthtype *preauth,
const char *password,
mit_krb5_ccache cache,
mit_krb5_creds *cred,
mit_krb5_kdc_rep **rep)
{
struct comb_principal *p;
krb5_error_code ret;
krb5_creds hcreds;
LOG_ENTRY();
if (rep)
*rep = NULL;
if (cred->client)
p = (struct comb_principal *)cred->client;
else
return KRB5_PRINC_NOMATCH;
memset(&hcreds, 0, sizeof(hcreds));
ret = heim_krb5_get_init_creds_password(HC(context), &hcreds, p->heim, password,
NULL, NULL, 0, NULL, NULL);
if (ret)
return ret;
if (cache)
heim_krb5_cc_store_cred(HC(context), (krb5_ccache)cache, &hcreds);
heim_krb5_free_cred_contents(HC(context), &hcreds);
return 0;
}
void KRB5_CALLCONV
krb5_verify_init_creds_opt_init(mit_krb5_verify_init_creds_opt *options)
{
memset(options, 0, sizeof(*options));
}
void KRB5_CALLCONV
krb5_verify_init_creds_opt_set_ap_req_nofail(mit_krb5_verify_init_creds_opt *options,
int ap_req_nofail)
{
if (ap_req_nofail) {
options->flags |= MIT_KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL;
} else {
options->flags &= ~MIT_KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL;
}
options->ap_req_nofail = ap_req_nofail;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_verify_init_creds(mit_krb5_context context,
mit_krb5_creds *creds,
mit_krb5_principal ap_req_server,
mit_krb5_keytab ap_req_keytab,
mit_krb5_ccache *ccache,
mit_krb5_verify_init_creds_opt *options)
{
struct comb_principal *p = (struct comb_principal *)ap_req_server;
krb5_error_code ret;
krb5_creds hcreds;
krb5_verify_init_creds_opt hopts;
memset(&hcreds, 0, sizeof(hcreds));
heim_krb5_verify_init_creds_opt_init(&hopts);
if (options->ap_req_nofail)
heim_krb5_verify_init_creds_opt_set_ap_req_nofail(&hopts, options->ap_req_nofail);
mshim_mcred2hcred(HC(context), creds, &hcreds);
ret = heim_krb5_verify_init_creds(HC(context),
&hcreds, p->heim,
(krb5_keytab)ap_req_keytab,
(krb5_ccache *)ccache,
&hopts);
heim_krb5_free_cred_contents(HC(context), &hcreds);
return ret;
}