From 49f4372f3f635a6f8722d430d86a480db7db6e79 Mon Sep 17 00:00:00 2001 From: Alexandra Ellwood Date: Mon, 29 Sep 2008 20:48:43 +0000 Subject: [PATCH] Added support for disabling password saving, both globally and also per prompt via the UI. ticket: 6055 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20781 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/kim/kim_ui_plugin.h | 7 +++++- src/kim/agent/mac/ServerDemux.h | 1 + src/kim/agent/mac/ServerDemux.m | 12 +++++++++- src/kim/lib/kim_credential.c | 33 ++++++++++++++++++++++++- src/kim/lib/kim_identity.c | 19 ++++++++++----- src/kim/lib/kim_identity_private.h | 10 +++++--- src/kim/lib/kim_ui.c | 26 +++++++++++++++++--- src/kim/lib/kim_ui_cli.c | 9 ++++++- src/kim/lib/kim_ui_cli_private.h | 4 +++- src/kim/lib/kim_ui_gui_private.h | 4 +++- src/kim/lib/kim_ui_plugin.c | 8 +++++-- src/kim/lib/kim_ui_plugin_private.h | 4 +++- src/kim/lib/kim_ui_private.h | 1 + src/kim/lib/mac/kim_os_identity.c | 37 +++++++++++++++++++++++++++++ src/kim/lib/mac/kim_os_ui_gui.c | 26 +++++++++++++------- 15 files changed, 172 insertions(+), 29 deletions(-) diff --git a/src/include/kim/kim_ui_plugin.h b/src/include/kim/kim_ui_plugin.h index 0f6895ffc..99923e510 100644 --- a/src/include/kim/kim_ui_plugin.h +++ b/src/include/kim/kim_ui_plugin.h @@ -88,14 +88,19 @@ typedef struct kim_ui_plugin_ftable_v0 { kim_identity *out_identity); /* Present UI to display authentication to the user */ + /* If in_allow_save_reply is FALSE do not display UI to allow the user + * to save their password. In this case the value of out_save_reply will + * be ignored. */ kim_error (*auth_prompt) (void *in_context, kim_identity in_identity, kim_prompt_type in_type, + kim_boolean in_allow_save_reply, kim_boolean in_hide_reply, kim_string in_title, kim_string in_message, kim_string in_description, - char **out_reply); + char **out_reply, + kim_boolean *out_save_reply); /* Prompt to change the identity's password. * May be combined with an auth_prompt if additional auth is required, diff --git a/src/kim/agent/mac/ServerDemux.h b/src/kim/agent/mac/ServerDemux.h index 12afa36c2..1f1de5964 100644 --- a/src/kim/agent/mac/ServerDemux.h +++ b/src/kim/agent/mac/ServerDemux.h @@ -43,6 +43,7 @@ int32_t kim_handle_reply_select_identity (mach_port_t in_reply_port, int32_t kim_handle_reply_auth_prompt (mach_port_t in_reply_port, kim_string in_prompt_response, + kim_boolean in_allow_save_response, int32_t in_error); int32_t kim_handle_reply_change_password (mach_port_t in_reply_port, diff --git a/src/kim/agent/mac/ServerDemux.m b/src/kim/agent/mac/ServerDemux.m index bc8525b0d..a70a668c4 100644 --- a/src/kim/agent/mac/ServerDemux.m +++ b/src/kim/agent/mac/ServerDemux.m @@ -267,6 +267,7 @@ static int32_t kim_handle_request_auth_prompt (mach_port_t in_client_port, int32_t err = 0; char *identity_string = NULL; int32_t type = 0; + int32_t allow_save_reply = 0; int32_t hide_reply = 0; char *title = NULL; char *message = NULL; @@ -280,6 +281,10 @@ static int32_t kim_handle_request_auth_prompt (mach_port_t in_client_port, err = k5_ipc_stream_read_int32 (in_request_stream, &type); } + if (!err) { + err = k5_ipc_stream_read_int32 (in_request_stream, &allow_save_reply); + } + if (!err) { err = k5_ipc_stream_read_int32 (in_request_stream, &hide_reply); } @@ -299,7 +304,7 @@ static int32_t kim_handle_request_auth_prompt (mach_port_t in_client_port, if (!err) { NSLog (@"Got auth prompt with identity '%s', type '%d', hide '%d', title '%s', message '%s', description '%s'", identity_string, type, hide_reply, title, message, description); - err = kim_handle_reply_auth_prompt (in_reply_port, "ydobon", 0); + err = kim_handle_reply_auth_prompt (in_reply_port, "ydobon", 0, 0); #warning Send auth prompt message to main thread with 2 ports and arguments } @@ -315,6 +320,7 @@ static int32_t kim_handle_request_auth_prompt (mach_port_t in_client_port, int32_t kim_handle_reply_auth_prompt (mach_port_t in_reply_port, kim_string in_prompt_response, + kim_boolean in_allow_save_response, int32_t in_error) { int32_t err = 0; @@ -332,6 +338,10 @@ int32_t kim_handle_reply_auth_prompt (mach_port_t in_reply_port, err = k5_ipc_stream_write_string (reply, in_prompt_response); } + if (!err && !in_error) { + err = k5_ipc_stream_write_int32 (reply, in_allow_save_response); + } + if (!err) { err = k5_ipc_server_send_reply (in_reply_port, reply); } diff --git a/src/kim/lib/kim_credential.c b/src/kim/lib/kim_credential.c index ee2ec0448..64561896d 100644 --- a/src/kim/lib/kim_credential.c +++ b/src/kim/lib/kim_credential.c @@ -278,10 +278,41 @@ kim_error kim_credential_create_new (kim_credential *out_credential, &credential->creds)); } + if (!err && context.password_to_save) { + /* If we were successful, save any password we got */ + err = kim_os_identity_set_saved_password (identity, + context.password_to_save); + + + } if (err == KRB5KDC_ERR_KEY_EXP) { + kim_string new_password = NULL; + err = kim_identity_change_password_common (identity, 1, - &context); + &context, + &new_password); + + if (!err) { + /* 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, + principal, + (char *) new_password, + kim_ui_prompter, + &context, + start_time, + service, + opts)); + + prompt_count = context.prompt_count; /* remember if we got prompts */ + if (!err) { free_creds = 1; } + } + + kim_string_free (&new_password); } if (!err || err == KIM_USER_CANCELED_ERR) { diff --git a/src/kim/lib/kim_identity.c b/src/kim/lib/kim_identity.c index b431ae8b8..10604e6d0 100644 --- a/src/kim/lib/kim_identity.c +++ b/src/kim/lib/kim_identity.c @@ -673,7 +673,8 @@ static kim_error kim_identity_change_password_with_credential (kim_identity i kim_error kim_identity_change_password_common (kim_identity in_identity, kim_boolean in_old_password_expired, - kim_ui_context *in_ui_context) + kim_ui_context *in_ui_context, + kim_string *out_new_password) { kim_error err = KIM_NO_ERROR; kim_boolean done = 0; @@ -700,7 +701,9 @@ kim_error kim_identity_change_password_common (kim_identity in_identity, if (!err) { kim_comparison comparison; - err = kim_string_compare (new_password, verify_password, &comparison); + err = kim_string_compare (new_password, + verify_password, + &comparison); if (!err && !kim_comparison_is_equal_to (comparison)) { err = check_error (KIM_PASSWORD_MISMATCH_ERR); } @@ -748,9 +751,8 @@ kim_error kim_identity_change_password_common (kim_identity 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. */ + if (was_prompted || err == KIM_PASSWORD_MISMATCH_ERR) { + /* User could have entered bad info so let them try again. */ err = terr; } @@ -758,6 +760,10 @@ kim_error kim_identity_change_password_common (kim_identity in_identity, /* password change succeeded or the user gave up */ done = 1; + if (!err && out_new_password) { + err = kim_string_copy (out_new_password, new_password); + } + if (!err) { kim_error terr = KIM_NO_ERROR; kim_string saved_password = NULL; @@ -801,7 +807,8 @@ kim_error kim_identity_change_password (kim_identity in_identity) } if (!err) { - err = kim_identity_change_password_common (in_identity, 0, &context); + err = kim_identity_change_password_common (in_identity, 0, + &context, NULL); } if (ui_inited) { diff --git a/src/kim/lib/kim_identity_private.h b/src/kim/lib/kim_identity_private.h index f8ef4d629..2a212aa1c 100644 --- a/src/kim/lib/kim_identity_private.h +++ b/src/kim/lib/kim_identity_private.h @@ -39,16 +39,20 @@ kim_error kim_identity_is_tgt_service (kim_identity in_identity, kim_error kim_os_identity_create_for_username (kim_identity *out_identity); + +kim_boolean kim_os_identity_allow_save_password (void); + kim_error kim_os_identity_get_saved_password (kim_identity in_identity, kim_string *out_password); kim_error kim_os_identity_set_saved_password (kim_identity in_identity, kim_string in_password); +kim_error kim_os_identity_remove_saved_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 kim_os_identity_remove_saved_password (kim_identity in_identity); + kim_ui_context *in_ui_context, + kim_string *out_new_password); #endif /* KIM_IDENTITY_PRIVATE_H */ diff --git a/src/kim/lib/kim_ui.c b/src/kim/lib/kim_ui.c index 3abc3f95c..b585ff7a0 100644 --- a/src/kim/lib/kim_ui.c +++ b/src/kim/lib/kim_ui.c @@ -103,6 +103,7 @@ kim_error kim_ui_init (kim_ui_context *io_context) io_context->initialized = 0; io_context->identity = NULL; io_context->prompt_count = 0; + io_context->password_to_save = NULL; } return check_error (err); @@ -228,6 +229,9 @@ krb5_error_code kim_ui_prompter (krb5_context in_krb5_context, } if (!got_saved_password) { + kim_boolean save_reply = FALSE; + kim_boolean allow_save_password = kim_os_identity_allow_save_password (); + context->prompt_count++; err = kim_ui_init_lazy (in_context); @@ -237,38 +241,52 @@ krb5_error_code kim_ui_prompter (krb5_context in_krb5_context, err = kim_ui_plugin_auth_prompt (context, context->identity, type, + allow_save_password, in_prompts[i].hidden, in_name, in_banner, in_prompts[i].prompt, - &reply); + &reply, + &save_reply); #ifndef LEAN_CLIENT } else if (context->type == kim_ui_type_gui_builtin) { err = kim_os_ui_gui_auth_prompt (context, context->identity, type, + allow_save_password, in_prompts[i].hidden, in_name, in_banner, in_prompts[i].prompt, - &reply); + &reply, + &save_reply); } else if (context->type == kim_ui_type_cli) { err = kim_ui_cli_auth_prompt (context, context->identity, type, + allow_save_password, in_prompts[i].hidden, in_name, in_banner, in_prompts[i].prompt, - &reply); + &reply, + &save_reply); #endif /* LEAN_CLIENT */ } else { err = check_error (KIM_NO_UI_ERR); } } + + if (!err && type == kim_prompt_type_password) { + kim_string_free (&context->password_to_save); + + if (allow_save_password && save_reply) { + err = kim_string_copy (&context->password_to_save, reply); + } + } } if (!err) { @@ -453,6 +471,8 @@ kim_error kim_ui_fini (kim_ui_context *io_context) } else { err = check_error (KIM_NO_UI_ERR); } + + kim_string_free (&io_context->password_to_save); } return check_error (err); diff --git a/src/kim/lib/kim_ui_cli.c b/src/kim/lib/kim_ui_cli.c index f26e32882..cd7cea601 100644 --- a/src/kim/lib/kim_ui_cli.c +++ b/src/kim/lib/kim_ui_cli.c @@ -152,11 +152,13 @@ kim_error kim_ui_cli_select_identity (kim_ui_context *in_context, kim_error kim_ui_cli_auth_prompt (kim_ui_context *in_context, kim_identity in_identity, kim_prompt_type in_type, + kim_boolean in_allow_save_reply, kim_boolean in_hide_reply, kim_string in_title, kim_string in_message, kim_string in_description, - char **out_reply) + char **out_reply, + kim_boolean *out_save_reply) { kim_error err = KIM_NO_ERROR; @@ -210,6 +212,11 @@ kim_error kim_ui_cli_auth_prompt (kim_ui_context *in_context, err = kim_string_create_from_buffer ((kim_string *) out_reply, prompts[0].reply->data, prompts[0].reply->length); + if (!err) { + /* always allow password saving */ + *out_save_reply = (in_allow_save_reply && + in_type == kim_prompt_type_password); + } } if (k5context) { krb5_free_context (k5context); } diff --git a/src/kim/lib/kim_ui_cli_private.h b/src/kim/lib/kim_ui_cli_private.h index 872fb4b22..505919600 100644 --- a/src/kim/lib/kim_ui_cli_private.h +++ b/src/kim/lib/kim_ui_cli_private.h @@ -46,11 +46,13 @@ kim_error kim_ui_cli_select_identity (kim_ui_context *in_context, kim_error kim_ui_cli_auth_prompt (kim_ui_context *in_context, kim_identity in_identity, kim_prompt_type in_type, + kim_boolean in_allow_save_reply, kim_boolean in_hide_reply, kim_string in_title, kim_string in_message, kim_string in_description, - char **out_reply); + char **out_reply, + kim_boolean *out_save_reply); kim_error kim_ui_cli_change_password (kim_ui_context *in_context, kim_identity in_identity, diff --git a/src/kim/lib/kim_ui_gui_private.h b/src/kim/lib/kim_ui_gui_private.h index b89cf348f..dd2f2a9e5 100644 --- a/src/kim/lib/kim_ui_gui_private.h +++ b/src/kim/lib/kim_ui_gui_private.h @@ -46,11 +46,13 @@ kim_error kim_os_ui_gui_select_identity (kim_ui_context *in_context, kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, kim_identity in_identity, kim_prompt_type in_type, + kim_boolean in_allow_save_reply, kim_boolean in_hide_reply, kim_string in_title, kim_string in_message, kim_string in_description, - char **out_reply); + char **out_reply, + kim_boolean *out_save_reply); kim_error kim_os_ui_gui_change_password (kim_ui_context *in_context, kim_identity in_identity, diff --git a/src/kim/lib/kim_ui_plugin.c b/src/kim/lib/kim_ui_plugin.c index 49cceaeb4..0ac2f1494 100644 --- a/src/kim/lib/kim_ui_plugin.c +++ b/src/kim/lib/kim_ui_plugin.c @@ -202,11 +202,13 @@ kim_error kim_ui_plugin_select_identity (kim_ui_context *in_context, kim_error kim_ui_plugin_auth_prompt (kim_ui_context *in_context, kim_identity in_identity, kim_prompt_type in_type, + kim_boolean in_allow_save_reply, kim_boolean in_hide_reply, kim_string in_title, kim_string in_message, kim_string in_description, - char **out_reply) + char **out_reply, + kim_boolean *out_save_reply) { kim_error err = KIM_NO_ERROR; @@ -221,11 +223,13 @@ kim_error kim_ui_plugin_auth_prompt (kim_ui_context *in_context, err = context->ftable->auth_prompt (context->plugin_context, in_identity, in_type, + in_allow_save_reply, in_hide_reply, in_title, in_message, in_description, - out_reply); + out_reply, + out_save_reply); } return check_error (err); diff --git a/src/kim/lib/kim_ui_plugin_private.h b/src/kim/lib/kim_ui_plugin_private.h index e4d354764..58eb60f40 100644 --- a/src/kim/lib/kim_ui_plugin_private.h +++ b/src/kim/lib/kim_ui_plugin_private.h @@ -45,11 +45,13 @@ kim_error kim_ui_plugin_select_identity (kim_ui_context *in_context, kim_error kim_ui_plugin_auth_prompt (kim_ui_context *in_context, kim_identity in_identity, kim_prompt_type in_type, + kim_boolean in_allow_save_reply, kim_boolean in_hide_reply, kim_string in_title, kim_string in_message, kim_string in_description, - char **out_reply); + char **out_reply, + kim_boolean *out_save_reply); kim_error kim_ui_plugin_change_password (kim_ui_context *in_context, kim_identity in_identity, diff --git a/src/kim/lib/kim_ui_private.h b/src/kim/lib/kim_ui_private.h index d280f5997..f4d1b10d9 100644 --- a/src/kim/lib/kim_ui_private.h +++ b/src/kim/lib/kim_ui_private.h @@ -50,6 +50,7 @@ typedef struct kim_ui_context { void *tcontext; kim_identity identity; kim_count prompt_count; + kim_string password_to_save; } kim_ui_context; diff --git a/src/kim/lib/mac/kim_os_identity.c b/src/kim/lib/mac/kim_os_identity.c index 690a2f252..fba941820 100644 --- a/src/kim/lib/mac/kim_os_identity.c +++ b/src/kim/lib/mac/kim_os_identity.c @@ -32,6 +32,33 @@ /* ------------------------------------------------------------------------ */ +kim_boolean kim_os_identity_allow_save_password (void) +{ + kim_boolean disabled = 0; + CFPropertyListRef disable_pref = NULL; + + disable_pref = CFPreferencesCopyValue (CFSTR ("SavePasswordDisabled"), + CFSTR ("edu.mit.Kerberos.KerberosAgent"), + kCFPreferencesAnyUser, + kCFPreferencesAnyHost); + if (!disable_pref) { + disable_pref = CFPreferencesCopyValue (CFSTR ("SavePasswordDisabled"), + CFSTR ("edu.mit.Kerberos.KerberosAgent"), + kCFPreferencesAnyUser, + kCFPreferencesCurrentHost); + } + + disabled = (disable_pref && + CFGetTypeID (disable_pref) == CFBooleanGetTypeID () && + CFBooleanGetValue (disable_pref)); + + if (disable_pref) { CFRelease (disable_pref); } + + return !disabled; +} + +/* ------------------------------------------------------------------------ */ + kim_error kim_os_identity_get_saved_password (kim_identity in_identity, kim_string *out_password) { @@ -44,6 +71,11 @@ kim_error kim_os_identity_get_saved_password (kim_identity in_identity, if (!err && !in_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !out_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* Short circuit if password saving is disabled */ + if (!err && !kim_os_identity_allow_save_password ()) { + return kim_os_identity_remove_saved_password (in_identity); + } + if (!err) { err = kim_identity_get_components_string (in_identity, &name); } @@ -85,6 +117,11 @@ kim_error kim_os_identity_set_saved_password (kim_identity in_identity, if (!err && !in_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_password) { err = check_error (KIM_NULL_PARAMETER_ERR); } + /* Short circuit if password saving is disabled */ + if (!err && !kim_os_identity_allow_save_password ()) { + return kim_os_identity_remove_saved_password (in_identity); + } + if (!err) { err = kim_identity_get_components_string (in_identity, &name); } diff --git a/src/kim/lib/mac/kim_os_ui_gui.c b/src/kim/lib/mac/kim_os_ui_gui.c index 1ada9e213..d87efb067 100644 --- a/src/kim/lib/mac/kim_os_ui_gui.c +++ b/src/kim/lib/mac/kim_os_ui_gui.c @@ -220,14 +220,16 @@ kim_error kim_os_ui_gui_select_identity (kim_ui_context *in_context, /* ------------------------------------------------------------------------ */ -kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, - kim_identity in_identity, - kim_prompt_type in_type, - kim_boolean in_hide_reply, - kim_string in_title, - kim_string in_message, - kim_string in_description, - char **out_reply) +kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, + kim_identity in_identity, + kim_prompt_type in_type, + kim_boolean in_allow_save_reply, + kim_boolean in_hide_reply, + kim_string in_title, + kim_string in_message, + kim_string in_description, + char **out_reply, + kim_boolean *out_save_reply) { kim_error err = KIM_NO_ERROR; k5_ipc_stream request = NULL; @@ -258,6 +260,10 @@ kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, err = k5_ipc_stream_write_int32 (request, in_type); } + if (!err) { + err = k5_ipc_stream_write_int32 (request, in_allow_save_reply); + } + if (!err) { err = k5_ipc_stream_write_int32 (request, in_hide_reply); } @@ -295,6 +301,10 @@ kim_error kim_os_ui_gui_auth_prompt (kim_ui_context *in_context, err = k5_ipc_stream_read_string (reply, out_reply); } + if (!err) { + err = k5_ipc_stream_read_int32 (reply, out_save_reply); + } + kim_string_free (&identity_string); k5_ipc_stream_release (request); -- 2.26.2