collect all init_creds context into a structure so it can easier be

passed around, also, while here, change nonce for every request


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@12847 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2003-09-18 18:40:44 +00:00
parent 763a230714
commit 21554e0cbb

View File

@@ -35,6 +35,86 @@
RCSID("$Id$"); RCSID("$Id$");
typedef struct krb5_get_init_creds_ctx {
krb5_kdc_flags flags;
krb5_creds cred;
krb5_addresses *addrs;
krb5_enctype *etypes;
krb5_preauthtype *pre_auth_types;
const char *in_tkt_service;
unsigned nonce;
AS_REQ as_req;
const char *password;
krb5_s2k_proc key_proc;
} krb5_get_init_creds_ctx;
static krb5_error_code
default_s2k_func(krb5_context context, krb5_enctype type,
krb5_const_pointer keyseed,
krb5_salt salt, krb5_data *s2kparms,
krb5_keyblock **key)
{
krb5_error_code ret;
krb5_data password;
krb5_data opaque;
password.data = (void *)keyseed;
password.length = strlen(keyseed);
if (s2kparms)
opaque = *s2kparms;
else
krb5_data_zero(&opaque);
*key = malloc(sizeof(**key));
if (*key == NULL)
return ENOMEM;
ret = krb5_string_to_key_data_salt_opaque(context, type, password,
salt, opaque, *key);
if (ret)
free(*key);
return ret;
}
static krb5_error_code
init_init_creds_ctx(krb5_context context,
krb5_get_init_creds_ctx *ctx,
const char *in_tkt_service,
const krb5_get_init_creds_opt *init_cred_opts)
{
memset(ctx, 0, sizeof(*ctx));
if (init_cred_opts->private) {
ctx->password = init_cred_opts->private->password;
ctx->key_proc = init_cred_opts->private->key_proc;
}
if (ctx->key_proc == NULL)
ctx->key_proc = default_s2k_func;
ctx->pre_auth_types = NULL;
ctx->flags.i = 0;
ctx->addrs = NULL;
ctx->etypes = NULL;
ctx->pre_auth_types = NULL;
ctx->in_tkt_service = in_tkt_service;
memset(&ctx->as_req, 0, sizeof(ctx->as_req));
return 0;
}
static void
free_init_creds_ctx(krb5_context context, krb5_get_init_creds_ctx *ctx)
{
if (ctx->etypes)
free(ctx->etypes);
if (ctx->pre_auth_types)
free (ctx->pre_auth_types);
free_AS_REQ(&ctx->as_req);
memset(&ctx->as_req, 0, sizeof(ctx->as_req));
}
static int static int
get_config_time (krb5_context context, get_config_time (krb5_context context,
const char *realm, const char *realm,
@@ -201,65 +281,65 @@ get_init_creds_common(krb5_context context,
krb5_deltat start_time, krb5_deltat start_time,
const char *in_tkt_service, const char *in_tkt_service,
krb5_get_init_creds_opt *options, krb5_get_init_creds_opt *options,
krb5_addresses **addrs, krb5_get_init_creds_ctx *ctx)
krb5_enctype **etypes,
krb5_creds *cred,
krb5_preauthtype **pre_auth_types,
krb5_kdc_flags *flags)
{ {
krb5_error_code ret;
krb5_get_init_creds_opt default_opt; krb5_get_init_creds_opt default_opt;
krb5_error_code ret;
krb5_enctype *etypes;
krb5_preauthtype *pre_auth_types;
if (options == NULL) { if (options == NULL) {
krb5_get_init_creds_opt_init (&default_opt); krb5_get_init_creds_opt_init (&default_opt);
options = &default_opt; options = &default_opt;
} }
ret = init_cred (context, cred, client, start_time, ret = init_cred (context, &ctx->cred, client, start_time,
in_tkt_service, options); in_tkt_service, options);
if (ret) if (ret)
return ret; return ret;
flags->i = 0; ctx->flags.i = 0;
if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE) if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)
flags->b.forwardable = options->forwardable; ctx->flags.b.forwardable = options->forwardable;
if (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE) if (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE)
flags->b.proxiable = options->proxiable; ctx->flags.b.proxiable = options->proxiable;
if (start_time) if (start_time)
flags->b.postdated = 1; ctx->flags.b.postdated = 1;
if (cred->times.renew_till) if (ctx->cred.times.renew_till)
flags->b.renewable = 1; ctx->flags.b.renewable = 1;
if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST)
*addrs = options->address_list; ctx->addrs = options->address_list;
if (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) { if (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) {
*etypes = malloc((options->etype_list_length + 1) etypes = malloc((options->etype_list_length + 1)
* sizeof(krb5_enctype)); * sizeof(krb5_enctype));
if (*etypes == NULL) { if (etypes == NULL) {
krb5_set_error_string(context, "malloc: out of memory"); krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM; return ENOMEM;
} }
memcpy (*etypes, options->etype_list, memcpy (etypes, options->etype_list,
options->etype_list_length * sizeof(krb5_enctype)); options->etype_list_length * sizeof(krb5_enctype));
(*etypes)[options->etype_list_length] = ETYPE_NULL; etypes[options->etype_list_length] = ETYPE_NULL;
ctx->etypes = etypes;
} }
if (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) { if (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) {
*pre_auth_types = malloc((options->preauth_list_length + 1) pre_auth_types = malloc((options->preauth_list_length + 1)
* sizeof(krb5_preauthtype)); * sizeof(krb5_preauthtype));
if (*pre_auth_types == NULL) { if (pre_auth_types == NULL) {
krb5_set_error_string(context, "malloc: out of memory"); krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM; return ENOMEM;
} }
memcpy (*pre_auth_types, options->preauth_list, memcpy (pre_auth_types, options->preauth_list,
options->preauth_list_length * sizeof(krb5_preauthtype)); options->preauth_list_length * sizeof(krb5_preauthtype));
(*pre_auth_types)[options->preauth_list_length] = KRB5_PADATA_NONE; pre_auth_types[options->preauth_list_length] = KRB5_PADATA_NONE;
ctx->pre_auth_types = pre_auth_types;
} }
if (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT) if (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT)
; /* XXX */ ; /* XXX */
if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS)
flags->b.request_anonymous = options->anonymous; ctx->flags.b.request_anonymous = options->anonymous;
return 0; return 0;
} }
@@ -392,18 +472,18 @@ krb5_get_init_creds_keytab(krb5_context context,
const char *in_tkt_service, const char *in_tkt_service,
krb5_get_init_creds_opt *options) krb5_get_init_creds_opt *options)
{ {
struct krb5_get_init_creds_ctx ctx;
krb5_error_code ret; krb5_error_code ret;
krb5_kdc_flags flags;
krb5_addresses *addrs = NULL;
krb5_enctype *etypes = NULL;
krb5_preauthtype *pre_auth_types = NULL;
krb5_creds this_cred;
krb5_keytab_key_proc_args *a; krb5_keytab_key_proc_args *a;
ret = init_init_creds_ctx(context, &ctx, in_tkt_service, options);
if (ret)
goto out;
ret = get_init_creds_common(context, creds, client, start_time, ret = get_init_creds_common(context, creds, client, start_time,
in_tkt_service, options, ctx.in_tkt_service,
&addrs, &etypes, &this_cred, &pre_auth_types, options,
&flags); &ctx);
if(ret) if(ret)
goto out; goto out;
@@ -413,37 +493,29 @@ krb5_get_init_creds_keytab(krb5_context context,
ret = ENOMEM; ret = ENOMEM;
goto out; goto out;
} }
a->principal = this_cred.client; a->principal = ctx.cred.client;
a->keytab = keytab; a->keytab = keytab;
ret = krb5_get_in_cred (context, ret = krb5_get_in_cred (context,
flags.i, ctx.flags.i,
addrs, ctx.addrs,
etypes, ctx.etypes,
pre_auth_types, ctx.pre_auth_types,
NULL, NULL,
krb5_keytab_key_proc, krb5_keytab_key_proc,
a, a,
NULL, NULL,
NULL, NULL,
&this_cred, &ctx.cred,
NULL); NULL);
free (a); free (a);
if (ret) if (ret == 0 && creds)
goto out; *creds = ctx.cred;
free (pre_auth_types);
free (etypes);
if (creds)
*creds = this_cred;
else else
krb5_free_creds_contents (context, &this_cred); krb5_free_creds_contents (context, &ctx.cred);
return 0;
out: free_init_creds_ctx(context, &ctx);
free (pre_auth_types);
free (etypes);
krb5_free_creds_contents (context, &this_cred);
return ret; return ret;
} }
@@ -457,7 +529,6 @@ init_creds_init_as_req (krb5_context context,
const krb5_creds *creds, const krb5_creds *creds,
const krb5_addresses *addrs, const krb5_addresses *addrs,
const krb5_enctype *etypes, const krb5_enctype *etypes,
unsigned nonce,
AS_REQ *a) AS_REQ *a)
{ {
krb5_error_code ret; krb5_error_code ret;
@@ -511,7 +582,7 @@ init_creds_init_as_req (krb5_context context,
} }
*a->req_body.rtime = creds->times.renew_till; *a->req_body.rtime = creds->times.renew_till;
} }
a->req_body.nonce = nonce; a->req_body.nonce = 0;
ret = krb5_init_etype (context, ret = krb5_init_etype (context,
&a->req_body.etype.len, &a->req_body.etype.len,
&a->req_body.etype.val, &a->req_body.etype.val,
@@ -558,11 +629,6 @@ init_creds_init_as_req (krb5_context context,
return ret; return ret;
} }
struct preauth_ctx {
const char *password;
krb5_s2k_proc key_proc;
};
struct pa_info_data { struct pa_info_data {
krb5_enctype etype; krb5_enctype etype;
krb5_salt salt; krb5_salt salt;
@@ -883,16 +949,16 @@ static krb5_error_code
pa_data_to_md_ts_enc(krb5_context context, pa_data_to_md_ts_enc(krb5_context context,
const AS_REQ *a, const AS_REQ *a,
const krb5_principal client, const krb5_principal client,
struct preauth_ctx *pa_ctx, krb5_get_init_creds_ctx *ctx,
struct pa_info_data *ppaid, struct pa_info_data *ppaid,
METHOD_DATA *md) METHOD_DATA *md)
{ {
if (pa_ctx->key_proc == NULL || pa_ctx->password == NULL) if (ctx->key_proc == NULL || ctx->password == NULL)
return 0; return 0;
if (ppaid) { if (ppaid) {
add_enc_ts_padata(context, md, client, add_enc_ts_padata(context, md, client,
pa_ctx->key_proc, pa_ctx->password, ctx->key_proc, ctx->password,
&ppaid->etype, 1, &ppaid->etype, 1,
&ppaid->salt, ppaid->s2kparams); &ppaid->salt, ppaid->s2kparams);
} else { } else {
@@ -900,7 +966,7 @@ pa_data_to_md_ts_enc(krb5_context context,
/* make a v5 salted pa-data */ /* make a v5 salted pa-data */
add_enc_ts_padata(context, md, client, add_enc_ts_padata(context, md, client,
pa_ctx->key_proc, pa_ctx->password, ctx->key_proc, ctx->password,
a->req_body.etype.val, a->req_body.etype.len, a->req_body.etype.val, a->req_body.etype.len,
NULL, NULL); NULL, NULL);
@@ -908,7 +974,7 @@ pa_data_to_md_ts_enc(krb5_context context,
salt.salttype = KRB5_PW_SALT; salt.salttype = KRB5_PW_SALT;
krb5_data_zero(&salt.saltvalue); krb5_data_zero(&salt.saltvalue);
add_enc_ts_padata(context, md, client, add_enc_ts_padata(context, md, client,
pa_ctx->key_proc, pa_ctx->password, ctx->key_proc, ctx->password,
a->req_body.etype.val, a->req_body.etype.len, a->req_body.etype.val, a->req_body.etype.len,
&salt, NULL); &salt, NULL);
} }
@@ -918,7 +984,7 @@ pa_data_to_md_ts_enc(krb5_context context,
static krb5_error_code static krb5_error_code
pa_data_to_key_plain(krb5_context context, pa_data_to_key_plain(krb5_context context,
const krb5_principal client, const krb5_principal client,
struct preauth_ctx *pa_ctx, krb5_get_init_creds_ctx *ctx,
krb5_salt salt, krb5_salt salt,
krb5_data *s2kparams, krb5_data *s2kparams,
krb5_enctype etype, krb5_enctype etype,
@@ -926,7 +992,7 @@ pa_data_to_key_plain(krb5_context context,
{ {
krb5_error_code ret; krb5_error_code ret;
ret = (*pa_ctx->key_proc)(context, etype, pa_ctx->password, ret = (*ctx->key_proc)(context, etype, ctx->password,
salt, s2kparams, key); salt, s2kparams, key);
return ret; return ret;
} }
@@ -936,7 +1002,7 @@ static krb5_error_code
process_pa_data_to_md(krb5_context context, process_pa_data_to_md(krb5_context context,
const krb5_creds *creds, const krb5_creds *creds,
const AS_REQ *a, const AS_REQ *a,
struct preauth_ctx *pa_ctx, krb5_get_init_creds_ctx *ctx,
METHOD_DATA *in_md, METHOD_DATA *in_md,
METHOD_DATA **out_md, METHOD_DATA **out_md,
krb5_prompter_fct prompter, krb5_prompter_fct prompter,
@@ -967,7 +1033,7 @@ process_pa_data_to_md(krb5_context context,
* KRB5_PADATA_ENC_TIMESTAMP * KRB5_PADATA_ENC_TIMESTAMP
*/ */
pa_data_to_md_ts_enc(context, a, creds->client, pa_ctx, ppaid, *out_md); pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md);
if (ppaid) if (ppaid)
free_paid(context, ppaid); free_paid(context, ppaid);
return 0; return 0;
@@ -975,7 +1041,7 @@ process_pa_data_to_md(krb5_context context,
static krb5_error_code static krb5_error_code
process_pa_data_to_key(krb5_context context, process_pa_data_to_key(krb5_context context,
struct preauth_ctx *pa_ctx, krb5_get_init_creds_ctx *ctx,
krb5_creds *creds, krb5_creds *creds,
AS_REQ *a, AS_REQ *a,
krb5_kdc_rep *rep, krb5_kdc_rep *rep,
@@ -1007,84 +1073,30 @@ process_pa_data_to_key(krb5_context context,
* other preauth mechs then KRB5_PA_ENC_TIMESTAMP. * other preauth mechs then KRB5_PA_ENC_TIMESTAMP.
*/ */
ret = pa_data_to_key_plain(context, creds->client, pa_ctx, ret = pa_data_to_key_plain(context, creds->client, ctx,
paid.salt, paid.s2kparams, etype, key); paid.salt, paid.s2kparams, etype, key);
free_paid(context, &paid); free_paid(context, &paid);
return ret; return ret;
} }
static krb5_error_code
default_s2k_func(krb5_context context, krb5_enctype type,
krb5_const_pointer keyseed,
krb5_salt salt, krb5_data *s2kparms,
krb5_keyblock **key)
{
krb5_error_code ret;
krb5_data password;
krb5_data opaque;
password.data = (void *)keyseed;
password.length = strlen(keyseed);
if (s2kparms)
opaque = *s2kparms;
else
krb5_data_zero(&opaque);
*key = malloc(sizeof(**key));
if (*key == NULL)
return ENOMEM;
ret = krb5_string_to_key_data_salt_opaque(context, type, password,
salt, opaque, *key);
if (ret)
free(*key);
return ret;
}
static krb5_error_code
init_pa_ctx(krb5_context context,
struct preauth_ctx *pa_ctx,
const krb5_get_init_creds_opt *init_cred_opts)
{
memset(pa_ctx, 0, sizeof(*pa_ctx));
if (init_cred_opts->private) {
pa_ctx->password = init_cred_opts->private->password;
pa_ctx->key_proc = init_cred_opts->private->key_proc;
}
if (pa_ctx->key_proc == NULL)
pa_ctx->key_proc = default_s2k_func;
return 0;
}
static krb5_error_code static krb5_error_code
init_cred_loop(krb5_context context, init_cred_loop(krb5_context context,
krb5_kdc_flags options,
const krb5_addresses *addrs,
const krb5_enctype *etypes,
const krb5_get_init_creds_opt *init_cred_opts, const krb5_get_init_creds_opt *init_cred_opts,
const krb5_prompter_fct prompter, const krb5_prompter_fct prompter,
void *prompter_data, void *prompter_data,
struct preauth_ctx *pa_ctx, krb5_get_init_creds_ctx *ctx,
krb5_creds *creds, krb5_creds *creds,
krb5_kdc_rep *ret_as_reply) krb5_kdc_rep *ret_as_reply)
{ {
krb5_error_code ret; krb5_error_code ret;
AS_REQ a;
krb5_kdc_rep rep; krb5_kdc_rep rep;
krb5_data resp; krb5_data resp;
size_t len; size_t len;
krb5_salt salt;
krb5_keyblock *key; krb5_keyblock *key;
size_t size; size_t size;
krb5_kdc_flags opts;
unsigned nonce;
int pa_counter; int pa_counter;
krb5_data s2kparam;
METHOD_DATA md; METHOD_DATA md;
krb5_data_zero(&s2kparam);
krb5_data_zero(&salt.saltvalue);
memset(&md, 0, sizeof(md)); memset(&md, 0, sizeof(md));
memset(&rep, 0, sizeof(rep)); memset(&rep, 0, sizeof(rep));
key = NULL; key = NULL;
@@ -1092,13 +1104,8 @@ init_cred_loop(krb5_context context,
if (ret_as_reply) if (ret_as_reply)
memset(ret_as_reply, 0, sizeof(*ret_as_reply)); memset(ret_as_reply, 0, sizeof(*ret_as_reply));
opts = options; ret = init_creds_init_as_req(context, ctx->flags, creds,
ctx->addrs, ctx->etypes, &ctx->as_req);
krb5_generate_random_block (&nonce, sizeof(nonce));
nonce &= 0xffffffff;
ret = init_creds_init_as_req(context, opts, creds,
addrs, etypes, nonce, &a);
if (ret) if (ret)
return ret; return ret;
@@ -1112,18 +1119,24 @@ init_cred_loop(krb5_context context,
for (pa_counter = 0; pa_counter < MAX_PA_COUNTER; pa_counter++) { for (pa_counter = 0; pa_counter < MAX_PA_COUNTER; pa_counter++) {
krb5_data req; krb5_data req;
if (a.padata) { if (ctx->as_req.padata) {
free_METHOD_DATA(a.padata); free_METHOD_DATA(ctx->as_req.padata);
a.padata = NULL; ctx->as_req.padata = NULL;
} }
/* Set a new nonce. */
krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce));
ctx->nonce &= 0xffffffff;
ctx->as_req.req_body.nonce = ctx->nonce;
/* fill_in_md_data */ /* fill_in_md_data */
ret = process_pa_data_to_md(context, creds, &a, pa_ctx, ret = process_pa_data_to_md(context, creds, &ctx->as_req, ctx,
&md, &a.padata, &md, &ctx->as_req.padata,
prompter, prompter_data); prompter, prompter_data);
if (ret) if (ret)
goto out; goto out;
ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, &a, &len, ret); ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length,
&ctx->as_req, &len, ret);
if (ret) if (ret)
goto out; goto out;
if(len != req.length) if(len != req.length)
@@ -1183,7 +1196,8 @@ init_cred_loop(krb5_context context,
} }
} }
ret = process_pa_data_to_key(context, pa_ctx, creds, &a, &rep, &key); ret = process_pa_data_to_key(context, ctx, creds,
&ctx->as_req, &rep, &key);
if (ret) if (ret)
goto out; goto out;
@@ -1197,18 +1211,14 @@ init_cred_loop(krb5_context context,
NULL, NULL,
KRB5_KU_AS_REP_ENC_PART, KRB5_KU_AS_REP_ENC_PART,
NULL, NULL,
nonce, ctx->nonce,
FALSE, FALSE,
opts.b.request_anonymous, ctx->flags.b.request_anonymous,
NULL, NULL,
NULL); NULL);
krb5_free_keyblock(context, key); krb5_free_keyblock(context, key);
out: out:
if (a.padata)
free_METHOD_DATA(a.padata);
free_AS_REQ(&a);
if (ret == 0 && ret_as_reply) if (ret == 0 && ret_as_reply)
*ret_as_reply = rep; *ret_as_reply = rep;
else else
@@ -1216,6 +1226,100 @@ out:
return ret; return ret;
} }
krb5_error_code
krb5_get_init_creds(krb5_context context,
krb5_creds *creds,
krb5_principal client,
krb5_prompter_fct prompter,
void *data,
krb5_deltat start_time,
const char *in_tkt_service,
krb5_get_init_creds_opt *options)
{
krb5_get_init_creds_ctx ctx;
krb5_kdc_rep kdc_reply;
krb5_error_code ret;
char buf[BUFSIZ];
int done;
memset(&kdc_reply, 0, sizeof(kdc_reply));
ret = init_init_creds_ctx(context, &ctx, in_tkt_service, options);
if (ret)
goto out;
ret = get_init_creds_common(context, creds, client, start_time,
ctx.in_tkt_service,
options,
&ctx);
if (ret)
goto out;
done = 0;
while(!done) {
memset(&kdc_reply, 0, sizeof(kdc_reply));
ret = init_cred_loop(context,
options,
prompter,
data,
&ctx,
&ctx.cred,
&kdc_reply);
switch (ret) {
case 0 :
done = 1;
break;
case KRB5KDC_ERR_KEY_EXPIRED :
/* try to avoid recursion */
/* don't try to change password where then where none */
if (prompter == NULL || ctx.password == NULL)
goto out;
krb5_clear_error_string (context);
if (ctx.in_tkt_service != NULL
&& strcmp (ctx.in_tkt_service, "kadmin/changepw") == 0)
goto out;
ret = change_password (context,
client,
ctx.password,
buf,
sizeof(buf),
prompter,
data,
options);
if (ret)
goto out;
ctx.password = buf;
break;
default:
goto out;
}
}
if (prompter)
print_expire (context,
krb5_princ_realm (context, ctx.cred.client),
&kdc_reply,
prompter,
data);
out:
memset (buf, 0, sizeof(buf));
free_init_creds_ctx(context, &ctx);
if (ret == 0) {
*creds = ctx.cred;
krb5_free_kdc_rep (context, &kdc_reply);
} else
krb5_free_creds_contents (context, &ctx.cred);
return ret;
}
krb5_error_code krb5_error_code
krb5_get_init_creds_password(krb5_context context, krb5_get_init_creds_password(krb5_context context,
krb5_creds *creds, krb5_creds *creds,
@@ -1225,39 +1329,22 @@ krb5_get_init_creds_password(krb5_context context,
void *data, void *data,
krb5_deltat start_time, krb5_deltat start_time,
const char *in_tkt_service, const char *in_tkt_service,
krb5_get_init_creds_opt *options) krb5_get_init_creds_opt *in_options)
{ {
krb5_error_code ret; krb5_get_init_creds_opt *options;
krb5_kdc_flags flags;
krb5_addresses *addrs = NULL;
krb5_enctype *etypes = NULL;
krb5_preauthtype *pre_auth_types = NULL;
krb5_creds this_cred;
char buf[BUFSIZ]; char buf[BUFSIZ];
krb5_kdc_rep kdc_reply; krb5_error_code ret;
int done;
struct preauth_ctx pa_ctx;
memset(&pa_ctx, 0, sizeof(pa_ctx)); ret = krb5_get_init_creds_opt_copy(context, in_options, &options);
memset(&kdc_reply, 0, sizeof(kdc_reply));
ret = get_init_creds_common(context, creds, client, start_time,
in_tkt_service, options,
&addrs, &etypes, &this_cred, &pre_auth_types,
&flags);
if (ret) if (ret)
return ret; return ret;
ret = init_pa_ctx(context, &pa_ctx, options); if (password == NULL && options->private->password == NULL) {
if (ret)
goto out;
if (password == NULL && pa_ctx.password == NULL) {
krb5_prompt prompt; krb5_prompt prompt;
krb5_data password_data; krb5_data password_data;
char *p, *q; char *p, *q;
krb5_unparse_name (context, this_cred.client, &p); krb5_unparse_name (context, client, &p);
asprintf (&q, "%s's Password: ", p); asprintf (&q, "%s's Password: ", p);
free (p); free (p);
prompt.prompt = q; prompt.prompt = q;
@@ -1271,79 +1358,27 @@ krb5_get_init_creds_password(krb5_context context,
free (q); free (q);
if (ret) { if (ret) {
memset (buf, 0, sizeof(buf)); memset (buf, 0, sizeof(buf));
krb5_get_init_creds_opt_free(options);
ret = KRB5_LIBOS_PWDINTR; ret = KRB5_LIBOS_PWDINTR;
krb5_clear_error_string (context); krb5_clear_error_string (context);
goto out; return ret;
} }
password = password_data.data; password = password_data.data;
} }
if (pa_ctx.password == NULL)
pa_ctx.password = password;
done = 0; if (options->private->password == NULL) {
while(!done) { ret = krb5_get_init_creds_opt_set_pa_password(context, options,
memset(&kdc_reply, 0, sizeof(kdc_reply)); password, NULL);
if (ret) {
ret = init_cred_loop(context, krb5_get_init_creds_opt_free(options);
flags, memset(buf, 0, sizeof(buf));
addrs, return ret;
etypes,
options,
prompter,
data,
&pa_ctx,
&this_cred,
&kdc_reply);
switch (ret) {
case 0 :
done = 1;
break;
case KRB5KDC_ERR_KEY_EXPIRED :
/* try to avoid recursion */
if (prompter == NULL)
goto out;
krb5_clear_error_string (context);
if (in_tkt_service != NULL
&& strcmp (in_tkt_service, "kadmin/changepw") == 0)
goto out;
ret = change_password (context,
client,
password,
buf,
sizeof(buf),
prompter,
data,
options);
if (ret)
goto out;
password = buf;
break;
default:
goto out;
} }
} }
if (prompter) ret = krb5_get_init_creds(context, creds, client, prompter,
print_expire (context, data, start_time, in_tkt_service, options);
krb5_princ_realm (context, this_cred.client), krb5_get_init_creds_opt_free(options);
&kdc_reply, memset(buf, 0, sizeof(buf));
prompter,
data);
out:
memset (buf, 0, sizeof(buf));
free (pre_auth_types);
free (etypes);
if (ret == 0) {
*creds = this_cred;
krb5_free_kdc_rep (context, &kdc_reply);
} else
krb5_free_creds_contents (context, &this_cred);
return ret; return ret;
} }