summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlexandra Ellwood <lxs@mit.edu>2008-09-25 19:53:18 +0000
committerAlexandra Ellwood <lxs@mit.edu>2008-09-25 19:53:18 +0000
commit7dd00aea5c305566d1e07ac6709fed49e9a747b5 (patch)
treeeb1376b9a9bbb85f3a7a8bf31334e084d2f1944f /src
parent3899d6842a98637a206a50e26115bafa01995836 (diff)
downloadkrb5-7dd00aea5c305566d1e07ac6709fed49e9a747b5.tar.gz
krb5-7dd00aea5c305566d1e07ac6709fed49e9a747b5.tar.xz
krb5-7dd00aea5c305566d1e07ac6709fed49e9a747b5.zip
Added support to track number of prompts so UIs do not try again unless
there is something the user can do differently the next time. ticket: 6055 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20752 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/kim/lib/kim_credential.c46
-rw-r--r--src/kim/lib/kim_credential_private.h3
-rw-r--r--src/kim/lib/kim_identity.c92
-rw-r--r--src/kim/lib/kim_identity_private.h5
-rw-r--r--src/kim/lib/kim_ui.c3
-rw-r--r--src/kim/lib/kim_ui_cli.c10
-rw-r--r--src/kim/lib/kim_ui_private.h1
7 files changed, 121 insertions, 39 deletions
diff --git a/src/kim/lib/kim_credential.c b/src/kim/lib/kim_credential.c
index f77be0993..b03cba183 100644
--- a/src/kim/lib/kim_credential.c
+++ b/src/kim/lib/kim_credential.c
@@ -260,7 +260,11 @@ kim_error kim_credential_create_new (kim_credential *out_credential,
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,
@@ -271,6 +275,7 @@ kim_error kim_credential_create_new (kim_credential *out_credential,
(char *) service,
init_cred_options));
+ prompt_count = context.prompt_count; /* remember if we got prompts */
if (!err) { free_creds = 1; }
if (!err) {
@@ -280,15 +285,27 @@ kim_error kim_credential_create_new (kim_credential *out_credential,
&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); }
@@ -495,7 +512,8 @@ kim_error kim_credential_create_from_krb5_creds (kim_credential *out_credential,
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;
@@ -504,9 +522,10 @@ kim_error kim_credential_create_for_change_password (kim_credential *out_creden
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);
@@ -541,6 +560,9 @@ kim_error kim_credential_create_for_change_password (kim_credential *out_creden
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,
@@ -549,8 +571,9 @@ kim_error kim_credential_create_for_change_password (kim_credential *out_creden
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,
@@ -565,6 +588,7 @@ kim_error kim_credential_create_for_change_password (kim_credential *out_creden
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;
}
diff --git a/src/kim/lib/kim_credential_private.h b/src/kim/lib/kim_credential_private.h
index f5045ad85..3f30d6c73 100644
--- a/src/kim/lib/kim_credential_private.h
+++ b/src/kim/lib/kim_credential_private.h
@@ -33,6 +33,7 @@
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 */
diff --git a/src/kim/lib/kim_identity.c b/src/kim/lib/kim_identity.c
index 1ef30c257..1308c3d7a 100644
--- a/src/kim/lib/kim_identity.c
+++ b/src/kim/lib/kim_identity.c
@@ -653,19 +653,15 @@ static kim_error kim_identity_change_password_with_credential (kim_identity i
/* ------------------------------------------------------------------------ */
-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;
@@ -674,10 +670,11 @@ kim_error kim_identity_change_password (kim_identity in_identity)
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);
@@ -694,21 +691,22 @@ kim_error kim_identity_change_password (kim_identity in_identity)
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);
@@ -719,27 +717,73 @@ kim_error kim_identity_change_password (kim_identity in_identity)
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) {
diff --git a/src/kim/lib/kim_identity_private.h b/src/kim/lib/kim_identity_private.h
index d22417955..44f8c631d 100644
--- a/src/kim/lib/kim_identity_private.h
+++ b/src/kim/lib/kim_identity_private.h
@@ -29,6 +29,7 @@
#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);
@@ -45,4 +46,8 @@ kim_error kim_os_identity_get_saved_password (kim_identity in_identity,
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 */
diff --git a/src/kim/lib/kim_ui.c b/src/kim/lib/kim_ui.c
index 4c1ad8b62..5060fb049 100644
--- a/src/kim/lib/kim_ui.c
+++ b/src/kim/lib/kim_ui.c
@@ -82,6 +82,7 @@ kim_error kim_ui_init (kim_ui_context *io_context)
if (!err) {
io_context->identity = NULL;
+ io_context->prompt_count = 0;
}
return check_error (err);
@@ -199,6 +200,8 @@ krb5_error_code kim_ui_prompter (krb5_context in_krb5_context,
}
if (!got_saved_password) {
+ context->prompt_count++;
+
if (context->type == kim_ui_type_gui_plugin) {
err = kim_ui_plugin_auth_prompt (context,
context->identity,
diff --git a/src/kim/lib/kim_ui_cli.c b/src/kim/lib/kim_ui_cli.c
index 79f28e0ff..0e5fc9ec4 100644
--- a/src/kim/lib/kim_ui_cli.c
+++ b/src/kim/lib/kim_ui_cli.c
@@ -349,6 +349,8 @@ kim_error kim_ui_cli_change_password (kim_ui_context *in_context,
}
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,
@@ -359,14 +361,16 @@ kim_error kim_ui_cli_change_password (kim_ui_context *in_context,
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;
}
diff --git a/src/kim/lib/kim_ui_private.h b/src/kim/lib/kim_ui_private.h
index abaffcf04..548836f8d 100644
--- a/src/kim/lib/kim_ui_private.h
+++ b/src/kim/lib/kim_ui_private.h
@@ -48,6 +48,7 @@ typedef struct kim_ui_context {
enum kim_ui_type type;
void *tcontext;
kim_identity identity;
+ kim_count prompt_count;
} kim_ui_context;