krb5: krb5_get_init_creds_opt_set_change_password_prompt incomplete (#322)

krb5_get_init_creds_opt_set_change_password_prompt() was being ignored by
krb5_init_creds_step() which broke pam_krb5 tests. MIT doesn't handle password
expiration within krb5_init_creds_step(), instead deferring to higher level
functions such as krb5_get_init_creds_password(). However, Heimdal kinit uses
krb5_init_creds_step() directly and thus requires this behaviour to be
implemented to pass its own tests.
This commit is contained in:
Luke Howard
2018-12-22 18:13:06 +11:00
parent 3c92747f2a
commit 070d0cf928

View File

@@ -66,6 +66,7 @@ typedef struct krb5_get_init_creds_ctx {
struct {
unsigned change_password:1;
unsigned change_password_prompt:1;
} runflags;
int used_pa_types;
@@ -386,6 +387,8 @@ static krb5_addresses no_addrs = { 0, NULL };
static krb5_error_code
get_init_creds_common(krb5_context context,
krb5_principal client,
krb5_prompter_fct prompter,
void *prompter_data,
krb5_deltat start_time,
krb5_get_init_creds_opt *options,
krb5_init_creds_context ctx)
@@ -502,6 +505,16 @@ get_init_creds_common(krb5_context context,
}
if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS)
ctx->flags.request_anonymous = options->anonymous;
ctx->prompter = prompter;
ctx->prompter_data = prompter_data;
if ((options->flags & KRB5_GET_INIT_CREDS_OPT_CHANGE_PASSWORD_PROMPT) &&
!options->change_password_prompt)
ctx->runflags.change_password_prompt = 0;
else
ctx->runflags.change_password_prompt = ctx->prompter != NULL;
if (default_opt)
krb5_get_init_creds_opt_free(context, default_opt);
return 0;
@@ -1412,7 +1425,8 @@ krb5_init_creds_init(krb5_context context,
if (ctx == NULL)
return krb5_enomem(context);
ret = get_init_creds_common(context, client, start_time, options, ctx);
ret = get_init_creds_common(context, client, prompter, prompter_data,
start_time, options, ctx);
if (ret) {
free(ctx);
return ret;
@@ -1424,9 +1438,6 @@ krb5_init_creds_init(krb5_context context,
/* XXX these just needs to be the same when using Windows PK-INIT */
ctx->pk_nonce = ctx->nonce;
ctx->prompter = prompter;
ctx->prompter_data = prompter_data;
*rctx = ctx;
return ret;
@@ -2378,11 +2389,13 @@ krb5_init_creds_step(krb5_context context,
memset_s(&ctx->as_req, sizeof(ctx->as_req), 0, sizeof(ctx->as_req));
ctx->used_pa_types = 0;
} else if (ret == KRB5KDC_ERR_KEY_EXP && ctx->runflags.change_password == 0 && ctx->prompter) {
} else if (ret == KRB5KDC_ERR_KEY_EXP && ctx->runflags.change_password == 0 &&
ctx->runflags.change_password_prompt) {
char buf2[1024];
ctx->runflags.change_password = 1;
heim_assert(ctx->prompter != NULL, "unexpected NULL prompter");
ctx->prompter(context, ctx->prompter_data, NULL, N_("Password has expired", ""), 0, NULL);
@@ -2717,14 +2730,10 @@ krb5_get_init_creds_password(krb5_context context,
if (in_tkt_service != NULL && strcmp(in_tkt_service, "kadmin/changepw") == 0)
goto out;
/* don't try to change password where then where none */
if (prompter == NULL)
/* don't try to change password if no prompter or prompting disabled */
if (!ctx->runflags.change_password_prompt)
goto out;
if ((options->flags & KRB5_GET_INIT_CREDS_OPT_CHANGE_PASSWORD_PROMPT) &&
!options->change_password_prompt)
goto out;
ret = change_password (context,
client,
ctx->password,