while (!err && !done) {
krb5_creds creds;
kim_boolean free_creds = 0;
-
+ kim_count prompt_count;
+
+ /* set counter to zero so we can tell if we got prompted */
+ context.prompt_count = 0;
+
err = krb5_error (credential->context,
krb5_get_init_creds_password (credential->context,
&creds,
(char *) service,
init_cred_options));
+ prompt_count = context.prompt_count; /* remember if we got prompts */
if (!err) { free_creds = 1; }
if (!err) {
&credential->creds));
}
+
+ if (err == KRB5KDC_ERR_KEY_EXP) {
+ err = kim_identity_change_password_common (in_identity, 1,
+ &context);
+ }
+
if (!err || err == KIM_USER_CANCELED_ERR) {
/* new creds obtained or the user gave up */
done = 1;
- } else {
+ } else {
/* new creds failed, report error to user */
- err = kim_ui_handle_kim_error (&context, in_identity,
- kim_ui_error_type_authentication,
- err);
+ kim_error terr = kim_ui_handle_kim_error (&context, in_identity,
+ kim_ui_error_type_authentication,
+ err);
+
+ if (prompt_count) {
+ /* User was prompted and might have entered bad info
+ * so let them try again. */
+ err = terr;
+ }
}
if (free_creds) { krb5_free_cred_contents (credential->context, &creds); }
kim_error kim_credential_create_for_change_password (kim_credential *out_credential,
kim_identity in_identity,
kim_string in_old_password,
- kim_ui_context *in_ui_context)
+ kim_ui_context *in_ui_context,
+ kim_boolean *out_user_was_prompted)
{
kim_error err = KIM_NO_ERROR;
kim_credential credential = NULL;
krb5_principal principal = NULL;
kim_string service_format = "kadmin/changepw@%s";
- if (!err && !out_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
- if (!err && !in_old_password) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !out_credential ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !in_old_password ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !out_user_was_prompted) { err = check_error (KIM_NULL_PARAMETER_ERR); }
if (!err) {
err = kim_credential_allocate (&credential);
krb5_get_init_creds_opt_set_forwardable (&opts, 0);
krb5_get_init_creds_opt_set_proxiable (&opts, 0);
+ /* set counter to zero so we can tell if we got prompted */
+ in_ui_context->prompt_count = 0;
+
err = krb5_error (credential->context,
krb5_get_init_creds_password (credential->context,
&creds,
kim_ui_prompter,
in_ui_context, 0,
(char *) service,
- &opts));
- if (!err) { free_creds = 1; }
+ &opts));
+
+ if (!err) { free_creds = 1; }
if (!err) {
err = krb5_error (credential->context,
if (principal) { krb5_free_principal (credential->context, principal); }
if (!err) {
+ *out_user_was_prompted = (in_ui_context->prompt_count > 0);
*out_credential = credential;
credential = NULL;
}
kim_error kim_credential_create_for_change_password (kim_credential *out_credential,
kim_identity in_identity,
kim_string in_old_password,
- kim_ui_context *in_ui_context);
+ kim_ui_context *in_ui_context,
+ kim_boolean *out_user_was_prompted);
#endif /* KIM_CREDENTIAL_PRIVATE_H */
/* ------------------------------------------------------------------------ */
-kim_error kim_identity_change_password (kim_identity in_identity)
+kim_error kim_identity_change_password_common (kim_identity in_identity,
+ kim_boolean in_old_password_expired,
+ kim_ui_context *in_ui_context)
{
kim_error err = KIM_NO_ERROR;
- kim_ui_context context;
- kim_boolean ui_inited = 0;
kim_boolean done = 0;
- if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-
- if (!err) {
- err = kim_ui_init (&context);
- if (!err) { ui_inited = 1; }
- }
+ if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+ if (!err && !in_ui_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
while (!err && !done) {
char *old_password = NULL;
kim_error rejected_err = KIM_NO_ERROR;
kim_string rejected_message = NULL;
kim_string rejected_description = NULL;
+ kim_boolean was_prompted = 0;
- err = kim_ui_change_password (&context,
+ err = kim_ui_change_password (in_ui_context,
in_identity,
- 0 /* old password not expired */,
+ in_old_password_expired,
&old_password,
&new_password,
&verify_password);
if (!err) {
kim_credential credential = NULL;
- if (context.type == kim_ui_type_cli && context.tcontext) {
+ if (in_ui_context->type == kim_ui_type_cli && in_ui_context->tcontext) {
/* command line has already gotten the credentials for us */
- credential = (kim_credential) context.tcontext;
+ credential = (kim_credential) in_ui_context->tcontext;
} else {
err = kim_credential_create_for_change_password (&credential,
in_identity,
old_password,
- &context);
+ in_ui_context,
+ &was_prompted);
}
if (!err) {
err = kim_identity_change_password_with_credential (in_identity,
credential,
new_password,
- &context,
+ in_ui_context,
&rejected_err,
&rejected_message,
&rejected_description);
if (!err && rejected_err) {
/* Password rejected, report it to the user */
- err = kim_ui_handle_error (&context, in_identity,
+ err = kim_ui_handle_error (in_ui_context, in_identity,
rejected_err,
rejected_message,
rejected_description);
-
+
} else if (err && err != KIM_USER_CANCELED_ERR) {
- /* new creds failed, report error to user */
- err = kim_ui_handle_kim_error (&context, in_identity,
- kim_ui_error_type_change_password,
- err);
+ /* new creds failed, report error to user */
+ kim_error terr = KIM_NO_ERROR;
+
+ terr = kim_ui_handle_kim_error (in_ui_context, in_identity,
+ kim_ui_error_type_change_password,
+ err);
+
+ if (was_prompted) {
+ /* User was prompted and might have entered bad info
+ * so let them try again. */
+ err = terr;
+ }
} else {
/* password change succeeded or the user gave up */
done = 1;
+
+ if (!err) {
+ kim_error terr = KIM_NO_ERROR;
+ kim_string saved_password = NULL;
+
+ terr = kim_os_identity_get_saved_password (in_identity,
+ &saved_password);
+ if (!terr) {
+ /* We changed the password and the user had their
+ * old password saved. Update it. */
+ terr = kim_os_identity_set_saved_password (in_identity,
+ new_password);
+ }
+
+ kim_string_free (&saved_password);
+ }
}
kim_string_free (&rejected_message);
kim_string_free (&rejected_description);
- kim_ui_free_string (&context, &old_password);
- kim_ui_free_string (&context, &new_password);
- kim_ui_free_string (&context, &verify_password);
+ kim_ui_free_string (in_ui_context, &old_password);
+ kim_ui_free_string (in_ui_context, &new_password);
+ kim_ui_free_string (in_ui_context, &verify_password);
+ }
+
+ return check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+kim_error kim_identity_change_password (kim_identity in_identity)
+{
+ kim_error err = KIM_NO_ERROR;
+ kim_ui_context context;
+ kim_boolean ui_inited = 0;
+
+ if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+
+ if (!err) {
+ err = kim_ui_init (&context);
+ if (!err) { ui_inited = 1; }
+ }
+
+ if (!err) {
+ err = kim_identity_change_password_common (in_identity, 0, &context);
}
if (ui_inited) {
#include <kim/kim.h>
#include "kim_library_private.h"
+#include "kim_ui_private.h"
kim_error kim_identity_get_components (kim_identity in_identity,
kim_string *out_components);
kim_error kim_os_identity_set_saved_password (kim_identity in_identity,
kim_string in_password);
+kim_error kim_identity_change_password_common (kim_identity in_identity,
+ kim_boolean in_old_password_expired,
+ kim_ui_context *in_ui_context);
+
#endif /* KIM_IDENTITY_PRIVATE_H */
if (!err) {
io_context->identity = NULL;
+ io_context->prompt_count = 0;
}
return check_error (err);
}
if (!got_saved_password) {
+ context->prompt_count++;
+
if (context->type == kim_ui_type_gui_plugin) {
err = kim_ui_plugin_auth_prompt (context,
context->identity,
}
while (!err && !done) {
+ kim_boolean was_prompted = 0; /* ignore because we always prompt */
+
kim_string_free (&old_password);
err = kim_ui_cli_read_string (&old_password,
err = kim_credential_create_for_change_password ((kim_credential *) &in_context->tcontext,
in_identity,
old_password,
- in_context);
+ in_context,
+ &was_prompted);
}
if (err && err != KIM_USER_CANCELED_ERR) {
- /* new creds failed, report error to user */
+ /* new creds failed, report error to user */
err = kim_ui_handle_kim_error (in_context, in_identity,
- kim_ui_error_type_change_password,
+ kim_ui_error_type_authentication,
err);
+
} else {
done = 1;
}
enum kim_ui_type type;
void *tcontext;
kim_identity identity;
+ kim_count prompt_count;
} kim_ui_context;